github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/google/resource_google_project_test.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/hashicorp/terraform/helper/acctest"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/terraform"
    12  	"google.golang.org/api/cloudresourcemanager/v1"
    13  )
    14  
    15  var (
    16  	org = multiEnvSearch([]string{
    17  		"GOOGLE_ORG",
    18  	})
    19  
    20  	pname          = "Terraform Acceptance Tests"
    21  	originalPolicy *cloudresourcemanager.Policy
    22  )
    23  
    24  func multiEnvSearch(ks []string) string {
    25  	for _, k := range ks {
    26  		if v := os.Getenv(k); v != "" {
    27  			return v
    28  		}
    29  	}
    30  	return ""
    31  }
    32  
    33  // Test that a Project resource can be created and an IAM policy
    34  // associated
    35  func TestAccGoogleProject_create(t *testing.T) {
    36  	pid := "terraform-" + acctest.RandString(10)
    37  	resource.Test(t, resource.TestCase{
    38  		PreCheck:  func() { testAccPreCheck(t) },
    39  		Providers: testAccProviders,
    40  		Steps: []resource.TestStep{
    41  			// This step imports an existing project
    42  			resource.TestStep{
    43  				Config: testAccGoogleProject_create(pid, pname, org),
    44  				Check: resource.ComposeTestCheckFunc(
    45  					testAccCheckGoogleProjectExists("google_project.acceptance", pid),
    46  				),
    47  			},
    48  		},
    49  	})
    50  }
    51  
    52  // Test that a Project resource can be created with an associated
    53  // billing account
    54  func TestAccGoogleProject_createBilling(t *testing.T) {
    55  	skipIfEnvNotSet(t,
    56  		[]string{
    57  			"GOOGLE_ORG",
    58  			"GOOGLE_BILLING_ACCOUNT",
    59  		}...,
    60  	)
    61  
    62  	billingId := os.Getenv("GOOGLE_BILLING_ACCOUNT")
    63  	pid := "terraform-" + acctest.RandString(10)
    64  	resource.Test(t, resource.TestCase{
    65  		PreCheck:  func() { testAccPreCheck(t) },
    66  		Providers: testAccProviders,
    67  		Steps: []resource.TestStep{
    68  			// This step creates a new project with a billing account
    69  			resource.TestStep{
    70  				Config: testAccGoogleProject_createBilling(pid, pname, org, billingId),
    71  				Check: resource.ComposeTestCheckFunc(
    72  					testAccCheckGoogleProjectHasBillingAccount("google_project.acceptance", pid, billingId),
    73  				),
    74  			},
    75  		},
    76  	})
    77  }
    78  
    79  // Test that a Project resource can be created and updated
    80  // with billing account information
    81  func TestAccGoogleProject_updateBilling(t *testing.T) {
    82  	skipIfEnvNotSet(t,
    83  		[]string{
    84  			"GOOGLE_ORG",
    85  			"GOOGLE_BILLING_ACCOUNT",
    86  			"GOOGLE_BILLING_ACCOUNT_2",
    87  		}...,
    88  	)
    89  
    90  	billingId := os.Getenv("GOOGLE_BILLING_ACCOUNT")
    91  	billingId2 := os.Getenv("GOOGLE_BILLING_ACCOUNT_2")
    92  	pid := "terraform-" + acctest.RandString(10)
    93  	resource.Test(t, resource.TestCase{
    94  		PreCheck:  func() { testAccPreCheck(t) },
    95  		Providers: testAccProviders,
    96  		Steps: []resource.TestStep{
    97  			// This step creates a new project without a billing account
    98  			resource.TestStep{
    99  				Config: testAccGoogleProject_create(pid, pname, org),
   100  				Check: resource.ComposeTestCheckFunc(
   101  					testAccCheckGoogleProjectExists("google_project.acceptance", pid),
   102  				),
   103  			},
   104  			// Update to include a billing account
   105  			resource.TestStep{
   106  				Config: testAccGoogleProject_createBilling(pid, pname, org, billingId),
   107  				Check: resource.ComposeTestCheckFunc(
   108  					testAccCheckGoogleProjectHasBillingAccount("google_project.acceptance", pid, billingId),
   109  				),
   110  			},
   111  			// Update to a different  billing account
   112  			resource.TestStep{
   113  				Config: testAccGoogleProject_createBilling(pid, pname, org, billingId2),
   114  				Check: resource.ComposeTestCheckFunc(
   115  					testAccCheckGoogleProjectHasBillingAccount("google_project.acceptance", pid, billingId2),
   116  				),
   117  			},
   118  		},
   119  	})
   120  }
   121  
   122  // Test that a Project resource merges the IAM policies that already
   123  // exist, and won't lock people out.
   124  func TestAccGoogleProject_merge(t *testing.T) {
   125  	pid := "terraform-" + acctest.RandString(10)
   126  	resource.Test(t, resource.TestCase{
   127  		PreCheck:  func() { testAccPreCheck(t) },
   128  		Providers: testAccProviders,
   129  		Steps: []resource.TestStep{
   130  			// when policy_data is set, merge
   131  			{
   132  				Config: testAccGoogleProject_toMerge(pid, pname, org),
   133  				Check: resource.ComposeTestCheckFunc(
   134  					testAccCheckGoogleProjectExists("google_project.acceptance", pid),
   135  					testAccCheckGoogleProjectHasMoreBindingsThan(pid, 1),
   136  				),
   137  			},
   138  			// when policy_data is unset, restore to what it was
   139  			{
   140  				Config: testAccGoogleProject_mergeEmpty(pid, pname, org),
   141  				Check: resource.ComposeTestCheckFunc(
   142  					testAccCheckGoogleProjectExists("google_project.acceptance", pid),
   143  					testAccCheckGoogleProjectHasMoreBindingsThan(pid, 0),
   144  				),
   145  			},
   146  		},
   147  	})
   148  }
   149  
   150  func testAccCheckGoogleProjectExists(r, pid string) resource.TestCheckFunc {
   151  	return func(s *terraform.State) error {
   152  		rs, ok := s.RootModule().Resources[r]
   153  		if !ok {
   154  			return fmt.Errorf("Not found: %s", r)
   155  		}
   156  
   157  		if rs.Primary.ID == "" {
   158  			return fmt.Errorf("No ID is set")
   159  		}
   160  
   161  		if rs.Primary.ID != pid {
   162  			return fmt.Errorf("Expected project %q to match ID %q in state", pid, rs.Primary.ID)
   163  		}
   164  
   165  		return nil
   166  	}
   167  }
   168  
   169  func testAccCheckGoogleProjectHasBillingAccount(r, pid, billingId string) resource.TestCheckFunc {
   170  	return func(s *terraform.State) error {
   171  		rs, ok := s.RootModule().Resources[r]
   172  		if !ok {
   173  			return fmt.Errorf("Not found: %s", r)
   174  		}
   175  
   176  		// State should match expected
   177  		if rs.Primary.Attributes["billing_account"] != billingId {
   178  			return fmt.Errorf("Billing ID in state (%s) does not match expected value (%s)", rs.Primary.Attributes["billing_account"], billingId)
   179  		}
   180  
   181  		// Actual value in API should match state and expected
   182  		// Read the billing account
   183  		config := testAccProvider.Meta().(*Config)
   184  		ba, err := config.clientBilling.Projects.GetBillingInfo(prefixedProject(pid)).Do()
   185  		if err != nil {
   186  			return fmt.Errorf("Error reading billing account for project %q: %v", prefixedProject(pid), err)
   187  		}
   188  		if billingId != strings.TrimPrefix(ba.BillingAccountName, "billingAccounts/") {
   189  			return fmt.Errorf("Billing ID returned by API (%s) did not match expected value (%s)", ba.BillingAccountName, billingId)
   190  		}
   191  		return nil
   192  	}
   193  }
   194  
   195  func testAccCheckGoogleProjectHasMoreBindingsThan(pid string, count int) resource.TestCheckFunc {
   196  	return func(s *terraform.State) error {
   197  		policy, err := getProjectIamPolicy(pid, testAccProvider.Meta().(*Config))
   198  		if err != nil {
   199  			return err
   200  		}
   201  		if len(policy.Bindings) <= count {
   202  			return fmt.Errorf("Expected more than %d bindings, got %d: %#v", count, len(policy.Bindings), policy.Bindings)
   203  		}
   204  		return nil
   205  	}
   206  }
   207  
   208  func testAccGoogleProjectImportExisting(pid string) string {
   209  	return fmt.Sprintf(`
   210  resource "google_project" "acceptance" {
   211      project_id = "%s"
   212  
   213  }
   214  `, pid)
   215  }
   216  
   217  func testAccGoogleProjectImportExistingWithIam(pid string) string {
   218  	return fmt.Sprintf(`
   219  resource "google_project" "acceptance" {
   220      project_id = "%v"
   221      policy_data = "${data.google_iam_policy.admin.policy_data}"
   222  }
   223  data "google_iam_policy" "admin" {
   224    binding {
   225      role = "roles/storage.objectViewer"
   226      members = [
   227        "user:evanbrown@google.com",
   228      ]
   229    }
   230    binding {
   231      role = "roles/compute.instanceAdmin"
   232      members = [
   233        "user:evanbrown@google.com",
   234        "user:evandbrown@gmail.com",
   235      ]
   236    }
   237  }`, pid)
   238  }
   239  
   240  func testAccGoogleProject_toMerge(pid, name, org string) string {
   241  	return fmt.Sprintf(`
   242  resource "google_project" "acceptance" {
   243      project_id = "%s"
   244      name = "%s"
   245      org_id = "%s"
   246      policy_data = "${data.google_iam_policy.acceptance.policy_data}"
   247  }
   248  
   249  data "google_iam_policy" "acceptance" {
   250      binding {
   251          role = "roles/storage.objectViewer"
   252  	members = [
   253  	  "user:evanbrown@google.com",
   254  	]
   255      }
   256  }`, pid, name, org)
   257  }
   258  
   259  func testAccGoogleProject_mergeEmpty(pid, name, org string) string {
   260  	return fmt.Sprintf(`
   261  resource "google_project" "acceptance" {
   262      project_id = "%s"
   263      name = "%s"
   264      org_id = "%s"
   265  }`, pid, name, org)
   266  }
   267  
   268  func skipIfEnvNotSet(t *testing.T, envs ...string) {
   269  	for _, k := range envs {
   270  		if os.Getenv(k) == "" {
   271  			t.Skipf("Environment variable %s is not set", k)
   272  		}
   273  	}
   274  }