github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/cloudstack/step_keypair.go (about)

     1  package cloudstack
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"runtime"
     9  
    10  	"github.com/hashicorp/packer/helper/multistep"
    11  	"github.com/hashicorp/packer/packer"
    12  	"github.com/xanzy/go-cloudstack/cloudstack"
    13  )
    14  
    15  type stepKeypair struct {
    16  	Debug                bool
    17  	DebugKeyPath         string
    18  	KeyPair              string
    19  	PrivateKeyFile       string
    20  	SSHAgentAuth         bool
    21  	TemporaryKeyPairName string
    22  }
    23  
    24  func (s *stepKeypair) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
    25  	ui := state.Get("ui").(packer.Ui)
    26  
    27  	if s.PrivateKeyFile != "" {
    28  		privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile)
    29  		if err != nil {
    30  			state.Put("error", fmt.Errorf(
    31  				"Error loading configured private key file: %s", err))
    32  			return multistep.ActionHalt
    33  		}
    34  
    35  		state.Put("keypair", s.KeyPair)
    36  		state.Put("privateKey", string(privateKeyBytes))
    37  
    38  		return multistep.ActionContinue
    39  	}
    40  
    41  	if s.SSHAgentAuth && s.KeyPair == "" {
    42  		ui.Say("Using SSH Agent with keypair in Source image")
    43  		return multistep.ActionContinue
    44  	}
    45  
    46  	if s.SSHAgentAuth && s.KeyPair != "" {
    47  		ui.Say(fmt.Sprintf("Using SSH Agent for existing keypair %s", s.KeyPair))
    48  		state.Put("keypair", s.KeyPair)
    49  		return multistep.ActionContinue
    50  	}
    51  
    52  	if s.TemporaryKeyPairName == "" {
    53  		ui.Say("Not using a keypair")
    54  		state.Put("keypair", "")
    55  		return multistep.ActionContinue
    56  	}
    57  
    58  	client := state.Get("client").(*cloudstack.CloudStackClient)
    59  
    60  	ui.Say(fmt.Sprintf("Creating temporary keypair: %s ...", s.TemporaryKeyPairName))
    61  
    62  	p := client.SSH.NewCreateSSHKeyPairParams(s.TemporaryKeyPairName)
    63  
    64  	cfg := state.Get("config").(*Config)
    65  	if cfg.Project != "" {
    66  		p.SetProjectid(cfg.Project)
    67  	}
    68  
    69  	keypair, err := client.SSH.CreateSSHKeyPair(p)
    70  	if err != nil {
    71  		err := fmt.Errorf("Error creating temporary keypair: %s", err)
    72  		state.Put("error", err)
    73  		ui.Error(err.Error())
    74  		return multistep.ActionHalt
    75  	}
    76  
    77  	if keypair.Privatekey == "" {
    78  		err := fmt.Errorf("The temporary keypair returned was blank")
    79  		state.Put("error", err)
    80  		ui.Error(err.Error())
    81  		return multistep.ActionHalt
    82  	}
    83  
    84  	ui.Say(fmt.Sprintf("Created temporary keypair: %s", s.TemporaryKeyPairName))
    85  
    86  	// If we're in debug mode, output the private key to the working directory.
    87  	if s.Debug {
    88  		ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
    89  		f, err := os.Create(s.DebugKeyPath)
    90  		if err != nil {
    91  			state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
    92  			return multistep.ActionHalt
    93  		}
    94  		defer f.Close()
    95  
    96  		// Write the key out
    97  		if _, err := f.Write([]byte(keypair.Privatekey)); err != nil {
    98  			err := fmt.Errorf("Error saving debug key: %s", err)
    99  			state.Put("error", err)
   100  			ui.Error(err.Error())
   101  			return multistep.ActionHalt
   102  		}
   103  
   104  		// Chmod it so that it is SSH ready
   105  		if runtime.GOOS != "windows" {
   106  			if err := f.Chmod(0600); err != nil {
   107  				err := fmt.Errorf("Error setting permissions of debug key: %s", err)
   108  				state.Put("error", err)
   109  				ui.Error(err.Error())
   110  				return multistep.ActionHalt
   111  			}
   112  		}
   113  	}
   114  
   115  	// Set some state data for use in future steps
   116  	state.Put("keypair", s.TemporaryKeyPairName)
   117  	state.Put("privateKey", keypair.Privatekey)
   118  
   119  	return multistep.ActionContinue
   120  }
   121  
   122  func (s *stepKeypair) Cleanup(state multistep.StateBag) {
   123  	if s.TemporaryKeyPairName == "" {
   124  		return
   125  	}
   126  
   127  	ui := state.Get("ui").(packer.Ui)
   128  	client := state.Get("client").(*cloudstack.CloudStackClient)
   129  	cfg := state.Get("config").(*Config)
   130  
   131  	p := client.SSH.NewDeleteSSHKeyPairParams(s.TemporaryKeyPairName)
   132  	if cfg.Project != "" {
   133  		p.SetProjectid(cfg.Project)
   134  	}
   135  
   136  	ui.Say(fmt.Sprintf("Deleting temporary keypair: %s ...", s.TemporaryKeyPairName))
   137  
   138  	_, err := client.SSH.DeleteSSHKeyPair(p)
   139  	if err != nil {
   140  		ui.Error(err.Error())
   141  		ui.Error(fmt.Sprintf(
   142  			"Error cleaning up keypair. Please delete the key manually: %s", s.TemporaryKeyPairName))
   143  	}
   144  }