github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/builder/amazon/common/ssh.go (about)

     1  package common
     2  
     3  import (
     4  	"code.google.com/p/go.crypto/ssh"
     5  	"errors"
     6  	"fmt"
     7  	"github.com/mitchellh/goamz/ec2"
     8  	"github.com/mitchellh/multistep"
     9  	"time"
    10  )
    11  
    12  // SSHAddress returns a function that can be given to the SSH communicator
    13  // for determining the SSH address based on the instance DNS name.
    14  func SSHAddress(e *ec2.EC2, port int, private bool) func(multistep.StateBag) (string, error) {
    15  	return func(state multistep.StateBag) (string, error) {
    16  		for j := 0; j < 2; j++ {
    17  			var host string
    18  			i := state.Get("instance").(*ec2.Instance)
    19  			if i.DNSName != "" {
    20  				host = i.DNSName
    21  			} else if i.VpcId != "" {
    22  				if i.PublicIpAddress != "" && !private {
    23  					host = i.PublicIpAddress
    24  				} else {
    25  					host = i.PrivateIpAddress
    26  				}
    27  			}
    28  
    29  			if host != "" {
    30  				return fmt.Sprintf("%s:%d", host, port), nil
    31  			}
    32  
    33  			r, err := e.Instances([]string{i.InstanceId}, ec2.NewFilter())
    34  			if err != nil {
    35  				return "", err
    36  			}
    37  
    38  			if len(r.Reservations) == 0 || len(r.Reservations[0].Instances) == 0 {
    39  				return "", fmt.Errorf("instance not found: %s", i.InstanceId)
    40  			}
    41  
    42  			state.Put("instance", &r.Reservations[0].Instances[0])
    43  			time.Sleep(1 * time.Second)
    44  		}
    45  
    46  		return "", errors.New("couldn't determine IP address for instance")
    47  	}
    48  }
    49  
    50  // SSHConfig returns a function that can be used for the SSH communicator
    51  // config for connecting to the instance created over SSH using the generated
    52  // private key.
    53  func SSHConfig(username string) func(multistep.StateBag) (*ssh.ClientConfig, error) {
    54  	return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
    55  		privateKey := state.Get("privateKey").(string)
    56  
    57  		signer, err := ssh.ParsePrivateKey([]byte(privateKey))
    58  		if err != nil {
    59  			return nil, fmt.Errorf("Error setting up SSH config: %s", err)
    60  		}
    61  
    62  		return &ssh.ClientConfig{
    63  			User: username,
    64  			Auth: []ssh.AuthMethod{
    65  				ssh.PublicKeys(signer),
    66  			},
    67  		}, nil
    68  	}
    69  }