From ac58a450bac27147d9df7bc15da4ec135978bf11 Mon Sep 17 00:00:00 2001 From: Pablo Lalloni Date: Wed, 25 Feb 2015 08:38:23 -0300 Subject: [PATCH] Add DigitalOcean SSH Key resource --- builtin/providers/digitalocean/provider.go | 1 + .../resource_digitalocean_ssh_key.go | 114 ++++++++++++++++++ .../resource_digitalocean_ssh_key_test.go | 99 +++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 builtin/providers/digitalocean/resource_digitalocean_ssh_key.go create mode 100644 builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go diff --git a/builtin/providers/digitalocean/provider.go b/builtin/providers/digitalocean/provider.go index ecc7d67b8..080716e2e 100644 --- a/builtin/providers/digitalocean/provider.go +++ b/builtin/providers/digitalocean/provider.go @@ -21,6 +21,7 @@ func Provider() terraform.ResourceProvider { "digitalocean_domain": resourceDigitalOceanDomain(), "digitalocean_droplet": resourceDigitalOceanDroplet(), "digitalocean_record": resourceDigitalOceanRecord(), + "digitalocean_ssh_key": resourceDigitalOceanSSHKey(), }, ConfigureFunc: providerConfigure, diff --git a/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go b/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go new file mode 100644 index 000000000..c509d4725 --- /dev/null +++ b/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go @@ -0,0 +1,114 @@ +package digitalocean + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/pearkes/digitalocean" +) + +func resourceDigitalOceanSSHKey() *schema.Resource { + return &schema.Resource{ + Create: resourceDigitalOceanSSHKeyCreate, + Read: resourceDigitalOceanSSHKeyRead, + Update: resourceDigitalOceanSSHKeyUpdate, + Delete: resourceDigitalOceanSSHKeyDelete, + + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "public_key": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceDigitalOceanSSHKeyCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + // Build up our creation options + opts := &digitalocean.CreateSSHKey{ + Name: d.Get("name").(string), + PublicKey: d.Get("public_key").(string), + } + + log.Printf("[DEBUG] SSH Key create configuration: %#v", opts) + id, err := client.CreateSSHKey(opts) + if err != nil { + return fmt.Errorf("Error creating SSH Key: %s", err) + } + + d.SetId(id) + log.Printf("[INFO] SSH Key: %s", id) + + return resourceDigitalOceanSSHKeyRead(d, meta) +} + +func resourceDigitalOceanSSHKeyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + key, err := client.RetrieveSSHKey(d.Id()) + if err != nil { + // If the key is somehow already destroyed, mark as + // succesfully gone + if strings.Contains(err.Error(), "404 Not Found") { + d.SetId("") + return nil + } + + return fmt.Errorf("Error retrieving SSH key: %s", err) + } + + d.Set("name", key.Name) + d.Set("fingerprint", key.Fingerprint) + + return nil +} + +func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + var newName string + if v, ok := d.GetOk("name"); ok { + newName = v.(string) + } + + log.Printf("[DEBUG] SSH key update name: %#v", newName) + err := client.RenameSSHKey(d.Id(), newName) + if err != nil { + return fmt.Errorf("Failed to update SSH key: %s", err) + } + + return resourceDigitalOceanSSHKeyRead(d, meta) +} + +func resourceDigitalOceanSSHKeyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + log.Printf("[INFO] Deleting SSH key: %s", d.Id()) + err := client.DestroySSHKey(d.Id()) + if err != nil { + return fmt.Errorf("Error deleting SSH key: %s", err) + } + + d.SetId("") + return nil +} diff --git a/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go b/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go new file mode 100644 index 000000000..d5c50e6f8 --- /dev/null +++ b/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go @@ -0,0 +1,99 @@ +package digitalocean + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/pearkes/digitalocean" +) + +func TestAccDigitalOceanSSHKey_Basic(t *testing.T) { + var key digitalocean.SSHKey + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanSSHKeyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckDigitalOceanSSHKeyConfig_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanSSHKeyExists("digitalocean_ssh_key.foobar", &key), + testAccCheckDigitalOceanSSHKeyAttributes(&key), + resource.TestCheckResourceAttr( + "digitalocean_ssh_key.foobar", "name", "foobar"), + resource.TestCheckResourceAttr( + "digitalocean_ssh_key.foobar", "public_key", "abcdef"), + ), + }, + }, + }) +} + +func testAccCheckDigitalOceanSSHKeyDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*digitalocean.Client) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "digitalocean_ssh_key" { + continue + } + + // Try to find the key + _, err := client.RetrieveSSHKey(rs.Primary.ID) + + if err == nil { + fmt.Errorf("SSH key still exists") + } + } + + return nil +} + +func testAccCheckDigitalOceanSSHKeyAttributes(key *digitalocean.SSHKey) resource.TestCheckFunc { + return func(s *terraform.State) error { + + if key.Name != "foobar" { + return fmt.Errorf("Bad name: %s", key.Name) + } + + return nil + } +} + +func testAccCheckDigitalOceanSSHKeyExists(n string, key *digitalocean.SSHKey) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No Record ID is set") + } + + client := testAccProvider.Meta().(*digitalocean.Client) + + foundKey, err := client.RetrieveSSHKey(rs.Primary.ID) + + if err != nil { + return err + } + + if foundKey.Name != rs.Primary.ID { + return fmt.Errorf("Record not found") + } + + *key = foundKey + + return nil + } +} + +const testAccCheckDigitalOceanSSHKeyConfig_basic = ` +resource "digitalocean_ssh_key" "foobar" { + name = "foobar" + public_key = "abcdef" +}`