Skip to content

Commit 2d90b19

Browse files
authored
serviceoffering: add params for custom offering, storage tags, encryptroot (#212)
1 parent 8c28240 commit 2d90b19

File tree

3 files changed

+192
-15
lines changed

3 files changed

+192
-15
lines changed

cloudstack/resource_cloudstack_service_offering.go

Lines changed: 133 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package cloudstack
2222
import (
2323
"fmt"
2424
"log"
25+
"strconv"
2526

2627
"github.com/apache/cloudstack-go/v2/cloudstack"
2728
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -97,6 +98,48 @@ func resourceCloudStackServiceOffering() *schema.Resource {
9798
return
9899
},
99100
},
101+
"customized": {
102+
Description: "Whether service offering allows custom CPU/memory or not",
103+
Type: schema.TypeBool,
104+
Optional: true,
105+
ForceNew: true,
106+
Computed: true,
107+
},
108+
"min_cpu_number": {
109+
Description: "Minimum number of CPU cores allowed",
110+
Type: schema.TypeInt,
111+
Optional: true,
112+
ForceNew: true,
113+
},
114+
"max_cpu_number": {
115+
Description: "Maximum number of CPU cores allowed",
116+
Type: schema.TypeInt,
117+
Optional: true,
118+
ForceNew: true,
119+
},
120+
"min_memory": {
121+
Description: "Minimum memory allowed (MB)",
122+
Type: schema.TypeInt,
123+
Optional: true,
124+
ForceNew: true,
125+
},
126+
"max_memory": {
127+
Description: "Maximum memory allowed (MB)",
128+
Type: schema.TypeInt,
129+
Optional: true,
130+
ForceNew: true,
131+
},
132+
"encrypt_root": {
133+
Description: "Encrypt the root disk for VMs using this service offering",
134+
Type: schema.TypeBool,
135+
Optional: true,
136+
ForceNew: true,
137+
},
138+
"storage_tags": {
139+
Description: "Storage tags to associate with the service offering",
140+
Type: schema.TypeString,
141+
Optional: true,
142+
},
100143
},
101144
}
102145
}
@@ -108,12 +151,15 @@ func resourceCloudStackServiceOfferingCreate(d *schema.ResourceData, meta interf
108151

109152
// Create a new parameter struct
110153
p := cs.ServiceOffering.NewCreateServiceOfferingParams(display_text, name)
111-
if v, ok := d.GetOk("cpu_number"); ok {
112-
p.SetCpunumber(v.(int))
154+
155+
cpuNumber, cpuNumberOk := d.GetOk("cpu_number")
156+
if cpuNumberOk {
157+
p.SetCpunumber(cpuNumber.(int))
113158
}
114159

115-
if v, ok := d.GetOk("cpu_speed"); ok {
116-
p.SetCpuspeed(v.(int))
160+
cpuSpeed, cpuSpeedOk := d.GetOk("cpu_speed")
161+
if cpuSpeedOk {
162+
p.SetCpuspeed(cpuSpeed.(int))
117163
}
118164

119165
if v, ok := d.GetOk("host_tags"); ok {
@@ -124,8 +170,9 @@ func resourceCloudStackServiceOfferingCreate(d *schema.ResourceData, meta interf
124170
p.SetLimitcpuuse(v.(bool))
125171
}
126172

127-
if v, ok := d.GetOk("memory"); ok {
128-
p.SetMemory(v.(int))
173+
memory, memoryOk := d.GetOk("memory")
174+
if memoryOk {
175+
p.SetMemory(memory.(int))
129176
}
130177

131178
if v, ok := d.GetOk("offer_ha"); ok {
@@ -136,6 +183,39 @@ func resourceCloudStackServiceOfferingCreate(d *schema.ResourceData, meta interf
136183
p.SetStoragetype(v.(string))
137184
}
138185

186+
customized := false
187+
if v, ok := d.GetOk("customized"); ok {
188+
customized = v.(bool)
189+
}
190+
if !cpuNumberOk && !cpuSpeedOk && !memoryOk {
191+
customized = true
192+
}
193+
p.SetCustomized(customized)
194+
195+
if v, ok := d.GetOk("min_cpu_number"); ok {
196+
p.SetMincpunumber(v.(int))
197+
}
198+
199+
if v, ok := d.GetOk("max_cpu_number"); ok {
200+
p.SetMaxcpunumber(v.(int))
201+
}
202+
203+
if v, ok := d.GetOk("min_memory"); ok {
204+
p.SetMinmemory(v.(int))
205+
}
206+
207+
if v, ok := d.GetOk("max_memory"); ok {
208+
p.SetMaxmemory(v.(int))
209+
}
210+
211+
if v, ok := d.GetOk("encrypt_root"); ok {
212+
p.SetEncryptroot(v.(bool))
213+
}
214+
215+
if v, ok := d.GetOk("storage_tags"); ok {
216+
p.SetTags(v.(string))
217+
}
218+
139219
log.Printf("[DEBUG] Creating Service Offering %s", name)
140220
s, err := cs.ServiceOffering.CreateServiceOffering(p)
141221

@@ -168,15 +248,22 @@ func resourceCloudStackServiceOfferingRead(d *schema.ResourceData, meta interfac
168248
d.SetId(s.Id)
169249

170250
fields := map[string]interface{}{
171-
"name": s.Name,
172-
"display_text": s.Displaytext,
173-
"cpu_number": s.Cpunumber,
174-
"cpu_speed": s.Cpuspeed,
175-
"host_tags": s.Hosttags,
176-
"limit_cpu_use": s.Limitcpuuse,
177-
"memory": s.Memory,
178-
"offer_ha": s.Offerha,
179-
"storage_type": s.Storagetype,
251+
"name": s.Name,
252+
"display_text": s.Displaytext,
253+
"cpu_number": s.Cpunumber,
254+
"cpu_speed": s.Cpuspeed,
255+
"host_tags": s.Hosttags,
256+
"limit_cpu_use": s.Limitcpuuse,
257+
"memory": s.Memory,
258+
"offer_ha": s.Offerha,
259+
"storage_type": s.Storagetype,
260+
"customized": s.Iscustomized,
261+
"min_cpu_number": getIntFromDetails(s.Serviceofferingdetails, "mincpunumber"),
262+
"max_cpu_number": getIntFromDetails(s.Serviceofferingdetails, "maxcpunumber"),
263+
"min_memory": getIntFromDetails(s.Serviceofferingdetails, "minmemory"),
264+
"max_memory": getIntFromDetails(s.Serviceofferingdetails, "maxmemory"),
265+
"encrypt_root": s.Encryptroot,
266+
"storage_tags": s.Storagetags,
180267
}
181268

182269
for k, v := range fields {
@@ -247,6 +334,24 @@ func resourceCloudStackServiceOfferingUpdate(d *schema.ResourceData, meta interf
247334

248335
}
249336

337+
if d.HasChange("storage_tags") {
338+
log.Printf("[DEBUG] Tags changed for %s, starting update", name)
339+
340+
// Create a new parameter struct
341+
p := cs.ServiceOffering.NewUpdateServiceOfferingParams(d.Id())
342+
343+
// Set the new tags
344+
p.SetStoragetags(d.Get("storage_tags").(string))
345+
346+
// Update the host tags
347+
_, err := cs.ServiceOffering.UpdateServiceOffering(p)
348+
if err != nil {
349+
return fmt.Errorf(
350+
"Error updating the storage tags for service offering %s: %s", name, err)
351+
}
352+
353+
}
354+
250355
return resourceCloudStackServiceOfferingRead(d, meta)
251356
}
252357

@@ -263,3 +368,16 @@ func resourceCloudStackServiceOfferingDelete(d *schema.ResourceData, meta interf
263368

264369
return nil
265370
}
371+
372+
// getIntFromDetails extracts an integer value from the service offering details map.
373+
func getIntFromDetails(details map[string]string, key string) interface{} {
374+
if details == nil {
375+
return nil
376+
}
377+
if val, ok := details[key]; ok {
378+
if i, err := strconv.Atoi(val); err == nil {
379+
return i
380+
}
381+
}
382+
return nil
383+
}

cloudstack/resource_cloudstack_service_offering_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,42 @@ func testAccCheckCloudStackServiceOfferingExists(n string, so *cloudstack.Servic
8383
return nil
8484
}
8585
}
86+
87+
func TestAccCloudStackServiceOffering_customized(t *testing.T) {
88+
var so cloudstack.ServiceOffering
89+
resource.Test(t, resource.TestCase{
90+
PreCheck: func() { testAccPreCheck(t) },
91+
Providers: testAccProviders,
92+
Steps: []resource.TestStep{
93+
{
94+
Config: testAccCloudStackServiceOffering_customized,
95+
Check: resource.ComposeTestCheckFunc(
96+
testAccCheckCloudStackServiceOfferingExists("cloudstack_service_offering.custom", &so),
97+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "customized", "true"),
98+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "min_cpu_number", "1"),
99+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "max_cpu_number", "8"),
100+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "min_memory", "1024"),
101+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "max_memory", "16384"),
102+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "cpu_speed", "1000"),
103+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "encrypt_root", "true"),
104+
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", "storage_tags", "production,ssd"),
105+
),
106+
},
107+
},
108+
})
109+
}
110+
111+
const testAccCloudStackServiceOffering_customized = `
112+
resource "cloudstack_service_offering" "custom" {
113+
name = "custom_service_offering"
114+
display_text = "Custom Test"
115+
customized = true
116+
min_cpu_number = 1
117+
max_cpu_number = 8
118+
min_memory = 1024
119+
max_memory = 16384
120+
cpu_speed = 1000
121+
encrypt_root = true
122+
storage_tags = "production,ssd"
123+
}
124+
`

website/docs/r/service_offering.html.markdown

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ The following arguments are supported:
4949
* `storage_type` - (Optional) The storage type of the service offering. Values are `local` and `shared`.
5050
Changing this forces a new resource to be created.
5151

52+
* `customized` - (Optional) Whether the service offering allows custom CPU and memory values. Set to `true` to enable users to specify CPU/memory within the min/max constraints for constrained offerings and any value for unconstrained offerings.
53+
Changing this forces a new resource to be created.
54+
55+
* `min_cpu_number` - (Optional) Minimum number of CPU cores allowed for customized offerings.
56+
Changing this forces a new resource to be created.
57+
58+
* `max_cpu_number` - (Optional) Maximum number of CPU cores allowed for customized offerings.
59+
Changing this forces a new resource to be created.
60+
61+
* `min_memory` - (Optional) Minimum memory (in MB) allowed for customized offerings.
62+
Changing this forces a new resource to be created.
63+
64+
* `max_memory` - (Optional) Maximum memory (in MB) allowed for customized offerings.
65+
Changing this forces a new resource to be created.
66+
67+
* `encrypt_root` - (Optional) Whether to encrypt the root disk for VMs using this service offering.
68+
Changing this forces a new resource to be created.
69+
70+
* `storage_tags` - (Optional) Storage tags to associate with the service offering.
71+
5272
## Attributes Reference
5373

5474
The following attributes are exported:

0 commit comments

Comments
 (0)