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  }