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