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  }