github.com/IBM-Cloud/terraform@v0.6.4-0.20170726051544-8872b87621df/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 data "google_container_engine_versions" "central1a" { 404 zone = "us-central1-a" 405 } 406 407 resource "google_container_cluster" "with_version" { 408 name = "cluster-test-%s" 409 zone = "us-central1-a" 410 node_version = "${data.google_container_engine_versions.central1a.latest_node_version}" 411 initial_node_count = 1 412 413 master_auth { 414 username = "mr.yoda" 415 password = "adoy.rm" 416 } 417 }`, acctest.RandString(10)) 418 419 var testAccContainerCluster_withNodeConfig = fmt.Sprintf(` 420 resource "google_container_cluster" "with_node_config" { 421 name = "cluster-test-%s" 422 zone = "us-central1-f" 423 initial_node_count = 1 424 425 master_auth { 426 username = "mr.yoda" 427 password = "adoy.rm" 428 } 429 430 node_config { 431 machine_type = "n1-standard-1" 432 disk_size_gb = 15 433 local_ssd_count = 1 434 oauth_scopes = [ 435 "https://www.googleapis.com/auth/compute", 436 "https://www.googleapis.com/auth/devstorage.read_only", 437 "https://www.googleapis.com/auth/logging.write", 438 "https://www.googleapis.com/auth/monitoring" 439 ] 440 service_account = "default" 441 metadata { 442 foo = "bar" 443 } 444 image_type = "CONTAINER_VM" 445 } 446 }`, acctest.RandString(10)) 447 448 var testAccContainerCluster_withNodeConfigScopeAlias = fmt.Sprintf(` 449 resource "google_container_cluster" "with_node_config_scope_alias" { 450 name = "cluster-test-%s" 451 zone = "us-central1-f" 452 initial_node_count = 1 453 454 master_auth { 455 username = "mr.yoda" 456 password = "adoy.rm" 457 } 458 459 node_config { 460 machine_type = "g1-small" 461 disk_size_gb = 15 462 oauth_scopes = [ "compute-rw", "storage-ro", "logging-write", "monitoring" ] 463 } 464 }`, acctest.RandString(10)) 465 466 var testAccContainerCluster_networkRef = fmt.Sprintf(` 467 resource "google_compute_network" "container_network" { 468 name = "container-net-%s" 469 auto_create_subnetworks = true 470 } 471 472 resource "google_container_cluster" "with_net_ref_by_url" { 473 name = "cluster-test-%s" 474 zone = "us-central1-a" 475 initial_node_count = 1 476 477 master_auth { 478 username = "mr.yoda" 479 password = "adoy.rm" 480 } 481 482 network = "${google_compute_network.container_network.self_link}" 483 } 484 485 resource "google_container_cluster" "with_net_ref_by_name" { 486 name = "cluster-test-%s" 487 zone = "us-central1-a" 488 initial_node_count = 1 489 490 master_auth { 491 username = "mr.yoda" 492 password = "adoy.rm" 493 } 494 495 network = "${google_compute_network.container_network.name}" 496 }`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10)) 497 498 var testAccContainerCluster_backendRef = fmt.Sprintf(` 499 resource "google_compute_backend_service" "my-backend-service" { 500 name = "terraform-test-%s" 501 port_name = "http" 502 protocol = "HTTP" 503 504 backend { 505 group = "${element(google_container_cluster.primary.instance_group_urls, 1)}" 506 } 507 508 health_checks = ["${google_compute_http_health_check.default.self_link}"] 509 } 510 511 resource "google_compute_http_health_check" "default" { 512 name = "terraform-test-%s" 513 request_path = "/" 514 check_interval_sec = 1 515 timeout_sec = 1 516 } 517 518 resource "google_container_cluster" "primary" { 519 name = "terraform-test-%s" 520 zone = "us-central1-a" 521 initial_node_count = 3 522 523 additional_zones = [ 524 "us-central1-b", 525 "us-central1-c", 526 ] 527 528 master_auth { 529 username = "mr.yoda" 530 password = "adoy.rm" 531 } 532 533 node_config { 534 oauth_scopes = [ 535 "https://www.googleapis.com/auth/compute", 536 "https://www.googleapis.com/auth/devstorage.read_only", 537 "https://www.googleapis.com/auth/logging.write", 538 "https://www.googleapis.com/auth/monitoring", 539 ] 540 } 541 } 542 `, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10)) 543 544 var testAccContainerCluster_withNodePoolBasic = fmt.Sprintf(` 545 resource "google_container_cluster" "with_node_pool" { 546 name = "tf-cluster-nodepool-test-%s" 547 zone = "us-central1-a" 548 549 master_auth { 550 username = "mr.yoda" 551 password = "adoy.rm" 552 } 553 554 node_pool { 555 name = "tf-cluster-nodepool-test-%s" 556 initial_node_count = 2 557 } 558 }`, acctest.RandString(10), acctest.RandString(10)) 559 560 var testAccContainerCluster_withNodePoolNamePrefix = fmt.Sprintf(` 561 resource "google_container_cluster" "with_node_pool_name_prefix" { 562 name = "tf-cluster-nodepool-test-%s" 563 zone = "us-central1-a" 564 565 master_auth { 566 username = "mr.yoda" 567 password = "adoy.rm" 568 } 569 570 node_pool { 571 name_prefix = "tf-np-test" 572 initial_node_count = 2 573 } 574 }`, acctest.RandString(10)) 575 576 var testAccContainerCluster_withNodePoolMultiple = fmt.Sprintf(` 577 resource "google_container_cluster" "with_node_pool_multiple" { 578 name = "tf-cluster-nodepool-test-%s" 579 zone = "us-central1-a" 580 581 master_auth { 582 username = "mr.yoda" 583 password = "adoy.rm" 584 } 585 586 node_pool { 587 name = "tf-cluster-nodepool-test-%s" 588 initial_node_count = 2 589 } 590 591 node_pool { 592 name = "tf-cluster-nodepool-test-%s" 593 initial_node_count = 3 594 } 595 }`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))