func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { config := state.Get("config").(*Config) var privateKey string var auth []gossh.AuthMethod if config.Comm.SSHPassword != "" { auth = []gossh.AuthMethod{ gossh.Password(config.Comm.SSHPassword), gossh.KeyboardInteractive( ssh.PasswordKeyboardInteractive(config.Comm.SSHPassword)), } } if config.Comm.SSHPrivateKey != "" { if priv, ok := state.GetOk("privateKey"); ok { privateKey = priv.(string) } signer, err := gossh.ParsePrivateKey([]byte(privateKey)) if err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } if err != nil { return nil, err } auth = append(auth, gossh.PublicKeys(signer)) } return &gossh.ClientConfig{ User: config.Comm.SSHUsername, Auth: auth, }, nil }
func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) { if s.createdGroupId == "" { return } ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) ui.Say("Deleting temporary security group...") var err error for i := 0; i < 5; i++ { _, err = ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{GroupId: &s.createdGroupId}) if err == nil { break } log.Printf("Error deleting security group: %s", err) time.Sleep(5 * time.Second) } if err != nil { ui.Error(fmt.Sprintf( "Error cleaning up security group. Please delete the group manually: %s", s.createdGroupId)) } }
func (s *StepOutputDir) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) if _, err := os.Stat(s.Path); err == nil && s.Force { ui.Say("Deleting previous output directory...") os.RemoveAll(s.Path) } // Create the directory if err := os.MkdirAll(s.Path, 0755); err != nil { state.Put("error", err) return multistep.ActionHalt } // Make sure we can write in the directory f, err := os.Create(filepath.Join(s.Path, "_packer_perm_check")) if err != nil { err = fmt.Errorf("Couldn't write to output directory: %s", err) state.Put("error", err) return multistep.ActionHalt } f.Close() os.Remove(f.Name()) return multistep.ActionContinue }
func (s *StepRegister) Cleanup(state multistep.StateBag) { if s.registeredPath == "" { return } driver := state.Get("driver").(vmwcommon.Driver) ui := state.Get("ui").(packer.Ui) if remoteDriver, ok := driver.(RemoteDriver); ok { if s.Format == "" { ui.Say("Unregistering virtual machine...") if err := remoteDriver.Unregister(s.registeredPath); err != nil { ui.Error(fmt.Sprintf("Error unregistering VM: %s", err)) } s.registeredPath = "" } else { ui.Say("Destroying virtual machine...") if err := remoteDriver.Destroy(); err != nil { ui.Error(fmt.Sprintf("Error destroying VM: %s", err)) } // Wait for the machine to actually destroy for { destroyed, _ := remoteDriver.IsDestroyed() if destroyed { break } time.Sleep(150 * time.Millisecond) } } } }
func (self *stepCreateInstance) Cleanup(state multistep.StateBag) { client := state.Get("client").(*SoftlayerClient) config := state.Get("config").(config) ui := state.Get("ui").(packer.Ui) if self.instanceId == "" { return } ui.Say("Waiting for the instance to have no active transactions before destroying it...") // We should wait until the instance is up/have no transactions, // since if the instance will have some assigned transactions the destroy API call will fail err := client.waitForInstanceReady(self.instanceId, config.StateTimeout) if err != nil { log.Printf("Error destroying instance: %v", err.Error()) ui.Error(fmt.Sprintf("Error waiting for instance to become ACTIVE for instance (%s)", self.instanceId)) } ui.Say("Destroying instance...") err = client.DestroyInstance(self.instanceId) if err != nil { log.Printf("Error destroying instance: %v", err.Error()) ui.Error(fmt.Sprintf("Error cleaning up the instance. Please delete the instance (%s) manually", self.instanceId)) } }
func (s *StepCreateImage) Run(state multistep.StateBag) multistep.StepAction { client := state.Get(constants.RequestManager).(management.Client) ui := state.Get(constants.Ui).(packer.Ui) errorMsg := "Error Creating Azure Image: %s" ui.Say("Creating Azure Image. If Successful, This Will Remove the Temporary VM...") description := "packer made image" imageFamily := "PackerMade" if err := retry.ExecuteAsyncOperation(client, func() (management.OperationID, error) { return vmi.NewClient(client).Capture(s.TmpServiceName, s.TmpVmName, s.TmpVmName, s.UserImageName, s.UserImageLabel, vmi.OSStateGeneralized, vmi.CaptureParameters{ Description: description, ImageFamily: imageFamily, RecommendedVMSize: s.RecommendedVMSize, }) }); err != nil { err := fmt.Errorf(errorMsg, err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } // CatpureVMImage removes the VM state.Put(constants.ImageCreated, 1) state.Put(constants.VmExists, 0) return multistep.ActionContinue }
func (s *stepRun) Cleanup(state multistep.StateBag) { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) // If we started the machine... stop it. if s.vmxPath != "" { // If we started it less than 5 seconds ago... wait. sinceBootTime := time.Since(s.bootTime) waitBootTime := 5 * time.Second if sinceBootTime < waitBootTime { sleepTime := waitBootTime - sinceBootTime ui.Say(fmt.Sprintf("Waiting %s to give VMware time to clean up...", sleepTime.String())) time.Sleep(sleepTime) } // See if it is running running, _ := driver.IsRunning(s.vmxPath) if running { ui.Say("Stopping virtual machine...") if err := driver.Stop(s.vmxPath); err != nil { ui.Error(fmt.Sprintf("Error stopping VM: %s", err)) } } if remoteDriver, ok := driver.(RemoteDriver); ok && s.registered { ui.Say("Unregistering virtual machine...") if err := remoteDriver.Unregister(s.vmxPath); err != nil { ui.Error(fmt.Sprintf("Error unregistering VM: %s", err)) } s.registered = false } } }
func (s *StepHTTPServer) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("commonconfig").(CommonConfig) ui := state.Get("ui").(packer.Ui) var httpPort uint = 0 if config.HTTPDir == "" { state.Put("http_port", httpPort) return multistep.ActionContinue } s.l, httpPort = FindPort(config.HTTPPortMin, config.HTTPPortMax) if s.l == nil || httpPort == 0 { ui.Error("Error: unable to find free HTTP server port. Try providing a larger range [http_port_min, http_port_max]") return multistep.ActionHalt } ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort)) // Start the HTTP server and run it in the background fileServer := http.FileServer(http.Dir(config.HTTPDir)) server := &http.Server{ Addr: fmt.Sprintf(":%d", httpPort), Handler: IPSnooper{ ch: s.Chan, handler: fileServer, }, } go server.Serve(s.l) // Save the address into the state so it can be accessed in the future state.Put("http_port", httpPort) return multistep.ActionContinue }
// Run executes the Packer build step that tears down a GCE instance. func (s *StepTeardownInstance) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) name := config.InstanceName if name == "" { return multistep.ActionHalt } ui.Say("Deleting instance...") instanceLog, _ := driver.GetSerialPortOutput(config.Zone, name) state.Put("instance_log", instanceLog) errCh, err := driver.DeleteInstance(config.Zone, name) if err == nil { select { case err = <-errCh: case <-time.After(config.stateTimeout): err = errors.New("time out while waiting for instance to delete") } } if err != nil { ui.Error(fmt.Sprintf( "Error deleting instance. Please delete it manually.\n\n"+ "Name: %s\n"+ "Error: %s", name, err)) return multistep.ActionHalt } ui.Message("Instance has been deleted!") state.Put("instance_name", "") return multistep.ActionContinue }
// Checks the configuration on the filesystem for syntax errors or // non-exsistance. func (*StepCheckConfigurationFile) Run(state multistep.StateBag) multistep.StepAction { log.Println("Checking configuration file...") configPath := state.Get("config_path").(string) var path string // Determine if we are dealing with a custom config path if configPath == "" { // Default to the home directory path = os.Getenv("HOME") + "/.gethubconfig" } else { // They've specified a custom config path log.Println("Environment specified config path", configPath) path = configPath + "/.gethubconfig" } // Is the config file even there? _, err := os.Stat(path) if err != nil { fmt.Println(RED + "It seems as though you haven't set-up gethub. Please run `gethub authorize`" + CLEAR) return multistep.ActionHalt } // Read the file and see if all is well with a basic config c, err2 := config.ReadDefault(path) checkPath, _ := c.String("gethub", "path") if checkPath == "" || err2 != nil { fmt.Println(RED + "Something seems to be wrong with your ~/.gethubconfig file. Please run `gethub authorize`" + CLEAR) return multistep.ActionHalt } return multistep.ActionContinue }
func (s *StepWaitForRackConnect) Run(state multistep.StateBag) multistep.StepAction { if !s.Wait { return multistep.ActionContinue } config := state.Get("config").(Config) server := state.Get("server").(*servers.Server) ui := state.Get("ui").(packer.Ui) // We need the v2 compute client computeClient, err := config.computeV2Client() if err != nil { err = fmt.Errorf("Error initializing compute client: %s", err) state.Put("error", err) return multistep.ActionHalt } ui.Say(fmt.Sprintf( "Waiting for server (%s) to become RackConnect ready...", server.ID)) for { server, err = servers.Get(computeClient, server.ID).Extract() if err != nil { return multistep.ActionHalt } if server.Metadata["rackconnect_automation_status"] == "DEPLOYED" { state.Put("server", server) break } time.Sleep(2 * time.Second) } return multistep.ActionContinue }
func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) { if s.server == nil { return } config := state.Get("config").(Config) ui := state.Get("ui").(packer.Ui) // We need the v2 compute client computeClient, err := config.computeV2Client() if err != nil { ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err)) return } ui.Say("Terminating the source server...") if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil { ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err)) return } stateChange := StateChangeConf{ Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"}, Refresh: ServerStateRefreshFunc(computeClient, s.server), Target: []string{"DELETED"}, } WaitForState(&stateChange) }
func (self *StepForwardPortOverSSH) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("commonconfig").(CommonConfig) ui := state.Get("ui").(packer.Ui) // Find a free local port: l, sshHostPort := FindPort(self.HostPortMin, self.HostPortMax) if l == nil || sshHostPort == 0 { ui.Error("Error: unable to find free host port. Try providing a larger range [host_port_min, host_port_max]") return multistep.ActionHalt } ui.Say(fmt.Sprintf("Creating a local port forward over SSH on local port %d", sshHostPort)) remotePort, _ := self.RemotePort(state) remoteDest, _ := self.RemoteDest(state) go ssh_port_forward(l, remotePort, remoteDest, config.HostIp, config.Username, config.Password) ui.Say(fmt.Sprintf("Port forward setup. %d ---> %s:%d on %s", sshHostPort, remoteDest, remotePort, config.HostIp)) // Provide the local port to future steps. state.Put(self.ResultKey, sshHostPort) return multistep.ActionContinue }
func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) client := state.Get("client").(xsclient.XenAPIClient) // Ignore if VdiName is not specified if self.VdiName == "" { return multistep.ActionContinue } vdis, err := client.GetVdiByNameLabel(self.VdiName) switch { case len(vdis) == 0: ui.Error(fmt.Sprintf("Couldn't find a VDI named '%s'", self.VdiName)) return multistep.ActionHalt case len(vdis) > 1: ui.Error(fmt.Sprintf("Found more than one VDI with name '%s'. Name must be unique", self.VdiName)) return multistep.ActionHalt } vdi := vdis[0] vdiUuid, err := vdi.GetUuid() if err != nil { ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", self.VdiName, err.Error())) return multistep.ActionHalt } state.Put(self.VdiUuidKey, vdiUuid) return multistep.ActionContinue }
func (s *stepWaitForShutdown) Run(state multistep.StateBag) multistep.StepAction { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) stopCh := make(chan struct{}) defer close(stopCh) cancelCh := make(chan struct{}) go func() { for { if _, ok := state.GetOk(multistep.StateCancelled); ok { close(cancelCh) return } select { case <-stopCh: return case <-time.After(100 * time.Millisecond): } } }() ui.Say(s.Message) driver.WaitForShutdown(cancelCh) return multistep.ActionContinue }
// Deleting the instance does not remove the boot disk. This cleanup removes // the disk. func (s *StepTeardownInstance) Cleanup(state multistep.StateBag) { config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) ui.Say("Deleting disk...") errCh, err := driver.DeleteDisk(config.Zone, config.DiskName) if err == nil { select { case err = <-errCh: case <-time.After(config.stateTimeout): err = errors.New("time out while waiting for disk to delete") } } if err != nil { ui.Error(fmt.Sprintf( "Error deleting disk. Please delete it manually.\n\n"+ "Name: %s\n"+ "Error: %s", config.InstanceName, err)) } ui.Message("Disk has been deleted!") return }
func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) name := config.VMName + "." + strings.ToLower(config.Format) path := filepath.Join(config.OutputDir, name) command := []string{ "create", "-f", config.Format, path, fmt.Sprintf("%vM", config.DiskSize), } if config.DiskImage == true { return multistep.ActionContinue } ui.Say("Creating hard drive...") if err := driver.QemuImg(command...); err != nil { err := fmt.Errorf("Error creating hard drive: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } state.Put("disk_filename", name) return multistep.ActionContinue }
func (s *stepAttachISO) Cleanup(state multistep.StateBag) { if s.diskPath == "" { return } config := state.Get("config").(*config) driver := state.Get("driver").(vboxcommon.Driver) vmName := state.Get("vmName").(string) controllerName := "IDE Controller" port := "0" device := "1" if config.ISOInterface == "sata" { controllerName = "SATA Controller" port = "1" device = "0" } command := []string{ "storageattach", vmName, "--storagectl", controllerName, "--port", port, "--device", device, "--medium", "none", } // Remove the ISO. Note that this will probably fail since // stepRemoveDevices does this as well. No big deal. driver.VBoxManage(command...) }
func (s *stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) ui := state.Get("ui").(packer.Ui) dir := s.outputDir(state) dir.SetOutputDir(config.OutputDir) exists, err := dir.DirExists() if err != nil { state.Put("error", err) return multistep.ActionHalt } if exists { if config.PackerForce { ui.Say("Deleting previous output directory...") dir.RemoveAll() } else { state.Put("error", fmt.Errorf( "Output directory '%s' already exists.", config.OutputDir)) return multistep.ActionHalt } } if err := dir.MkdirAll(); err != nil { state.Put("error", err) return multistep.ActionHalt } s.dir = dir state.Put("dir", dir) return multistep.ActionContinue }
func (self *stepCreateInstance) Cleanup(state multistep.StateBag) { config := state.Get("config").(config) if config.ShouldKeepVM(state) { return } ui := state.Get("ui").(packer.Ui) if self.instance != nil { ui.Say("Destroying VM") _ = self.instance.HardShutdown() // redundant, just in case err := self.instance.Destroy() if err != nil { ui.Error(err.Error()) } } if self.vdi != nil { ui.Say("Destroying VDI") err := self.vdi.Destroy() if err != nil { ui.Error(err.Error()) } } }
func (s *StepCloneVMX) Run(state multistep.StateBag) multistep.StepAction { driver := state.Get("driver").(vmwcommon.Driver) ui := state.Get("ui").(packer.Ui) vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx") ui.Say("Cloning source VM...") log.Printf("Cloning from: %s", s.Path) log.Printf("Cloning to: %s", vmxPath) if err := driver.Clone(vmxPath, s.Path); err != nil { state.Put("error", err) return multistep.ActionHalt } vmxData, err := vmwcommon.ReadVMX(vmxPath) if err != nil { state.Put("error", err) return multistep.ActionHalt } diskName, ok := vmxData["scsi0:0.filename"] if !ok { err := fmt.Errorf("Root disk filename could not be found!") state.Put("error", err) return multistep.ActionHalt } state.Put("full_disk_path", filepath.Join(s.OutputDir, diskName)) state.Put("vmx_path", vmxPath) return multistep.ActionContinue }
func (s *stepResizeDisk) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) path := filepath.Join(config.OutputDir, config.VMName) command := []string{ "resize", path, fmt.Sprintf("%vM", config.DiskSize), } if config.DiskImage == false { return multistep.ActionContinue } ui.Say("Resizing hard drive...") if err := driver.QemuImg(command...); err != nil { err := fmt.Errorf("Error creating hard drive: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } return multistep.ActionContinue }
// Cleanup destroys the GCE instance created during the image creation process. func (s *StepCreateInstance) Cleanup(state multistep.StateBag) { if s.instanceName == "" { return } config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) ui.Say("Deleting instance...") errCh, err := driver.DeleteInstance(config.Zone, s.instanceName) if err == nil { select { case err = <-errCh: case <-time.After(config.stateTimeout): err = errors.New("time out while waiting for instance to delete") } } if err != nil { ui.Error(fmt.Sprintf( "Error deleting instance. Please delete it manually.\n\n"+ "Name: %s\n"+ "Error: %s", s.instanceName, err)) } s.instanceName = "" return }
func (s *StepDownload) Run(state multistep.StateBag) multistep.StepAction { cache := state.Get("cache").(packer.Cache) ui := state.Get("ui").(packer.Ui) var checksum []byte if s.Checksum != "" { var err error checksum, err = hex.DecodeString(s.Checksum) if err != nil { state.Put("error", fmt.Errorf("Error parsing checksum: %s", err)) return multistep.ActionHalt } } ui.Say(fmt.Sprintf("Downloading or copying %s", s.Description)) var finalPath string for _, url := range s.Url { ui.Message(fmt.Sprintf("Downloading or copying: %s", url)) targetPath := s.TargetPath if targetPath == "" { log.Printf("Acquiring lock to download: %s", url) targetPath = cache.Lock(url) defer cache.Unlock(url) } config := &DownloadConfig{ Url: url, TargetPath: targetPath, CopyFile: false, Hash: HashForType(s.ChecksumType), Checksum: checksum, } path, err, retry := s.download(config, state) if err != nil { ui.Message(fmt.Sprintf("Error downloading: %s", err)) } if !retry { return multistep.ActionHalt } if err == nil { finalPath = path break } } if finalPath == "" { err := fmt.Errorf("%s download failed.", s.Description) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } state.Put(s.ResultKey, finalPath) return multistep.ActionContinue }
func (s *StepMountDvdDrive) Cleanup(state multistep.StateBag) { if s.path == "" { return } errorMsg := "Error unmounting dvd drive: %s" vmName := state.Get("vmName").(string) driver := state.Get("driver").(hypervcommon.Driver) ui := state.Get("ui").(packer.Ui) ui.Say("Unmounting dvd drive...") var err error = nil var blockBuffer bytes.Buffer blockBuffer.WriteString("Invoke-Command -scriptblock {Set-VMDvdDrive -VMName '") blockBuffer.WriteString(vmName) blockBuffer.WriteString("' -Path $null}") err = driver.HypervManage(blockBuffer.String()) if err != nil { ui.Error(fmt.Sprintf(errorMsg, err)) } }
func (stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) // Find an open VNC port. Note that this can still fail later on // because we have to release the port at some point. But this does its // best. msg := fmt.Sprintf("Looking for available port between %d and %d on %s", config.VNCPortMin, config.VNCPortMax, config.VNCBindAddress) ui.Say(msg) log.Printf(msg) var vncPort uint portRange := int(config.VNCPortMax - config.VNCPortMin) for { if portRange > 0 { vncPort = uint(rand.Intn(portRange)) + config.VNCPortMin } else { vncPort = config.VNCPortMin } log.Printf("Trying port: %d", vncPort) l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", config.VNCBindAddress, vncPort)) if err == nil { defer l.Close() break } } log.Printf("Found available VNC port: %d on IP: %s", vncPort, config.VNCBindAddress) state.Put("vnc_port", vncPort) state.Put("vnc_ip", config.VNCBindAddress) return multistep.ActionContinue }
func (s *StepCreateSwitch) Run(state multistep.StateBag) multistep.StepAction { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) ui.Say("Creating internal switch...") var blockBuffer bytes.Buffer blockBuffer.WriteString("Invoke-Command -scriptblock {$TestSwitch = Get-VMSwitch -Name '") blockBuffer.WriteString(s.SwitchName) blockBuffer.WriteString("' -ErrorAction SilentlyContinue; if ($TestSwitch.Count -EQ 0){New-VMSwitch -Name '") blockBuffer.WriteString(s.SwitchName) blockBuffer.WriteString("' -SwitchType Internal}}") err := driver.HypervManage(blockBuffer.String()) if err != nil { err := fmt.Errorf("Error creating switch: %s", err) state.Put("error", err) ui.Error(err.Error()) s.SwitchName = "" return multistep.ActionHalt } // Set the final name in the state bag so others can use it state.Put("SwitchName", s.SwitchName) return multistep.ActionContinue }
func (s *StepPreValidate) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) if s.ForceDeregister { ui.Say("Force Deregister flag found, skipping prevalidating AMI Name") return multistep.ActionContinue } ec2conn := state.Get("ec2").(*ec2.EC2) ui.Say("Prevalidating AMI Name...") resp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ Filters: []*ec2.Filter{&ec2.Filter{ Name: aws.String("name"), Values: []*string{aws.String(s.DestAmiName)}, }}}) if err != nil { err := fmt.Errorf("Error querying AMI: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } if len(resp.Images) > 0 { err := fmt.Errorf("Error: name conflicts with an existing AMI: %s", *resp.Images[0].ImageId) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } return multistep.ActionContinue }
func (s *StepOutputDir) Run(state multistep.StateBag) multistep.StepAction { dir := state.Get("dir").(OutputDir) ui := state.Get("ui").(packer.Ui) exists, err := dir.DirExists() if err != nil { state.Put("error", err) return multistep.ActionHalt } if exists { if s.Force { ui.Say("Deleting previous output directory...") dir.RemoveAll() } else { state.Put("error", fmt.Errorf( "Output directory '%s' already exists.", dir.String())) return multistep.ActionHalt } } if err := dir.MkdirAll(); err != nil { state.Put("error", err) return multistep.ActionHalt } s.success = true return multistep.ActionContinue }
func (s *StepGetCertificate) Run(state multistep.StateBag) multistep.StepAction { s.say("Getting the certificate's URL ...") var keyVaultName = state.Get(constants.ArmKeyVaultName).(string) s.say(fmt.Sprintf(" -> Key Vault Name : '%s'", keyVaultName)) s.say(fmt.Sprintf(" -> Key Vault Secret Name : '%s'", DefaultSecretName)) var err error var url string for i := 0; i < 5; i++ { url, err = s.get(keyVaultName, DefaultSecretName) if err == nil { break } s.say(fmt.Sprintf(" ...failed to get certificate URL, retry(%d)", i)) s.pause() } if err != nil { state.Put(constants.Error, err) s.error(err) return multistep.ActionHalt } s.say(fmt.Sprintf(" -> Certificate URL : '%s'", url)) state.Put(constants.ArmCertificateUrl, url) return multistep.ActionContinue }