github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/google/resource_container_cluster_test.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"strconv"
     8  
     9  	"github.com/hashicorp/terraform/helper/acctest"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/terraform"
    12  )
    13  
    14  func TestAccContainerCluster_basic(t *testing.T) {
    15  	resource.Test(t, resource.TestCase{
    16  		PreCheck:     func() { testAccPreCheck(t) },
    17  		Providers:    testAccProviders,
    18  		CheckDestroy: testAccCheckContainerClusterDestroy,
    19  		Steps: []resource.TestStep{
    20  			resource.TestStep{
    21  				Config: testAccContainerCluster_basic,
    22  				Check: resource.ComposeTestCheckFunc(
    23  					testAccCheckContainerCluster(
    24  						"google_container_cluster.primary"),
    25  				),
    26  			},
    27  		},
    28  	})
    29  }
    30  
    31  func TestAccContainerCluster_withAdditionalZones(t *testing.T) {
    32  	resource.Test(t, resource.TestCase{
    33  		PreCheck:     func() { testAccPreCheck(t) },
    34  		Providers:    testAccProviders,
    35  		CheckDestroy: testAccCheckContainerClusterDestroy,
    36  		Steps: []resource.TestStep{
    37  			resource.TestStep{
    38  				Config: testAccContainerCluster_withAdditionalZones,
    39  				Check: resource.ComposeTestCheckFunc(
    40  					testAccCheckContainerCluster(
    41  						"google_container_cluster.with_additional_zones"),
    42  				),
    43  			},
    44  		},
    45  	})
    46  }
    47  
    48  func TestAccContainerCluster_withVersion(t *testing.T) {
    49  	resource.Test(t, resource.TestCase{
    50  		PreCheck:     func() { testAccPreCheck(t) },
    51  		Providers:    testAccProviders,
    52  		CheckDestroy: testAccCheckContainerClusterDestroy,
    53  		Steps: []resource.TestStep{
    54  			resource.TestStep{
    55  				Config: testAccContainerCluster_withVersion,
    56  				Check: resource.ComposeTestCheckFunc(
    57  					testAccCheckContainerCluster(
    58  						"google_container_cluster.with_version"),
    59  				),
    60  			},
    61  		},
    62  	})
    63  }
    64  
    65  func TestAccContainerCluster_withNodeConfig(t *testing.T) {
    66  	resource.Test(t, resource.TestCase{
    67  		PreCheck:     func() { testAccPreCheck(t) },
    68  		Providers:    testAccProviders,
    69  		CheckDestroy: testAccCheckContainerClusterDestroy,
    70  		Steps: []resource.TestStep{
    71  			resource.TestStep{
    72  				Config: testAccContainerCluster_withNodeConfig,
    73  				Check: resource.ComposeTestCheckFunc(
    74  					testAccCheckContainerCluster(
    75  						"google_container_cluster.with_node_config"),
    76  				),
    77  			},
    78  		},
    79  	})
    80  }
    81  
    82  func TestAccContainerCluster_withNodeConfigScopeAlias(t *testing.T) {
    83  	resource.Test(t, resource.TestCase{
    84  		PreCheck:     func() { testAccPreCheck(t) },
    85  		Providers:    testAccProviders,
    86  		CheckDestroy: testAccCheckContainerClusterDestroy,
    87  		Steps: []resource.TestStep{
    88  			resource.TestStep{
    89  				Config: testAccContainerCluster_withNodeConfigScopeAlias,
    90  				Check: resource.ComposeTestCheckFunc(
    91  					testAccCheckContainerCluster(
    92  						"google_container_cluster.with_node_config_scope_alias"),
    93  				),
    94  			},
    95  		},
    96  	})
    97  }
    98  
    99  func TestAccContainerCluster_network(t *testing.T) {
   100  	resource.Test(t, resource.TestCase{
   101  		PreCheck:     func() { testAccPreCheck(t) },
   102  		Providers:    testAccProviders,
   103  		CheckDestroy: testAccCheckContainerClusterDestroy,
   104  		Steps: []resource.TestStep{
   105  			resource.TestStep{
   106  				Config: testAccContainerCluster_networkRef,
   107  				Check: resource.ComposeTestCheckFunc(
   108  					testAccCheckContainerCluster(
   109  						"google_container_cluster.with_net_ref_by_url"),
   110  					testAccCheckContainerCluster(
   111  						"google_container_cluster.with_net_ref_by_name"),
   112  				),
   113  			},
   114  		},
   115  	})
   116  }
   117  
   118  func TestAccContainerCluster_backend(t *testing.T) {
   119  	resource.Test(t, resource.TestCase{
   120  		PreCheck:     func() { testAccPreCheck(t) },
   121  		Providers:    testAccProviders,
   122  		CheckDestroy: testAccCheckContainerClusterDestroy,
   123  		Steps: []resource.TestStep{
   124  			resource.TestStep{
   125  				Config: testAccContainerCluster_backendRef,
   126  				Check: resource.ComposeTestCheckFunc(
   127  					testAccCheckContainerCluster(
   128  						"google_container_cluster.primary"),
   129  				),
   130  			},
   131  		},
   132  	})
   133  }
   134  
   135  func TestAccContainerCluster_withNodePoolBasic(t *testing.T) {
   136  	resource.Test(t, resource.TestCase{
   137  		PreCheck:     func() { testAccPreCheck(t) },
   138  		Providers:    testAccProviders,
   139  		CheckDestroy: testAccCheckContainerClusterDestroy,
   140  		Steps: []resource.TestStep{
   141  			resource.TestStep{
   142  				Config: testAccContainerCluster_withNodePoolBasic,
   143  				Check: resource.ComposeTestCheckFunc(
   144  					testAccCheckContainerCluster(
   145  						"google_container_cluster.with_node_pool"),
   146  				),
   147  			},
   148  		},
   149  	})
   150  }
   151  
   152  func TestAccContainerCluster_withNodePoolNamePrefix(t *testing.T) {
   153  	resource.Test(t, resource.TestCase{
   154  		PreCheck:     func() { testAccPreCheck(t) },
   155  		Providers:    testAccProviders,
   156  		CheckDestroy: testAccCheckContainerClusterDestroy,
   157  		Steps: []resource.TestStep{
   158  			resource.TestStep{
   159  				Config: testAccContainerCluster_withNodePoolNamePrefix,
   160  				Check: resource.ComposeTestCheckFunc(
   161  					testAccCheckContainerCluster(
   162  						"google_container_cluster.with_node_pool_name_prefix"),
   163  				),
   164  			},
   165  		},
   166  	})
   167  }
   168  
   169  func TestAccContainerCluster_withNodePoolMultiple(t *testing.T) {
   170  	resource.Test(t, resource.TestCase{
   171  		PreCheck:     func() { testAccPreCheck(t) },
   172  		Providers:    testAccProviders,
   173  		CheckDestroy: testAccCheckContainerClusterDestroy,
   174  		Steps: []resource.TestStep{
   175  			resource.TestStep{
   176  				Config: testAccContainerCluster_withNodePoolMultiple,
   177  				Check: resource.ComposeTestCheckFunc(
   178  					testAccCheckContainerCluster(
   179  						"google_container_cluster.with_node_pool_multiple"),
   180  				),
   181  			},
   182  		},
   183  	})
   184  }
   185  
   186  func testAccCheckContainerClusterDestroy(s *terraform.State) error {
   187  	config := testAccProvider.Meta().(*Config)
   188  
   189  	for _, rs := range s.RootModule().Resources {
   190  		if rs.Type != "google_container_cluster" {
   191  			continue
   192  		}
   193  
   194  		attributes := rs.Primary.Attributes
   195  		_, err := config.clientContainer.Projects.Zones.Clusters.Get(
   196  			config.Project, attributes["zone"], attributes["name"]).Do()
   197  		if err == nil {
   198  			return fmt.Errorf("Cluster still exists")
   199  		}
   200  	}
   201  
   202  	return nil
   203  }
   204  
   205  func testAccCheckContainerCluster(n string) resource.TestCheckFunc {
   206  	return func(s *terraform.State) error {
   207  		attributes, err := getResourceAttributes(n, s)
   208  		if err != nil {
   209  			return err
   210  		}
   211  
   212  		config := testAccProvider.Meta().(*Config)
   213  		cluster, err := config.clientContainer.Projects.Zones.Clusters.Get(
   214  			config.Project, attributes["zone"], attributes["name"]).Do()
   215  		if err != nil {
   216  			return err
   217  		}
   218  
   219  		if cluster.Name != attributes["name"] {
   220  			return fmt.Errorf("Cluster %s not found, found %s instead", attributes["name"], cluster.Name)
   221  		}
   222  
   223  		type clusterTestField struct {
   224  			tf_attr  string
   225  			gcp_attr interface{}
   226  		}
   227  
   228  		var igUrls []string
   229  		if igUrls, err = getInstanceGroupUrlsFromManagerUrls(config, cluster.InstanceGroupUrls); err != nil {
   230  			return err
   231  		}
   232  		clusterTests := []clusterTestField{
   233  			{"initial_node_count", strconv.FormatInt(cluster.InitialNodeCount, 10)},
   234  			{"master_auth.0.client_certificate", cluster.MasterAuth.ClientCertificate},
   235  			{"master_auth.0.client_key", cluster.MasterAuth.ClientKey},
   236  			{"master_auth.0.cluster_ca_certificate", cluster.MasterAuth.ClusterCaCertificate},
   237  			{"master_auth.0.password", cluster.MasterAuth.Password},
   238  			{"master_auth.0.username", cluster.MasterAuth.Username},
   239  			{"zone", cluster.Zone},
   240  			{"cluster_ipv4_cidr", cluster.ClusterIpv4Cidr},
   241  			{"description", cluster.Description},
   242  			{"endpoint", cluster.Endpoint},
   243  			{"instance_group_urls", igUrls},
   244  			{"logging_service", cluster.LoggingService},
   245  			{"monitoring_service", cluster.MonitoringService},
   246  			{"subnetwork", cluster.Subnetwork},
   247  			{"node_config.0.machine_type", cluster.NodeConfig.MachineType},
   248  			{"node_config.0.disk_size_gb", strconv.FormatInt(cluster.NodeConfig.DiskSizeGb, 10)},
   249  			{"node_config.0.local_ssd_count", strconv.FormatInt(cluster.NodeConfig.LocalSsdCount, 10)},
   250  			{"node_config.0.oauth_scopes", cluster.NodeConfig.OauthScopes},
   251  			{"node_config.0.service_account", cluster.NodeConfig.ServiceAccount},
   252  			{"node_config.0.metadata", cluster.NodeConfig.Metadata},
   253  			{"node_config.0.image_type", cluster.NodeConfig.ImageType},
   254  			{"node_version", cluster.CurrentNodeVersion},
   255  		}
   256  
   257  		// Remove Zone from additional_zones since that's what the resource writes in state
   258  		additionalZones := []string{}
   259  		for _, location := range cluster.Locations {
   260  			if location != cluster.Zone {
   261  				additionalZones = append(additionalZones, location)
   262  			}
   263  		}
   264  		clusterTests = append(clusterTests, clusterTestField{"additional_zones", additionalZones})
   265  
   266  		// AddonsConfig is neither Required or Computed, so the API may return nil for it
   267  		if cluster.AddonsConfig != nil {
   268  			if cluster.AddonsConfig.HttpLoadBalancing != nil {
   269  				clusterTests = append(clusterTests, clusterTestField{"addons_config.0.http_load_balancing.0.disabled", strconv.FormatBool(cluster.AddonsConfig.HttpLoadBalancing.Disabled)})
   270  			}
   271  			if cluster.AddonsConfig.HorizontalPodAutoscaling != nil {
   272  				clusterTests = append(clusterTests, clusterTestField{"addons_config.0.horizontal_pod_autoscaling.0.disabled", strconv.FormatBool(cluster.AddonsConfig.HorizontalPodAutoscaling.Disabled)})
   273  			}
   274  		}
   275  
   276  		for i, np := range cluster.NodePools {
   277  			prefix := fmt.Sprintf("node_pool.%d.", i)
   278  			clusterTests = append(clusterTests,
   279  				clusterTestField{prefix + "name", np.Name},
   280  				clusterTestField{prefix + "initial_node_count", strconv.FormatInt(np.InitialNodeCount, 10)})
   281  		}
   282  
   283  		for _, attrs := range clusterTests {
   284  			if c := checkMatch(attributes, attrs.tf_attr, attrs.gcp_attr); c != "" {
   285  				return fmt.Errorf(c)
   286  			}
   287  		}
   288  
   289  		// Network has to be done separately in order to normalize the two values
   290  		tf, err := getNetworkNameFromSelfLink(attributes["network"])
   291  		if err != nil {
   292  			return err
   293  		}
   294  		gcp, err := getNetworkNameFromSelfLink(cluster.Network)
   295  		if err != nil {
   296  			return err
   297  		}
   298  		if tf != gcp {
   299  			return fmt.Errorf(matchError("network", tf, gcp))
   300  		}
   301  
   302  		return nil
   303  	}
   304  }
   305  
   306  func getResourceAttributes(n string, s *terraform.State) (map[string]string, error) {
   307  	rs, ok := s.RootModule().Resources[n]
   308  	if !ok {
   309  		return nil, fmt.Errorf("Not found: %s", n)
   310  	}
   311  
   312  	if rs.Primary.ID == "" {
   313  		return nil, fmt.Errorf("No ID is set")
   314  	}
   315  
   316  	return rs.Primary.Attributes, nil
   317  }
   318  
   319  func checkMatch(attributes map[string]string, attr string, gcp interface{}) string {
   320  	if gcpList, ok := gcp.([]string); ok {
   321  		return checkListMatch(attributes, attr, gcpList)
   322  	}
   323  	if gcpMap, ok := gcp.(map[string]string); ok {
   324  		return checkMapMatch(attributes, attr, gcpMap)
   325  	}
   326  	tf := attributes[attr]
   327  	if tf != gcp {
   328  		return matchError(attr, tf, gcp)
   329  	}
   330  	return ""
   331  }
   332  
   333  func checkListMatch(attributes map[string]string, attr string, gcpList []string) string {
   334  	num, err := strconv.Atoi(attributes[attr+".#"])
   335  	if err != nil {
   336  		return fmt.Sprintf("Error in number conversion for attribute %s: %s", attr, err)
   337  	}
   338  	if num != len(gcpList) {
   339  		return fmt.Sprintf("Cluster has mismatched %s size.\nTF Size: %d\nGCP Size: %d", attr, num, len(gcpList))
   340  	}
   341  
   342  	for i, gcp := range gcpList {
   343  		if tf := attributes[fmt.Sprintf("%s.%d", attr, i)]; tf != gcp {
   344  			return matchError(fmt.Sprintf("%s[%d]", attr, i), tf, gcp)
   345  		}
   346  	}
   347  
   348  	return ""
   349  }
   350  
   351  func checkMapMatch(attributes map[string]string, attr string, gcpMap map[string]string) string {
   352  	num, err := strconv.Atoi(attributes[attr+".%"])
   353  	if err != nil {
   354  		return fmt.Sprintf("Error in number conversion for attribute %s: %s", attr, err)
   355  	}
   356  	if num != len(gcpMap) {
   357  		return fmt.Sprintf("Cluster has mismatched %s size.\nTF Size: %d\nGCP Size: %d", attr, num, len(gcpMap))
   358  	}
   359  
   360  	for k, gcp := range gcpMap {
   361  		if tf := attributes[fmt.Sprintf("%s.%s", attr, k)]; tf != gcp {
   362  			return matchError(fmt.Sprintf("%s[%s]", attr, k), tf, gcp)
   363  		}
   364  	}
   365  
   366  	return ""
   367  }
   368  
   369  func matchError(attr, tf string, gcp interface{}) string {
   370  	return fmt.Sprintf("Cluster has mismatched %s.\nTF State: %+v\nGCP State: %+v", attr, tf, gcp)
   371  }
   372  
   373  var testAccContainerCluster_basic = fmt.Sprintf(`
   374  resource "google_container_cluster" "primary" {
   375  	name = "cluster-test-%s"
   376  	zone = "us-central1-a"
   377  	initial_node_count = 3
   378  
   379  	master_auth {
   380  		username = "mr.yoda"
   381  		password = "adoy.rm"
   382  	}
   383  }`, acctest.RandString(10))
   384  
   385  var testAccContainerCluster_withAdditionalZones = fmt.Sprintf(`
   386  resource "google_container_cluster" "with_additional_zones" {
   387  	name = "cluster-test-%s"
   388  	zone = "us-central1-a"
   389  	initial_node_count = 1
   390  
   391  	additional_zones = [
   392  		"us-central1-b",
   393  		"us-central1-c"
   394  	]
   395  
   396  	master_auth {
   397  		username = "mr.yoda"
   398  		password = "adoy.rm"
   399  	}
   400  }`, acctest.RandString(10))
   401  
   402  var testAccContainerCluster_withVersion = fmt.Sprintf(`
   403  resource "google_container_cluster" "with_version" {
   404  	name = "cluster-test-%s"
   405  	zone = "us-central1-a"
   406  	node_version = "1.6.0"
   407  	initial_node_count = 1
   408  
   409  	master_auth {
   410  		username = "mr.yoda"
   411  		password = "adoy.rm"
   412  	}
   413  }`, acctest.RandString(10))
   414  
   415  var testAccContainerCluster_withNodeConfig = fmt.Sprintf(`
   416  resource "google_container_cluster" "with_node_config" {
   417  	name = "cluster-test-%s"
   418  	zone = "us-central1-f"
   419  	initial_node_count = 1
   420  
   421  	master_auth {
   422  		username = "mr.yoda"
   423  		password = "adoy.rm"
   424  	}
   425  
   426  	node_config {
   427  		machine_type = "n1-standard-1"
   428  		disk_size_gb = 15
   429  		local_ssd_count = 1
   430  		oauth_scopes = [
   431  			"https://www.googleapis.com/auth/compute",
   432  			"https://www.googleapis.com/auth/devstorage.read_only",
   433  			"https://www.googleapis.com/auth/logging.write",
   434  			"https://www.googleapis.com/auth/monitoring"
   435  		]
   436  		service_account = "default"
   437  		metadata {
   438  			foo = "bar"
   439  		}
   440  		image_type = "CONTAINER_VM"
   441  	}
   442  }`, acctest.RandString(10))
   443  
   444  var testAccContainerCluster_withNodeConfigScopeAlias = fmt.Sprintf(`
   445  resource "google_container_cluster" "with_node_config_scope_alias" {
   446  	name = "cluster-test-%s"
   447  	zone = "us-central1-f"
   448  	initial_node_count = 1
   449  
   450  	master_auth {
   451  		username = "mr.yoda"
   452  		password = "adoy.rm"
   453  	}
   454  
   455  	node_config {
   456  		machine_type = "g1-small"
   457  		disk_size_gb = 15
   458  		oauth_scopes = [ "compute-rw", "storage-ro", "logging-write", "monitoring" ]
   459  	}
   460  }`, acctest.RandString(10))
   461  
   462  var testAccContainerCluster_networkRef = fmt.Sprintf(`
   463  resource "google_compute_network" "container_network" {
   464  	name = "container-net-%s"
   465  	auto_create_subnetworks = true
   466  }
   467  
   468  resource "google_container_cluster" "with_net_ref_by_url" {
   469  	name = "cluster-test-%s"
   470  	zone = "us-central1-a"
   471  	initial_node_count = 1
   472  
   473  	master_auth {
   474  		username = "mr.yoda"
   475  		password = "adoy.rm"
   476  	}
   477  
   478  	network = "${google_compute_network.container_network.self_link}"
   479  }
   480  
   481  resource "google_container_cluster" "with_net_ref_by_name" {
   482  	name = "cluster-test-%s"
   483  	zone = "us-central1-a"
   484  	initial_node_count = 1
   485  
   486  	master_auth {
   487  		username = "mr.yoda"
   488  		password = "adoy.rm"
   489  	}
   490  
   491  	network = "${google_compute_network.container_network.name}"
   492  }`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))
   493  
   494  var testAccContainerCluster_backendRef = fmt.Sprintf(`
   495  resource "google_compute_backend_service" "my-backend-service" {
   496    name      = "terraform-test-%s"
   497    port_name = "http"
   498    protocol  = "HTTP"
   499  
   500    backend {
   501      group = "${element(google_container_cluster.primary.instance_group_urls, 1)}"
   502    }
   503  
   504    health_checks = ["${google_compute_http_health_check.default.self_link}"]
   505  }
   506  
   507  resource "google_compute_http_health_check" "default" {
   508    name               = "terraform-test-%s"
   509    request_path       = "/"
   510    check_interval_sec = 1
   511    timeout_sec        = 1
   512  }
   513  
   514  resource "google_container_cluster" "primary" {
   515    name               = "terraform-test-%s"
   516    zone               = "us-central1-a"
   517    initial_node_count = 3
   518  
   519    additional_zones = [
   520      "us-central1-b",
   521      "us-central1-c",
   522    ]
   523  
   524    master_auth {
   525      username = "mr.yoda"
   526      password = "adoy.rm"
   527    }
   528  
   529    node_config {
   530      oauth_scopes = [
   531        "https://www.googleapis.com/auth/compute",
   532        "https://www.googleapis.com/auth/devstorage.read_only",
   533        "https://www.googleapis.com/auth/logging.write",
   534        "https://www.googleapis.com/auth/monitoring",
   535      ]
   536    }
   537  }
   538  `, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))
   539  
   540  var testAccContainerCluster_withNodePoolBasic = fmt.Sprintf(`
   541  resource "google_container_cluster" "with_node_pool" {
   542  	name = "tf-cluster-nodepool-test-%s"
   543  	zone = "us-central1-a"
   544  
   545  	master_auth {
   546  		username = "mr.yoda"
   547  		password = "adoy.rm"
   548  	}
   549  
   550  	node_pool {
   551  		name               = "tf-cluster-nodepool-test-%s"
   552  		initial_node_count = 2
   553  	}
   554  }`, acctest.RandString(10), acctest.RandString(10))
   555  
   556  var testAccContainerCluster_withNodePoolNamePrefix = fmt.Sprintf(`
   557  resource "google_container_cluster" "with_node_pool_name_prefix" {
   558  	name = "tf-cluster-nodepool-test-%s"
   559  	zone = "us-central1-a"
   560  
   561  	master_auth {
   562  		username = "mr.yoda"
   563  		password = "adoy.rm"
   564  	}
   565  
   566  	node_pool {
   567  		name_prefix        = "tf-np-test"
   568  		initial_node_count = 2
   569  	}
   570  }`, acctest.RandString(10))
   571  
   572  var testAccContainerCluster_withNodePoolMultiple = fmt.Sprintf(`
   573  resource "google_container_cluster" "with_node_pool_multiple" {
   574  	name = "tf-cluster-nodepool-test-%s"
   575  	zone = "us-central1-a"
   576  
   577  	master_auth {
   578  		username = "mr.yoda"
   579  		password = "adoy.rm"
   580  	}
   581  
   582  	node_pool {
   583  		name               = "tf-cluster-nodepool-test-%s"
   584  		initial_node_count = 2
   585  	}
   586  
   587  	node_pool {
   588  		name               = "tf-cluster-nodepool-test-%s"
   589  		initial_node_count = 3
   590  	}
   591  }`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))