Handle external state changes for Packet resources gracefully.
When a Packet provision exceeds our time limit, we move the device to an internal project for Packet staff to investigate. When this happens, the original user no longer has access to the device, and they get a 403. These changes make that and other external state changes more pleasant for users of Terraform.
This commit is contained in:
parent
ea4595840c
commit
a1935a135d
|
@ -13,7 +13,7 @@ type Config struct {
|
||||||
AuthToken string
|
AuthToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client() returns a new client for accessing packet.
|
// Client() returns a new client for accessing Packet's API.
|
||||||
func (c *Config) Client() *packngo.Client {
|
func (c *Config) Client() *packngo.Client {
|
||||||
return packngo.NewClient(consumerToken, c.AuthToken, cleanhttp.DefaultClient())
|
return packngo.NewClient(consumerToken, c.AuthToken, cleanhttp.DefaultClient())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package packet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/packethost/packngo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func friendlyError(err error) error {
|
||||||
|
if e, ok := err.(*packngo.ErrorResponse); ok {
|
||||||
|
return &ErrorResponse{
|
||||||
|
StatusCode: e.Response.StatusCode,
|
||||||
|
Errors: Errors(e.Errors),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func isForbidden(err error) bool {
|
||||||
|
if r, ok := err.(*ErrorResponse); ok {
|
||||||
|
return r.StatusCode == http.StatusForbidden
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNotFound(err error) bool {
|
||||||
|
if r, ok := err.(*ErrorResponse); ok {
|
||||||
|
return r.StatusCode == http.StatusNotFound
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type Errors []string
|
||||||
|
|
||||||
|
func (e Errors) Error() string {
|
||||||
|
return strings.Join(e, "; ")
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorResponse struct {
|
||||||
|
StatusCode int
|
||||||
|
Errors
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Provider returns a schema.Provider for Packet.
|
// Provider returns a schema.Provider for managing Packet infrastructure.
|
||||||
func Provider() terraform.ResourceProvider {
|
func Provider() terraform.ResourceProvider {
|
||||||
return &schema.Provider{
|
return &schema.Provider{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
|
@ -31,6 +31,5 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||||
config := Config{
|
config := Config{
|
||||||
AuthToken: d.Get("auth_token").(string),
|
AuthToken: d.Get("auth_token").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
return config.Client(), nil
|
return config.Client(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package packet
|
package packet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
@ -146,22 +146,23 @@ func resourcePacketDeviceCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Device create configuration: %#v", createRequest)
|
|
||||||
|
|
||||||
newDevice, _, err := client.Devices.Create(createRequest)
|
newDevice, _, err := client.Devices.Create(createRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating device: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign the device id
|
|
||||||
d.SetId(newDevice.ID)
|
d.SetId(newDevice.ID)
|
||||||
|
|
||||||
log.Printf("[INFO] Device ID: %s", d.Id())
|
// Wait for the device so we can get the networking attributes that show up after a while.
|
||||||
|
_, err = waitForDeviceAttribute(d, "active", []string{"queued", "provisioning"}, "state", meta)
|
||||||
_, err = WaitForDeviceAttribute(d, "active", []string{"queued", "provisioning"}, "state", meta)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
if isForbidden(err) {
|
||||||
"Error waiting for device (%s) to become ready: %s", d.Id(), err)
|
// If the device doesn't get to the active state, we can't recover it from here.
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return errors.New("provisioning time limit exceeded; the Packet team will investigate")
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourcePacketDeviceRead(d, meta)
|
return resourcePacketDeviceRead(d, meta)
|
||||||
|
@ -170,10 +171,17 @@ func resourcePacketDeviceCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
|
func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
// Retrieve the device properties for updating the state
|
|
||||||
device, _, err := client.Devices.Get(d.Id())
|
device, _, err := client.Devices.Get(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error retrieving device: %s", err)
|
err = friendlyError(err)
|
||||||
|
|
||||||
|
// If the device somehow already destroyed, mark as succesfully gone.
|
||||||
|
if isNotFound(err) {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("name", device.Hostname)
|
d.Set("name", device.Hostname)
|
||||||
|
@ -186,35 +194,36 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
d.Set("created", device.Created)
|
d.Set("created", device.Created)
|
||||||
d.Set("updated", device.Updated)
|
d.Set("updated", device.Updated)
|
||||||
|
|
||||||
tags := make([]string, 0)
|
tags := make([]string, 0, len(device.Tags))
|
||||||
for _, tag := range device.Tags {
|
for _, tag := range device.Tags {
|
||||||
tags = append(tags, tag)
|
tags = append(tags, tag)
|
||||||
}
|
}
|
||||||
d.Set("tags", tags)
|
d.Set("tags", tags)
|
||||||
|
|
||||||
provisionerAddress := ""
|
var (
|
||||||
|
host string
|
||||||
networks := make([]map[string]interface{}, 0, 1)
|
networks = make([]map[string]interface{}, 0, 1)
|
||||||
|
)
|
||||||
for _, ip := range device.Network {
|
for _, ip := range device.Network {
|
||||||
network := make(map[string]interface{})
|
network := map[string]interface{}{
|
||||||
network["address"] = ip.Address
|
"address": ip.Address,
|
||||||
network["gateway"] = ip.Gateway
|
"gateway": ip.Gateway,
|
||||||
network["family"] = ip.Family
|
"family": ip.Family,
|
||||||
network["cidr"] = ip.Cidr
|
"cidr": ip.Cidr,
|
||||||
network["public"] = ip.Public
|
"public": ip.Public,
|
||||||
|
}
|
||||||
networks = append(networks, network)
|
networks = append(networks, network)
|
||||||
|
|
||||||
if ip.Family == 4 && ip.Public == true {
|
if ip.Family == 4 && ip.Public == true {
|
||||||
provisionerAddress = ip.Address
|
host = ip.Address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.Set("network", networks)
|
d.Set("network", networks)
|
||||||
|
|
||||||
log.Printf("[DEBUG] Provisioner Address set to %v", provisionerAddress)
|
if host != "" {
|
||||||
|
|
||||||
if provisionerAddress != "" {
|
|
||||||
d.SetConnInfo(map[string]string{
|
d.SetConnInfo(map[string]string{
|
||||||
"type": "ssh",
|
"type": "ssh",
|
||||||
"host": provisionerAddress,
|
"host": host,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,19 +233,15 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
func resourcePacketDeviceUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourcePacketDeviceUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
if d.HasChange("locked") && d.Get("locked").(bool) {
|
if d.HasChange("locked") {
|
||||||
_, err := client.Devices.Lock(d.Id())
|
var action func(string) (*packngo.Response, error)
|
||||||
|
if d.Get("locked").(bool) {
|
||||||
if err != nil {
|
action = client.Devices.Lock
|
||||||
return fmt.Errorf(
|
} else {
|
||||||
"Error locking device (%s): %s", d.Id(), err)
|
action = client.Devices.Unlock
|
||||||
}
|
}
|
||||||
} else if d.HasChange("locked") {
|
if _, err := action(d.Id()); err != nil {
|
||||||
_, err := client.Devices.Unlock(d.Id())
|
return friendlyError(err)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"Error unlocking device (%s): %s", d.Id(), err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,22 +251,14 @@ func resourcePacketDeviceUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
func resourcePacketDeviceDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourcePacketDeviceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
log.Printf("[INFO] Deleting device: %s", d.Id())
|
|
||||||
if _, err := client.Devices.Delete(d.Id()); err != nil {
|
if _, err := client.Devices.Delete(d.Id()); err != nil {
|
||||||
return fmt.Errorf("Error deleting device: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WaitForDeviceAttribute(
|
func waitForDeviceAttribute(d *schema.ResourceData, target string, pending []string, attribute string, meta interface{}) (interface{}, error) {
|
||||||
d *schema.ResourceData, target string, pending []string, attribute string, meta interface{}) (interface{}, error) {
|
|
||||||
// Wait for the device so we can get the networking attributes
|
|
||||||
// that show up after a while
|
|
||||||
log.Printf(
|
|
||||||
"[INFO] Waiting for device (%s) to have %s of %s",
|
|
||||||
d.Id(), attribute, target)
|
|
||||||
|
|
||||||
stateConf := &resource.StateChangeConf{
|
stateConf := &resource.StateChangeConf{
|
||||||
Pending: pending,
|
Pending: pending,
|
||||||
Target: target,
|
Target: target,
|
||||||
|
@ -270,27 +267,22 @@ func WaitForDeviceAttribute(
|
||||||
Delay: 10 * time.Second,
|
Delay: 10 * time.Second,
|
||||||
MinTimeout: 3 * time.Second,
|
MinTimeout: 3 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
return stateConf.WaitForState()
|
return stateConf.WaitForState()
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDeviceStateRefreshFunc(
|
func newDeviceStateRefreshFunc(d *schema.ResourceData, attribute string, meta interface{}) resource.StateRefreshFunc {
|
||||||
d *schema.ResourceData, attribute string, meta interface{}) resource.StateRefreshFunc {
|
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
return func() (interface{}, string, error) {
|
return func() (interface{}, string, error) {
|
||||||
err := resourcePacketDeviceRead(d, meta)
|
if err := resourcePacketDeviceRead(d, meta); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we can access our attribute
|
|
||||||
if attr, ok := d.GetOk(attribute); ok {
|
if attr, ok := d.GetOk(attribute); ok {
|
||||||
// Retrieve the device properties
|
|
||||||
device, _, err := client.Devices.Get(d.Id())
|
device, _, err := client.Devices.Get(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", fmt.Errorf("Error retrieving device: %s", err)
|
return nil, "", friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &device, attr.(string), nil
|
return &device, attr.(string), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,19 +290,14 @@ func newDeviceStateRefreshFunc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Powers on the device and waits for it to be active
|
// powerOnAndWait Powers on the device and waits for it to be active.
|
||||||
func powerOnAndWait(d *schema.ResourceData, meta interface{}) error {
|
func powerOnAndWait(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
_, err := client.Devices.PowerOn(d.Id())
|
_, err := client.Devices.PowerOn(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for power on
|
_, err = waitForDeviceAttribute(d, "active", []string{"off"}, "state", client)
|
||||||
_, err = WaitForDeviceAttribute(d, "active", []string{"off"}, "state", client)
|
return err
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package packet
|
package packet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/packethost/packngo"
|
"github.com/packethost/packngo"
|
||||||
)
|
)
|
||||||
|
@ -53,14 +49,12 @@ func resourcePacketProjectCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
PaymentMethod: d.Get("payment_method").(string),
|
PaymentMethod: d.Get("payment_method").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Project create configuration: %#v", createRequest)
|
|
||||||
project, _, err := client.Projects.Create(createRequest)
|
project, _, err := client.Projects.Create(createRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating Project: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId(project.ID)
|
d.SetId(project.ID)
|
||||||
log.Printf("[INFO] Project created: %s", project.ID)
|
|
||||||
|
|
||||||
return resourcePacketProjectRead(d, meta)
|
return resourcePacketProjectRead(d, meta)
|
||||||
}
|
}
|
||||||
|
@ -70,14 +64,16 @@ func resourcePacketProjectRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
key, _, err := client.Projects.Get(d.Id())
|
key, _, err := client.Projects.Get(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If the project somehow already destroyed, mark as
|
err = friendlyError(err)
|
||||||
// succesfully gone
|
|
||||||
if strings.Contains(err.Error(), "404") {
|
// If the project somehow already destroyed, mark as succesfully gone.
|
||||||
|
if isNotFound(err) {
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Error retrieving Project: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("id", key.ID)
|
d.Set("id", key.ID)
|
||||||
|
@ -100,10 +96,9 @@ func resourcePacketProjectUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
updateRequest.PaymentMethod = attr.(string)
|
updateRequest.PaymentMethod = attr.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Project update: %#v", d.Get("id"))
|
|
||||||
_, _, err := client.Projects.Update(updateRequest)
|
_, _, err := client.Projects.Update(updateRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to update Project: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourcePacketProjectRead(d, meta)
|
return resourcePacketProjectRead(d, meta)
|
||||||
|
@ -112,10 +107,9 @@ func resourcePacketProjectUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
func resourcePacketProjectDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourcePacketProjectDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
log.Printf("[INFO] Deleting Project: %s", d.Id())
|
|
||||||
_, err := client.Projects.Delete(d.Id())
|
_, err := client.Projects.Delete(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error deleting SSH key: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
|
|
|
@ -37,11 +37,8 @@ func testAccCheckPacketProjectDestroy(s *terraform.State) error {
|
||||||
if rs.Type != "packet_project" {
|
if rs.Type != "packet_project" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if _, _, err := client.Projects.Get(rs.Primary.ID); err == nil {
|
||||||
_, _, err := client.Projects.Get(rs.Primary.ID)
|
return fmt.Errorf("Project cstill exists")
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
fmt.Errorf("Project cstill exists")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +47,9 @@ func testAccCheckPacketProjectDestroy(s *terraform.State) error {
|
||||||
|
|
||||||
func testAccCheckPacketProjectAttributes(project *packngo.Project) resource.TestCheckFunc {
|
func testAccCheckPacketProjectAttributes(project *packngo.Project) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
|
|
||||||
if project.Name != "foobar" {
|
if project.Name != "foobar" {
|
||||||
return fmt.Errorf("Bad name: %s", project.Name)
|
return fmt.Errorf("Bad name: %s", project.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +57,9 @@ func testAccCheckPacketProjectAttributes(project *packngo.Project) resource.Test
|
||||||
func testAccCheckPacketProjectExists(n string, project *packngo.Project) resource.TestCheckFunc {
|
func testAccCheckPacketProjectExists(n string, project *packngo.Project) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Not found: %s", n)
|
return fmt.Errorf("Not found: %s", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rs.Primary.ID == "" {
|
if rs.Primary.ID == "" {
|
||||||
return fmt.Errorf("No Record ID is set")
|
return fmt.Errorf("No Record ID is set")
|
||||||
}
|
}
|
||||||
|
@ -74,11 +67,9 @@ func testAccCheckPacketProjectExists(n string, project *packngo.Project) resourc
|
||||||
client := testAccProvider.Meta().(*packngo.Client)
|
client := testAccProvider.Meta().(*packngo.Client)
|
||||||
|
|
||||||
foundProject, _, err := client.Projects.Get(rs.Primary.ID)
|
foundProject, _, err := client.Projects.Get(rs.Primary.ID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if foundProject.ID != rs.Primary.ID {
|
if foundProject.ID != rs.Primary.ID {
|
||||||
return fmt.Errorf("Record not found: %v - %v", rs.Primary.ID, foundProject)
|
return fmt.Errorf("Record not found: %v - %v", rs.Primary.ID, foundProject)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package packet
|
package packet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/packethost/packngo"
|
"github.com/packethost/packngo"
|
||||||
)
|
)
|
||||||
|
@ -59,14 +55,12 @@ func resourcePacketSSHKeyCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
Key: d.Get("public_key").(string),
|
Key: d.Get("public_key").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] SSH Key create configuration: %#v", createRequest)
|
|
||||||
key, _, err := client.SSHKeys.Create(createRequest)
|
key, _, err := client.SSHKeys.Create(createRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating SSH Key: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId(key.ID)
|
d.SetId(key.ID)
|
||||||
log.Printf("[INFO] SSH Key: %s", key.ID)
|
|
||||||
|
|
||||||
return resourcePacketSSHKeyRead(d, meta)
|
return resourcePacketSSHKeyRead(d, meta)
|
||||||
}
|
}
|
||||||
|
@ -76,14 +70,16 @@ func resourcePacketSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
key, _, err := client.SSHKeys.Get(d.Id())
|
key, _, err := client.SSHKeys.Get(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
err = friendlyError(err)
|
||||||
|
|
||||||
// If the key is somehow already destroyed, mark as
|
// If the key is somehow already destroyed, mark as
|
||||||
// succesfully gone
|
// succesfully gone
|
||||||
if strings.Contains(err.Error(), "404") {
|
if isNotFound(err) {
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Error retrieving SSH key: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("id", key.ID)
|
d.Set("id", key.ID)
|
||||||
|
@ -105,10 +101,9 @@ func resourcePacketSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
Key: d.Get("public_key").(string),
|
Key: d.Get("public_key").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] SSH key update: %#v", d.Get("id"))
|
|
||||||
_, _, err := client.SSHKeys.Update(updateRequest)
|
_, _, err := client.SSHKeys.Update(updateRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to update SSH key: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourcePacketSSHKeyRead(d, meta)
|
return resourcePacketSSHKeyRead(d, meta)
|
||||||
|
@ -117,10 +112,9 @@ func resourcePacketSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
func resourcePacketSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourcePacketSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*packngo.Client)
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
log.Printf("[INFO] Deleting SSH key: %s", d.Id())
|
|
||||||
_, err := client.SSHKeys.Delete(d.Id())
|
_, err := client.SSHKeys.Delete(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error deleting SSH key: %s", err)
|
return friendlyError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
|
|
|
@ -40,11 +40,8 @@ func testAccCheckPacketSSHKeyDestroy(s *terraform.State) error {
|
||||||
if rs.Type != "packet_ssh_key" {
|
if rs.Type != "packet_ssh_key" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if _, _, err := client.SSHKeys.Get(rs.Primary.ID); err == nil {
|
||||||
_, _, err := client.SSHKeys.Get(rs.Primary.ID)
|
return fmt.Errorf("SSH key still exists")
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
fmt.Errorf("SSH key still exists")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,11 +50,9 @@ func testAccCheckPacketSSHKeyDestroy(s *terraform.State) error {
|
||||||
|
|
||||||
func testAccCheckPacketSSHKeyAttributes(key *packngo.SSHKey) resource.TestCheckFunc {
|
func testAccCheckPacketSSHKeyAttributes(key *packngo.SSHKey) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
|
|
||||||
if key.Label != "foobar" {
|
if key.Label != "foobar" {
|
||||||
return fmt.Errorf("Bad name: %s", key.Label)
|
return fmt.Errorf("Bad name: %s", key.Label)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,11 +60,9 @@ func testAccCheckPacketSSHKeyAttributes(key *packngo.SSHKey) resource.TestCheckF
|
||||||
func testAccCheckPacketSSHKeyExists(n string, key *packngo.SSHKey) resource.TestCheckFunc {
|
func testAccCheckPacketSSHKeyExists(n string, key *packngo.SSHKey) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Not found: %s", n)
|
return fmt.Errorf("Not found: %s", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rs.Primary.ID == "" {
|
if rs.Primary.ID == "" {
|
||||||
return fmt.Errorf("No Record ID is set")
|
return fmt.Errorf("No Record ID is set")
|
||||||
}
|
}
|
||||||
|
@ -77,11 +70,9 @@ func testAccCheckPacketSSHKeyExists(n string, key *packngo.SSHKey) resource.Test
|
||||||
client := testAccProvider.Meta().(*packngo.Client)
|
client := testAccProvider.Meta().(*packngo.Client)
|
||||||
|
|
||||||
foundKey, _, err := client.SSHKeys.Get(rs.Primary.ID)
|
foundKey, _, err := client.SSHKeys.Get(rs.Primary.ID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if foundKey.ID != rs.Primary.ID {
|
if foundKey.ID != rs.Primary.ID {
|
||||||
return fmt.Errorf("SSh Key not found: %v - %v", rs.Primary.ID, foundKey)
|
return fmt.Errorf("SSh Key not found: %v - %v", rs.Primary.ID, foundKey)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue