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