provider/google: fix container instance group URLs

Google Container Engine's cluster API returned instance group manager
URLs when it meant to return instance group URLs. See #4336 for details
about the bug.

While this is undeniably an upstream problem, this PR:

* detects the error, meaning it will work as expected when the API is
  fixed.
* corrects the error by requesting the instance group manager, then
  retrieving its instance group URL, and using that instead.
* adds a test that exercises the error and the solution, to ensure it is
  functioning properly.
This commit is contained in:
Paddy 2017-03-06 21:14:32 -08:00
parent bbad8be2f3
commit 6ea1b17f8f
2 changed files with 91 additions and 2 deletions

View File

@ -13,6 +13,10 @@ import (
"google.golang.org/api/googleapi"
)
var (
instanceGroupManagerURL = regexp.MustCompile("^https://www.googleapis.com/compute/v1/projects/([a-z][a-z0-9-]{5}(?:[-a-z0-9]{0,23}[a-z0-9])?)/zones/([a-z0-9-]*)/instanceGroupManagers/([^/]*)")
)
func resourceContainerCluster() *schema.Resource {
return &schema.Resource{
Create: resourceContainerClusterCreate,
@ -474,7 +478,28 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
d.Set("network", d.Get("network").(string))
d.Set("subnetwork", cluster.Subnetwork)
d.Set("node_config", flattenClusterNodeConfig(cluster.NodeConfig))
d.Set("instance_group_urls", cluster.InstanceGroupUrls)
// container engine's API currently mistakenly returns the instance group manager's
// URL instead of the instance group's URL in its responses. This shim detects that
// error, and corrects it, by fetching the instance group manager URL and retrieving
// the instance group manager, then using that to look up the instance group URL, which
// is then substituted.
//
// This should be removed when the API response is fixed.
instanceGroupURLs := make([]string, 0, len(cluster.InstanceGroupUrls))
for _, u := range cluster.InstanceGroupUrls {
if !instanceGroupManagerURL.MatchString(u) {
instanceGroupURLs = append(instanceGroupURLs, u)
continue
}
matches := instanceGroupManagerURL.FindStringSubmatch(u)
instanceGroupManager, err := config.clientCompute.InstanceGroupManagers.Get(matches[1], matches[2], matches[3]).Do()
if err != nil {
return fmt.Errorf("Error reading instance group manager returned as an instance group URL: %s", err)
}
instanceGroupURLs = append(instanceGroupURLs, instanceGroupManager.InstanceGroup)
}
d.Set("instance_group_urls", instanceGroupURLs)
return nil
}

View File

@ -4,10 +4,11 @@ import (
"fmt"
"testing"
"strconv"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"strconv"
)
func TestAccContainerCluster_basic(t *testing.T) {
@ -116,6 +117,23 @@ func TestAccContainerCluster_network(t *testing.T) {
})
}
func TestAccContainerCluster_backend(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccContainerCluster_backendRef,
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerClusterExists(
"google_container_cluster.primary"),
),
},
},
})
}
func testAccCheckContainerClusterDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
@ -296,3 +314,49 @@ resource "google_container_cluster" "with_net_ref_by_name" {
network = "${google_compute_network.container_network.name}"
}`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))
var testAccContainerCluster_backendRef = fmt.Sprintf(`
resource "google_compute_backend_service" "my-backend-service" {
name = "terraform-test-%s"
port_name = "http"
protocol = "HTTP"
backend {
group = "${element(google_container_cluster.primary.instance_group_urls, 1)}"
}
health_checks = ["${google_compute_http_health_check.default.self_link}"]
}
resource "google_compute_http_health_check" "default" {
name = "terraform-test-%s"
request_path = "/"
check_interval_sec = 1
timeout_sec = 1
}
resource "google_container_cluster" "primary" {
name = "terraform-test-%s"
zone = "us-central1-a"
initial_node_count = 3
additional_zones = [
"us-central1-b",
"us-central1-c",
]
master_auth {
username = "mr.yoda"
password = "adoy.rm"
}
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
]
}
}
`, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))