-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds support for creating KMS KeyRing resources #518
Changes from 13 commits
ab18653
d18db25
946eef1
7afead9
b491ad0
0ce76d7
34e5b64
7536f92
5b815d7
bc9527f
1248ab8
e3de446
d6cb880
9d7ff51
c524051
5a7b690
33b74c0
5c49d08
775d43f
23500d0
b8d0dbe
c4317ab
c2106a9
27fc744
a2c3363
82f4785
6e2a6c0
2120b47
65cbadc
024b45b
2791c74
248d518
3fbf0bb
6dc9035
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package google | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"google.golang.org/api/cloudkms/v1" | ||
"log" | ||
) | ||
|
||
func resourceKmsKeyRing() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceKmsKeyRingCreate, | ||
Read: resourceKmsKeyRingRead, | ||
Delete: resourceKmsKeyRingDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"location": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"project": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func kmsResourceParentString(project, location string) string { | ||
return fmt.Sprintf("projects/%s/locations/%s", project, location) | ||
} | ||
|
||
func kmsResourceParentKeyRingName(project, location, name string) string { | ||
return fmt.Sprintf("%s/keyRings/%s", kmsResourceParentString(project, location), name) | ||
} | ||
|
||
func resourceKmsKeyRingCreate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
project, err := getProject(d, config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
name := d.Get("name").(string) | ||
location := d.Get("location").(string) | ||
|
||
parent := kmsResourceParentString(project, location) | ||
|
||
keyRing, err := config.clientKms.Projects.Locations.KeyRings. | ||
Create(parent, &cloudkms.KeyRing{}). | ||
KeyRingId(name). | ||
Do() | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error creating KeyRing: %s", err) | ||
} | ||
|
||
log.Printf("[DEBUG] Created KeyRing %s", keyRing.Name) | ||
|
||
d.SetId(keyRing.Name) | ||
|
||
return resourceKmsKeyRingRead(d, meta) | ||
} | ||
|
||
func resourceKmsKeyRingRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
keyRingName := d.Id() | ||
|
||
log.Printf("[DEBUG] Executing read for KMS KeyRing %s", keyRingName) | ||
|
||
_, err := config.clientKms.Projects.Locations.KeyRings. | ||
Get(keyRingName). | ||
Do() | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error reading KeyRing: %s", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceKmsKeyRingDelete(d *schema.ResourceData, meta interface{}) error { | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package google | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"log" | ||
"os" | ||
) | ||
|
||
func TestAccGoogleKmsKeyRing_basic(t *testing.T) { | ||
skipIfEnvNotSet(t, | ||
[]string{ | ||
"GOOGLE_ORG", | ||
"GOOGLE_BILLING_ACCOUNT", | ||
}..., | ||
) | ||
|
||
projectId := "terraform-" + acctest.RandString(10) | ||
projectOrg := os.Getenv("GOOGLE_ORG") | ||
projectBillingAccount := os.Getenv("GOOGLE_BILLING_ACCOUNT") | ||
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testGoogleKmsKeyRing_recreate(keyRingName), | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testGoogleKmsKeyRing_basic(projectId, projectOrg, projectBillingAccount, keyRingName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckGoogleKmsKeyRingExists("google_kms_key_ring.key_ring"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckGoogleKmsKeyRingExists(resourceName string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
config := testAccProvider.Meta().(*Config) | ||
|
||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return fmt.Errorf("Resource not found: %s", resourceName) | ||
} | ||
|
||
name := rs.Primary.Attributes["name"] | ||
location := rs.Primary.Attributes["location"] | ||
project := rs.Primary.Attributes["project"] | ||
|
||
parent := kmsResourceParentString(project, location) | ||
keyRingName := kmsResourceParentKeyRingName(project, location, name) | ||
|
||
listKeyRingsResponse, err := config.clientKms.Projects.Locations.KeyRings.List(parent).Do() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why list rather than get? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used list because I don't like it when my tests look similar to the production code. I thought this would be a good way to still test the intended functionality without making it too similar to I am open to changing it if you would like me to. |
||
if err != nil { | ||
return fmt.Errorf("Error listing KeyRings: %s", err) | ||
} | ||
|
||
for _, keyRing := range listKeyRingsResponse.KeyRings { | ||
log.Printf("[DEBUG] Found KeyRing: %s", keyRing.Name) | ||
|
||
if keyRing.Name == keyRingName { | ||
return nil | ||
} | ||
} | ||
|
||
return fmt.Errorf("KeyRing not found: %s", keyRingName) | ||
} | ||
} | ||
|
||
// TODO | ||
// KMS KeyRings cannot be deleted. This will test if the resource can be added back to state after being removed | ||
func testGoogleKmsKeyRing_recreate(name string) resource.TestCheckFunc { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the resource already exists server-side, we can add import functionality instead of trying to get it to essentially import on create. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the expected behavior of attempting to create a KeyRing that already exists? Should it fail because the resource already exists on the server? Or should it handle it similar to how an import would? I think most resources would fail here because you'd expect to have to use In either case, my intention was for this test to capture that logic, where I either expect a failure when re-creating, or for it to be handled gracefully. |
||
return func(s *terraform.State) error { | ||
return nil | ||
} | ||
} | ||
|
||
func testGoogleKmsKeyRing_basic(projectId, projectOrg, projectBillingAccount, keyRingName string) string { | ||
return fmt.Sprintf(` | ||
resource "google_project" "acceptance" { | ||
name = "%s" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you fix the formatting here? I think you just have a mix of tabs and spaces There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you fix the formatting here? I think you've got a spaces vs tabs issue (we usually use tabs) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, my editor automatically converts tabs to spaces for me. I can fix this. |
||
project_id = "%s" | ||
org_id = "%s" | ||
billing_account = "%s" | ||
} | ||
|
||
resource "google_project_services" "acceptance" { | ||
project = "${google_project.acceptance.project_id}" | ||
services = [ | ||
"cloudkms.googleapis.com" | ||
] | ||
} | ||
|
||
resource "google_kms_key_ring" "key_ring" { | ||
project = "${google_project_services.acceptance.project}" | ||
name = "%s" | ||
location = "us-central1" | ||
} | ||
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry to point this out again, but mind fixing the style here and elsewhere? https://github.com/golang/go/wiki/CodeReviewComments#line-length
I think one line would be fine, two is also fine (we usually break after the left paren)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I don't think I understood before but I see what you're saying now. I'll change it to a single line.