github.phpd.cn/hashicorp/packer@v1.3.2/builder/triton/access_config.go (about)

     1  package triton
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  
     9  	"github.com/hashicorp/errwrap"
    10  	"github.com/hashicorp/packer/helper/communicator"
    11  	"github.com/hashicorp/packer/template/interpolate"
    12  	tgo "github.com/joyent/triton-go"
    13  	"github.com/joyent/triton-go/authentication"
    14  	"github.com/joyent/triton-go/compute"
    15  	"github.com/joyent/triton-go/network"
    16  )
    17  
    18  // AccessConfig is for common configuration related to Triton access
    19  type AccessConfig struct {
    20  	Endpoint              string `mapstructure:"triton_url"`
    21  	Account               string `mapstructure:"triton_account"`
    22  	Username              string `mapstructure:"triton_user"`
    23  	KeyID                 string `mapstructure:"triton_key_id"`
    24  	KeyMaterial           string `mapstructure:"triton_key_material"`
    25  	InsecureSkipTLSVerify bool   `mapstructure:"insecure_skip_tls_verify"`
    26  
    27  	signer authentication.Signer
    28  }
    29  
    30  // Prepare performs basic validation on the AccessConfig and ensures we can sign
    31  // a request.
    32  func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
    33  	var errs []error
    34  
    35  	if c.Endpoint == "" {
    36  		// Use Joyent public cloud as the default endpoint if none is specified
    37  		c.Endpoint = "https://us-sw-1.api.joyent.com"
    38  	}
    39  
    40  	if c.Account == "" {
    41  		errs = append(errs, errors.New("triton_account is required to use the triton builder"))
    42  	}
    43  
    44  	if c.KeyID == "" {
    45  		errs = append(errs, errors.New("triton_key_id is required to use the triton builder"))
    46  	}
    47  
    48  	if c.KeyMaterial == "" {
    49  		signer, err := c.createSSHAgentSigner()
    50  		if err != nil {
    51  			errs = append(errs, err)
    52  		}
    53  		c.signer = signer
    54  	} else {
    55  		signer, err := c.createPrivateKeySigner()
    56  		if err != nil {
    57  			errs = append(errs, err)
    58  		}
    59  		c.signer = signer
    60  	}
    61  
    62  	if len(errs) > 0 {
    63  		return errs
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  func (c *AccessConfig) createSSHAgentSigner() (authentication.Signer, error) {
    70  	input := authentication.SSHAgentSignerInput{
    71  		KeyID:       c.KeyID,
    72  		AccountName: c.Account,
    73  		Username:    c.Username,
    74  	}
    75  	signer, err := authentication.NewSSHAgentSigner(input)
    76  	if err != nil {
    77  		return nil, fmt.Errorf("Error creating Triton request signer: %s", err)
    78  	}
    79  
    80  	// Ensure we can sign a request
    81  	_, err = signer.Sign("Wed, 26 Apr 2017 16:01:11 UTC")
    82  	if err != nil {
    83  		return nil, fmt.Errorf("Error signing test request: %s", err)
    84  	}
    85  
    86  	return signer, nil
    87  }
    88  
    89  func (c *AccessConfig) createPrivateKeySigner() (authentication.Signer, error) {
    90  	var privateKeyMaterial []byte
    91  	var err error
    92  
    93  	// Check for keyMaterial being a file path
    94  	if _, err = os.Stat(c.KeyMaterial); err != nil {
    95  		privateKeyMaterial = []byte(c.KeyMaterial)
    96  	} else {
    97  		privateKeyMaterial, err = ioutil.ReadFile(c.KeyMaterial)
    98  		if err != nil {
    99  			return nil, fmt.Errorf("Error reading key material from path '%s': %s",
   100  				c.KeyMaterial, err)
   101  		}
   102  	}
   103  
   104  	input := authentication.PrivateKeySignerInput{
   105  		KeyID:              c.KeyID,
   106  		AccountName:        c.Account,
   107  		Username:           c.Username,
   108  		PrivateKeyMaterial: privateKeyMaterial,
   109  	}
   110  
   111  	signer, err := authentication.NewPrivateKeySigner(input)
   112  	if err != nil {
   113  		return nil, fmt.Errorf("Error creating Triton request signer: %s", err)
   114  	}
   115  
   116  	// Ensure we can sign a request
   117  	_, err = signer.Sign("Wed, 26 Apr 2017 16:01:11 UTC")
   118  	if err != nil {
   119  		return nil, fmt.Errorf("Error signing test request: %s", err)
   120  	}
   121  
   122  	return signer, nil
   123  }
   124  
   125  func (c *AccessConfig) CreateTritonClient() (*Client, error) {
   126  
   127  	config := &tgo.ClientConfig{
   128  		AccountName: c.Account,
   129  		TritonURL:   c.Endpoint,
   130  		Username:    c.Username,
   131  		Signers:     []authentication.Signer{c.signer},
   132  	}
   133  
   134  	return &Client{
   135  		config:                config,
   136  		insecureSkipTLSVerify: c.InsecureSkipTLSVerify,
   137  	}, nil
   138  }
   139  
   140  type Client struct {
   141  	config                *tgo.ClientConfig
   142  	insecureSkipTLSVerify bool
   143  }
   144  
   145  func (c *Client) Compute() (*compute.ComputeClient, error) {
   146  	computeClient, err := compute.NewClient(c.config)
   147  	if err != nil {
   148  		return nil, errwrap.Wrapf("Error Creating Triton Compute Client: {{err}}", err)
   149  	}
   150  
   151  	if c.insecureSkipTLSVerify {
   152  		computeClient.Client.InsecureSkipTLSVerify()
   153  	}
   154  
   155  	return computeClient, nil
   156  }
   157  
   158  func (c *Client) Network() (*network.NetworkClient, error) {
   159  	networkClient, err := network.NewClient(c.config)
   160  	if err != nil {
   161  		return nil, errwrap.Wrapf("Error Creating Triton Network Client: {{err}}", err)
   162  	}
   163  
   164  	if c.insecureSkipTLSVerify {
   165  		networkClient.Client.InsecureSkipTLSVerify()
   166  	}
   167  
   168  	return networkClient, nil
   169  }
   170  
   171  func (c *AccessConfig) Comm() communicator.Config {
   172  	return communicator.Config{}
   173  }