Skip to content

Commit 0f5c04a

Browse files
authored
Add compute_instance_v2 data source (terraform-provider-openstack#984)
* Add initial support for the compute_instance_v2 data source * Add test case for compute instance data source * Add documentation page for data source * Add initial support for the compute_instance_v2 data source * Add test case for compute instance data source * Add documentation page for data source * Fix test case * Remove incorrect use of expandObjectReadTags in data source
1 parent af4489f commit 0f5c04a

4 files changed

Lines changed: 368 additions & 0 deletions

File tree

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
package openstack
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strings"
7+
8+
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
9+
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tags"
10+
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
11+
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
12+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
13+
)
14+
15+
func dataSourceComputeInstanceV2() *schema.Resource {
16+
return &schema.Resource{
17+
Read: dataSourceComputeInstanceV2Read,
18+
Schema: map[string]*schema.Schema{
19+
"region": {
20+
Type: schema.TypeString,
21+
Optional: true,
22+
Computed: true,
23+
},
24+
"id": {
25+
Type: schema.TypeString,
26+
Required: true,
27+
},
28+
"name": {
29+
Type: schema.TypeString,
30+
Computed: true,
31+
},
32+
"image_id": {
33+
Type: schema.TypeString,
34+
Computed: true,
35+
},
36+
"flavor_id": {
37+
Type: schema.TypeString,
38+
Computed: true,
39+
},
40+
"flavor_name": {
41+
Type: schema.TypeString,
42+
Computed: true,
43+
},
44+
"user_data": {
45+
Type: schema.TypeString,
46+
Optional: true,
47+
Computed: true,
48+
// just stash the hash for state & diff comparisons
49+
},
50+
"security_groups": {
51+
Type: schema.TypeSet,
52+
Computed: true,
53+
Elem: &schema.Schema{Type: schema.TypeString},
54+
Set: schema.HashString,
55+
},
56+
"availability_zone": {
57+
Type: schema.TypeString,
58+
Computed: true,
59+
},
60+
"network": {
61+
Type: schema.TypeList,
62+
Optional: true,
63+
Computed: true,
64+
Elem: &schema.Resource{
65+
Schema: map[string]*schema.Schema{
66+
"uuid": {
67+
Type: schema.TypeString,
68+
Computed: true,
69+
},
70+
"name": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
},
74+
"port": {
75+
Type: schema.TypeString,
76+
Computed: true,
77+
},
78+
"fixed_ip_v4": {
79+
Type: schema.TypeString,
80+
Computed: true,
81+
},
82+
"fixed_ip_v6": {
83+
Type: schema.TypeString,
84+
Computed: true,
85+
},
86+
"mac": {
87+
Type: schema.TypeString,
88+
Computed: true,
89+
},
90+
},
91+
},
92+
},
93+
"access_ip_v4": {
94+
Type: schema.TypeString,
95+
Computed: true,
96+
},
97+
"access_ip_v6": {
98+
Type: schema.TypeString,
99+
Computed: true,
100+
},
101+
"key_pair": {
102+
Type: schema.TypeString,
103+
Computed: true,
104+
},
105+
"metadata": {
106+
Type: schema.TypeMap,
107+
Computed: true,
108+
},
109+
"tags": {
110+
Type: schema.TypeSet,
111+
Computed: true,
112+
Elem: &schema.Schema{Type: schema.TypeString},
113+
},
114+
},
115+
}
116+
}
117+
118+
func dataSourceComputeInstanceV2Read(d *schema.ResourceData, meta interface{}) error {
119+
config := meta.(*Config)
120+
log.Print("[DEBUG] Creating compute client")
121+
computeClient, err := config.ComputeV2Client(GetRegion(d, config))
122+
if err != nil {
123+
return fmt.Errorf("Error creating OpenStack compute client: %s", err)
124+
}
125+
126+
id := d.Get("id").(string)
127+
log.Printf("[DEBUG] Attempting to retrieve server %s", id)
128+
server, err := servers.Get(computeClient, id).Extract()
129+
if err != nil {
130+
return CheckDeleted(d, err, "server")
131+
}
132+
133+
log.Printf("[DEBUG] Retrieved Server %s: %+v", id, server)
134+
135+
d.SetId(server.ID)
136+
137+
d.Set("name", server.Name)
138+
d.Set("image_id", server.Image["ID"])
139+
140+
// Get the instance network and address information
141+
networks, err := flattenInstanceNetworks(d, meta)
142+
if err != nil {
143+
return err
144+
}
145+
146+
// Determine the best IPv4 and IPv6 addresses to access the instance with
147+
hostv4, hostv6 := getInstanceAccessAddresses(d, networks)
148+
149+
// AccessIPv4/v6 isn't standard in OpenStack, but there have been reports
150+
// of them being used in some environments.
151+
if server.AccessIPv4 != "" && hostv4 == "" {
152+
hostv4 = server.AccessIPv4
153+
}
154+
155+
if server.AccessIPv6 != "" && hostv6 == "" {
156+
hostv6 = server.AccessIPv6
157+
}
158+
159+
log.Printf("[DEBUG] Setting networks: %+v", networks)
160+
161+
d.Set("network", networks)
162+
d.Set("access_ip_v4", hostv4)
163+
d.Set("access_ip_v6", hostv6)
164+
165+
d.Set("metadata", server.Metadata)
166+
167+
secGrpNames := []string{}
168+
for _, sg := range server.SecurityGroups {
169+
secGrpNames = append(secGrpNames, sg["name"].(string))
170+
}
171+
172+
log.Printf("[DEBUG] Setting security groups: %+v", secGrpNames)
173+
174+
d.Set("security_groups", secGrpNames)
175+
176+
flavorId, ok := server.Flavor["id"].(string)
177+
if !ok {
178+
return fmt.Errorf("Error setting OpenStack server's flavor: %v", server.Flavor)
179+
}
180+
d.Set("flavor_id", flavorId)
181+
182+
d.Set("key_pair", server.KeyName)
183+
flavor, err := flavors.Get(computeClient, flavorId).Extract()
184+
if err != nil {
185+
return err
186+
}
187+
d.Set("flavor_name", flavor.Name)
188+
189+
// Set the instance's image information appropriately
190+
if err := setImageInformation(computeClient, server, d); err != nil {
191+
return err
192+
}
193+
194+
// Build a custom struct for the availability zone extension
195+
var serverWithAZ struct {
196+
servers.Server
197+
availabilityzones.ServerAvailabilityZoneExt
198+
}
199+
200+
// Do another Get so the above work is not disturbed.
201+
err = servers.Get(computeClient, d.Id()).ExtractInto(&serverWithAZ)
202+
if err != nil {
203+
return CheckDeleted(d, err, "server")
204+
}
205+
// Set the availability zone
206+
d.Set("availability_zone", serverWithAZ.AvailabilityZone)
207+
208+
// Set the region
209+
d.Set("region", GetRegion(d, config))
210+
211+
// Set the current power_state
212+
currentStatus := strings.ToLower(server.Status)
213+
switch currentStatus {
214+
case "active", "shutoff", "error", "migrating", "shelved_offloaded", "shelved":
215+
d.Set("power_state", currentStatus)
216+
default:
217+
return fmt.Errorf("Invalid power_state for instance %s: %s", d.Id(), server.Status)
218+
}
219+
220+
// Populate tags.
221+
computeClient.Microversion = computeV2TagsExtensionMicroversion
222+
instanceTags, err := tags.List(computeClient, server.ID).Extract()
223+
if err != nil {
224+
log.Printf("[DEBUG] Unable to get tags for openstack_compute_instance_v2: %s", err)
225+
} else {
226+
d.Set("tags", instanceTags)
227+
}
228+
229+
return nil
230+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package openstack
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
9+
)
10+
11+
func TestAccComputeV2InstanceDataSource(t *testing.T) {
12+
13+
resource.Test(t, resource.TestCase{
14+
PreCheck: func() { testAccPreCheck(t) },
15+
Providers: testAccProviders,
16+
Steps: []resource.TestStep{
17+
{
18+
Config: testAccComputeV2InstanceDataSource_basic,
19+
},
20+
{
21+
Config: testAccComputeV2InstanceDataSource_source,
22+
Check: resource.ComposeTestCheckFunc(
23+
testAccCheckComputeInstanceV2DataSourceId("data.openstack_compute_instance_v2.source_1"),
24+
resource.TestCheckResourceAttr("data.openstack_compute_instance_v2.source_1", "name", "instance_1"),
25+
resource.TestCheckResourceAttrPair("data.openstack_compute_instance_v2.source_1", "metadata", "openstack_compute_instance_v2.instance_1", "metadata"),
26+
resource.TestCheckResourceAttrSet("data.openstack_compute_instance_v2.source_1", "network.0.name"),
27+
),
28+
},
29+
},
30+
})
31+
}
32+
33+
func testAccCheckComputeInstanceV2DataSourceId(n string) resource.TestCheckFunc {
34+
return func(s *terraform.State) error {
35+
rs, ok := s.RootModule().Resources[n]
36+
if !ok {
37+
return fmt.Errorf("Can't find compute instance data source: %s", n)
38+
}
39+
40+
if rs.Primary.ID == "" {
41+
return fmt.Errorf("Compute instance data source ID not set")
42+
}
43+
44+
return nil
45+
}
46+
}
47+
48+
var testAccComputeV2InstanceDataSource_basic = fmt.Sprintf(`
49+
resource "openstack_compute_instance_v2" "instance_1" {
50+
name = "instance_1"
51+
security_groups = ["default"]
52+
metadata = {
53+
foo = "bar"
54+
}
55+
network {
56+
uuid = "%s"
57+
}
58+
}
59+
`, OS_NETWORK_ID)
60+
61+
var testAccComputeV2InstanceDataSource_source = fmt.Sprintf(`
62+
%s
63+
64+
data "openstack_compute_instance_v2" "source_1" {
65+
id = "${openstack_compute_instance_v2.instance_1.id}"
66+
}
67+
`, testAccComputeV2InstanceDataSource_basic)

‎openstack/provider.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ func Provider() terraform.ResourceProvider {
255255
"openstack_blockstorage_volume_v2": dataSourceBlockStorageVolumeV2(),
256256
"openstack_blockstorage_volume_v3": dataSourceBlockStorageVolumeV3(),
257257
"openstack_compute_availability_zones_v2": dataSourceComputeAvailabilityZonesV2(),
258+
"openstack_compute_instance_v2": dataSourceComputeInstanceV2(),
258259
"openstack_compute_flavor_v2": dataSourceComputeFlavorV2(),
259260
"openstack_compute_keypair_v2": dataSourceComputeKeypairV2(),
260261
"openstack_containerinfra_clustertemplate_v1": dataSourceContainerInfraClusterTemplateV1(),
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
layout: "openstack"
3+
page_title: "OpenStack: openstack_compute_instance_v2"
4+
sidebar_current: "docs-openstack-datasource-compute-instance-v2"
5+
description: |-
6+
Get information on an OpenStack Instance
7+
---
8+
9+
# openstack\_compute\_flavor\_v2
10+
11+
Use this data source to get the details of a running server
12+
13+
## Example Usage
14+
15+
```hcl
16+
data "openstack_compute_instance_v2" "instance" {
17+
# Randomly generated UUID, for demonstration purposes
18+
id = "2ba26dc6-a12d-4889-8f25-794ea5bf4453"
19+
}
20+
```
21+
22+
## Argument Reference
23+
24+
* `id` - (Required) The UUID of the instance
25+
26+
27+
## Attributes Reference
28+
29+
In addition to the above, the following attributes are exported:
30+
31+
* `name` - The name of the server.
32+
33+
* `image_id` - The image ID used to create the server.
34+
35+
* `flavor_id` - The flavor ID used to create the server.
36+
37+
* `flavor_name` - The flavor name used to create the server.
38+
39+
* `user_data` - The user data added when the server was created.
40+
41+
* `security_groups` - An array of security group names associated with this server.
42+
43+
* `availability_zone` - The availability zone of this server.
44+
45+
* `network` - An array of maps, detailed below.
46+
47+
* `access_ip_v4` - The first IPv4 address assigned to this server.
48+
49+
* `access_ip_v6` - The first IPv6 address assigned to this server.
50+
51+
* `key_pair` - The name of the key pair assigned to this server.
52+
53+
* `tags` - A set of string tags assigned to this server.
54+
55+
* `metadata` - A set of key/value pairs made available to the server.
56+
57+
58+
The `network` block is defined as:
59+
60+
* `uuid` - The UUID of the network
61+
62+
* `name` - The name of the network
63+
64+
* `fixed_ip_v4` - The IPv4 address assigned to this network port.
65+
66+
* `fixed_ip_v6` - The IPv6 address assigned to this network port.
67+
68+
* `port` - The port UUID for this network
69+
70+
* `mac` - The MAC address assigned to this network interface.

0 commit comments

Comments
 (0)