diff --git a/google/data_source_google_compute_instance_group.go b/google/data_source_google_compute_instance_group.go new file mode 100644 index 00000000000..c93caf22586 --- /dev/null +++ b/google/data_source_google_compute_instance_group.go @@ -0,0 +1,83 @@ +package google + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceGoogleComputeInstanceGroup() *schema.Resource { + return &schema.Resource{ + Read: dataSourceComputeInstanceGroupRead, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "zone": { + Type: schema.TypeString, + Required: true, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + }, + + "description": { + Type: schema.TypeString, + Computed: true, + }, + + "instances": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "named_port": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "port": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "network": { + Type: schema.TypeString, + Computed: true, + }, + + "self_link": { + Type: schema.TypeString, + Computed: true, + }, + + "size": { + Type: schema.TypeInt, + Computed: true, + }, + }, + } +} + +func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{}) error { + zone := d.Get("zone").(string) + name := d.Get("name").(string) + + d.SetId(fmt.Sprintf("%s/%s", zone, name)) + + return resourceComputeInstanceGroupRead(d, meta) +} diff --git a/google/data_source_google_compute_instance_group_test.go b/google/data_source_google_compute_instance_group_test.go new file mode 100644 index 00000000000..92bd8215cb6 --- /dev/null +++ b/google/data_source_google_compute_instance_group_test.go @@ -0,0 +1,253 @@ +package google + +import ( + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccDataSourceGoogleComputeInstanceGroup_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckDataSourceGoogleComputeInstanceGroupConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceGoogleComputeInstanceGroup("data.google_compute_instance_group.test"), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleComputeInstanceGroup_withNamedPort(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckDataSourceGoogleComputeInstanceGroupConfigWithNamedPort, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceGoogleComputeInstanceGroup("data.google_compute_instance_group.test"), + ), + }, + }, + }) +} + +func testAccCheckDataSourceGoogleComputeInstanceGroup(dataSourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + dsFullName := "data.google_compute_instance_group.test" + rsFullName := "google_compute_instance_group.test" + ds, ok := s.RootModule().Resources[dsFullName] + if !ok { + return fmt.Errorf("cant' find resource called %s in state", dsFullName) + } + + rs, ok := s.RootModule().Resources[rsFullName] + if !ok { + return fmt.Errorf("can't find data source called %s in state", rsFullName) + } + + dsAttrs := ds.Primary.Attributes + rsAttrs := rs.Primary.Attributes + + attrsToTest := []string{ + "id", + "name", + "zone", + "project", + "description", + "network", + "self_link", + "size", + } + + for _, attrToTest := range attrsToTest { + if dsAttrs[attrToTest] != rsAttrs[attrToTest] { + return fmt.Errorf("%s is %s; want %s", attrToTest, dsAttrs[attrToTest], rsAttrs[attrToTest]) + } + } + + dsNamedPortsCount, ok := dsAttrs["named_port.#"] + if !ok { + return errors.New("can't find 'named_port' attribute in data source") + } + + dsNoOfNamedPorts, err := strconv.Atoi(dsNamedPortsCount) + if err != nil { + return errors.New("failed to read number of named ports in data source") + } + + rsNamedPortsCount, ok := rsAttrs["named_port.#"] + if !ok { + return errors.New("can't find 'named_port' attribute in resource") + } + + rsNoOfNamedPorts, err := strconv.Atoi(rsNamedPortsCount) + if err != nil { + return errors.New("failed to read number of named ports in resource") + } + + if dsNoOfNamedPorts != rsNoOfNamedPorts { + return fmt.Errorf( + "expected %d number of named port, received %d, this is most likely a bug", + rsNoOfNamedPorts, + dsNoOfNamedPorts, + ) + } + + namedPortItemKeys := []string{"name", "value"} + for i := 0; i < dsNoOfNamedPorts; i++ { + for _, key := range namedPortItemKeys { + idx := fmt.Sprintf("named_port.%d.%s", i, key) + if dsAttrs[idx] != rsAttrs[idx] { + return fmt.Errorf("%s is %s; want %s", idx, dsAttrs[idx], rsAttrs[idx]) + } + } + } + + dsInstancesCount, ok := dsAttrs["instances.#"] + if !ok { + return errors.New("can't find 'instances' attribute in data source") + } + + dsNoOfInstances, err := strconv.Atoi(dsInstancesCount) + if err != nil { + return errors.New("failed to read number of named ports in data source") + } + + rsInstancesCount, ok := rsAttrs["instances.#"] + if !ok { + return errors.New("can't find 'instances' attribute in resource") + } + + rsNoOfInstances, err := strconv.Atoi(rsInstancesCount) + if err != nil { + return errors.New("failed to read number of instances in resource") + } + + if dsNoOfInstances != rsNoOfInstances { + return fmt.Errorf( + "expected %d number of instances, received %d, this is most likely a bug", + rsNoOfInstances, + dsNoOfInstances, + ) + } + + // We don't know the exact keys of the elements, so go through the whole list looking for matching ones + dsInstancesValues := []string{} + for k, v := range dsAttrs { + if strings.HasPrefix(k, "instances") && !strings.HasSuffix(k, "#") { + dsInstancesValues = append(dsInstancesValues, v) + } + } + + rsInstancesValues := []string{} + for k, v := range rsAttrs { + if strings.HasPrefix(k, "instances") && !strings.HasSuffix(k, "#") { + rsInstancesValues = append(rsInstancesValues, v) + } + } + + sort.Strings(dsInstancesValues) + sort.Strings(rsInstancesValues) + + if !reflect.DeepEqual(dsInstancesValues, rsInstancesValues) { + return fmt.Errorf("expected %v list of instances, received %v", rsInstancesValues, dsInstancesValues) + } + + return nil + } +} + +var testAccCheckDataSourceGoogleComputeInstanceGroupConfig = fmt.Sprintf(` +resource "google_compute_instance" "test" { + name = "tf-test-%s" + machine_type = "n1-standard-1" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = "debian-cloud/debian-8" + } + } + + network_interface { + network = "default" + + access_config { + // Ephemeral IP + } + } +} + +resource "google_compute_instance_group" "test" { + name = "tf-test-%s" + zone = "${google_compute_instance.test.zone}" + + instances = [ + "${google_compute_instance.test.self_link}", + ] +} + +data "google_compute_instance_group" "test" { + name = "${google_compute_instance_group.test.name}" + zone = "${google_compute_instance_group.test.zone}" +} +`, acctest.RandString(10), acctest.RandString(10)) + +var testAccCheckDataSourceGoogleComputeInstanceGroupConfigWithNamedPort = fmt.Sprintf(` +resource "google_compute_instance" "test" { + name = "tf-test-%s" + machine_type = "n1-standard-1" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = "debian-cloud/debian-8" + } + } + + network_interface { + network = "default" + + access_config { + // Ephemeral IP + } + } +} + +resource "google_compute_instance_group" "test" { + name = "tf-test-%s" + zone = "${google_compute_instance.test.zone}" + + named_port { + name = "http" + port = "8080" + } + + named_port { + name = "https" + port = "8443" + } + + instances = [ + "${google_compute_instance.test.self_link}", + ] +} + +data "google_compute_instance_group" "test" { + name = "${google_compute_instance_group.test.name}" + zone = "${google_compute_instance_group.test.zone}" +} +`, acctest.RandString(10), acctest.RandString(10)) diff --git a/google/provider.go b/google/provider.go index 769c8d7f6cd..9693365ab65 100644 --- a/google/provider.go +++ b/google/provider.go @@ -60,6 +60,7 @@ func Provider() terraform.ResourceProvider { "google_compute_network": dataSourceGoogleComputeNetwork(), "google_compute_subnetwork": dataSourceGoogleComputeSubnetwork(), "google_compute_zones": dataSourceGoogleComputeZones(), + "google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(), "google_container_engine_versions": dataSourceGoogleContainerEngineVersions(), "google_iam_policy": dataSourceGoogleIamPolicy(), "google_storage_object_signed_url": dataSourceGoogleSignedUrl(), diff --git a/website/docs/d/google_compute_instance_group.html.markdown b/website/docs/d/google_compute_instance_group.html.markdown new file mode 100644 index 00000000000..0c1ec1adae2 --- /dev/null +++ b/website/docs/d/google_compute_instance_group.html.markdown @@ -0,0 +1,49 @@ +--- +layout: "google" +page_title: "Google: google_compute_instance_group" +sidebar_current: "docs-google-datasource-compute-instance-group" +description: |- + Get a Compute Instance Group within GCE. +--- + +# google\_compute\_instance\_group + +Get a Compute Instance Group within GCE. +For more information, see [the official documentation](https://cloud.google.com/compute/docs/instance-groups/#unmanaged_instance_groups) +and [API](https://cloud.google.com/compute/docs/reference/latest/instanceGroups) + +``` +data "google_compute_instance_group" "all" { + name = "instance-group-name" + zone = "us-central1-a" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the instance group. + +* `zone` - (Required) The zone of the instance group. + +- - - + +* `project` - (Optional) The project in which the resource belongs. If it + is not provided, the provider project is used. + +## Attributes Reference + +The following arguments are exported: + +* `description` - Textual description of the instance group. + +* `instances` - List of instances in the group. + +* `named_port` - List of named ports in the group. + +* `network` - The URL of the network the instance group is in. + +* `self_link` - The URI of the resource. + +* `size` - The number of instances in the group. diff --git a/website/google.erb b/website/google.erb index 08aba54f67c..4633e22b4ff 100644 --- a/website/google.erb +++ b/website/google.erb @@ -22,6 +22,9 @@