Skip to content

Commit f0615b8

Browse files
jeanvetorellojean
andauthored
feat: Add service_offering_details support for GPU configuration (#247)
* feat: Add service_offering_details support for GPU configuration - Add service_offering_details attribute to cloudstack_service_offering resource - Support for GPU configuration with pciDevice and vgpuType parameters - Include comprehensive test coverage and documentation - Add practical examples for GPU service offerings - Addresses issue #246 * docs: Add documentation for service_offering_details feature - Update service offering documentation with GPU examples - Add service_offering_details parameter documentation - Update CHANGELOG with new feature entry - Include practical examples for GPU configuration * fix: Apply gofmt formatting to resource_cloudstack_service_offering.go - Fix code formatting to comply with Go standards - Align map fields and remove trailing whitespace - Required for CI/CD pipeline to pass * Add missing cpu_speed to GPU service offering test add missing cpu_speed --------- Co-authored-by: jean <[email protected]>
1 parent c50eed8 commit f0615b8

File tree

4 files changed

+123
-16
lines changed

4 files changed

+123
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## 0.4.0 (Unreleased)
22

3+
FEATURES:
4+
5+
* **New Resource Attribute**: `cloudstack_service_offering` now supports `service_offering_details` for GPU configuration and other advanced settings [GH-246]
6+
37
IMPROVEMENTS:
48

59
* Restore support for managing resource tags as CloudStack 4.11.3+ and 4.12+ support tags again [GH-65]

cloudstack/resource_cloudstack_service_offering.go

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ func resourceCloudStackServiceOffering() *schema.Resource {
140140
Type: schema.TypeString,
141141
Optional: true,
142142
},
143+
"service_offering_details": {
144+
Description: "Service offering details for GPU configuration and other advanced settings",
145+
Type: schema.TypeMap,
146+
Optional: true,
147+
ForceNew: true,
148+
Elem: &schema.Schema{
149+
Type: schema.TypeString,
150+
},
151+
},
143152
},
144153
}
145154
}
@@ -216,6 +225,14 @@ func resourceCloudStackServiceOfferingCreate(d *schema.ResourceData, meta interf
216225
p.SetTags(v.(string))
217226
}
218227

228+
if details, ok := d.GetOk("service_offering_details"); ok {
229+
serviceOfferingDetails := make(map[string]string)
230+
for k, v := range details.(map[string]interface{}) {
231+
serviceOfferingDetails[k] = v.(string)
232+
}
233+
p.SetServiceofferingdetails(serviceOfferingDetails)
234+
}
235+
219236
log.Printf("[DEBUG] Creating Service Offering %s", name)
220237
s, err := cs.ServiceOffering.CreateServiceOffering(p)
221238

@@ -248,22 +265,23 @@ func resourceCloudStackServiceOfferingRead(d *schema.ResourceData, meta interfac
248265
d.SetId(s.Id)
249266

250267
fields := map[string]interface{}{
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,
268+
"name": s.Name,
269+
"display_text": s.Displaytext,
270+
"cpu_number": s.Cpunumber,
271+
"cpu_speed": s.Cpuspeed,
272+
"host_tags": s.Hosttags,
273+
"limit_cpu_use": s.Limitcpuuse,
274+
"memory": s.Memory,
275+
"offer_ha": s.Offerha,
276+
"storage_type": s.Storagetype,
277+
"customized": s.Iscustomized,
278+
"min_cpu_number": getIntFromDetails(s.Serviceofferingdetails, "mincpunumber"),
279+
"max_cpu_number": getIntFromDetails(s.Serviceofferingdetails, "maxcpunumber"),
280+
"min_memory": getIntFromDetails(s.Serviceofferingdetails, "minmemory"),
281+
"max_memory": getIntFromDetails(s.Serviceofferingdetails, "maxmemory"),
282+
"encrypt_root": s.Encryptroot,
283+
"storage_tags": s.Storagetags,
284+
"service_offering_details": getServiceOfferingDetails(s.Serviceofferingdetails),
267285
}
268286

269287
for k, v := range fields {
@@ -381,3 +399,28 @@ func getIntFromDetails(details map[string]string, key string) interface{} {
381399
}
382400
return nil
383401
}
402+
403+
// getServiceOfferingDetails extracts custom service offering details while excluding
404+
// built-in details that are handled as separate schema fields
405+
func getServiceOfferingDetails(details map[string]string) map[string]interface{} {
406+
if details == nil {
407+
return make(map[string]interface{})
408+
}
409+
410+
// List of built-in details that are handled as separate schema fields
411+
builtInKeys := map[string]bool{
412+
"mincpunumber": true,
413+
"maxcpunumber": true,
414+
"minmemory": true,
415+
"maxmemory": true,
416+
}
417+
418+
result := make(map[string]interface{})
419+
for k, v := range details {
420+
if !builtInKeys[k] {
421+
result[k] = v
422+
}
423+
}
424+
425+
return result
426+
}

cloudstack/resource_cloudstack_service_offering_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,40 @@ resource "cloudstack_service_offering" "custom" {
122122
storage_tags = "production,ssd"
123123
}
124124
`
125+
126+
func TestAccCloudStackServiceOffering_gpu(t *testing.T) {
127+
var so cloudstack.ServiceOffering
128+
resource.Test(t, resource.TestCase{
129+
PreCheck: func() { testAccPreCheck(t) },
130+
Providers: testAccProviders,
131+
Steps: []resource.TestStep{
132+
{
133+
Config: testAccCloudStackServiceOffering_gpu,
134+
Check: resource.ComposeTestCheckFunc(
135+
testAccCheckCloudStackServiceOfferingExists("cloudstack_service_offering.gpu", &so),
136+
resource.TestCheckResourceAttr("cloudstack_service_offering.gpu", "name", "gpu_service_offering"),
137+
resource.TestCheckResourceAttr("cloudstack_service_offering.gpu", "display_text", "GPU Test"),
138+
resource.TestCheckResourceAttr("cloudstack_service_offering.gpu", "cpu_number", "4"),
139+
resource.TestCheckResourceAttr("cloudstack_service_offering.gpu", "memory", "16384"),
140+
resource.TestCheckResourceAttr("cloudstack_service_offering.gpu", "service_offering_details.pciDevice", "Group of NVIDIA A6000 GPUs"),
141+
resource.TestCheckResourceAttr("cloudstack_service_offering.gpu", "service_offering_details.vgpuType", "A6000-8A"),
142+
),
143+
},
144+
},
145+
})
146+
}
147+
148+
const testAccCloudStackServiceOffering_gpu = `
149+
resource "cloudstack_service_offering" "gpu" {
150+
name = "gpu_service_offering"
151+
display_text = "GPU Test"
152+
cpu_number = 4
153+
memory = 16384
154+
cpu_speed = 1000
155+
156+
service_offering_details = {
157+
pciDevice = "Group of NVIDIA A6000 GPUs"
158+
vgpuType = "A6000-8A"
159+
}
160+
}
161+
`

website/docs/r/service_offering.html.markdown

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,30 @@ A `cloudstack_service_offering` resource manages a service offering within Cloud
1212

1313
## Example Usage
1414

15+
### Basic Service Offering
16+
1517
```hcl
1618
resource "cloudstack_service_offering" "example" {
1719
name = "example-service-offering"
1820
display_text = "Example Service Offering"
21+
cpu_number = 2
22+
memory = 4096
23+
}
24+
```
25+
26+
### GPU Service Offering
27+
28+
```hcl
29+
resource "cloudstack_service_offering" "gpu_offering" {
30+
name = "gpu-a6000"
31+
display_text = "GPU A6000 Instance"
32+
cpu_number = 4
33+
memory = 16384
34+
35+
service_offering_details = {
36+
pciDevice = "Group of NVIDIA A6000 GPUs"
37+
vgpuType = "A6000-8A"
38+
}
1939
}
2040
```
2141

@@ -69,6 +89,9 @@ The following arguments are supported:
6989

7090
* `storage_tags` - (Optional) Storage tags to associate with the service offering.
7191

92+
* `service_offering_details` - (Optional) A map of service offering details for GPU configuration and other advanced settings. Common keys include `pciDevice` and `vgpuType` for GPU offerings.
93+
Changing this forces a new resource to be created.
94+
7295
## Attributes Reference
7396

7497
The following attributes are exported:

0 commit comments

Comments
 (0)