github.com/cbroglie/terraform@v0.7.0-rc3.0.20170410193827-735dfc416d46/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 testAccCheckContainerClusterDestroy(s *terraform.State) error {
   136  	config := testAccProvider.Meta().(*Config)
   137  
   138  	for _, rs := range s.RootModule().Resources {
   139  		if rs.Type != "google_container_cluster" {
   140  			continue
   141  		}
   142  
   143  		attributes := rs.Primary.Attributes
   144  		_, err := config.clientContainer.Projects.Zones.Clusters.Get(
   145  			config.Project, attributes["zone"], attributes["name"]).Do()
   146  		if err == nil {
   147  			return fmt.Errorf("Cluster still exists")
   148  		}
   149  	}
   150  
   151  	return nil
   152  }
   153  
   154  func testAccCheckContainerCluster(n string) resource.TestCheckFunc {
   155  	return func(s *terraform.State) error {
   156  		attributes, err := getResourceAttributes(n, s)
   157  		if err != nil {
   158  			return err
   159  		}
   160  
   161  		config := testAccProvider.Meta().(*Config)
   162  		cluster, err := config.clientContainer.Projects.Zones.Clusters.Get(
   163  			config.Project, attributes["zone"], attributes["name"]).Do()
   164  		if err != nil {
   165  			return err
   166  		}
   167  
   168  		if cluster.Name != attributes["name"] {
   169  			return fmt.Errorf("Cluster %s not found, found %s instead", attributes["name"], cluster.Name)
   170  		}
   171  
   172  		type clusterTestField struct {
   173  			tf_attr  string
   174  			gcp_attr interface{}
   175  		}
   176  
   177  		var igUrls []string
   178  		if igUrls, err = getInstanceGroupUrlsFromManagerUrls(config, cluster.InstanceGroupUrls); err != nil {
   179  			return err
   180  		}
   181  		clusterTests := []clusterTestField{
   182  			{"initial_node_count", strconv.FormatInt(cluster.InitialNodeCount, 10)},
   183  			{"master_auth.0.client_certificate", cluster.MasterAuth.ClientCertificate},
   184  			{"master_auth.0.client_key", cluster.MasterAuth.ClientKey},
   185  			{"master_auth.0.cluster_ca_certificate", cluster.MasterAuth.ClusterCaCertificate},
   186  			{"master_auth.0.password", cluster.MasterAuth.Password},
   187  			{"master_auth.0.username", cluster.MasterAuth.Username},
   188  			{"zone", cluster.Zone},
   189  			{"cluster_ipv4_cidr", cluster.ClusterIpv4Cidr},
   190  			{"description", cluster.Description},
   191  			{"endpoint", cluster.Endpoint},
   192  			{"instance_group_urls", igUrls},
   193  			{"logging_service", cluster.LoggingService},
   194  			{"monitoring_service", cluster.MonitoringService},
   195  			{"subnetwork", cluster.Subnetwork},
   196  			{"node_config.0.machine_type", cluster.NodeConfig.MachineType},
   197  			{"node_config.0.disk_size_gb", strconv.FormatInt(cluster.NodeConfig.DiskSizeGb, 10)},
   198  			{"node_config.0.local_ssd_count", strconv.FormatInt(cluster.NodeConfig.LocalSsdCount, 10)},
   199  			{"node_config.0.oauth_scopes", cluster.NodeConfig.OauthScopes},
   200  			{"node_config.0.service_account", cluster.NodeConfig.ServiceAccount},
   201  			{"node_config.0.metadata", cluster.NodeConfig.Metadata},
   202  			{"node_config.0.image_type", cluster.NodeConfig.ImageType},
   203  			{"node_version", cluster.CurrentNodeVersion},
   204  		}
   205  
   206  		// Remove Zone from additional_zones since that's what the resource writes in state
   207  		additionalZones := []string{}
   208  		for _, location := range cluster.Locations {
   209  			if location != cluster.Zone {
   210  				additionalZones = append(additionalZones, location)
   211  			}
   212  		}
   213  		clusterTests = append(clusterTests, clusterTestField{"additional_zones", additionalZones})
   214  
   215  		// AddonsConfig is neither Required or Computed, so the API may return nil for it
   216  		if cluster.AddonsConfig != nil {
   217  			if cluster.AddonsConfig.HttpLoadBalancing != nil {
   218  				clusterTests = append(clusterTests, clusterTestField{"addons_config.0.http_load_balancing.0.disabled", strconv.FormatBool(cluster.AddonsConfig.HttpLoadBalancing.Disabled)})
   219  			}
   220  			if cluster.AddonsConfig.HorizontalPodAutoscaling != nil {
   221  				clusterTests = append(clusterTests, clusterTestField{"addons_config.0.horizontal_pod_autoscaling.0.disabled", strconv.FormatBool(cluster.AddonsConfig.HorizontalPodAutoscaling.Disabled)})
   222  			}
   223  		}
   224  
   225  		for _, attrs := range clusterTests {
   226  			if c := checkMatch(attributes, attrs.tf_attr, attrs.gcp_attr); c != "" {
   227  				return fmt.Errorf(c)
   228  			}
   229  		}
   230  
   231  		// Network has to be done separately in order to normalize the two values
   232  		tf, err := getNetworkNameFromSelfLink(attributes["network"])
   233  		if err != nil {
   234  			return err
   235  		}
   236  		gcp, err := getNetworkNameFromSelfLink(cluster.Network)
   237  		if err != nil {
   238  			return err
   239  		}
   240  		if tf != gcp {
   241  			return fmt.Errorf(matchError("network", tf, gcp))
   242  		}
   243  
   244  		return nil
   245  	}
   246  }
   247  
   248  func getResourceAttributes(n string, s *terraform.State) (map[string]string, error) {
   249  	rs, ok := s.RootModule().Resources[n]
   250  	if !ok {
   251  		return nil, fmt.Errorf("Not found: %s", n)
   252  	}
   253  
   254  	if rs.Primary.ID == "" {
   255  		return nil, fmt.Errorf("No ID is set")
   256  	}
   257  
   258  	return rs.Primary.Attributes, nil
   259  }
   260  
   261  func checkMatch(attributes map[string]string, attr string, gcp interface{}) string {
   262  	if gcpList, ok := gcp.([]string); ok {
   263  		return checkListMatch(attributes, attr, gcpList)
   264  	}
   265  	if gcpMap, ok := gcp.(map[string]string); ok {
   266  		return checkMapMatch(attributes, attr, gcpMap)
   267  	}
   268  	tf := attributes[attr]
   269  	if tf != gcp {
   270  		return matchError(attr, tf, gcp)
   271  	}
   272  	return ""
   273  }
   274  
   275  func checkListMatch(attributes map[string]string, attr string, gcpList []string) string {
   276  	num, err := strconv.Atoi(attributes[attr+".#"])
   277  	if err != nil {
   278  		return fmt.Sprintf("Error in number conversion for attribute %s: %s", attr, err)
   279  	}
   280  	if num != len(gcpList) {
   281  		return fmt.Sprintf("Cluster has mismatched %s size.\nTF Size: %d\nGCP Size: %d", attr, num, len(gcpList))
   282  	}
   283  
   284  	for i, gcp := range gcpList {
   285  		if tf := attributes[fmt.Sprintf("%s.%d", attr, i)]; tf != gcp {
   286  			return matchError(fmt.Sprintf("%s[%d]", attr, i), tf, gcp)
   287  		}
   288  	}
   289  
   290  	return ""
   291  }
   292  
   293  func checkMapMatch(attributes map[string]string, attr string, gcpMap map[string]string) string {
   294  	num, err := strconv.Atoi(attributes[attr+".%"])
   295  	if err != nil {
   296  		return fmt.Sprintf("Error in number conversion for attribute %s: %s", attr, err)
   297  	}
   298  	if num != len(gcpMap) {
   299  		return fmt.Sprintf("Cluster has mismatched %s size.\nTF Size: %d\nGCP Size: %d", attr, num, len(gcpMap))
   300  	}
   301  
   302  	for k, gcp := range gcpMap {
   303  		if tf := attributes[fmt.Sprintf("%s.%s", attr, k)]; tf != gcp {
   304  			return matchError(fmt.Sprintf("%s[%s]", attr, k), tf, gcp)
   305  		}
   306  	}
   307  
   308  	return ""
   309  }
   310  
   311  func matchError(attr, tf string, gcp interface{}) string {
   312  	return fmt.Sprintf("Cluster has mismatched %s.\nTF State: %+v\nGCP State: %+v", attr, tf, gcp)
   313  }
   314  
   315  var testAccContainerCluster_basic = fmt.Sprintf(`
   316  resource "google_container_cluster" "primary" {
   317  	name = "cluster-test-%s"
   318  	zone = "us-central1-a"
   319  	initial_node_count = 3
   320  
   321  	master_auth {
   322  		username = "mr.yoda"
   323  		password = "adoy.rm"
   324  	}
   325  }`, acctest.RandString(10))
   326  
   327  var testAccContainerCluster_withAdditionalZones = fmt.Sprintf(`
   328  resource "google_container_cluster" "with_additional_zones" {
   329  	name = "cluster-test-%s"
   330  	zone = "us-central1-a"
   331  	initial_node_count = 1
   332  
   333  	additional_zones = [
   334  		"us-central1-b",
   335  		"us-central1-c"
   336  	]
   337  
   338  	master_auth {
   339  		username = "mr.yoda"
   340  		password = "adoy.rm"
   341  	}
   342  }`, acctest.RandString(10))
   343  
   344  var testAccContainerCluster_withVersion = fmt.Sprintf(`
   345  resource "google_container_cluster" "with_version" {
   346  	name = "cluster-test-%s"
   347  	zone = "us-central1-a"
   348  	node_version = "1.5.2"
   349  	initial_node_count = 1
   350  
   351  	master_auth {
   352  		username = "mr.yoda"
   353  		password = "adoy.rm"
   354  	}
   355  }`, acctest.RandString(10))
   356  
   357  var testAccContainerCluster_withNodeConfig = fmt.Sprintf(`
   358  resource "google_container_cluster" "with_node_config" {
   359  	name = "cluster-test-%s"
   360  	zone = "us-central1-f"
   361  	initial_node_count = 1
   362  
   363  	master_auth {
   364  		username = "mr.yoda"
   365  		password = "adoy.rm"
   366  	}
   367  
   368  	node_config {
   369  		machine_type = "n1-standard-1"
   370  		disk_size_gb = 15
   371  		local_ssd_count = 1
   372  		oauth_scopes = [
   373  			"https://www.googleapis.com/auth/compute",
   374  			"https://www.googleapis.com/auth/devstorage.read_only",
   375  			"https://www.googleapis.com/auth/logging.write",
   376  			"https://www.googleapis.com/auth/monitoring"
   377  		]
   378  		service_account = "default"
   379  		metadata {
   380  			foo = "bar"
   381  		}
   382  		image_type = "CONTAINER_VM"
   383  	}
   384  }`, acctest.RandString(10))
   385  
   386  var testAccContainerCluster_withNodeConfigScopeAlias = fmt.Sprintf(`
   387  resource "google_container_cluster" "with_node_config_scope_alias" {
   388  	name = "cluster-test-%s"
   389  	zone = "us-central1-f"
   390  	initial_node_count = 1
   391  
   392  	master_auth {
   393  		username = "mr.yoda"
   394  		password = "adoy.rm"
   395  	}
   396  
   397  	node_config {
   398  		machine_type = "g1-small"
   399  		disk_size_gb = 15
   400  		oauth_scopes = [ "compute-rw", "storage-ro", "logging-write", "monitoring" ]
   401  	}
   402  }`, acctest.RandString(10))
   403  
   404  var testAccContainerCluster_networkRef = fmt.Sprintf(`
   405  resource "google_compute_network" "container_network" {
   406  	name = "container-net-%s"
   407  	auto_create_subnetworks = true
   408  }
   409  
   410  resource "google_container_cluster" "with_net_ref_by_url" {
   411  	name = "cluster-test-%s"
   412  	zone = "us-central1-a"
   413  	initial_node_count = 1
   414  
   415  	master_auth {
   416  		username = "mr.yoda"
   417  		password = "adoy.rm"
   418  	}
   419  
   420  	network = "${google_compute_network.container_network.self_link}"
   421  }
   422  
   423  resource "google_container_cluster" "with_net_ref_by_name" {
   424  	name = "cluster-test-%s"
   425  	zone = "us-central1-a"
   426  	initial_node_count = 1
   427  
   428  	master_auth {
   429  		username = "mr.yoda"
   430  		password = "adoy.rm"
   431  	}
   432  
   433  	network = "${google_compute_network.container_network.name}"
   434  }`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))
   435  
   436  var testAccContainerCluster_backendRef = fmt.Sprintf(`
   437  resource "google_compute_backend_service" "my-backend-service" {
   438    name      = "terraform-test-%s"
   439    port_name = "http"
   440    protocol  = "HTTP"
   441  
   442    backend {
   443      group = "${element(google_container_cluster.primary.instance_group_urls, 1)}"
   444    }
   445  
   446    health_checks = ["${google_compute_http_health_check.default.self_link}"]
   447  }
   448  
   449  resource "google_compute_http_health_check" "default" {
   450    name               = "terraform-test-%s"
   451    request_path       = "/"
   452    check_interval_sec = 1
   453    timeout_sec        = 1
   454  }
   455  
   456  resource "google_container_cluster" "primary" {
   457    name               = "terraform-test-%s"
   458    zone               = "us-central1-a"
   459    initial_node_count = 3
   460  
   461    additional_zones = [
   462      "us-central1-b",
   463      "us-central1-c",
   464    ]
   465  
   466    master_auth {
   467      username = "mr.yoda"
   468      password = "adoy.rm"
   469    }
   470  
   471    node_config {
   472      oauth_scopes = [
   473        "https://www.googleapis.com/auth/compute",
   474        "https://www.googleapis.com/auth/devstorage.read_only",
   475        "https://www.googleapis.com/auth/logging.write",
   476        "https://www.googleapis.com/auth/monitoring",
   477      ]
   478    }
   479  }
   480  `, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))