github.com/andrewrynhard/terraform@v0.9.5-0.20170502003928-8d286b83eae4/builtin/providers/google/resource_google_project_services_test.go (about) 1 package google 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "os" 8 "reflect" 9 "sort" 10 "testing" 11 12 "github.com/hashicorp/terraform/helper/acctest" 13 "github.com/hashicorp/terraform/helper/resource" 14 "github.com/hashicorp/terraform/terraform" 15 "google.golang.org/api/servicemanagement/v1" 16 ) 17 18 // Test that services can be enabled and disabled on a project 19 func TestAccGoogleProjectServices_basic(t *testing.T) { 20 pid := "terraform-" + acctest.RandString(10) 21 services1 := []string{"iam.googleapis.com", "cloudresourcemanager.googleapis.com"} 22 services2 := []string{"cloudresourcemanager.googleapis.com"} 23 oobService := "iam.googleapis.com" 24 resource.Test(t, resource.TestCase{ 25 PreCheck: func() { testAccPreCheck(t) }, 26 Providers: testAccProviders, 27 Steps: []resource.TestStep{ 28 // Create a new project with some services 29 resource.TestStep{ 30 Config: testAccGoogleProjectAssociateServicesBasic(services1, pid, pname, org), 31 Check: resource.ComposeTestCheckFunc( 32 testProjectServicesMatch(services1, pid), 33 ), 34 }, 35 // Update services to remove one 36 resource.TestStep{ 37 Config: testAccGoogleProjectAssociateServicesBasic(services2, pid, pname, org), 38 Check: resource.ComposeTestCheckFunc( 39 testProjectServicesMatch(services2, pid), 40 ), 41 }, 42 // Add a service out-of-band and ensure it is removed 43 resource.TestStep{ 44 PreConfig: func() { 45 config := testAccProvider.Meta().(*Config) 46 enableService(oobService, pid, config) 47 }, 48 Config: testAccGoogleProjectAssociateServicesBasic(services2, pid, pname, org), 49 Check: resource.ComposeTestCheckFunc( 50 testProjectServicesMatch(services2, pid), 51 ), 52 }, 53 }, 54 }) 55 } 56 57 // Test that services are authoritative when a project has existing 58 // sevices not represented in config 59 func TestAccGoogleProjectServices_authoritative(t *testing.T) { 60 pid := "terraform-" + acctest.RandString(10) 61 services := []string{"cloudresourcemanager.googleapis.com"} 62 oobService := "iam.googleapis.com" 63 resource.Test(t, resource.TestCase{ 64 PreCheck: func() { testAccPreCheck(t) }, 65 Providers: testAccProviders, 66 Steps: []resource.TestStep{ 67 // Create a new project with no services 68 resource.TestStep{ 69 Config: testAccGoogleProject_create(pid, pname, org), 70 Check: resource.ComposeTestCheckFunc( 71 testAccCheckGoogleProjectExists("google_project.acceptance", pid), 72 ), 73 }, 74 // Add a service out-of-band, then apply a config that creates a service. 75 // It should remove the out-of-band service. 76 resource.TestStep{ 77 PreConfig: func() { 78 config := testAccProvider.Meta().(*Config) 79 enableService(oobService, pid, config) 80 }, 81 Config: testAccGoogleProjectAssociateServicesBasic(services, pid, pname, org), 82 Check: resource.ComposeTestCheckFunc( 83 testProjectServicesMatch(services, pid), 84 ), 85 }, 86 }, 87 }) 88 } 89 90 // Test that services are authoritative when a project has existing 91 // sevices, some which are represented in the config and others 92 // that are not 93 func TestAccGoogleProjectServices_authoritative2(t *testing.T) { 94 pid := "terraform-" + acctest.RandString(10) 95 oobServices := []string{"iam.googleapis.com", "cloudresourcemanager.googleapis.com"} 96 services := []string{"iam.googleapis.com"} 97 98 resource.Test(t, resource.TestCase{ 99 PreCheck: func() { testAccPreCheck(t) }, 100 Providers: testAccProviders, 101 Steps: []resource.TestStep{ 102 // Create a new project with no services 103 resource.TestStep{ 104 Config: testAccGoogleProject_create(pid, pname, org), 105 Check: resource.ComposeTestCheckFunc( 106 testAccCheckGoogleProjectExists("google_project.acceptance", pid), 107 ), 108 }, 109 // Add a service out-of-band, then apply a config that creates a service. 110 // It should remove the out-of-band service. 111 resource.TestStep{ 112 PreConfig: func() { 113 config := testAccProvider.Meta().(*Config) 114 for _, s := range oobServices { 115 enableService(s, pid, config) 116 } 117 }, 118 Config: testAccGoogleProjectAssociateServicesBasic(services, pid, pname, org), 119 Check: resource.ComposeTestCheckFunc( 120 testProjectServicesMatch(services, pid), 121 ), 122 }, 123 }, 124 }) 125 } 126 127 // Test that services that can't be enabled on their own (such as dataproc-control.googleapis.com) 128 // don't end up causing diffs when they are enabled as a side-effect of a different service's 129 // enablement. 130 func TestAccGoogleProjectServices_ignoreUnenablableServices(t *testing.T) { 131 skipIfEnvNotSet(t, 132 []string{ 133 "GOOGLE_ORG", 134 "GOOGLE_BILLING_ACCOUNT", 135 }..., 136 ) 137 138 billingId := os.Getenv("GOOGLE_BILLING_ACCOUNT") 139 pid := "terraform-" + acctest.RandString(10) 140 services := []string{ 141 "dataproc.googleapis.com", 142 // The following services are enabled as a side-effect of dataproc's enablement 143 "storage-component.googleapis.com", 144 "deploymentmanager.googleapis.com", 145 "replicapool.googleapis.com", 146 "replicapoolupdater.googleapis.com", 147 "resourceviews.googleapis.com", 148 "compute-component.googleapis.com", 149 "container.googleapis.com", 150 "storage-api.googleapis.com", 151 } 152 153 resource.Test(t, resource.TestCase{ 154 PreCheck: func() { testAccPreCheck(t) }, 155 Providers: testAccProviders, 156 Steps: []resource.TestStep{ 157 resource.TestStep{ 158 Config: testAccGoogleProjectAssociateServicesBasic_withBilling(services, pid, pname, org, billingId), 159 Check: resource.ComposeTestCheckFunc( 160 testProjectServicesMatch(services, pid), 161 ), 162 }, 163 }, 164 }) 165 } 166 167 func TestAccGoogleProjectServices_manyServices(t *testing.T) { 168 skipIfEnvNotSet(t, 169 []string{ 170 "GOOGLE_ORG", 171 "GOOGLE_BILLING_ACCOUNT", 172 }..., 173 ) 174 175 billingId := os.Getenv("GOOGLE_BILLING_ACCOUNT") 176 pid := "terraform-" + acctest.RandString(10) 177 services := []string{ 178 "bigquery-json.googleapis.com", 179 "cloudbuild.googleapis.com", 180 "cloudfunctions.googleapis.com", 181 "cloudresourcemanager.googleapis.com", 182 "cloudtrace.googleapis.com", 183 "compute-component.googleapis.com", 184 "container.googleapis.com", 185 "containerregistry.googleapis.com", 186 "dataflow.googleapis.com", 187 "dataproc.googleapis.com", 188 "deploymentmanager.googleapis.com", 189 "dns.googleapis.com", 190 "endpoints.googleapis.com", 191 "iam.googleapis.com", 192 "logging.googleapis.com", 193 "ml.googleapis.com", 194 "monitoring.googleapis.com", 195 "pubsub.googleapis.com", 196 "replicapool.googleapis.com", 197 "replicapoolupdater.googleapis.com", 198 "resourceviews.googleapis.com", 199 "runtimeconfig.googleapis.com", 200 "servicecontrol.googleapis.com", 201 "servicemanagement.googleapis.com", 202 "sourcerepo.googleapis.com", 203 "spanner.googleapis.com", 204 "storage-api.googleapis.com", 205 "storage-component.googleapis.com", 206 } 207 208 resource.Test(t, resource.TestCase{ 209 PreCheck: func() { testAccPreCheck(t) }, 210 Providers: testAccProviders, 211 Steps: []resource.TestStep{ 212 resource.TestStep{ 213 Config: testAccGoogleProjectAssociateServicesBasic_withBilling(services, pid, pname, org, billingId), 214 Check: resource.ComposeTestCheckFunc( 215 testProjectServicesMatch(services, pid), 216 ), 217 }, 218 }, 219 }) 220 } 221 222 func testAccGoogleProjectAssociateServicesBasic(services []string, pid, name, org string) string { 223 return fmt.Sprintf(` 224 resource "google_project" "acceptance" { 225 project_id = "%s" 226 name = "%s" 227 org_id = "%s" 228 } 229 resource "google_project_services" "acceptance" { 230 project = "${google_project.acceptance.project_id}" 231 services = [%s] 232 } 233 `, pid, name, org, testStringsToString(services)) 234 } 235 236 func testAccGoogleProjectAssociateServicesBasic_withBilling(services []string, pid, name, org, billing string) string { 237 return fmt.Sprintf(` 238 resource "google_project" "acceptance" { 239 project_id = "%s" 240 name = "%s" 241 org_id = "%s" 242 billing_account = "%s" 243 } 244 resource "google_project_services" "acceptance" { 245 project = "${google_project.acceptance.project_id}" 246 services = [%s] 247 } 248 `, pid, name, org, billing, testStringsToString(services)) 249 } 250 251 func testProjectServicesMatch(services []string, pid string) resource.TestCheckFunc { 252 return func(s *terraform.State) error { 253 config := testAccProvider.Meta().(*Config) 254 255 apiServices, err := getApiServices(pid, config) 256 if err != nil { 257 return fmt.Errorf("Error listing services for project %q: %v", pid, err) 258 } 259 260 sort.Strings(services) 261 sort.Strings(apiServices) 262 if !reflect.DeepEqual(services, apiServices) { 263 return fmt.Errorf("Services in config (%v) do not exactly match services returned by API (%v)", services, apiServices) 264 } 265 266 return nil 267 } 268 } 269 270 func testStringsToString(s []string) string { 271 var b bytes.Buffer 272 for i, v := range s { 273 b.WriteString(fmt.Sprintf("\"%s\"", v)) 274 if i < len(s)-1 { 275 b.WriteString(",") 276 } 277 } 278 r := b.String() 279 log.Printf("[DEBUG]: Converted list of strings to %s", r) 280 return b.String() 281 } 282 283 func testManagedServicesToString(svcs []*servicemanagement.ManagedService) string { 284 var b bytes.Buffer 285 for _, s := range svcs { 286 b.WriteString(s.ServiceName) 287 } 288 return b.String() 289 }