Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a datasource for google_compute_instance #1906

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions google/data_source_google_compute_instance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package google

import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceGoogleComputeInstance() *schema.Resource {
// Generate datasource schema from resource
dsSchema := datasourceSchemaFromResourceSchema(resourceComputeInstance().Schema)

// Set 'Required' schema elements
addRequiredFieldsToSchema(dsSchema, "name")

// Set 'Optional' schema elements
addOptionalFieldsToSchema(dsSchema, "project", "zone")

return &schema.Resource{
Read: dataSourceGoogleComputeInstanceRead,
Schema: dsSchema,
}
}

func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

project, zone, name, err := GetZonalResourcePropertiesFromSelfLinkOrSchema(d, config)
if err != nil {
return err
}

instance, err := config.clientComputeBeta.Instances.Get(project, zone, name).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Instance %s", name))
}

md := flattenMetadataBeta(instance.Metadata)
if err = d.Set("metadata", md); err != nil {
return fmt.Errorf("error setting metadata: %s", err)
}

d.Set("can_ip_forward", instance.CanIpForward)
d.Set("machine_type", GetResourceNameFromSelfLink(instance.MachineType))

// Set the networks
// Use the first external IP found for the default connection info.
networkInterfaces, _, internalIP, externalIP, err := flattenNetworkInterfaces(d, config, instance.NetworkInterfaces)
if err != nil {
return err
}
if err := d.Set("network_interface", networkInterfaces); err != nil {
return err
}

// Fall back on internal ip if there is no external ip. This makes sense in the situation where
// terraform is being used on a cloud instance and can therefore access the instances it creates
// via their internal ips.
sshIP := externalIP
if sshIP == "" {
sshIP = internalIP
}

// Initialize the connection info
d.SetConnInfo(map[string]string{
"type": "ssh",
"host": sshIP,
})

// Set the metadata fingerprint if there is one.
if instance.Metadata != nil {
d.Set("metadata_fingerprint", instance.Metadata.Fingerprint)
}

// Set the tags fingerprint if there is one.
if instance.Tags != nil {
d.Set("tags_fingerprint", instance.Tags.Fingerprint)
d.Set("tags", convertStringArrToInterface(instance.Tags.Items))
}

if err := d.Set("labels", instance.Labels); err != nil {
return err
}

if instance.LabelFingerprint != "" {
d.Set("label_fingerprint", instance.LabelFingerprint)
}

attachedDisks := []map[string]interface{}{}
scratchDisks := []map[string]interface{}{}
for _, disk := range instance.Disks {
if disk.Boot {
err = d.Set("boot_disk", flattenBootDisk(d, disk, config))
if err != nil {
return err
}
} else if disk.Type == "SCRATCH" {
scratchDisks = append(scratchDisks, flattenScratchDisk(disk))
} else {
di := map[string]interface{}{
"source": ConvertSelfLinkToV1(disk.Source),
"device_name": disk.DeviceName,
"mode": disk.Mode,
}
if key := disk.DiskEncryptionKey; key != nil {
di["disk_encryption_key_sha256"] = key.Sha256
}
attachedDisks = append(attachedDisks, di)
}
}
// Remove nils from map in case there were disks in the config that were not present on read;
// i.e. a disk was detached out of band
ads := []map[string]interface{}{}
for _, d := range attachedDisks {
if d != nil {
ads = append(ads, d)
}
}

err = d.Set("service_account", flattenServiceAccounts(instance.ServiceAccounts))
if err != nil {
return err
}

err = d.Set("scheduling", flattenScheduling(instance.Scheduling))
if err != nil {
return err
}

err = d.Set("guest_accelerator", flattenGuestAccelerators(instance.GuestAccelerators))
if err != nil {
return err
}

err = d.Set("scratch_disk", scratchDisks)
if err != nil {
return err
}

d.Set("attached_disk", ads)
d.Set("cpu_platform", instance.CpuPlatform)
d.Set("min_cpu_platform", instance.MinCpuPlatform)
d.Set("deletion_protection", instance.DeletionProtection)
d.Set("self_link", ConvertSelfLinkToV1(instance.SelfLink))
d.Set("instance_id", fmt.Sprintf("%d", instance.Id))
d.Set("project", project)
d.Set("zone", GetResourceNameFromSelfLink(instance.Zone))
d.Set("name", instance.Name)
d.SetId(ConvertSelfLinkToV1(instance.SelfLink))
return nil
}
135 changes: 135 additions & 0 deletions google/data_source_google_compute_instance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package google

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccDataSourceComputeInstance_basic(t *testing.T) {
t.Parallel()

instanceName := fmt.Sprintf("data-instance-test-%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDataSourceComputeInstanceConfig(instanceName),
Check: resource.ComposeTestCheckFunc(
testAccDataSourceComputeInstanceCheck("data.google_compute_instance.bar", "google_compute_instance.foo"),
resource.TestCheckResourceAttr("data.google_compute_instance.bar", "network_interface.#", "1"),
resource.TestCheckResourceAttr("data.google_compute_instance.bar", "boot_disk.0.initialize_params.0.size", "10"),
resource.TestCheckResourceAttr("data.google_compute_instance.bar", "boot_disk.0.initialize_params.0.type", "pd-standard"),
resource.TestCheckResourceAttr("data.google_compute_instance.bar", "scratch_disk.0.interface", "SCSI"),
resource.TestCheckResourceAttr("data.google_compute_instance.bar", "network_interface.0.access_config.0.network_tier", "PREMIUM"),
),
},
},
})
}

func testAccDataSourceComputeInstanceCheck(datasourceName string, resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
ds, ok := s.RootModule().Resources[datasourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", datasourceName)
}

rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("can't find %s in state", resourceName)
}

datasourceAttributes := ds.Primary.Attributes
resourceAttributes := rs.Primary.Attributes

instanceAttrsToTest := []string{
"name",
"machine_type",
"can_ip_forward",
"description",
"deletion_protection",
"labels",
"metadata",
"min_cpu_platform",
"project",
"tags",
"zone",
"cpu_platform",
"instance_id",
"label_fingerprint",
"metadata_fingerprint",
"self_link",
"tags_fingerprint",
}

for _, attrToCheck := range instanceAttrsToTest {
if datasourceAttributes[attrToCheck] != resourceAttributes[attrToCheck] {
return fmt.Errorf(
"%s is %s; want %s",
attrToCheck,
datasourceAttributes[attrToCheck],
resourceAttributes[attrToCheck],
)
}
}

return nil
}
}

func testAccDataSourceComputeInstanceConfig(instanceName string) string {
return fmt.Sprintf(`
resource "google_compute_instance" "foo" {
name = "%s"
machine_type = "n1-standard-1"
zone = "us-central1-a"
can_ip_forward = false
tags = ["foo", "bar"]

boot_disk {
initialize_params{
image = "debian-8-jessie-v20160803"
}
}

scratch_disk {
}

network_interface {
network = "default"

access_config {
// Ephemeral IP
}
}

metadata {
foo = "bar"
baz = "qux"
}

create_timeout = 5

metadata {
startup-script = "echo Hello"
}

labels {
my_key = "my_value"
my_other_key = "my_other_value"
}
}

data "google_compute_instance" "bar" {
name = "${google_compute_instance.foo.name}"
zone = "us-central1-a"
}
`, instanceName)
}
35 changes: 5 additions & 30 deletions google/data_source_google_compute_region_instance_group.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package google

import (
"errors"
"fmt"
"log"
"net/url"
"strconv"
"strings"

"github.com/hashicorp/terraform/helper/schema"
compute "google.golang.org/api/compute/v1"

"google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi"
)

Expand Down Expand Up @@ -90,32 +88,9 @@ func dataSourceGoogleComputeRegionInstanceGroup() *schema.Resource {

func dataSourceComputeRegionInstanceGroupRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
var project, region, name string
if self_link, ok := d.GetOk("self_link"); ok {
parsed, err := url.Parse(self_link.(string))
if err != nil {
return err
}
s := strings.Split(parsed.Path, "/")
project, region, name = s[4], s[6], s[8]
// e.g. https://www.googleapis.com/compute/beta/projects/project_name/regions/region_name/instanceGroups/foobarbaz

} else {
var err error
project, err = getProject(d, config)
if err != nil {
return err
}

region, err = getRegion(d, config)
if err != nil {
return err
}
n, ok := d.GetOk("name")
name = n.(string)
if !ok {
return errors.New("Must provide either `self_link` or `name`.")
}
project, region, name, err := GetRegionalResourcePropertiesFromSelfLinkOrSchema(d, config)
if err != nil {
return err
}

instanceGroup, err := config.clientCompute.RegionInstanceGroups.Get(
Expand Down
15 changes: 8 additions & 7 deletions google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,20 @@ func Provider() terraform.ResourceProvider {
"google_client_config": dataSourceGoogleClientConfig(),
"google_cloudfunctions_function": dataSourceGoogleCloudFunctionsFunction(),
"google_compute_address": dataSourceGoogleComputeAddress(),
"google_compute_backend_service": dataSourceGoogleComputeBackendService(),
"google_compute_default_service_account": dataSourceGoogleComputeDefaultServiceAccount(),
"google_compute_forwarding_rule": dataSourceGoogleComputeForwardingRule(),
"google_compute_image": dataSourceGoogleComputeImage(),
"google_compute_instance": dataSourceGoogleComputeInstance(),
"google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(),
"google_compute_global_address": dataSourceGoogleComputeGlobalAddress(),
"google_compute_lb_ip_ranges": dataSourceGoogleComputeLbIpRanges(),
"google_compute_network": dataSourceGoogleComputeNetwork(),
"google_project": dataSourceGoogleProject(),
"google_project_services": dataSourceGoogleProjectServices(),
"google_compute_regions": dataSourceGoogleComputeRegions(),
"google_compute_region_instance_group": dataSourceGoogleComputeRegionInstanceGroup(),
"google_compute_subnetwork": dataSourceGoogleComputeSubnetwork(),
"google_compute_zones": dataSourceGoogleComputeZones(),
"google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(),
"google_compute_region_instance_group": dataSourceGoogleComputeRegionInstanceGroup(),
"google_compute_vpn_gateway": dataSourceGoogleComputeVpnGateway(),
"google_compute_forwarding_rule": dataSourceGoogleComputeForwardingRule(),
"google_compute_ssl_policy": dataSourceGoogleComputeSslPolicy(),
"google_container_cluster": dataSourceGoogleContainerCluster(),
"google_container_engine_versions": dataSourceGoogleContainerEngineVersions(),
Expand All @@ -90,12 +91,12 @@ func Provider() terraform.ResourceProvider {
"google_folder": dataSourceGoogleFolder(),
"google_netblock_ip_ranges": dataSourceGoogleNetblockIpRanges(),
"google_organization": dataSourceGoogleOrganization(),
"google_project": dataSourceGoogleProject(),
"google_project_services": dataSourceGoogleProjectServices(),
"google_service_account": dataSourceGoogleServiceAccount(),
"google_service_account_key": dataSourceGoogleServiceAccountKey(),
"google_storage_object_signed_url": dataSourceGoogleSignedUrl(),
"google_storage_project_service_account": dataSourceGoogleStorageProjectServiceAccount(),
"google_compute_backend_service": dataSourceGoogleComputeBackendService(),
"google_compute_regions": dataSourceGoogleComputeRegions(),
},

ResourcesMap: mergeResourceMaps(
Expand Down
Loading