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 }