github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/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 "containerregistry.googleapis.com", 151 "storage-api.googleapis.com", 152 "pubsub.googleapis.com", 153 } 154 155 resource.Test(t, resource.TestCase{ 156 PreCheck: func() { testAccPreCheck(t) }, 157 Providers: testAccProviders, 158 Steps: []resource.TestStep{ 159 resource.TestStep{ 160 Config: testAccGoogleProjectAssociateServicesBasic_withBilling(services, pid, pname, org, billingId), 161 Check: resource.ComposeTestCheckFunc( 162 testProjectServicesMatch(services, pid), 163 ), 164 }, 165 }, 166 }) 167 } 168 169 func TestAccGoogleProjectServices_manyServices(t *testing.T) { 170 skipIfEnvNotSet(t, 171 []string{ 172 "GOOGLE_ORG", 173 "GOOGLE_BILLING_ACCOUNT", 174 }..., 175 ) 176 177 billingId := os.Getenv("GOOGLE_BILLING_ACCOUNT") 178 pid := "terraform-" + acctest.RandString(10) 179 services := []string{ 180 "bigquery-json.googleapis.com", 181 "cloudbuild.googleapis.com", 182 "cloudfunctions.googleapis.com", 183 "cloudresourcemanager.googleapis.com", 184 "cloudtrace.googleapis.com", 185 "compute-component.googleapis.com", 186 "container.googleapis.com", 187 "containerregistry.googleapis.com", 188 "dataflow.googleapis.com", 189 "dataproc.googleapis.com", 190 "deploymentmanager.googleapis.com", 191 "dns.googleapis.com", 192 "endpoints.googleapis.com", 193 "iam.googleapis.com", 194 "logging.googleapis.com", 195 "ml.googleapis.com", 196 "monitoring.googleapis.com", 197 "pubsub.googleapis.com", 198 "replicapool.googleapis.com", 199 "replicapoolupdater.googleapis.com", 200 "resourceviews.googleapis.com", 201 "runtimeconfig.googleapis.com", 202 "servicecontrol.googleapis.com", 203 "servicemanagement.googleapis.com", 204 "sourcerepo.googleapis.com", 205 "spanner.googleapis.com", 206 "storage-api.googleapis.com", 207 "storage-component.googleapis.com", 208 } 209 210 resource.Test(t, resource.TestCase{ 211 PreCheck: func() { testAccPreCheck(t) }, 212 Providers: testAccProviders, 213 Steps: []resource.TestStep{ 214 resource.TestStep{ 215 Config: testAccGoogleProjectAssociateServicesBasic_withBilling(services, pid, pname, org, billingId), 216 Check: resource.ComposeTestCheckFunc( 217 testProjectServicesMatch(services, pid), 218 ), 219 }, 220 }, 221 }) 222 } 223 224 func testAccGoogleProjectAssociateServicesBasic(services []string, pid, name, org string) string { 225 return fmt.Sprintf(` 226 resource "google_project" "acceptance" { 227 project_id = "%s" 228 name = "%s" 229 org_id = "%s" 230 } 231 resource "google_project_services" "acceptance" { 232 project = "${google_project.acceptance.project_id}" 233 services = [%s] 234 } 235 `, pid, name, org, testStringsToString(services)) 236 } 237 238 func testAccGoogleProjectAssociateServicesBasic_withBilling(services []string, pid, name, org, billing string) string { 239 return fmt.Sprintf(` 240 resource "google_project" "acceptance" { 241 project_id = "%s" 242 name = "%s" 243 org_id = "%s" 244 billing_account = "%s" 245 } 246 resource "google_project_services" "acceptance" { 247 project = "${google_project.acceptance.project_id}" 248 services = [%s] 249 } 250 `, pid, name, org, billing, testStringsToString(services)) 251 } 252 253 func testProjectServicesMatch(services []string, pid string) resource.TestCheckFunc { 254 return func(s *terraform.State) error { 255 config := testAccProvider.Meta().(*Config) 256 257 apiServices, err := getApiServices(pid, config) 258 if err != nil { 259 return fmt.Errorf("Error listing services for project %q: %v", pid, err) 260 } 261 262 sort.Strings(services) 263 sort.Strings(apiServices) 264 if !reflect.DeepEqual(services, apiServices) { 265 return fmt.Errorf("Services in config (%v) do not exactly match services returned by API (%v)", services, apiServices) 266 } 267 268 return nil 269 } 270 } 271 272 func testStringsToString(s []string) string { 273 var b bytes.Buffer 274 for i, v := range s { 275 b.WriteString(fmt.Sprintf("\"%s\"", v)) 276 if i < len(s)-1 { 277 b.WriteString(",") 278 } 279 } 280 r := b.String() 281 log.Printf("[DEBUG]: Converted list of strings to %s", r) 282 return b.String() 283 } 284 285 func testManagedServicesToString(svcs []*servicemanagement.ManagedService) string { 286 var b bytes.Buffer 287 for _, s := range svcs { 288 b.WriteString(s.ServiceName) 289 } 290 return b.String() 291 }