-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '0.4.7' into Orchestrator
- Loading branch information
Showing
11 changed files
with
354 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package rundeck | ||
|
||
import ( | ||
"context" | ||
"crypto/sha1" | ||
"encoding/hex" | ||
"fmt" | ||
"io" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
|
||
"github.com/rundeck/go-rundeck/rundeck" | ||
) | ||
|
||
type BaseKeyType int32 | ||
|
||
const ( | ||
PRIVATE_KEY BaseKeyType = 0 | ||
PASSWORD BaseKeyType = 1 | ||
) | ||
|
||
func CreateOrUpdateBaseKey(d *schema.ResourceData, meta interface{}, baseKeyType BaseKeyType) error { | ||
client := meta.(*rundeck.BaseClient) | ||
|
||
var payload string | ||
path := d.Get("path").(string) | ||
|
||
var err error | ||
|
||
ctx := context.Background() | ||
|
||
var contentType string | ||
switch baseKeyType { | ||
case PRIVATE_KEY: | ||
contentType = "application/octet-stream" | ||
payload = d.Get("key_material").(string) | ||
case PASSWORD: | ||
contentType = "application/x-rundeck-data-password" | ||
payload = d.Get("password").(string) | ||
default: | ||
return fmt.Errorf("Internal error. Unknown key type") | ||
} | ||
|
||
payloadReader := io.NopCloser(strings.NewReader(payload)) | ||
|
||
if d.Id() != "" { | ||
resp, err := client.StorageKeyUpdate(ctx, path, payloadReader, contentType) | ||
if resp.StatusCode == 409 || err != nil { | ||
return fmt.Errorf("Error updating or adding key: Key exists") | ||
} | ||
} else { | ||
resp, err := client.StorageKeyCreate(ctx, path, payloadReader, contentType) | ||
if resp.StatusCode == 409 || err != nil { | ||
return fmt.Errorf("Error updating or adding key: Key exists") | ||
} | ||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId(path) | ||
|
||
return ReadBaseKey(d, meta) | ||
} | ||
|
||
func DeleteBaseKey(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*rundeck.BaseClient) | ||
ctx := context.Background() | ||
|
||
path := d.Id() | ||
|
||
// The only "delete" call we have is oblivious to key type, but | ||
// that's okay since our Exists implementation makes sure that we | ||
// won't try to delete a key of the wrong type since we'll pretend | ||
// that it's already been deleted. | ||
_, err := client.StorageKeyDelete(ctx, path) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func ReadBaseKey(d *schema.ResourceData, meta interface{}) error { | ||
// Nothing to read for a private key: existence is all we need to | ||
// worry about, and PrivateKeyExists took care of that. | ||
return nil | ||
} | ||
|
||
func BaseKeyExists(d *schema.ResourceData, meta interface{}, baseKeyType BaseKeyType) (bool, error) { | ||
client := meta.(*rundeck.BaseClient) | ||
ctx := context.Background() | ||
|
||
path := d.Id() | ||
|
||
resp, err := client.StorageKeyGetMetadata(ctx, path) | ||
if err != nil { | ||
if resp.StatusCode != 404 { | ||
err = nil | ||
} | ||
return false, err | ||
} | ||
|
||
// If the resource is not password or private key as far as this resource is | ||
// concerned it doesn't exist. (We'll fail properly when we try to | ||
// create a key where one already exists.) | ||
// Content-type are: | ||
// application/octet-stream specifies a private key | ||
// application/pgp-keys specifies a public key | ||
// application/x-rundeck-data-password specifies a password | ||
switch baseKeyType { | ||
case PRIVATE_KEY: | ||
if *resp.Meta.RundeckContentType != "application/octet-stream" { | ||
return false, nil | ||
} | ||
case PASSWORD: | ||
if *resp.Meta.RundeckContentType != "application/x-rundeck-data-password" { | ||
return false, nil | ||
} | ||
default: | ||
return false, fmt.Errorf("Internal error. Unknown key type") | ||
} | ||
|
||
return true, nil | ||
} | ||
|
||
func BaseKeyStateFunction(val interface{}) string { | ||
switch v := val.(type) { | ||
case string: | ||
hash := sha1.Sum([]byte(v)) | ||
return hex.EncodeToString(hash[:]) | ||
default: | ||
return "" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package rundeck | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/rundeck/go-rundeck/rundeck" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/terraform" | ||
) | ||
|
||
func testAccBaseKeyCheckDestroy(key *rundeck.StorageKeyListResponse) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
client := testAccProvider.Meta().(*rundeck.BaseClient) | ||
ctx := context.Background() | ||
|
||
resp, err := client.StorageKeyGetMetadata(ctx, *key.Path) | ||
|
||
if resp.StatusCode == 200 { | ||
return fmt.Errorf("key still exists") | ||
} | ||
if resp.StatusCode != 404 { | ||
return fmt.Errorf("got something other than NotFoundError (%v) when getting key", err) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccBaseKeyCheckExists(rn string, key *rundeck.StorageKeyListResponse) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[rn] | ||
if !ok { | ||
return fmt.Errorf("resource not found: %s", rn) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("key id not set") | ||
} | ||
|
||
client := testAccProvider.Meta().(*rundeck.BaseClient) | ||
ctx := context.Background() | ||
gotKey, err := client.StorageKeyGetMetadata(ctx, rs.Primary.ID) | ||
if gotKey.StatusCode == 404 || err != nil { | ||
return fmt.Errorf("error getting key metadata: %s", err) | ||
} | ||
|
||
*key = gotKey | ||
|
||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package rundeck | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
func resourceRundeckPassword() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: func(rd *schema.ResourceData, i interface{}) error { | ||
return CreateOrUpdateBaseKey(rd, i, PASSWORD) | ||
}, | ||
Update: func(rd *schema.ResourceData, i interface{}) error { | ||
return CreateOrUpdateBaseKey(rd, i, PASSWORD) | ||
}, | ||
Delete: DeleteBaseKey, | ||
Exists: func(rd *schema.ResourceData, i interface{}) (bool, error) { | ||
return BaseKeyExists(rd, i, PASSWORD) | ||
}, | ||
Read: ReadBaseKey, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"path": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
Description: "Path to the key within the key store", | ||
ForceNew: true, | ||
}, | ||
|
||
"password": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
Description: "The password to store", | ||
StateFunc: BaseKeyStateFunction, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package rundeck | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/rundeck/go-rundeck/rundeck" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/terraform" | ||
) | ||
|
||
func TestAccPassword_basic(t *testing.T) { | ||
var key rundeck.StorageKeyListResponse | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccBaseKeyCheckDestroy(&key), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccPasswordConfig_basic, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccBaseKeyCheckExists("rundeck_password.test", &key), | ||
func(s *terraform.State) error { | ||
if expected := "keys/terraform_acceptance_tests/password"; *key.Path != expected { | ||
return fmt.Errorf("wrong path; expected %v, got %v", expected, *key.Path) | ||
} | ||
if !strings.HasSuffix(*key.URL, "/storage/keys/terraform_acceptance_tests/password") { | ||
return fmt.Errorf("wrong URL; expected to end with the key path") | ||
} | ||
if expected := "file"; *key.Type != expected { | ||
return fmt.Errorf("wrong resource type; expected %v, got %v", expected, *key.Type) | ||
} | ||
if expected := ""; string(key.Meta.RundeckKeyType) != expected { | ||
return fmt.Errorf("wrong key type; expected %v, got %v", expected, key.Meta.RundeckKeyType) | ||
} | ||
if expected := "application/x-rundeck-data-password"; *key.Meta.RundeckContentType != expected { | ||
return fmt.Errorf("wrong RundeckContentType; expected %v, got %v", expected, *key.Meta.RundeckContentType) | ||
} | ||
// Rundeck won't let us re-retrieve a private key payload, so we can't test | ||
// that the key material was submitted and stored correctly. | ||
return nil | ||
}, | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
const testAccPasswordConfig_basic = ` | ||
resource "rundeck_password" "test" { | ||
path = "terraform_acceptance_tests/password" | ||
password = "qwerty" | ||
} | ||
` |
Oops, something went wrong.