github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/triton/provider.go (about)

     1  package triton
     2  
     3  import (
     4  	"crypto/md5"
     5  	"encoding/base64"
     6  	"errors"
     7  	"sort"
     8  	"time"
     9  
    10  	"github.com/hashicorp/errwrap"
    11  	"github.com/hashicorp/go-multierror"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  	"github.com/hashicorp/terraform/terraform"
    14  	"github.com/joyent/triton-go"
    15  	"github.com/joyent/triton-go/authentication"
    16  )
    17  
    18  // Provider returns a terraform.ResourceProvider.
    19  func Provider() terraform.ResourceProvider {
    20  	return &schema.Provider{
    21  		Schema: map[string]*schema.Schema{
    22  			"account": {
    23  				Type:        schema.TypeString,
    24  				Required:    true,
    25  				DefaultFunc: schema.EnvDefaultFunc("SDC_ACCOUNT", ""),
    26  			},
    27  
    28  			"url": {
    29  				Type:        schema.TypeString,
    30  				Required:    true,
    31  				DefaultFunc: schema.EnvDefaultFunc("SDC_URL", "https://us-west-1.api.joyentcloud.com"),
    32  			},
    33  
    34  			"key_material": {
    35  				Type:        schema.TypeString,
    36  				Optional:    true,
    37  				DefaultFunc: schema.EnvDefaultFunc("SDC_KEY_MATERIAL", ""),
    38  			},
    39  
    40  			"key_id": {
    41  				Type:        schema.TypeString,
    42  				Required:    true,
    43  				DefaultFunc: schema.EnvDefaultFunc("SDC_KEY_ID", ""),
    44  			},
    45  		},
    46  
    47  		ResourcesMap: map[string]*schema.Resource{
    48  			"triton_firewall_rule": resourceFirewallRule(),
    49  			"triton_machine":       resourceMachine(),
    50  			"triton_key":           resourceKey(),
    51  			"triton_vlan":          resourceVLAN(),
    52  			"triton_fabric":        resourceFabric(),
    53  		},
    54  		ConfigureFunc: providerConfigure,
    55  	}
    56  }
    57  
    58  type Config struct {
    59  	Account     string
    60  	KeyMaterial string
    61  	KeyID       string
    62  	URL         string
    63  }
    64  
    65  func (c Config) validate() error {
    66  	var err *multierror.Error
    67  
    68  	if c.URL == "" {
    69  		err = multierror.Append(err, errors.New("URL must be configured for the Triton provider"))
    70  	}
    71  	if c.KeyID == "" {
    72  		err = multierror.Append(err, errors.New("Key ID must be configured for the Triton provider"))
    73  	}
    74  	if c.Account == "" {
    75  		err = multierror.Append(err, errors.New("Account must be configured for the Triton provider"))
    76  	}
    77  
    78  	return err.ErrorOrNil()
    79  }
    80  
    81  func (c Config) getTritonClient() (*triton.Client, error) {
    82  	var signer authentication.Signer
    83  	var err error
    84  	if c.KeyMaterial == "" {
    85  		signer, err = authentication.NewSSHAgentSigner(c.KeyID, c.Account)
    86  		if err != nil {
    87  			return nil, errwrap.Wrapf("Error Creating SSH Agent Signer: {{err}}", err)
    88  		}
    89  	} else {
    90  		signer, err = authentication.NewPrivateKeySigner(c.KeyID, []byte(c.KeyMaterial), c.Account)
    91  		if err != nil {
    92  			return nil, errwrap.Wrapf("Error Creating SSH Private Key Signer: {{err}}", err)
    93  		}
    94  	}
    95  
    96  	client, err := triton.NewClient(c.URL, c.Account, signer)
    97  	if err != nil {
    98  		return nil, errwrap.Wrapf("Error Creating Triton Client: {{err}}", err)
    99  	}
   100  
   101  	return client, nil
   102  }
   103  
   104  func providerConfigure(d *schema.ResourceData) (interface{}, error) {
   105  	config := Config{
   106  		Account: d.Get("account").(string),
   107  		URL:     d.Get("url").(string),
   108  		KeyID:   d.Get("key_id").(string),
   109  	}
   110  
   111  	if keyMaterial, ok := d.GetOk("key_material"); ok {
   112  		config.KeyMaterial = keyMaterial.(string)
   113  	}
   114  
   115  	if err := config.validate(); err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	client, err := config.getTritonClient()
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	return client, nil
   125  }
   126  
   127  func resourceExists(resource interface{}, err error) (bool, error) {
   128  	if err != nil {
   129  		if triton.IsResourceNotFound(err) {
   130  			return false, nil
   131  		}
   132  
   133  		return false, err
   134  	}
   135  
   136  	return resource != nil, nil
   137  }
   138  
   139  func stableMapHash(input map[string]string) string {
   140  	keys := make([]string, 0, len(input))
   141  	for k := range input {
   142  		keys = append(keys, k)
   143  	}
   144  	sort.Strings(keys)
   145  
   146  	hash := md5.New()
   147  	for _, key := range keys {
   148  		hash.Write([]byte(key))
   149  		hash.Write([]byte(input[key]))
   150  	}
   151  
   152  	return base64.StdEncoding.EncodeToString(hash.Sum([]byte{}))
   153  }
   154  
   155  var fastResourceTimeout = &schema.ResourceTimeout{
   156  	Create: schema.DefaultTimeout(1 * time.Minute),
   157  	Read:   schema.DefaultTimeout(30 * time.Second),
   158  	Update: schema.DefaultTimeout(1 * time.Minute),
   159  	Delete: schema.DefaultTimeout(1 * time.Minute),
   160  }
   161  
   162  var slowResourceTimeout = &schema.ResourceTimeout{
   163  	Create: schema.DefaultTimeout(10 * time.Minute),
   164  	Read:   schema.DefaultTimeout(30 * time.Second),
   165  	Update: schema.DefaultTimeout(10 * time.Minute),
   166  	Delete: schema.DefaultTimeout(10 * time.Minute),
   167  }