This is an automated email from the ASF dual-hosted git repository.

vishesh pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/cloudstack-terraform-provider.git


The following commit(s) were added to refs/heads/main by this push:
     new 2d90b19  serviceoffering: add params for custom offering, storage 
tags, encryptroot (#212)
2d90b19 is described below

commit 2d90b197c345f209cbfc73a25ff67d95e3efd5a9
Author: Abhishek Kumar <abhishek.mr...@gmail.com>
AuthorDate: Thu Aug 28 17:10:21 2025 +0530

    serviceoffering: add params for custom offering, storage tags, encryptroot 
(#212)
---
 cloudstack/resource_cloudstack_service_offering.go | 148 ++++++++++++++++++---
 .../resource_cloudstack_service_offering_test.go   |  39 ++++++
 website/docs/r/service_offering.html.markdown      |  20 +++
 3 files changed, 192 insertions(+), 15 deletions(-)

diff --git a/cloudstack/resource_cloudstack_service_offering.go 
b/cloudstack/resource_cloudstack_service_offering.go
index 170e05e..107938d 100644
--- a/cloudstack/resource_cloudstack_service_offering.go
+++ b/cloudstack/resource_cloudstack_service_offering.go
@@ -22,6 +22,7 @@ package cloudstack
 import (
        "fmt"
        "log"
+       "strconv"
 
        "github.com/apache/cloudstack-go/v2/cloudstack"
        "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -97,6 +98,48 @@ func resourceCloudStackServiceOffering() *schema.Resource {
                                        return
                                },
                        },
+                       "customized": {
+                               Description: "Whether service offering allows 
custom CPU/memory or not",
+                               Type:        schema.TypeBool,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Computed:    true,
+                       },
+                       "min_cpu_number": {
+                               Description: "Minimum number of CPU cores 
allowed",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "max_cpu_number": {
+                               Description: "Maximum number of CPU cores 
allowed",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "min_memory": {
+                               Description: "Minimum memory allowed (MB)",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "max_memory": {
+                               Description: "Maximum memory allowed (MB)",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "encrypt_root": {
+                               Description: "Encrypt the root disk for VMs 
using this service offering",
+                               Type:        schema.TypeBool,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "storage_tags": {
+                               Description: "Storage tags to associate with 
the service offering",
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                       },
                },
        }
 }
@@ -108,12 +151,15 @@ func resourceCloudStackServiceOfferingCreate(d 
*schema.ResourceData, meta interf
 
        // Create a new parameter struct
        p := cs.ServiceOffering.NewCreateServiceOfferingParams(display_text, 
name)
-       if v, ok := d.GetOk("cpu_number"); ok {
-               p.SetCpunumber(v.(int))
+
+       cpuNumber, cpuNumberOk := d.GetOk("cpu_number")
+       if cpuNumberOk {
+               p.SetCpunumber(cpuNumber.(int))
        }
 
-       if v, ok := d.GetOk("cpu_speed"); ok {
-               p.SetCpuspeed(v.(int))
+       cpuSpeed, cpuSpeedOk := d.GetOk("cpu_speed")
+       if cpuSpeedOk {
+               p.SetCpuspeed(cpuSpeed.(int))
        }
 
        if v, ok := d.GetOk("host_tags"); ok {
@@ -124,8 +170,9 @@ func resourceCloudStackServiceOfferingCreate(d 
*schema.ResourceData, meta interf
                p.SetLimitcpuuse(v.(bool))
        }
 
-       if v, ok := d.GetOk("memory"); ok {
-               p.SetMemory(v.(int))
+       memory, memoryOk := d.GetOk("memory")
+       if memoryOk {
+               p.SetMemory(memory.(int))
        }
 
        if v, ok := d.GetOk("offer_ha"); ok {
@@ -136,6 +183,39 @@ func resourceCloudStackServiceOfferingCreate(d 
*schema.ResourceData, meta interf
                p.SetStoragetype(v.(string))
        }
 
+       customized := false
+       if v, ok := d.GetOk("customized"); ok {
+               customized = v.(bool)
+       }
+       if !cpuNumberOk && !cpuSpeedOk && !memoryOk {
+               customized = true
+       }
+       p.SetCustomized(customized)
+
+       if v, ok := d.GetOk("min_cpu_number"); ok {
+               p.SetMincpunumber(v.(int))
+       }
+
+       if v, ok := d.GetOk("max_cpu_number"); ok {
+               p.SetMaxcpunumber(v.(int))
+       }
+
+       if v, ok := d.GetOk("min_memory"); ok {
+               p.SetMinmemory(v.(int))
+       }
+
+       if v, ok := d.GetOk("max_memory"); ok {
+               p.SetMaxmemory(v.(int))
+       }
+
+       if v, ok := d.GetOk("encrypt_root"); ok {
+               p.SetEncryptroot(v.(bool))
+       }
+
+       if v, ok := d.GetOk("storage_tags"); ok {
+               p.SetTags(v.(string))
+       }
+
        log.Printf("[DEBUG] Creating Service Offering %s", name)
        s, err := cs.ServiceOffering.CreateServiceOffering(p)
 
@@ -168,15 +248,22 @@ func resourceCloudStackServiceOfferingRead(d 
*schema.ResourceData, meta interfac
        d.SetId(s.Id)
 
        fields := map[string]interface{}{
-               "name":          s.Name,
-               "display_text":  s.Displaytext,
-               "cpu_number":    s.Cpunumber,
-               "cpu_speed":     s.Cpuspeed,
-               "host_tags":     s.Hosttags,
-               "limit_cpu_use": s.Limitcpuuse,
-               "memory":        s.Memory,
-               "offer_ha":      s.Offerha,
-               "storage_type":  s.Storagetype,
+               "name":           s.Name,
+               "display_text":   s.Displaytext,
+               "cpu_number":     s.Cpunumber,
+               "cpu_speed":      s.Cpuspeed,
+               "host_tags":      s.Hosttags,
+               "limit_cpu_use":  s.Limitcpuuse,
+               "memory":         s.Memory,
+               "offer_ha":       s.Offerha,
+               "storage_type":   s.Storagetype,
+               "customized":     s.Iscustomized,
+               "min_cpu_number": getIntFromDetails(s.Serviceofferingdetails, 
"mincpunumber"),
+               "max_cpu_number": getIntFromDetails(s.Serviceofferingdetails, 
"maxcpunumber"),
+               "min_memory":     getIntFromDetails(s.Serviceofferingdetails, 
"minmemory"),
+               "max_memory":     getIntFromDetails(s.Serviceofferingdetails, 
"maxmemory"),
+               "encrypt_root":   s.Encryptroot,
+               "storage_tags":   s.Storagetags,
        }
 
        for k, v := range fields {
@@ -247,6 +334,24 @@ func resourceCloudStackServiceOfferingUpdate(d 
*schema.ResourceData, meta interf
 
        }
 
+       if d.HasChange("storage_tags") {
+               log.Printf("[DEBUG] Tags changed for %s, starting update", name)
+
+               // Create a new parameter struct
+               p := cs.ServiceOffering.NewUpdateServiceOfferingParams(d.Id())
+
+               // Set the new tags
+               p.SetStoragetags(d.Get("storage_tags").(string))
+
+               // Update the host tags
+               _, err := cs.ServiceOffering.UpdateServiceOffering(p)
+               if err != nil {
+                       return fmt.Errorf(
+                               "Error updating the storage tags for service 
offering %s: %s", name, err)
+               }
+
+       }
+
        return resourceCloudStackServiceOfferingRead(d, meta)
 }
 
@@ -263,3 +368,16 @@ func resourceCloudStackServiceOfferingDelete(d 
*schema.ResourceData, meta interf
 
        return nil
 }
+
+// getIntFromDetails extracts an integer value from the service offering 
details map.
+func getIntFromDetails(details map[string]string, key string) interface{} {
+       if details == nil {
+               return nil
+       }
+       if val, ok := details[key]; ok {
+               if i, err := strconv.Atoi(val); err == nil {
+                       return i
+               }
+       }
+       return nil
+}
diff --git a/cloudstack/resource_cloudstack_service_offering_test.go 
b/cloudstack/resource_cloudstack_service_offering_test.go
index fc29628..d4634c9 100644
--- a/cloudstack/resource_cloudstack_service_offering_test.go
+++ b/cloudstack/resource_cloudstack_service_offering_test.go
@@ -83,3 +83,42 @@ func testAccCheckCloudStackServiceOfferingExists(n string, 
so *cloudstack.Servic
                return nil
        }
 }
+
+func TestAccCloudStackServiceOffering_customized(t *testing.T) {
+       var so cloudstack.ServiceOffering
+       resource.Test(t, resource.TestCase{
+               PreCheck:  func() { testAccPreCheck(t) },
+               Providers: testAccProviders,
+               Steps: []resource.TestStep{
+                       {
+                               Config: 
testAccCloudStackServiceOffering_customized,
+                               Check: resource.ComposeTestCheckFunc(
+                                       
testAccCheckCloudStackServiceOfferingExists("cloudstack_service_offering.custom",
 &so),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"customized", "true"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"min_cpu_number", "1"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"max_cpu_number", "8"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"min_memory", "1024"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"max_memory", "16384"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"cpu_speed", "1000"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"encrypt_root", "true"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.custom", 
"storage_tags", "production,ssd"),
+                               ),
+                       },
+               },
+       })
+}
+
+const testAccCloudStackServiceOffering_customized = `
+resource "cloudstack_service_offering" "custom" {
+  name             = "custom_service_offering"
+  display_text     = "Custom Test"
+  customized       = true
+  min_cpu_number   = 1
+  max_cpu_number   = 8
+  min_memory       = 1024
+  max_memory       = 16384
+  cpu_speed        = 1000
+  encrypt_root     = true
+  storage_tags     = "production,ssd"
+}
+`
diff --git a/website/docs/r/service_offering.html.markdown 
b/website/docs/r/service_offering.html.markdown
index 94735eb..33852cb 100644
--- a/website/docs/r/service_offering.html.markdown
+++ b/website/docs/r/service_offering.html.markdown
@@ -49,6 +49,26 @@ The following arguments are supported:
 * `storage_type` - (Optional) The storage type of the service offering. Values 
are `local` and `shared`.
     Changing this forces a new resource to be created.
 
+* `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.
+    Changing this forces a new resource to be created.
+
+* `min_cpu_number` - (Optional) Minimum number of CPU cores allowed for 
customized offerings.
+    Changing this forces a new resource to be created.
+
+* `max_cpu_number` - (Optional) Maximum number of CPU cores allowed for 
customized offerings.
+    Changing this forces a new resource to be created.
+
+* `min_memory` - (Optional) Minimum memory (in MB) allowed for customized 
offerings.
+    Changing this forces a new resource to be created.
+
+* `max_memory` - (Optional) Maximum memory (in MB) allowed for customized 
offerings.
+    Changing this forces a new resource to be created.
+
+* `encrypt_root` - (Optional) Whether to encrypt the root disk for VMs using 
this service offering.
+    Changing this forces a new resource to be created.
+
+* `storage_tags` - (Optional) Storage tags to associate with the service 
offering.
+
 ## Attributes Reference
 
 The following attributes are exported:

Reply via email to