Skip to content

Commit 02a57d5

Browse files
authored
Add new resource blockstorage_volume_type_v3 (terraform-provider-openstack#1204)
Add new resource volume_type. Update gophercloud to required functionality for volume_type extra_specs. For: terraform-provider-openstack#1201
1 parent 01106c6 commit 02a57d5

10 files changed

Lines changed: 491 additions & 1 deletion

‎go.mod‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/terraform-provider-openstack/terraform-provider-openstack
33
go 1.15
44

55
require (
6-
github.com/gophercloud/gophercloud v0.16.0
6+
github.com/gophercloud/gophercloud v0.16.1-0.20210310004848-3dc4bb870058
77
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae
88
github.com/hashicorp/terraform-plugin-sdk v1.16.0
99
github.com/mitchellh/go-homedir v1.1.0

‎go.sum‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055 h1:/wFA
155155
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
156156
github.com/gophercloud/gophercloud v0.16.0 h1:sWjPfypuzxRxjVbk3/MsU4H8jS0NNlyauZtIUl78BPU=
157157
github.com/gophercloud/gophercloud v0.16.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
158+
github.com/gophercloud/gophercloud v0.16.1-0.20210310004848-3dc4bb870058 h1:hPAQ2fnoMgzk5xOzaBDfL792GorxU5amuX5fBWODPVw=
159+
github.com/gophercloud/gophercloud v0.16.1-0.20210310004848-3dc4bb870058/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
158160
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae h1:Hi3IgB9RQDE15Kfovd8MTZrcana+UlQqNbOif8dLpA0=
159161
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae/go.mod h1:wx8HMD8oQD0Ryhz6+6ykq75PJ79iPyEqYHfwZ4l7OsA=
160162
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package openstack
2+
3+
import (
4+
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
5+
)
6+
7+
func expandBlockStorageVolumeTypeV3ExtraSpecs(raw map[string]interface{}) volumetypes.ExtraSpecsOpts {
8+
extraSpecs := make(volumetypes.ExtraSpecsOpts, len(raw))
9+
for k, v := range raw {
10+
extraSpecs[k] = v.(string)
11+
}
12+
13+
return extraSpecs
14+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package openstack
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
8+
)
9+
10+
func TestExpandBlockStorageVolumeTypeV3ExtraSpecs(t *testing.T) {
11+
raw := map[string]interface{}{
12+
"foo": "foo",
13+
"bar": "bar",
14+
}
15+
16+
expected := volumetypes.ExtraSpecsOpts{
17+
"foo": "foo",
18+
"bar": "bar",
19+
}
20+
21+
actual := expandBlockStorageVolumeTypeV3ExtraSpecs(raw)
22+
23+
if !reflect.DeepEqual(expected, actual) {
24+
t.Fatalf("Results differ. Want: %#v, but got %#v", expected, actual)
25+
}
26+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package openstack
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
7+
)
8+
9+
func TestAccBlockStorageV3VolumeType_importBasic(t *testing.T) {
10+
resourceName := "openstack_blockstorage_volume_type_v3.volume_type_1"
11+
12+
resource.Test(t, resource.TestCase{
13+
PreCheck: func() {
14+
testAccPreCheck(t)
15+
testAccPreCheckAdminOnly(t)
16+
},
17+
Providers: testAccProviders,
18+
CheckDestroy: testAccCheckBlockStorageVolumeTypeV3Destroy,
19+
Steps: []resource.TestStep{
20+
{
21+
Config: testAccBlockStorageVolumeTypeV3Basic,
22+
},
23+
24+
{
25+
ResourceName: resourceName,
26+
ImportState: true,
27+
ImportStateVerify: true,
28+
},
29+
},
30+
})
31+
}

‎openstack/provider.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ func Provider() terraform.ResourceProvider {
301301
"openstack_blockstorage_volume_v3": resourceBlockStorageVolumeV3(),
302302
"openstack_blockstorage_volume_attach_v2": resourceBlockStorageVolumeAttachV2(),
303303
"openstack_blockstorage_volume_attach_v3": resourceBlockStorageVolumeAttachV3(),
304+
"openstack_blockstorage_volume_type_v3": resourceBlockStorageVolumeTypeV3(),
304305
"openstack_compute_aggregate_v2": resourceComputeAggregateV2(),
305306
"openstack_compute_flavor_v2": resourceComputeFlavorV2(),
306307
"openstack_compute_flavor_access_v2": resourceComputeFlavorAccessV2(),
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package openstack
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
9+
)
10+
11+
func resourceBlockStorageVolumeTypeV3() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceBlockStorageVolumeTypeV3Create,
14+
Read: resourceBlockStorageVolumeTypeV3Read,
15+
Update: resourceBlockStorageVolumeTypeV3Update,
16+
Delete: resourceBlockStorageVolumeTypeV3Delete,
17+
Importer: &schema.ResourceImporter{
18+
State: schema.ImportStatePassthrough,
19+
},
20+
21+
Schema: map[string]*schema.Schema{
22+
"region": {
23+
Type: schema.TypeString,
24+
Optional: true,
25+
Computed: true,
26+
ForceNew: true,
27+
},
28+
29+
"name": {
30+
Type: schema.TypeString,
31+
Required: true,
32+
},
33+
34+
"description": {
35+
Type: schema.TypeString,
36+
Optional: true,
37+
Computed: true,
38+
},
39+
40+
"is_public": {
41+
Type: schema.TypeBool,
42+
Optional: true,
43+
Computed: true,
44+
},
45+
46+
"extra_specs": {
47+
Type: schema.TypeMap,
48+
Optional: true,
49+
Computed: true,
50+
},
51+
},
52+
}
53+
}
54+
55+
func resourceBlockStorageVolumeTypeV3Create(d *schema.ResourceData, meta interface{}) error {
56+
config := meta.(*Config)
57+
blockStorageClient, err := config.BlockStorageV3Client(GetRegion(d, config))
58+
if err != nil {
59+
return fmt.Errorf("Error creating OpenStack block storage client: %s", err)
60+
}
61+
62+
name := d.Get("name").(string)
63+
description := d.Get("description").(string)
64+
isPublic := d.Get("is_public").(bool)
65+
extraSpecs := d.Get("extra_specs").(map[string]interface{})
66+
createOpts := volumetypes.CreateOpts{
67+
Name: name,
68+
Description: description,
69+
IsPublic: &isPublic,
70+
ExtraSpecs: expandToMapStringString(extraSpecs),
71+
}
72+
73+
log.Printf("[DEBUG] openstack_blockstorage_volume_type_v3 create options: %#v", createOpts)
74+
vt, err := volumetypes.Create(blockStorageClient, &createOpts).Extract()
75+
if err != nil {
76+
return fmt.Errorf("Error creating openstack_blockstorage_volume_type_v3 %s: %s", name, err)
77+
}
78+
79+
d.SetId(vt.ID)
80+
81+
return resourceBlockStorageVolumeTypeV3Read(d, meta)
82+
}
83+
84+
func resourceBlockStorageVolumeTypeV3Read(d *schema.ResourceData, meta interface{}) error {
85+
config := meta.(*Config)
86+
blockStorageClient, err := config.BlockStorageV3Client(GetRegion(d, config))
87+
if err != nil {
88+
return fmt.Errorf("Error creating OpenStack block storage client: %s", err)
89+
}
90+
91+
vt, err := volumetypes.Get(blockStorageClient, d.Id()).Extract()
92+
if err != nil {
93+
return CheckDeleted(d, err, "Error retrieving openstack_blockstorage_volume_type_v3")
94+
}
95+
96+
log.Printf("[DEBUG] Retrieved openstack_blockstorage_volume_type_v3 %s: %#v", d.Id(), vt)
97+
98+
d.Set("name", vt.Name)
99+
d.Set("description", vt.Description)
100+
d.Set("is_public", vt.IsPublic)
101+
d.Set("region", GetRegion(d, config))
102+
103+
es, err := volumetypes.ListExtraSpecs(blockStorageClient, d.Id()).Extract()
104+
if err != nil {
105+
return fmt.Errorf("Error reading extra_specs for openstack_blockstorage_volume_type_v3 %s: %s", d.Id(), err)
106+
}
107+
108+
if err := d.Set("extra_specs", es); err != nil {
109+
log.Printf("[WARN] Unable to set extra_specs for openstack_blockstorage_volume_type_v3 %s: %s", d.Id(), err)
110+
}
111+
112+
return nil
113+
}
114+
115+
func resourceBlockStorageVolumeTypeV3Update(d *schema.ResourceData, meta interface{}) error {
116+
config := meta.(*Config)
117+
blockStorageClient, err := config.BlockStorageV3Client(GetRegion(d, config))
118+
if err != nil {
119+
return fmt.Errorf("Error creating OpenStack block storage client: %s", err)
120+
}
121+
122+
hasChange := false
123+
var updateOpts volumetypes.UpdateOpts
124+
125+
if d.HasChange("name") {
126+
hasChange = true
127+
name := d.Get("name").(string)
128+
updateOpts.Name = &name
129+
}
130+
131+
if d.HasChange("description") {
132+
hasChange = true
133+
description := d.Get("description").(string)
134+
updateOpts.Description = &description
135+
}
136+
137+
if d.HasChange("is_public") {
138+
hasChange = true
139+
isPublic := d.Get("is_public").(bool)
140+
updateOpts.IsPublic = &isPublic
141+
}
142+
143+
if hasChange {
144+
_, err = volumetypes.Update(blockStorageClient, d.Id(), updateOpts).Extract()
145+
if err != nil {
146+
return fmt.Errorf("Error updating openstack_blockstorage_volume_type_v3 %s: %s", d.Id(), err)
147+
}
148+
}
149+
150+
if d.HasChange("extra_specs") {
151+
oldES, newES := d.GetChange("extra_specs")
152+
153+
// Delete all old extra specs.
154+
for oldKey := range oldES.(map[string]interface{}) {
155+
if err := volumetypes.DeleteExtraSpec(blockStorageClient, d.Id(), oldKey).ExtractErr(); err != nil {
156+
return fmt.Errorf("Error deleting extra_spec %s from openstack_blockstorage_volume_type_v3 %s: %s", oldKey, d.Id(), err)
157+
}
158+
}
159+
160+
// Add new extra specs.
161+
newESRaw := newES.(map[string]interface{})
162+
if len(newESRaw) > 0 {
163+
extraSpecs := expandBlockStorageVolumeTypeV3ExtraSpecs(newESRaw)
164+
165+
_, err := volumetypes.CreateExtraSpecs(blockStorageClient, d.Id(), extraSpecs).Extract()
166+
if err != nil {
167+
return fmt.Errorf("Error creating extra_specs for openstack_blockstorage_volume_type_v3 %s: %s", d.Id(), err)
168+
}
169+
}
170+
}
171+
172+
return resourceBlockStorageVolumeTypeV3Read(d, meta)
173+
}
174+
175+
func resourceBlockStorageVolumeTypeV3Delete(d *schema.ResourceData, meta interface{}) error {
176+
config := meta.(*Config)
177+
blockStorageClient, err := config.BlockStorageV3Client(GetRegion(d, config))
178+
if err != nil {
179+
return fmt.Errorf("Error creating OpenStack block storage client: %s", err)
180+
}
181+
182+
err = volumetypes.Delete(blockStorageClient, d.Id()).ExtractErr()
183+
if err != nil {
184+
return CheckDeleted(d, err, "Error deleting openstack_blockstorage_volume_type_v3")
185+
}
186+
187+
return nil
188+
}

0 commit comments

Comments
 (0)