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