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))