github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/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 testAccGoogleProjectAssociateServicesBasic(services []string, pid, name, org string) string { 168 return fmt.Sprintf(` 169 resource "google_project" "acceptance" { 170 project_id = "%s" 171 name = "%s" 172 org_id = "%s" 173 } 174 resource "google_project_services" "acceptance" { 175 project = "${google_project.acceptance.project_id}" 176 services = [%s] 177 } 178 `, pid, name, org, testStringsToString(services)) 179 } 180 181 func testAccGoogleProjectAssociateServicesBasic_withBilling(services []string, pid, name, org, billing string) string { 182 return fmt.Sprintf(` 183 resource "google_project" "acceptance" { 184 project_id = "%s" 185 name = "%s" 186 org_id = "%s" 187 billing_account = "%s" 188 } 189 resource "google_project_services" "acceptance" { 190 project = "${google_project.acceptance.project_id}" 191 services = [%s] 192 } 193 `, pid, name, org, billing, testStringsToString(services)) 194 } 195 196 func testProjectServicesMatch(services []string, pid string) resource.TestCheckFunc { 197 return func(s *terraform.State) error { 198 config := testAccProvider.Meta().(*Config) 199 200 apiServices, err := getApiServices(pid, config) 201 if err != nil { 202 return fmt.Errorf("Error listing services for project %q: %v", pid, err) 203 } 204 205 sort.Strings(services) 206 sort.Strings(apiServices) 207 if !reflect.DeepEqual(services, apiServices) { 208 return fmt.Errorf("Services in config (%v) do not exactly match services returned by API (%v)", services, apiServices) 209 } 210 211 return nil 212 } 213 } 214 215 func testStringsToString(s []string) string { 216 var b bytes.Buffer 217 for i, v := range s { 218 b.WriteString(fmt.Sprintf("\"%s\"", v)) 219 if i < len(s)-1 { 220 b.WriteString(",") 221 } 222 } 223 r := b.String() 224 log.Printf("[DEBUG]: Converted list of strings to %s", r) 225 return b.String() 226 } 227 228 func testManagedServicesToString(svcs []*servicemanagement.ManagedService) string { 229 var b bytes.Buffer 230 for _, s := range svcs { 231 b.WriteString(s.ServiceName) 232 } 233 return b.String() 234 }