Add Kms bootstrap step for terraform tests (#2837)

Signed-off-by: Modular Magician <magic-modules@google.com>
This commit is contained in:
The Magician 2019-01-08 18:32:27 -08:00 committed by Chris Stephens
parent 04ecac9a8d
commit 98d2972c31
3 changed files with 117 additions and 65 deletions

View File

@ -0,0 +1,105 @@
package google
import (
"fmt"
"log"
"os"
"testing"
"google.golang.org/api/cloudkms/v1"
)
var SharedKeyRing = "tftest-shared-keyring-1"
var SharedCyptoKey = "tftest-shared-key-1"
type bootstrappedKMS struct {
*cloudkms.KeyRing
*cloudkms.CryptoKey
}
/**
* BootstrapKMSkey will return a KMS key that can be used in tests that are
* testing KMS integration with other resources.
*
* This will either return an existing key or create one if it hasn't been created
* in the project yet. The motivation is because keyrings don't get deleted and we
* don't want a linear growth of disabled keyrings in a project. We also don't want
* to incur the overhead of creating a new project for each test that needs to use
* a KMS key.
**/
func BootstrapKMSKey(t *testing.T) bootstrappedKMS {
if v := os.Getenv("TF_ACC"); v == "" {
log.Println("Acceptance tests and bootstrapping skipped unless env 'TF_ACC' set")
// If not running acceptance tests, return an empty object
return bootstrappedKMS{
&cloudkms.KeyRing{},
&cloudkms.CryptoKey{},
}
}
projectID := getTestProjectFromEnv()
locationID := "global"
keyRingParent := fmt.Sprintf("projects/%s/locations/%s", projectID, locationID)
keyRingName := fmt.Sprintf("%s/keyRings/%s", keyRingParent, SharedKeyRing)
keyParent := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", projectID, locationID, SharedKeyRing)
keyName := fmt.Sprintf("%s/cryptoKeys/%s", keyParent, SharedCyptoKey)
config := Config{
Credentials: getTestCredsFromEnv(),
Project: getTestProjectFromEnv(),
Region: getTestRegionFromEnv(),
Zone: getTestZoneFromEnv(),
}
if err := config.loadAndValidate(); err != nil {
t.Errorf("Unable to bootstrap KMS key: %s", err)
}
// Get or Create the hard coded shared keyring for testing
kmsClient := config.clientKms
keyRing, err := kmsClient.Projects.Locations.KeyRings.Get(keyRingName).Do()
if err != nil {
if isGoogleApiErrorWithCode(err, 404) {
keyRing, err = kmsClient.Projects.Locations.KeyRings.Create(keyRingParent, &cloudkms.KeyRing{}).
KeyRingId(SharedKeyRing).Do()
if err != nil {
t.Errorf("Unable to bootstrap KMS key. Cannot create keyRing: %s", err)
}
} else {
t.Errorf("Unable to bootstrap KMS key. Cannot retrieve keyRing: %s", err)
}
}
if keyRing == nil {
t.Fatalf("Unable to bootstrap KMS key. keyRing is nil!")
}
// Get or Create the hard coded, shared crypto key for testing
cryptoKey, err := kmsClient.Projects.Locations.KeyRings.CryptoKeys.Get(keyName).Do()
if err != nil {
if isGoogleApiErrorWithCode(err, 404) {
newKey := cloudkms.CryptoKey{
Purpose: "ENCRYPT_DECRYPT",
}
cryptoKey, err = kmsClient.Projects.Locations.KeyRings.CryptoKeys.Create(keyParent, &newKey).
CryptoKeyId(SharedCyptoKey).Do()
if err != nil {
t.Errorf("Unable to bootstrap KMS key. Cannot create new CryptoKey: %s", err)
}
} else {
t.Errorf("Unable to bootstrap KMS key. Cannot call CryptoKey service: %s", err)
}
}
if cryptoKey == nil {
t.Fatalf("Unable to bootstrap KMS key. CryptoKey is nil!")
}
return bootstrappedKMS{
keyRing,
cryptoKey,
}
}

View File

@ -178,6 +178,10 @@ func getTestRegionFromEnv() string {
return multiEnvSearch(regionEnvVars)
}
func getTestZoneFromEnv() string {
return multiEnvSearch(zoneEnvVars)
}
func getTestOrgFromEnv(t *testing.T) string {
skipIfEnvNotSet(t, orgEnvVars...)
return multiEnvSearch(orgEnvVars)

View File

@ -476,13 +476,7 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) {
t.Parallel()
var instanceTemplate compute.InstanceTemplate
org := getTestOrgFromEnv(t)
pid := "tf-test-" + acctest.RandString(10)
billingAccount := getTestBillingAccountFromEnv(t)
diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
kms := BootstrapKMSKey(t)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -490,7 +484,7 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) {
CheckDestroy: testAccCheckComputeInstanceTemplateDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_encryptionKMS(pid, pname, org, billingAccount, diskName, keyRingName, keyName),
Config: testAccComputeInstanceTemplate_encryptionKMS(kms.CryptoKey.Name),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists("google_compute_instance_template.foobar", &instanceTemplate),
),
@ -1186,7 +1180,7 @@ func testAccComputeInstanceTemplate_subnet_xpn(org, billingId, projectName strin
resource "google_compute_shared_vpc_host_project" "host_project" {
project = "${google_project_service.host_project.project}"
}
resource "google_project" "service_project" {
name = "Test Project XPN Service"
project_id = "%s-service"
@ -1347,7 +1341,7 @@ resource "google_compute_instance_template" "foobar" {
// Note that unlike compute instances, instance templates seem to be
// only able to specify the netmask here. Trying a full CIDR string
// results in:
// results in:
// Invalid value for field 'resource.properties.networkInterfaces[0].aliasIpRanges[0].ipCidrRange':
// '172.16.0.0/24'. Alias IP CIDR range must be a valid netmask starting with '/' (e.g. '/24')
alias_ip_range {
@ -1423,64 +1417,13 @@ resource "google_compute_instance_template" "foobar" {
}`, i, DEFAULT_MIN_CPU_TEST_VALUE)
}
func testAccComputeInstanceTemplate_encryptionKMS(pid, pname, org, billing, diskName, keyRingName, keyName string) string {
func testAccComputeInstanceTemplate_encryptionKMS(kmsLink string) string {
return fmt.Sprintf(`
resource "google_project" "project" {
project_id = "%s"
name = "%s"
org_id = "%s"
billing_account = "%s"
}
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}
resource "google_project_services" "apis" {
project = "${google_project.project.project_id}"
services = [
"oslogin.googleapis.com",
"compute.googleapis.com",
"cloudkms.googleapis.com",
"appengine.googleapis.com",
]
}
resource "google_project_iam_member" "kms-project-binding" {
project = "${google_project.project.project_id}"
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${google_project.project.number}@compute-system.iam.gserviceaccount.com"
depends_on = ["google_project_services.apis"]
}
resource "google_kms_crypto_key_iam_binding" "kms-key-binding" {
crypto_key_id = "${google_kms_crypto_key.my_crypto_key.self_link}"
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
members = [
"serviceAccount:service-${google_project.project.number}@compute-system.iam.gserviceaccount.com",
]
depends_on = ["google_project_services.apis"]
}
resource "google_kms_key_ring" "my_key_ring" {
name = "%s"
project = "${google_project.project.project_id}"
location = "us-central1"
depends_on = ["google_project_services.apis"]
}
resource "google_kms_crypto_key" "my_crypto_key" {
name = "%s"
key_ring = "${google_kms_key_ring.my_key_ring.self_link}"
}
resource "google_compute_instance_template" "foobar" {
name = "instancet-test-%s"
machine_type = "n1-standard-1"
@ -1489,8 +1432,8 @@ resource "google_compute_instance_template" "foobar" {
disk {
source_image = "${data.google_compute_image.my_image.self_link}"
disk_encryption_key {
kms_key_self_link = "${google_kms_crypto_key.my_crypto_key.self_link}"
}
kms_key_self_link = "%s"
}
}
network_interface {
@ -1504,5 +1447,5 @@ resource "google_compute_instance_template" "foobar" {
labels = {
my_label = "foobar"
}
}`, pid, pname, org, billing, keyRingName, keyName, acctest.RandString(10))
}`, acctest.RandString(10), kmsLink)
}