diff --git a/builtin/providers/triton/provider.go b/builtin/providers/triton/provider.go index 4c21722c27f4..8a56b5dc46e1 100644 --- a/builtin/providers/triton/provider.go +++ b/builtin/providers/triton/provider.go @@ -42,6 +42,12 @@ func Provider() terraform.ResourceProvider { Required: true, DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_ID", "SDC_KEY_ID"}, ""), }, + + "insecure_skip_tls_verify": { + Type: schema.TypeBool, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("TRITON_SKIP_TLS_VERIFY", ""), + }, }, ResourcesMap: map[string]*schema.Resource{ @@ -56,10 +62,11 @@ func Provider() terraform.ResourceProvider { } type Config struct { - Account string - KeyMaterial string - KeyID string - URL string + Account string + KeyMaterial string + KeyID string + URL string + InsecureSkipTLSVerify bool } func (c Config) validate() error { @@ -98,6 +105,10 @@ func (c Config) getTritonClient() (*triton.Client, error) { return nil, errwrap.Wrapf("Error Creating Triton Client: {{err}}", err) } + if c.InsecureSkipTLSVerify { + client.InsecureSkipTLSVerify() + } + return client, nil } @@ -106,6 +117,8 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { Account: d.Get("account").(string), URL: d.Get("url").(string), KeyID: d.Get("key_id").(string), + + InsecureSkipTLSVerify: d.Get("insecure_skip_tls_verify").(bool), } if keyMaterial, ok := d.GetOk("key_material"); ok { diff --git a/vendor/github.com/joyent/triton-go/accounts.go b/vendor/github.com/joyent/triton-go/accounts.go index 8049d4e7e4df..474cce000cb2 100644 --- a/vendor/github.com/joyent/triton-go/accounts.go +++ b/vendor/github.com/joyent/triton-go/accounts.go @@ -5,8 +5,9 @@ import ( "net/http" "time" - "github.com/hashicorp/errwrap" "fmt" + + "github.com/hashicorp/errwrap" ) type AccountsClient struct { @@ -40,7 +41,8 @@ type Account struct { type GetAccountInput struct{} func (client *AccountsClient) GetAccount(input *GetAccountInput) (*Account, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my", nil) + path := fmt.Sprintf("/%s", client.accountName) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } @@ -58,17 +60,17 @@ func (client *AccountsClient) GetAccount(input *GetAccountInput) (*Account, erro } type UpdateAccountInput struct { - Email string `json:"email,omitempty"` - CompanyName string `json:"companyName,omitempty"` - FirstName string `json:"firstName,omitempty"` - LastName string `json:"lastName,omitempty"` - Address string `json:"address,omitempty"` - PostalCode string `json:"postalCode,omitempty"` - City string `json:"city,omitempty"` - State string `json:"state,omitempty"` - Country string `json:"country,omitempty"` - Phone string `json:"phone,omitempty"` - TritonCNSEnabled bool `json:"triton_cns_enabled,omitempty"` + Email string `json:"email,omitempty"` + CompanyName string `json:"companyName,omitempty"` + FirstName string `json:"firstName,omitempty"` + LastName string `json:"lastName,omitempty"` + Address string `json:"address,omitempty"` + PostalCode string `json:"postalCode,omitempty"` + City string `json:"city,omitempty"` + State string `json:"state,omitempty"` + Country string `json:"country,omitempty"` + Phone string `json:"phone,omitempty"` + TritonCNSEnabled bool `json:"triton_cns_enabled,omitempty"` } // UpdateAccount updates your account details with the given parameters. diff --git a/vendor/github.com/joyent/triton-go/client.go b/vendor/github.com/joyent/triton-go/client.go index e34c6b1fe665..5ee1f0be73f3 100644 --- a/vendor/github.com/joyent/triton-go/client.go +++ b/vendor/github.com/joyent/triton-go/client.go @@ -2,6 +2,7 @@ package triton import ( "bytes" + "crypto/tls" "encoding/json" "fmt" "io" @@ -45,16 +46,7 @@ func NewClient(endpoint string, accountName string, signers ...authentication.Si } httpClient := &http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, - DisableKeepAlives: true, - MaxIdleConnsPerHost: -1, - }, + Transport: httpTransport(false), CheckRedirect: doNotFollowRedirects, } @@ -75,6 +67,34 @@ func NewClient(endpoint string, accountName string, signers ...authentication.Si }, nil } +// InsecureSkipTLSVerify turns off TLS verification for the client connection. This +// allows connection to an endpoint with a certificate which was signed by a non- +// trusted CA, such as self-signed certificates. This can be useful when connecting +// to temporary Triton installations such as Triton Cloud-On-A-Laptop. +func (c *Client) InsecureSkipTLSVerify() { + if c.client == nil { + return + } + + c.client.HTTPClient.Transport = httpTransport(true) +} + +func httpTransport(insecureSkipTLSVerify bool) *http.Transport { + return &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + DisableKeepAlives: true, + MaxIdleConnsPerHost: -1, + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: insecureSkipTLSVerify, + }, + } +} + func doNotFollowRedirects(*http.Request, []*http.Request) error { return http.ErrUseLastResponse } diff --git a/vendor/github.com/joyent/triton-go/datacenters.go b/vendor/github.com/joyent/triton-go/datacenters.go index c90cc954ab2a..72ccbd6d91b5 100644 --- a/vendor/github.com/joyent/triton-go/datacenters.go +++ b/vendor/github.com/joyent/triton-go/datacenters.go @@ -28,7 +28,8 @@ type DataCenter struct { type ListDataCentersInput struct{} func (client *DataCentersClient) ListDataCenters(*ListDataCentersInput) ([]*DataCenter, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my/datacenters", nil) + path := fmt.Sprintf("/%s/datacenters", client.accountName) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } @@ -68,7 +69,8 @@ type GetDataCenterInput struct { } func (client *DataCentersClient) GetDataCenter(input *GetDataCenterInput) (*DataCenter, error) { - resp, err := client.executeRequestRaw(http.MethodGet, fmt.Sprintf("/my/datacenters/%s", input.Name), nil) + path := fmt.Sprintf("/%s/datacenters/%s", client.accountName, input.Name) + resp, err := client.executeRequestRaw(http.MethodGet, path, nil) if err != nil { return nil, errwrap.Wrapf("Error executing GetDatacenter request: {{err}}", err) } diff --git a/vendor/github.com/joyent/triton-go/fabrics.go b/vendor/github.com/joyent/triton-go/fabrics.go index 5404d10bba88..5b1caa521114 100644 --- a/vendor/github.com/joyent/triton-go/fabrics.go +++ b/vendor/github.com/joyent/triton-go/fabrics.go @@ -27,7 +27,8 @@ type FabricVLAN struct { type ListFabricVLANsInput struct{} func (client *FabricsClient) ListFabricVLANs(*ListFabricVLANsInput) ([]*FabricVLAN, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my/fabrics/default/vlans", nil) + path := fmt.Sprintf("/%s/fabrics/default/vlans", client.accountName) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } diff --git a/vendor/github.com/joyent/triton-go/firewall.go b/vendor/github.com/joyent/triton-go/firewall.go index c91d012d9a7c..e9d57a80eb92 100644 --- a/vendor/github.com/joyent/triton-go/firewall.go +++ b/vendor/github.com/joyent/triton-go/firewall.go @@ -39,7 +39,8 @@ type FirewallRule struct { type ListFirewallRulesInput struct{} func (client *FirewallClient) ListFirewallRules(*ListFirewallRulesInput) ([]*FirewallRule, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my/fwrules", nil) + path := fmt.Sprintf("/%s/fwrules", client.accountName) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } @@ -194,7 +195,8 @@ type ListMachineFirewallRulesInput struct { } func (client *FirewallClient) ListMachineFirewallRules(input *ListMachineFirewallRulesInput) ([]*FirewallRule, error) { - respReader, err := client.executeRequest(http.MethodGet, fmt.Sprintf("/my/machines/%s/firewallrules", input.MachineID), nil) + path := fmt.Sprintf("/%s/machines/%s/firewallrules", client.accountName, input.MachineID) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } diff --git a/vendor/github.com/joyent/triton-go/images.go b/vendor/github.com/joyent/triton-go/images.go index 3e0aa8a75dcd..01d6ea96d493 100644 --- a/vendor/github.com/joyent/triton-go/images.go +++ b/vendor/github.com/joyent/triton-go/images.go @@ -49,7 +49,8 @@ type Image struct { type ListImagesInput struct{} func (client *ImagesClient) ListImages(*ListImagesInput) ([]*Image, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my/images", nil) + path := fmt.Sprintf("/%s/images", client.accountName) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } @@ -148,7 +149,7 @@ type CreateImageFromMachineInput struct { HomePage string `json:"homepage,omitempty"` EULA string `json:"eula,omitempty"` ACL []string `json:"acl,omitempty"` - tags map[string]string `json:"tags,omitempty"` + Tags map[string]string `json:"tags,omitempty"` } func (client *ImagesClient) CreateImageFromMachine(input *CreateImageFromMachineInput) (*Image, error) { @@ -178,7 +179,7 @@ type UpdateImageInput struct { HomePage string `json:"homepage,omitempty"` EULA string `json:"eula,omitempty"` ACL []string `json:"acl,omitempty"` - tags map[string]string `json:"tags,omitempty"` + Tags map[string]string `json:"tags,omitempty"` } func (client *ImagesClient) UpdateImage(input *UpdateImageInput) (*Image, error) { diff --git a/vendor/github.com/joyent/triton-go/keys.go b/vendor/github.com/joyent/triton-go/keys.go index a4f394a21bcf..e633023492bb 100644 --- a/vendor/github.com/joyent/triton-go/keys.go +++ b/vendor/github.com/joyent/triton-go/keys.go @@ -35,7 +35,8 @@ type ListKeysInput struct{} // ListKeys lists all public keys we have on record for the specified // account. func (client *KeysClient) ListKeys(*ListKeysInput) ([]*Key, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my/keys", nil) + path := fmt.Sprintf("/%s/keys") + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } diff --git a/vendor/github.com/joyent/triton-go/machines.go b/vendor/github.com/joyent/triton-go/machines.go index 0fae69b4a896..287c706c7aa5 100644 --- a/vendor/github.com/joyent/triton-go/machines.go +++ b/vendor/github.com/joyent/triton-go/machines.go @@ -100,7 +100,7 @@ func (client *MachinesClient) GetMachine(input *GetMachineInput) (*Machine, erro if response != nil { defer response.Body.Close() } - if response.StatusCode == http.StatusNotFound { + if response.StatusCode == http.StatusNotFound || response.StatusCode == http.StatusGone { return nil, &TritonError{ Code: "ResourceNotFound", } @@ -219,7 +219,8 @@ func (input *CreateMachineInput) toAPI() map[string]interface{} { } func (client *MachinesClient) CreateMachine(input *CreateMachineInput) (*Machine, error) { - respReader, err := client.executeRequest(http.MethodPost, "/my/machines", input.toAPI()) + path := fmt.Sprintf("/%s/machines", client.accountName) + respReader, err := client.executeRequest(http.MethodPost, path, input.toAPI()) if respReader != nil { defer respReader.Close() } @@ -501,7 +502,8 @@ type ListNICsInput struct { } func (client *MachinesClient) ListNICs(input *ListNICsInput) ([]*NIC, error) { - respReader, err := client.executeRequest(http.MethodGet, fmt.Sprintf("/my/machines/%s/nics", input.MachineID), nil) + path := fmt.Sprintf("/%s/machines/%s/nics", client.accountName, input.MachineID) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } @@ -560,6 +562,48 @@ func (client *MachinesClient) RemoveNIC(input *RemoveNICInput) error { return nil } +type StopMachineInput struct { + MachineID string +} + +func (client *MachinesClient) StopMachine(input *StopMachineInput) error { + path := fmt.Sprintf("/%s/machines/%s", client.accountName, input.MachineID) + + params := &url.Values{} + params.Set("action", "stop") + + respReader, err := client.executeRequestURIParams(http.MethodPost, path, nil, params) + if respReader != nil { + defer respReader.Close() + } + if err != nil { + return errwrap.Wrapf("Error executing StopMachine request: {{err}}", err) + } + + return nil +} + +type StartMachineInput struct { + MachineID string +} + +func (client *MachinesClient) StartMachine(input *StartMachineInput) error { + path := fmt.Sprintf("/%s/machines/%s", client.accountName, input.MachineID) + + params := &url.Values{} + params.Set("action", "start") + + respReader, err := client.executeRequestURIParams(http.MethodPost, path, nil, params) + if respReader != nil { + defer respReader.Close() + } + if err != nil { + return errwrap.Wrapf("Error executing StartMachine request: {{err}}", err) + } + + return nil +} + var reservedMachineCNSTags = map[string]struct{}{ machineCNSTagDisable: {}, machineCNSTagReversePTR: {}, diff --git a/vendor/github.com/joyent/triton-go/networks.go b/vendor/github.com/joyent/triton-go/networks.go index cb1ec17005d0..440e3bc87a01 100644 --- a/vendor/github.com/joyent/triton-go/networks.go +++ b/vendor/github.com/joyent/triton-go/networks.go @@ -36,7 +36,8 @@ type Network struct { type ListNetworksInput struct{} func (client *NetworksClient) ListNetworks(*ListNetworksInput) ([]*Network, error) { - respReader, err := client.executeRequest(http.MethodGet, "/my/networks", nil) + path := fmt.Sprintf("/%s/networks", client.accountName) + respReader, err := client.executeRequest(http.MethodGet, path, nil) if respReader != nil { defer respReader.Close() } diff --git a/vendor/vendor.json b/vendor/vendor.json index 1c0c7ca53ee9..9e78284fc271 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -2341,16 +2341,16 @@ "revisionTime": "2016-06-16T18:50:15Z" }, { - "checksumSHA1": "2HimxaJVVp2QDVQ0570L71Zd5s4=", + "checksumSHA1": "XsjyaC6eTHUy/n0iuR46TZcgAK8=", "path": "github.com/joyent/triton-go", - "revision": "5db9e2b6a4c1f7ffd2a7e7aa625f42dba956608c", - "revisionTime": "2017-04-12T23:23:58Z" + "revision": "c73729fd38522591909a371c8180ca7090a59ab9", + "revisionTime": "2017-04-28T18:47:44Z" }, { "checksumSHA1": "QzUqkCSn/ZHyIK346xb9V6EBw9U=", "path": "github.com/joyent/triton-go/authentication", - "revision": "66b31a94af28a65e902423879a2820ea34b773fb", - "revisionTime": "2017-03-31T18:12:29Z" + "revision": "c73729fd38522591909a371c8180ca7090a59ab9", + "revisionTime": "2017-04-28T18:47:44Z" }, { "checksumSHA1": "YhQcOsGx8r2S/jkJ0Qt4cZ5BLCU=", diff --git a/website/source/docs/providers/triton/index.html.markdown b/website/source/docs/providers/triton/index.html.markdown index 7dc866d271c9..22b9a40e6bda 100644 --- a/website/source/docs/providers/triton/index.html.markdown +++ b/website/source/docs/providers/triton/index.html.markdown @@ -33,3 +33,4 @@ The following arguments are supported in the `provider` block: * `key_material` - (Optional) This is the private key of an SSH key associated with the Triton account to be used. If this is not set, the private key corresponding to the fingerprint in `key_id` must be available via an SSH Agent. * `key_id` - (Required) This is the fingerprint of the public key matching the key specified in `key_path`. It can be obtained via the command `ssh-keygen -l -E md5 -f /path/to/key` * `url` - (Optional) This is the URL to the Triton API endpoint. It is required if using a private installation of Triton. The default is to use the Joyent public cloud us-west-1 endpoint. Valid public cloud endpoints include: `us-east-1`, `us-east-2`, `us-east-3`, `us-sw-1`, `us-west-1`, `eu-ams-1` +* `insecure_skip_tls_verify` (Optional - defaults to false) This allows skipping TLS verification of the Triton endpoint. It is useful when connecting to a temporary Triton installation such as Cloud-On-A-Laptop which does not generally use a certificate signed by a trusted root CA.