Skip to content

Commit bb42821

Browse files
rundeck_private_key resource type.
1 parent aba9698 commit bb42821

3 files changed

Lines changed: 207 additions & 1 deletion

File tree

builtin/providers/rundeck/provider.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func Provider() terraform.ResourceProvider {
3232
ResourcesMap: map[string]*schema.Resource{
3333
"rundeck_project": resourceRundeckProject(),
3434
//"rundeck_job": resourceRundeckJob(),
35-
//"rundeck_private_key": resourceRundeckPrivateKey(),
35+
"rundeck_private_key": resourceRundeckPrivateKey(),
3636
"rundeck_public_key": resourceRundeckPublicKey(),
3737
},
3838

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package rundeck
2+
3+
import (
4+
"crypto/sha1"
5+
"encoding/hex"
6+
7+
"github.com/hashicorp/terraform/helper/schema"
8+
9+
"github.com/apparentlymart/go-rundeck-api/rundeck"
10+
)
11+
12+
func resourceRundeckPrivateKey() *schema.Resource {
13+
return &schema.Resource{
14+
Create: CreateOrUpdatePrivateKey,
15+
Update: CreateOrUpdatePrivateKey,
16+
Delete: DeletePrivateKey,
17+
Exists: PrivateKeyExists,
18+
Read: ReadPrivateKey,
19+
20+
Schema: map[string]*schema.Schema{
21+
"path": &schema.Schema{
22+
Type: schema.TypeString,
23+
Required: true,
24+
Description: "Path to the key within the key store",
25+
ForceNew: true,
26+
},
27+
28+
"key_material": &schema.Schema{
29+
Type: schema.TypeString,
30+
Required: true,
31+
Description: "The private key material to store, in PEM format",
32+
StateFunc: func(v interface{}) string {
33+
switch v.(type) {
34+
case string:
35+
hash := sha1.Sum([]byte(v.(string)))
36+
return hex.EncodeToString(hash[:])
37+
default:
38+
return ""
39+
}
40+
},
41+
},
42+
},
43+
}
44+
}
45+
46+
func CreateOrUpdatePrivateKey(d *schema.ResourceData, meta interface{}) error {
47+
client := meta.(*rundeck.Client)
48+
49+
path := d.Get("path").(string)
50+
keyMaterial := d.Get("key_material").(string)
51+
52+
var err error
53+
54+
if d.Id() != "" {
55+
err = client.ReplacePrivateKey(path, keyMaterial)
56+
} else {
57+
err = client.CreatePrivateKey(path, keyMaterial)
58+
}
59+
60+
if err != nil {
61+
return err
62+
}
63+
64+
d.SetId(path)
65+
66+
return ReadPrivateKey(d, meta)
67+
}
68+
69+
func DeletePrivateKey(d *schema.ResourceData, meta interface{}) error {
70+
client := meta.(*rundeck.Client)
71+
72+
path := d.Id()
73+
74+
// The only "delete" call we have is oblivious to key type, but
75+
// that's okay since our Exists implementation makes sure that we
76+
// won't try to delete a key of the wrong type since we'll pretend
77+
// that it's already been deleted.
78+
err := client.DeleteKey(path)
79+
if err != nil {
80+
return err
81+
}
82+
83+
d.SetId("")
84+
return nil
85+
}
86+
87+
func ReadPrivateKey(d *schema.ResourceData, meta interface{}) error {
88+
// Nothing to read for a private key: existence is all we need to
89+
// worry about, and PrivateKeyExists took care of that.
90+
return nil
91+
}
92+
93+
func PrivateKeyExists(d *schema.ResourceData, meta interface{}) (bool, error) {
94+
client := meta.(*rundeck.Client)
95+
96+
path := d.Id()
97+
98+
key, err := client.GetKeyMeta(path)
99+
if err != nil {
100+
if _, ok := err.(rundeck.NotFoundError); ok {
101+
err = nil
102+
}
103+
return false, err
104+
}
105+
106+
if key.KeyType != "private" {
107+
// If the key type isn't public then as far as this resource is
108+
// concerned it doesn't exist. (We'll fail properly when we try to
109+
// create a key where one already exists.)
110+
return false, nil
111+
}
112+
113+
return true, nil
114+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package rundeck
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
8+
"github.com/apparentlymart/go-rundeck-api/rundeck"
9+
10+
"github.com/hashicorp/terraform/helper/resource"
11+
"github.com/hashicorp/terraform/terraform"
12+
)
13+
14+
func TestAccPrivateKey_basic(t *testing.T) {
15+
var key rundeck.KeyMeta
16+
17+
resource.Test(t, resource.TestCase{
18+
PreCheck: func() { testAccPreCheck(t) },
19+
Providers: testAccProviders,
20+
CheckDestroy: testAccPrivateKeyCheckDestroy(&key),
21+
Steps: []resource.TestStep{
22+
resource.TestStep{
23+
Config: testAccPrivateKeyConfig_basic,
24+
Check: resource.ComposeTestCheckFunc(
25+
testAccPrivateKeyCheckExists("rundeck_private_key.test", &key),
26+
func(s *terraform.State) error {
27+
if expected := "keys/terraform_acceptance_tests/private_key"; key.Path != expected {
28+
return fmt.Errorf("wrong path; expected %v, got %v", expected, key.Path)
29+
}
30+
if !strings.HasSuffix(key.URL, "/storage/keys/terraform_acceptance_tests/private_key") {
31+
return fmt.Errorf("wrong URL; expected to end with the key path")
32+
}
33+
if expected := "file"; key.ResourceType != expected {
34+
return fmt.Errorf("wrong resource type; expected %v, got %v", expected, key.ResourceType)
35+
}
36+
if expected := "private"; key.KeyType != expected {
37+
return fmt.Errorf("wrong key type; expected %v, got %v", expected, key.KeyType)
38+
}
39+
// Rundeck won't let us re-retrieve a private key payload, so we can't test
40+
// that the key material was submitted and stored correctly.
41+
return nil
42+
},
43+
),
44+
},
45+
},
46+
})
47+
}
48+
49+
func testAccPrivateKeyCheckDestroy(key *rundeck.KeyMeta) resource.TestCheckFunc {
50+
return func(s *terraform.State) error {
51+
client := testAccProvider.Meta().(*rundeck.Client)
52+
_, err := client.GetKeyMeta(key.Path)
53+
if err == nil {
54+
return fmt.Errorf("key still exists")
55+
}
56+
if _, ok := err.(*rundeck.NotFoundError); !ok {
57+
return fmt.Errorf("got something other than NotFoundError (%v) when getting key", err)
58+
}
59+
60+
return nil
61+
}
62+
}
63+
64+
func testAccPrivateKeyCheckExists(rn string, key *rundeck.KeyMeta) resource.TestCheckFunc {
65+
return func(s *terraform.State) error {
66+
rs, ok := s.RootModule().Resources[rn]
67+
if !ok {
68+
return fmt.Errorf("resource not found: %s", rn)
69+
}
70+
71+
if rs.Primary.ID == "" {
72+
return fmt.Errorf("key id not set")
73+
}
74+
75+
client := testAccProvider.Meta().(*rundeck.Client)
76+
gotKey, err := client.GetKeyMeta(rs.Primary.ID)
77+
if err != nil {
78+
return fmt.Errorf("error getting key metadata: %s", err)
79+
}
80+
81+
*key = *gotKey
82+
83+
return nil
84+
}
85+
}
86+
87+
const testAccPrivateKeyConfig_basic = `
88+
resource "rundeck_private_key" "test" {
89+
path = "terraform_acceptance_tests/private_key"
90+
key_material = "this is not a real private key"
91+
}
92+
`

0 commit comments

Comments
 (0)