terraform-provider-google/google/resource_google_project_services_test.go
The Magician 0310ea2f75 add other side effect services to project_services test (#3653)
Signed-off-by: Modular Magician <magic-modules@google.com>
2019-05-17 12:56:52 -07:00

332 lines
9.9 KiB
Go

package google
import (
"bytes"
"fmt"
"log"
"reflect"
"sort"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
// Test that services can be enabled and disabled on a project
func TestAccProjectServices_basic(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
services1 := []string{"logging.googleapis.com", "cloudresourcemanager.googleapis.com"}
services2 := []string{"cloudresourcemanager.googleapis.com"}
oobService := "logging.googleapis.com"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new project with some services
{
Config: testAccProjectAssociateServicesBasic(services1, pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services1, pid),
),
},
// Update services to remove one
{
Config: testAccProjectAssociateServicesBasic(services2, pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services2, pid),
),
},
// Add a service out-of-band and ensure it is removed
{
PreConfig: func() {
config := testAccProvider.Meta().(*Config)
if err := enableService(oobService, pid, config); err != nil {
t.Fatalf("Error enabling %q: %v", oobService, err)
}
},
Config: testAccProjectAssociateServicesBasic(services2, pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services2, pid),
),
},
{
ResourceName: "google_project_services.acceptance",
ImportState: true,
ImportStateId: pid,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"disable_on_destroy"},
},
},
})
}
// Test that services are authoritative when a project has existing
// sevices not represented in config
func TestAccProjectServices_authoritative(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
services := []string{"cloudresourcemanager.googleapis.com"}
oobService := "logging.googleapis.com"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new project with no services
{
Config: testAccProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectExists("google_project.acceptance", pid),
),
},
// Add a service out-of-band, then apply a config that creates a service.
// It should remove the out-of-band service.
{
PreConfig: func() {
config := testAccProvider.Meta().(*Config)
if err := enableService(oobService, pid, config); err != nil {
t.Fatalf("Error enabling %q: %v", oobService, err)
}
},
Config: testAccProjectAssociateServicesBasic(services, pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services, pid),
),
},
},
})
}
// Test that services are authoritative when a project has existing
// sevices, some which are represented in the config and others
// that are not
func TestAccProjectServices_authoritative2(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
oobServices := []string{"logging.googleapis.com", "cloudresourcemanager.googleapis.com"}
services := []string{"logging.googleapis.com"}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new project with no services
{
Config: testAccProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectExists("google_project.acceptance", pid),
),
},
// Add a service out-of-band, then apply a config that creates a service.
// It should remove the out-of-band service.
{
PreConfig: func() {
config := testAccProvider.Meta().(*Config)
for _, s := range oobServices {
if err := enableService(s, pid, config); err != nil {
t.Fatalf("Error enabling %q: %v", s, err)
}
}
},
Config: testAccProjectAssociateServicesBasic(services, pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services, pid),
),
},
},
})
}
// Test that services that can't be enabled on their own (such as dataproc-control.googleapis.com)
// don't end up causing diffs when they are enabled as a side-effect of a different service's
// enablement.
func TestAccProjectServices_ignoreUnenablableServices(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
billingId := getTestBillingAccountFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
services := []string{
"dataproc.googleapis.com",
// The following services are enabled as a side-effect of dataproc's enablement
"storage-component.googleapis.com",
"deploymentmanager.googleapis.com",
"replicapool.googleapis.com",
"replicapoolupdater.googleapis.com",
"resourceviews.googleapis.com",
"compute.googleapis.com",
"container.googleapis.com",
"containerregistry.googleapis.com",
"storage-api.googleapis.com",
"pubsub.googleapis.com",
"oslogin.googleapis.com",
"bigquery-json.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccProjectAssociateServicesBasic_withBilling(services, pid, pname, org, billingId),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services, pid),
),
},
},
})
}
func TestAccProjectServices_pagination(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
billingId := getTestBillingAccountFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
// we need at least 50 services (doesn't matter what they are) to exercise the
// pagination handling code.
services := []string{
"actions.googleapis.com",
"appengine.googleapis.com",
"appengineflex.googleapis.com",
"bigquery-json.googleapis.com",
"bigquerydatatransfer.googleapis.com",
"bigtableadmin.googleapis.com",
"bigtabletableadmin.googleapis.com",
"cloudbuild.googleapis.com",
"clouderrorreporting.googleapis.com",
"cloudfunctions.googleapis.com",
"cloudiot.googleapis.com",
"cloudkms.googleapis.com",
"cloudmonitoring.googleapis.com",
"cloudresourcemanager.googleapis.com",
"cloudtrace.googleapis.com",
"compute.googleapis.com",
"container.googleapis.com",
"containerregistry.googleapis.com",
"dataflow.googleapis.com",
"dataproc.googleapis.com",
"datastore.googleapis.com",
"deploymentmanager.googleapis.com",
"dialogflow.googleapis.com",
"dns.googleapis.com",
"endpoints.googleapis.com",
"firebaserules.googleapis.com",
"firestore.googleapis.com",
"genomics.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
"language.googleapis.com",
"logging.googleapis.com",
"ml.googleapis.com",
"monitoring.googleapis.com",
"oslogin.googleapis.com",
"pubsub.googleapis.com",
"replicapool.googleapis.com",
"replicapoolupdater.googleapis.com",
"resourceviews.googleapis.com",
"runtimeconfig.googleapis.com",
"servicecontrol.googleapis.com",
"servicemanagement.googleapis.com",
"sourcerepo.googleapis.com",
"spanner.googleapis.com",
"speech.googleapis.com",
"sql-component.googleapis.com",
"storage-api.googleapis.com",
"storage-component.googleapis.com",
"storagetransfer.googleapis.com",
"testing.googleapis.com",
"toolresults.googleapis.com",
"translate.googleapis.com",
"videointelligence.googleapis.com",
"vision.googleapis.com",
"zync.googleapis.com",
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccProjectAssociateServicesBasic_withBilling(services, pid, pname, org, billingId),
Check: resource.ComposeTestCheckFunc(
testProjectServicesMatch(services, pid),
),
},
},
})
}
func testAccProjectAssociateServicesBasic(services []string, pid, name, org string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
}
resource "google_project_services" "acceptance" {
project = "${google_project.acceptance.project_id}"
services = [%s]
disable_on_destroy = true
}
`, pid, name, org, testStringsToString(services))
}
func testAccProjectAssociateServicesBasic_withBilling(services []string, pid, name, org, billing string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
billing_account = "%s"
}
resource "google_project_services" "acceptance" {
project = "${google_project.acceptance.project_id}"
services = [%s]
disable_on_destroy = false
}
`, pid, name, org, billing, testStringsToString(services))
}
func testProjectServicesMatch(services []string, pid string) resource.TestCheckFunc {
return func(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
apiServices, err := getApiServices(pid, config, ignoreProjectServices)
if err != nil {
return fmt.Errorf("Error listing services for project %q: %v", pid, err)
}
sort.Strings(services)
sort.Strings(apiServices)
if !reflect.DeepEqual(services, apiServices) {
return fmt.Errorf("Services in config (%v) do not exactly match services returned by API (%v)", services, apiServices)
}
return nil
}
}
func testStringsToString(s []string) string {
var b bytes.Buffer
for i, v := range s {
b.WriteString(fmt.Sprintf("\"%s\"", v))
if i < len(s)-1 {
b.WriteString(",")
}
}
r := b.String()
log.Printf("[DEBUG]: Converted list of strings to %s", r)
return b.String()
}