func (p *Provisioner) deployOhaiHints( o terraform.UIOutput, comm communicator.Communicator, hintDir string) error { for _, hint := range p.OhaiHints { // Open the hint file f, err := os.Open(hint) if err != nil { return err } defer f.Close() // Copy the hint to the new instance if err := comm.Upload(path.Join(hintDir, path.Base(hint)), f); err != nil { return fmt.Errorf("Uploading %s failed: %v", path.Base(hint), err) } } return nil }
// copyFiles is used to copy the files from a source to a destination func (p *ResourceProvisioner) copyFiles(comm communicator.Communicator, src, dst string) error { // Wait and retry until we establish the connection err := retryFunc(comm.Timeout(), func() error { err := comm.Connect(nil) return err }) if err != nil { return err } defer comm.Disconnect() info, err := os.Stat(src) if err != nil { return err } // If we're uploading a directory, short circuit and do that if info.IsDir() { if err := comm.UploadDir(dst, src); err != nil { return fmt.Errorf("Upload failed: %v", err) } return nil } // We're uploading a file... f, err := os.Open(src) if err != nil { return err } defer f.Close() err = comm.Upload(dst, f) if err != nil { return fmt.Errorf("Upload failed: %v", err) } return err }
func (p *Provisioner) deployConfigFiles( o terraform.UIOutput, comm communicator.Communicator, confDir string) error { // Open the validation key file f, err := os.Open(p.ValidationKeyPath) if err != nil { return err } defer f.Close() // Copy the validation key to the new instance if err := comm.Upload(path.Join(confDir, validationKey), f); err != nil { return fmt.Errorf("Uploading %s failed: %v", validationKey, err) } if p.SecretKeyPath != "" { // Open the secret key file s, err := os.Open(p.SecretKeyPath) if err != nil { return err } defer s.Close() // Copy the secret key to the new instance if err := comm.Upload(path.Join(confDir, secretKey), s); err != nil { return fmt.Errorf("Uploading %s failed: %v", secretKey, err) } } // Make strings.Join available for use within the template funcMap := template.FuncMap{ "join": strings.Join, } // Create a new template and parse the client config into it t := template.Must(template.New(clienrb).Funcs(funcMap).Parse(clientConf)) var buf bytes.Buffer err = t.Execute(&buf, p) if err != nil { return fmt.Errorf("Error executing %s template: %s", clienrb, err) } // Copy the client config to the new instance if err := comm.Upload(path.Join(confDir, clienrb), &buf); err != nil { return fmt.Errorf("Uploading %s failed: %v", clienrb, err) } // Create a map with first boot settings fb := make(map[string]interface{}) if p.Attributes != nil { fb = p.Attributes.(map[string]interface{}) } // Check if the run_list was also in the attributes and if so log a warning // that it will be overwritten with the value of the run_list argument. if _, found := fb["run_list"]; found { log.Printf("[WARNING] Found a 'run_list' specified in the configured attributes! " + "This value will be overwritten by the value of the `run_list` argument!") } // Marshal the first boot settings to JSON d, err := json.Marshal(fb) if err != nil { return fmt.Errorf("Failed to create %s data: %s", firstBoot, err) } // Copy the first-boot.json to the new instance if err := comm.Upload(path.Join(confDir, firstBoot), bytes.NewReader(d)); err != nil { return fmt.Errorf("Uploading %s failed: %v", firstBoot, err) } return nil }
func (p *Provisioner) deployConfigFiles( o terraform.UIOutput, comm communicator.Communicator, confDir string) error { contents, _, err := pathorcontents.Read(p.ValidationKey) if err != nil { return err } f := strings.NewReader(contents) // Copy the validation key to the new instance if err := comm.Upload(path.Join(confDir, validationKey), f); err != nil { return fmt.Errorf("Uploading %s failed: %v", validationKey, err) } if p.SecretKey != "" { contents, _, err := pathorcontents.Read(p.SecretKey) if err != nil { return err } s := strings.NewReader(contents) // Copy the secret key to the new instance if err := comm.Upload(path.Join(confDir, secretKey), s); err != nil { return fmt.Errorf("Uploading %s failed: %v", secretKey, err) } } // Make sure the SSLVerifyMode value is written as a symbol if p.SSLVerifyMode != "" && !strings.HasPrefix(p.SSLVerifyMode, ":") { p.SSLVerifyMode = fmt.Sprintf(":%s", p.SSLVerifyMode) } // Make strings.Join available for use within the template funcMap := template.FuncMap{ "join": strings.Join, } // Create a new template and parse the client config into it t := template.Must(template.New(clienrb).Funcs(funcMap).Parse(clientConf)) var buf bytes.Buffer err = t.Execute(&buf, p) if err != nil { return fmt.Errorf("Error executing %s template: %s", clienrb, err) } // Copy the client config to the new instance if err := comm.Upload(path.Join(confDir, clienrb), &buf); err != nil { return fmt.Errorf("Uploading %s failed: %v", clienrb, err) } // Create a map with first boot settings fb := make(map[string]interface{}) if p.Attributes != nil { fb = p.Attributes.(map[string]interface{}) } // Check if the run_list was also in the attributes and if so log a warning // that it will be overwritten with the value of the run_list argument. if _, found := fb["run_list"]; found { log.Printf("[WARNING] Found a 'run_list' specified in the configured attributes! " + "This value will be overwritten by the value of the `run_list` argument!") } // Add the initial runlist to the first boot settings if !p.UsePolicyfile { fb["run_list"] = p.RunList } // Marshal the first boot settings to JSON d, err := json.Marshal(fb) if err != nil { return fmt.Errorf("Failed to create %s data: %s", firstBoot, err) } // Copy the first-boot.json to the new instance if err := comm.Upload(path.Join(confDir, firstBoot), bytes.NewReader(d)); err != nil { return fmt.Errorf("Uploading %s failed: %v", firstBoot, err) } return nil }
// runScripts is used to copy and execute a set of scripts func (p *ResourceProvisioner) runScripts( o terraform.UIOutput, comm communicator.Communicator, scripts []io.ReadCloser) error { // Wait and retry until we establish the connection err := retryFunc(comm.Timeout(), func() error { err := comm.Connect(o) return err }) if err != nil { return err } defer comm.Disconnect() for _, script := range scripts { var cmd *remote.Cmd outR, outW := io.Pipe() errR, errW := io.Pipe() outDoneCh := make(chan struct{}) errDoneCh := make(chan struct{}) go p.copyOutput(o, outR, outDoneCh) go p.copyOutput(o, errR, errDoneCh) err = retryFunc(comm.Timeout(), func() error { remotePath := comm.ScriptPath() if err := comm.UploadScript(remotePath, script); err != nil { return fmt.Errorf("Failed to upload script: %v", err) } cmd = &remote.Cmd{ Command: remotePath, Stdout: outW, Stderr: errW, } if err := comm.Start(cmd); err != nil { return fmt.Errorf("Error starting script: %v", err) } // Upload a blank follow up file in the same path to prevent residual // script contents from remaining on remote machine empty := bytes.NewReader([]byte("")) if err := comm.Upload(remotePath, empty); err != nil { return fmt.Errorf("Failed to upload empty follow up script: %v", err) } return nil }) if err == nil { cmd.Wait() if cmd.ExitStatus != 0 { err = fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus) } } // Wait for output to clean up outW.Close() errW.Close() <-outDoneCh <-errDoneCh // If we have an error, return it out now that we've cleaned up if err != nil { return err } } return nil }