Skip to content
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

Data Sources for KMS Key Ring and Key #1235

Merged
merged 10 commits into from Jan 17, 2019
Merged

Data Sources for KMS Key Ring and Key #1235

merged 10 commits into from Jan 17, 2019

Conversation

ghost
Copy link

@ghost ghost commented Jan 11, 2019


[all]

Adding datasources to KMS key ring and crypto key for the sake of not having to import them once they've been created and making it easier to manage them in case the state needs to be rolled back after initial create.

This is a bit tricky because tests require creating non-destructible resources.
There's no yaml-based template for these yet so I just added plain go code.

The tests expect specific environment variables to run, so I was only able to verify by hardcoding my own account/etc.

  • I verified this by building my own copy of terraform-provider and running against my own project:
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
 <= read (data resources)

Terraform will perform the following actions:

 <= data.google_kms_key_ring.kms-key-ring
      id:       <computed>
      location: "us-west1"
      name:     "tf-state-key-ring"


Plan: 0 to add, 0 to change, 0 to destroy.
  • Outputs of data:
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

2019-01-11T18:15:17.040-0700 [DEBUG] plugin.terraform-provider-google:                                                  
test-key = projects/my-project/locations/us-west1/keyRings/tf-state-key-ring/cryptoKeys/tf-state-key
test-ring = projects/my-project/locations/us-west1/keyRings/tf-state-key-ring

Related issue: hashicorp/terraform-provider-google#2847

[terraform]

[terraform-beta]

@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here (e.g. I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

@ghost
Copy link
Author

ghost commented Jan 11, 2019

I signed it!

@googlebot
Copy link

CLAs look good, thanks!

"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceGoogleKmsKeyRing() *schema.Resource {
Copy link
Author

@ghost ghost Jan 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the resource-related tests/func for this do not have google in the name: don't know if you have a standard, but I just went with how other data sources are named

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think consistency with the other data sources is just fine.

@ghost ghost changed the title [WIP] Data Sources for KMS Key Ring and Key Data Sources for KMS Key Ring and Key Jan 12, 2019
Type: schema.TypeList,
MaxItems: 1,
Computed: true,
Elem: &schema.Resource{
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure how this is parsed in a data source

@nat-henderson
Copy link
Contributor

Thanks for your contribution! Can you elaborate a little on your use case, or link a related issue?

@nat-henderson nat-henderson self-requested a review January 16, 2019 02:50
@chrisst
Copy link
Contributor

chrisst commented Jan 16, 2019

Looks like this duplicates work in hashicorp/terraform-provider-google#2804 as well as adding the key_ring data source

@ghost
Copy link
Author

ghost commented Jan 16, 2019

Dangit, missed that other PR :( I was told to look here if I wanted to make changes to the provider

I asked about this feature in this issue: hashicorp/terraform-provider-google#2847 ( I think the link is buried at the bottom of the original PR template)

My current use case is outline there and here's how I am getting about without these data sources currently: https://github.com/kierachell/k8s-in-gcp/blob/master/tf/setup.sh#L48

Basically, this would allow me to roll all of my terraform config forward and back in its entirety. (with resource blocks I run into errors since the 2nd+ create requires me importing resource that were made on the first run)

@nat-henderson nat-henderson requested review from chrisst and removed request for nat-henderson January 16, 2019 18:26
@chrisst
Copy link
Contributor

chrisst commented Jan 16, 2019

No worries, I was mostly commenting to make sure the 2 get linked and followed up with appropriately.

Copy link
Contributor

@chrisst chrisst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for all the work!

There are a couple of breaking issues related to the current schema. However I think they should be fixed if you inherit the schema instead of duplicating it. I've tried to review the rest of the changes not related to the schema (docs, etc) but I'll run the tests and finish the review when you've address the schema issues.

return &schema.Resource{
Read: dataSourceGoogleKmsCryptoKeyRead,
Schema: map[string]*schema.Schema{
"name": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like you've duplicated the schema from the resource. This was how we used to do things but we've added a convenience method in our newer data sources that just inherits the schema from the resource so that we don't have to maintain it in two different places.

Check out the cloud functions data source for an example

if err != nil {
return fmt.Errorf("Error reading CryptoKey: %s", err)
}
d.Set("key_ring", cryptoKeyId.KeyRingId.terraformId())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the comment above, you should reuse the Read method from the resource so you don't have to set all the properties manually. Again see cloud functions for an example.

}

/*
This test should run in its own project, because KMS key rings and crypto keys are not deletable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding full tests! I recently added a test helper that will rely on a shared project for KMS tests that don't explicitly need to test key creation/deletion. See https://github.com/terraform-providers/terraform-provider-google/blob/master/google/resource_compute_disk_test.go#L319 for an example using this pattern. This helps us cut down on superfluous project creation which slows down our test suite and creates a bog of projects that are partially deleted.

},
"protection_level": {
Type: schema.TypeString,
Commpute: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inheriting from the resource will also help catch typos like this :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️ somehow that still built and ran... Thank you for all the suggestions, I'll get it updated tonight

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm, found that my symlinks got all wonky with gomodules

"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceGoogleKmsKeyRing() *schema.Resource {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think consistency with the other data sources is just fine.

* `name` - (Required) The CryptoKey's name.
A CryptoKey’s name belonging to the specified Google Cloud Platform KeyRing and match the regular expression `[a-zA-Z0-9_-]{1,63}`

* `key_ring` - (Required) The id of the Google Cloud Platform KeyRing to which the key shall belong.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change this to "The self_link of..." This helps user's differentiate between using a name or self_link here when referencing a key_ring specified elsewhere in a terraform config. We also encourage people not to rely on the terraform id as it's not a consistent experience between resources as to what it actually contains.

# google\_kms\_crypto\_key

Provides access to a Google Cloud Platform KMS CryptoKey. For more information see
[the official documentation](https://cloud.google.com/kms/docs/object-hierarchy#cryptokey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this anchor tag be #key ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should and should be updated in the resource doc 😲

---
layout: "google"
page_title: "Google: google_kms_crypto_key"
sidebar_current: "docs-google-kms-crypto-key-x"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the side_bar to docs-google-datasource-kms-crypto-key. Also feel free to add the 2 new docs files to website/google.erb . This is so that the links show up in the side bar, and when clicked they will highlight the current page in purple and the parent section based on a prefix match of the sidebar_current field (hence adding the -datasource- in there).
example here

---
layout: "google"
page_title: "Google: google_kms_key_ring"
sidebar_current: "docs-google-kms-key-ring-x"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to docs-google-datasource-kms-key-ring

@chrisst chrisst self-assigned this Jan 16, 2019
@ghost
Copy link
Author

ghost commented Jan 17, 2019

@chrisst Thank you for detailed comments . I think I covered all of them; and double checked all the links and rebuilt the provider and it still works on my own project 😰 .

Let me know if there is anything else to update - I think I'm getting a hang of the build/test/run process 😄

PROOF:


Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
2019/01/17 09:18:46 [DEBUG] plugin: waiting for all plugin processes to complete...

Outputs:

key = tf-state-key
ring = projects/proj/locations/us-central1/keyRings/tf-state-key-ring

Copy link
Contributor

@chrisst chrisst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a couple more comments, but mostly around paring down the amount of work your tests need to do. Since you've already done a ton of work here and I think people want this I'm going to just push up my changes to the tests and get it running through our build system. Thanks again for adding this!

return err
}

cryptoKeyId := &kmsCryptoKeyId{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to be a reference, you can just use a plain struct.

Suggested change
cryptoKeyId := &kmsCryptoKeyId{
cryptoKeyId := kmsCryptoKeyId{

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I saw it being a reference in other files and it didn't quite make sense but I followed the "common denominator"

return err
}

keyRingId := &kmsKeyRingId{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Suggested change
keyRingId := &kmsKeyRingId{
keyRingId := kmsKeyRingId{

}
d.SetId(keyRingId.terraformId())

err = resourceKmsKeyRingRead(d, meta)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of capturing and returning the error or nil separately, you can just shortcut and return the call to read. This way if the call returns an error, this method will return that error and vice versa. So it's equivalent to what you have here.
eg:

return resourceKmsKeyRingRead(d, meta)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gah, I left that from when I was trying to make the method fail and debug what the error would be, sorry.

Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, kms.KeyRing.Name, kms.CryptoKey.Name),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is closer to what I imagined using bootstrapKMS would be, but you can still exclude a ton of the resource building so that this test only focuses on the datasource functionality (which is test that an existing resource can be imported).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did wonder about that but it make more sense now that the read function is shared.

Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, kms.KeyRing.Name, kms.CryptoKey.Name),
Check: resource.TestMatchResourceAttr("data.google_kms_crypto_key", "name", regexp.MustCompile(kms.CryptoKey.Name)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Check: resource.TestMatchResourceAttr("data.google_kms_crypto_key", "name", regexp.MustCompile(kms.CryptoKey.Name)),
Check: resource.TestMatchResourceAttr("data.google_kms_crypto_key.kms_crypto_key", "name", regexp.MustCompile(kms.CryptoKey.Name)),

@chrisst
Copy link
Contributor

chrisst commented Jan 17, 2019

If you have any questions on the changes I've made I'm happy to explain them.

@modular-magician
Copy link
Collaborator

I am a robot that works on MagicModules PRs!

I built this PR into one or more PRs on other repositories, and when those are closed, this PR will also be merged and closed.
depends: hashicorp/terraform-provider-google-beta#359
depends: hashicorp/terraform-provider-google#2891
depends: modular-magician/inspec-gcp#78

artemvovk and others added 7 commits January 17, 2019 21:38
Use kms bootstrap to avoid creating projects
Simplify returns in the resource
Tracked submodules are build/terraform-beta build/terraform build/ansible build/inspec.
@modular-magician modular-magician merged commit a10725b into GoogleCloudPlatform:master Jan 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants