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

pearl11594 pushed a commit to branch add-autoscale-support
in repository 
https://gitbox.apache.org/repos/asf/cloudstack-terraform-provider.git

commit 65495540fa211752c3c76e8bc77302ecff6bb6a4
Author: Pearl Dsilva <pearl1...@gmail.com>
AuthorDate: Fri Aug 29 11:59:47 2025 -0400

    Add support for Autoscale VM groups
---
 cloudstack/resource_cloudstack_autoscale_policy.go | 195 ++++++++++++++
 .../resource_cloudstack_autoscale_vm_group.go      | 286 +++++++++++++++++++++
 .../resource_cloudstack_autoscale_vm_profile.go    | 230 +++++++++++++++--
 cloudstack/resource_cloudstack_condition.go        | 172 +++++++++++++
 cloudstack/resource_cloudstack_counter.go          | 126 +++++++++
 5 files changed, 981 insertions(+), 28 deletions(-)

diff --git a/cloudstack/resource_cloudstack_autoscale_policy.go 
b/cloudstack/resource_cloudstack_autoscale_policy.go
new file mode 100644
index 0000000..85c6ed3
--- /dev/null
+++ b/cloudstack/resource_cloudstack_autoscale_policy.go
@@ -0,0 +1,195 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+       "fmt"
+       "log"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceCloudStackAutoScalePolicy() *schema.Resource {
+       return &schema.Resource{
+               Create: resourceCloudStackAutoScalePolicyCreate,
+               Read:   resourceCloudStackAutoScalePolicyRead,
+               Update: resourceCloudStackAutoScalePolicyUpdate,
+               Delete: resourceCloudStackAutoScalePolicyDelete,
+
+               Schema: map[string]*schema.Schema{
+                       "name": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Description: "the name of the autoscale policy",
+                       },
+                       "action": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "the action to be executed if all 
the conditions evaluate to true for the specified duration",
+                               ForceNew:    true,
+                       },
+                       "duration": {
+                               Type:        schema.TypeInt,
+                               Required:    true,
+                               Description: "the duration in which the 
conditions have to be true before action is taken",
+                       },
+                       "quiet_time": {
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               Description: "the cool down period in which the 
policy should not be evaluated after the action has been taken",
+                       },
+                       "condition_ids": {
+                               Type:        schema.TypeSet,
+                               Elem:        &schema.Schema{Type: 
schema.TypeString},
+                               Required:    true,
+                               Description: "the list of IDs of the conditions 
that are being evaluated on every interval",
+                       },
+               },
+       }
+}
+
+func resourceCloudStackAutoScalePolicyCreate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       action := d.Get("action").(string)
+       duration := d.Get("duration").(int)
+
+       conditionIds := []string{}
+       if v, ok := d.GetOk("condition_ids"); ok {
+               conditionSet := v.(*schema.Set)
+               for _, id := range conditionSet.List() {
+                       conditionIds = append(conditionIds, id.(string))
+               }
+       }
+
+       p := cs.AutoScale.NewCreateAutoScalePolicyParams(action, conditionIds, 
duration)
+
+       if v, ok := d.GetOk("name"); ok {
+               p.SetName(v.(string))
+       }
+       if v, ok := d.GetOk("quiet_time"); ok {
+               p.SetQuiettime(v.(int))
+       }
+
+       log.Printf("[DEBUG] Creating autoscale policy")
+       resp, err := cs.AutoScale.CreateAutoScalePolicy(p)
+       if err != nil {
+               return fmt.Errorf("Error creating autoscale policy: %s", err)
+       }
+
+       d.SetId(resp.Id)
+       log.Printf("[DEBUG] Autoscale policy created with ID: %s", resp.Id)
+
+       return resourceCloudStackAutoScalePolicyRead(d, meta)
+}
+
+func resourceCloudStackAutoScalePolicyRead(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewListAutoScalePoliciesParams()
+       p.SetId(d.Id())
+
+       resp, err := cs.AutoScale.ListAutoScalePolicies(p)
+       if err != nil {
+               return fmt.Errorf("Error retrieving autoscale policy: %s", err)
+       }
+
+       if resp.Count == 0 {
+               log.Printf("[DEBUG] Autoscale policy %s no longer exists", 
d.Id())
+               d.SetId("")
+               return nil
+       }
+
+       policy := resp.AutoScalePolicies[0]
+       d.Set("name", policy.Name)
+       d.Set("action", policy.Action)
+       d.Set("duration", policy.Duration)
+       d.Set("quiet_time", policy.Quiettime)
+
+       conditionIds := schema.NewSet(schema.HashString, []interface{}{})
+       for _, conditionId := range policy.Conditions {
+               conditionIds.Add(conditionId)
+       }
+       d.Set("condition_ids", conditionIds)
+
+       return nil
+}
+
+func resourceCloudStackAutoScalePolicyUpdate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       if d.HasChange("name") || d.HasChange("condition_ids") || 
d.HasChange("duration") || d.HasChange("quiet_time") {
+               log.Printf("[DEBUG] Updating autoscale policy: %s", d.Id())
+
+               p := cs.AutoScale.NewUpdateAutoScalePolicyParams(d.Id())
+
+               if d.HasChange("name") {
+                       if v, ok := d.GetOk("name"); ok {
+                               p.SetName(v.(string))
+                       }
+               }
+
+               if d.HasChange("duration") {
+                       duration := d.Get("duration").(int)
+                       p.SetDuration(duration)
+               }
+
+               if d.HasChange("quiet_time") {
+                       if v, ok := d.GetOk("quiet_time"); ok {
+                               p.SetQuiettime(v.(int))
+                       }
+               }
+
+               if d.HasChange("condition_ids") {
+                       conditionIds := []string{}
+                       if v, ok := d.GetOk("condition_ids"); ok {
+                               conditionSet := v.(*schema.Set)
+                               for _, id := range conditionSet.List() {
+                                       conditionIds = append(conditionIds, 
id.(string))
+                               }
+                       }
+                       p.SetConditionids(conditionIds)
+               }
+
+               _, err := cs.AutoScale.UpdateAutoScalePolicy(p)
+               if err != nil {
+                       return fmt.Errorf("Error updating autoscale policy: 
%s", err)
+               }
+
+               log.Printf("[DEBUG] Autoscale policy updated successfully: %s", 
d.Id())
+       }
+
+       return resourceCloudStackAutoScalePolicyRead(d, meta)
+}
+
+func resourceCloudStackAutoScalePolicyDelete(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewDeleteAutoScalePolicyParams(d.Id())
+
+       log.Printf("[DEBUG] Deleting autoscale policy: %s", d.Id())
+       _, err := cs.AutoScale.DeleteAutoScalePolicy(p)
+       if err != nil {
+               return fmt.Errorf("Error deleting autoscale policy: %s", err)
+       }
+
+       return nil
+}
diff --git a/cloudstack/resource_cloudstack_autoscale_vm_group.go 
b/cloudstack/resource_cloudstack_autoscale_vm_group.go
new file mode 100644
index 0000000..0d50e02
--- /dev/null
+++ b/cloudstack/resource_cloudstack_autoscale_vm_group.go
@@ -0,0 +1,286 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+       "fmt"
+       "log"
+       "strings"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceCloudStackAutoScaleVMGroup() *schema.Resource {
+       return &schema.Resource{
+               Create: resourceCloudStackAutoScaleVMGroupCreate,
+               Read:   resourceCloudStackAutoScaleVMGroupRead,
+               Update: resourceCloudStackAutoScaleVMGroupUpdate,
+               Delete: resourceCloudStackAutoScaleVMGroupDelete,
+
+               Schema: map[string]*schema.Schema{
+                       "lbrule_id": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               ForceNew:    true,
+                               Description: "the ID of the load balancer rule",
+                       },
+
+                       "name": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Description: "the name of the autoscale 
vmgroup",
+                       },
+
+                       "min_members": {
+                               Type:        schema.TypeInt,
+                               Required:    true,
+                               Description: "the minimum number of members in 
the vmgroup, the number of instances in the vm group will be equal to or more 
than this number",
+                       },
+
+                       "max_members": {
+                               Type:        schema.TypeInt,
+                               Required:    true,
+                               Description: "the maximum number of members in 
the vmgroup, The number of instances in the vm group will be equal to or less 
than this number",
+                       },
+
+                       "interval": {
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               Description: "the frequency in which the 
performance counters to be collected",
+                       },
+
+                       "scaleup_policy_ids": {
+                               Type:        schema.TypeSet,
+                               Elem:        &schema.Schema{Type: 
schema.TypeString},
+                               Required:    true,
+                               Description: "list of scaleup autoscale 
policies",
+                       },
+
+                       "scaledown_policy_ids": {
+                               Type:        schema.TypeSet,
+                               Elem:        &schema.Schema{Type: 
schema.TypeString},
+                               Required:    true,
+                               Description: "list of scaledown autoscale 
policies",
+                       },
+
+                       "vm_profile_id": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               ForceNew:    true,
+                               Description: "the autoscale profile that 
contains information about the vms in the vm group",
+                       },
+
+                       "display": {
+                               Type:        schema.TypeBool,
+                               Optional:    true,
+                               Description: "an optional field, whether to the 
display the group to the end user or not",
+                       },
+               },
+       }
+}
+
+func resourceCloudStackAutoScaleVMGroupCreate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       lbruleid := d.Get("lbrule_id").(string)
+       minmembers := d.Get("min_members").(int)
+       maxmembers := d.Get("max_members").(int)
+       vmprofileid := d.Get("vm_profile_id").(string)
+
+       scaleUpPolicyIds := []string{}
+       if v, ok := d.GetOk("scaleup_policy_ids"); ok {
+               scaleUpSet := v.(*schema.Set)
+               for _, id := range scaleUpSet.List() {
+                       scaleUpPolicyIds = append(scaleUpPolicyIds, id.(string))
+               }
+       }
+
+       scaleDownPolicyIds := []string{}
+       if v, ok := d.GetOk("scaledown_policy_ids"); ok {
+               scaleDownSet := v.(*schema.Set)
+               for _, id := range scaleDownSet.List() {
+                       scaleDownPolicyIds = append(scaleDownPolicyIds, 
id.(string))
+               }
+       }
+
+       p := cs.AutoScale.NewCreateAutoScaleVmGroupParams(lbruleid, maxmembers, 
minmembers, scaleDownPolicyIds, scaleUpPolicyIds, vmprofileid)
+
+       if v, ok := d.GetOk("name"); ok {
+               p.SetName(v.(string))
+       }
+
+       if v, ok := d.GetOk("interval"); ok {
+               p.SetInterval(v.(int))
+       }
+
+       if v, ok := d.GetOk("display"); ok {
+               p.SetFordisplay(v.(bool))
+       }
+
+       log.Printf("[DEBUG] Creating autoscale VM group")
+       resp, err := cs.AutoScale.CreateAutoScaleVmGroup(p)
+       if err != nil {
+               return fmt.Errorf("Error creating autoscale VM group: %s", err)
+       }
+
+       d.SetId(resp.Id)
+       log.Printf("[DEBUG] Autoscale VM group created with ID: %s", resp.Id)
+
+       return resourceCloudStackAutoScaleVMGroupRead(d, meta)
+}
+
+func resourceCloudStackAutoScaleVMGroupRead(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewListAutoScaleVmGroupsParams()
+       p.SetId(d.Id())
+
+       resp, err := cs.AutoScale.ListAutoScaleVmGroups(p)
+       if err != nil {
+               return fmt.Errorf("Error retrieving autoscale VM group: %s", 
err)
+       }
+
+       if resp.Count == 0 {
+               log.Printf("[DEBUG] Autoscale VM group %s no longer exists", 
d.Id())
+               d.SetId("")
+               return nil
+       }
+
+       group := resp.AutoScaleVmGroups[0]
+       d.Set("name", group.Name)
+       d.Set("lbrule_id", group.Lbruleid)
+       d.Set("min_members", group.Minmembers)
+       d.Set("max_members", group.Maxmembers)
+       d.Set("interval", group.Interval)
+       d.Set("vm_profile_id", group.Vmprofileid)
+       d.Set("display", group.Fordisplay)
+
+       scaleUpPolicyIds := schema.NewSet(schema.HashString, []interface{}{})
+       if group.Scaleuppolicies != nil {
+               for _, policyId := range group.Scaleuppolicies {
+                       scaleUpPolicyIds.Add(policyId)
+               }
+       }
+       d.Set("scaleup_policy_ids", scaleUpPolicyIds)
+
+       scaleDownPolicyIds := schema.NewSet(schema.HashString, []interface{}{})
+       if group.Scaledownpolicies != nil {
+               for _, policyId := range group.Scaledownpolicies {
+                       scaleDownPolicyIds.Add(policyId)
+               }
+       }
+       d.Set("scaledown_policy_ids", scaleDownPolicyIds)
+
+       return nil
+}
+
+func resourceCloudStackAutoScaleVMGroupUpdate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       if d.HasChange("name") || d.HasChange("min_members") || 
d.HasChange("max_members") ||
+               d.HasChange("interval") || d.HasChange("scaleup_policy_ids") ||
+               d.HasChange("scaledown_policy_ids") || d.HasChange("display") {
+
+               log.Printf("[DEBUG] Updating autoscale VM group: %s", d.Id())
+
+               p := cs.AutoScale.NewUpdateAutoScaleVmGroupParams(d.Id())
+
+               if d.HasChange("name") {
+                       if v, ok := d.GetOk("name"); ok {
+                               p.SetName(v.(string))
+                       }
+               }
+
+               if d.HasChange("min_members") {
+                       minmembers := d.Get("min_members").(int)
+                       p.SetMinmembers(minmembers)
+               }
+
+               if d.HasChange("max_members") {
+                       maxmembers := d.Get("max_members").(int)
+                       p.SetMaxmembers(maxmembers)
+               }
+
+               if d.HasChange("interval") {
+                       if v, ok := d.GetOk("interval"); ok {
+                               p.SetInterval(v.(int))
+                       }
+               }
+
+               if d.HasChange("scaleup_policy_ids") {
+                       scaleUpPolicyIds := []string{}
+                       if v, ok := d.GetOk("scaleup_policy_ids"); ok {
+                               scaleUpSet := v.(*schema.Set)
+                               for _, id := range scaleUpSet.List() {
+                                       scaleUpPolicyIds = 
append(scaleUpPolicyIds, id.(string))
+                               }
+                       }
+                       p.SetScaleuppolicyids(scaleUpPolicyIds)
+               }
+
+               if d.HasChange("scaledown_policy_ids") {
+                       scaleDownPolicyIds := []string{}
+                       if v, ok := d.GetOk("scaledown_policy_ids"); ok {
+                               scaleDownSet := v.(*schema.Set)
+                               for _, id := range scaleDownSet.List() {
+                                       scaleDownPolicyIds = 
append(scaleDownPolicyIds, id.(string))
+                               }
+                       }
+                       p.SetScaledownpolicyids(scaleDownPolicyIds)
+               }
+
+               if d.HasChange("display") {
+                       if v, ok := d.GetOk("display"); ok {
+                               p.SetFordisplay(v.(bool))
+                       }
+               }
+
+               _, err := cs.AutoScale.UpdateAutoScaleVmGroup(p)
+               if err != nil {
+                       return fmt.Errorf("Error updating autoscale VM group: 
%s", err)
+               }
+
+               log.Printf("[DEBUG] Autoscale VM group updated successfully: 
%s", d.Id())
+       }
+
+       return resourceCloudStackAutoScaleVMGroupRead(d, meta)
+}
+
+func resourceCloudStackAutoScaleVMGroupDelete(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewDeleteAutoScaleVmGroupParams(d.Id())
+
+       log.Printf("[DEBUG] Deleting autoscale VM group: %s", d.Id())
+       _, err := cs.AutoScale.DeleteAutoScaleVmGroup(p)
+       if err != nil {
+               // This is a very poor way to be told the ID does no longer 
exist :(
+               if strings.Contains(err.Error(), fmt.Sprintf(
+                       "Invalid parameter id value=%s due to incorrect long 
value format, "+
+                               "or entity does not exist", d.Id())) {
+                       return nil
+               }
+
+               return fmt.Errorf("Error deleting autoscale VM group: %s", err)
+       }
+
+       return nil
+}
diff --git a/cloudstack/resource_cloudstack_autoscale_vm_profile.go 
b/cloudstack/resource_cloudstack_autoscale_vm_profile.go
index 04fc5d5..5c2cf4c 100644
--- a/cloudstack/resource_cloudstack_autoscale_vm_profile.go
+++ b/cloudstack/resource_cloudstack_autoscale_vm_profile.go
@@ -38,33 +38,95 @@ func resourceCloudStackAutoScaleVMProfile() 
*schema.Resource {
 
                Schema: map[string]*schema.Schema{
                        "service_offering": {
-                               Type:     schema.TypeString,
-                               Required: true,
-                               ForceNew: true,
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               ForceNew:    true,
+                               Description: "the service offering of the auto 
deployed virtual machine",
                        },
 
                        "template": {
-                               Type:     schema.TypeString,
-                               Required: true,
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "the template of the auto deployed 
virtual machine",
                        },
 
                        "zone": {
-                               Type:     schema.TypeString,
-                               Required: true,
-                               ForceNew: true,
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               ForceNew:    true,
+                               Description: "availability zone for the auto 
deployed virtual machine",
                        },
 
                        "destroy_vm_grace_period": {
-                               Type:     schema.TypeString,
-                               Optional: true,
-                               Computed: true,
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Computed:    true,
+                               Description: "the time allowed for existing 
connections to get closed before a vm is expunged",
                        },
 
                        "other_deploy_params": {
-                               Type:     schema.TypeMap,
-                               Optional: true,
-                               Computed: true,
-                               ForceNew: true,
+                               Type:        schema.TypeMap,
+                               Optional:    true,
+                               Computed:    true,
+                               ForceNew:    true,
+                               Description: "parameters other than 
zoneId/serviceOfferringId/templateId of the auto deployed virtual machine",
+                       },
+
+                       "counter_param_list": {
+                               Type:        schema.TypeMap,
+                               Optional:    true,
+                               Description: "counterparam list. Example: 
counterparam[0].name=snmpcommunity&counterparam[0].value=public&counterparam[1].name=snmpport&counterparam[1].value=161",
+                       },
+
+                       "user_data": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Description: "an optional binary data that can 
be sent to the virtual machine upon a successful deployment. This binary data 
must be base64 encoded before adding it to the request.",
+                       },
+
+                       "user_data_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Description: "the ID of the Userdata",
+                       },
+
+                       "user_data_details": {
+                               Type:        schema.TypeMap,
+                               Optional:    true,
+                               Description: "used to specify the parameters 
values for the variables in userdata",
+                       },
+
+                       "autoscale_user_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Description: "the ID of the user used to launch 
and destroy the VMs",
+                       },
+
+                       "display": {
+                               Type:        schema.TypeBool,
+                               Optional:    true,
+                               Description: "an optional field, whether to the 
display the profile to the end user or not",
+                       },
+
+                       "account_name": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "account that will own the 
autoscale VM profile",
+                       },
+
+                       "project_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "an optional project for the 
autoscale VM profile",
+                       },
+
+                       "domain_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "domain ID of the account owning a 
autoscale VM profile",
                        },
 
                        "metadata": metadataSchema(),
@@ -75,19 +137,16 @@ func resourceCloudStackAutoScaleVMProfile() 
*schema.Resource {
 func resourceCloudStackAutoScaleVMProfileCreate(d *schema.ResourceData, meta 
interface{}) error {
        cs := meta.(*cloudstack.CloudStackClient)
 
-       // Retrieve the service_offering ID
        serviceofferingid, e := retrieveID(cs, "service_offering", 
d.Get("service_offering").(string))
        if e != nil {
                return e.Error()
        }
 
-       // Retrieve the zone ID
        zoneid, e := retrieveID(cs, "zone", d.Get("zone").(string))
        if e != nil {
                return e.Error()
        }
 
-       // Retrieve the template ID
        templateid, e := retrieveTemplateID(cs, zoneid, 
d.Get("template").(string))
        if e != nil {
                return e.Error()
@@ -111,7 +170,50 @@ func resourceCloudStackAutoScaleVMProfileCreate(d 
*schema.ResourceData, meta int
                p.SetOtherdeployparams(nv)
        }
 
-       // Create the new vm profile
+       if v, ok := d.GetOk("counter_param_list"); ok {
+               nv := make(map[string]string)
+               for k, v := range v.(map[string]interface{}) {
+                       nv[k] = v.(string)
+               }
+               p.SetCounterparam(nv)
+       }
+
+       if v, ok := d.GetOk("user_data"); ok {
+               p.SetUserdata(v.(string))
+       }
+
+       if v, ok := d.GetOk("user_data_id"); ok {
+               p.SetUserdataid(v.(string))
+       }
+
+       if v, ok := d.GetOk("user_data_details"); ok {
+               nv := make(map[string]string)
+               for k, v := range v.(map[string]interface{}) {
+                       nv[k] = v.(string)
+               }
+               p.SetUserdatadetails(nv)
+       }
+
+       if v, ok := d.GetOk("autoscale_user_id"); ok {
+               p.SetAutoscaleuserid(v.(string))
+       }
+
+       if v, ok := d.GetOk("display"); ok {
+               p.SetFordisplay(v.(bool))
+       }
+
+       if v, ok := d.GetOk("account_name"); ok {
+               p.SetAccount(v.(string))
+       }
+
+       if v, ok := d.GetOk("project_id"); ok {
+               p.SetProjectid(v.(string))
+       }
+
+       if v, ok := d.GetOk("domain_id"); ok {
+               p.SetDomainid(v.(string))
+       }
+
        r, err := cs.AutoScale.CreateAutoScaleVmProfile(p)
        if err != nil {
                return fmt.Errorf("Error creating AutoScaleVmProfile %s: %s", 
d.Id(), err)
@@ -119,12 +221,11 @@ func resourceCloudStackAutoScaleVMProfileCreate(d 
*schema.ResourceData, meta int
 
        d.SetId(r.Id)
 
-       // Set metadata if necessary
        if err = setMetadata(cs, d, "AutoScaleVmProfile"); err != nil {
                return fmt.Errorf("Error setting metadata on the 
AutoScaleVmProfile %s: %s", d.Id(), err)
        }
 
-       return nil
+       return resourceCloudStackAutoScaleVMProfileRead(d, meta)
 }
 
 func resourceCloudStackAutoScaleVMProfileRead(d *schema.ResourceData, meta 
interface{}) error {
@@ -168,6 +269,36 @@ func resourceCloudStackAutoScaleVMProfileRead(d 
*schema.ResourceData, meta inter
                d.Set("other_deploy_params", p.Otherdeployparams)
        }
 
+       if p.Userdata != "" {
+               d.Set("user_data", p.Userdata)
+       }
+
+       if p.Userdataid != "" {
+               d.Set("user_data_id", p.Userdataid)
+       }
+
+       if p.Userdatadetails != "" {
+               d.Set("user_data_details", map[string]interface{}{})
+       }
+
+       if p.Autoscaleuserid != "" {
+               d.Set("autoscale_user_id", p.Autoscaleuserid)
+       }
+
+       d.Set("display", p.Fordisplay)
+
+       if p.Account != "" {
+               d.Set("account_name", p.Account)
+       }
+
+       if p.Projectid != "" {
+               d.Set("project_id", p.Projectid)
+       }
+
+       if p.Domainid != "" {
+               d.Set("domain_id", p.Domainid)
+       }
+
        metadata, err := getMetadata(cs, d, "AutoScaleVmProfile")
        if err != nil {
                return err
@@ -180,7 +311,6 @@ func resourceCloudStackAutoScaleVMProfileRead(d 
*schema.ResourceData, meta inter
 func resourceCloudStackAutoScaleVMProfileUpdate(d *schema.ResourceData, meta 
interface{}) error {
        cs := meta.(*cloudstack.CloudStackClient)
 
-       // Create a new parameter struct
        p := cs.AutoScale.NewUpdateAutoScaleVmProfileParams(d.Id())
 
        if d.HasChange("template") {
@@ -196,11 +326,57 @@ func resourceCloudStackAutoScaleVMProfileUpdate(d 
*schema.ResourceData, meta int
        }
 
        if d.HasChange("destroy_vm_grace_period") {
-               duration, err := 
time.ParseDuration(d.Get("destroy_vm_grace_period").(string))
-               if err != nil {
-                       return err
+               if v, ok := d.GetOk("destroy_vm_grace_period"); ok {
+                       duration, err := time.ParseDuration(v.(string))
+                       if err != nil {
+                               return err
+                       }
+                       p.SetExpungevmgraceperiod(int(duration.Seconds()))
+               }
+       }
+
+       if d.HasChange("counter_param_list") {
+               if v, ok := d.GetOk("counter_param_list"); ok {
+                       nv := make(map[string]string)
+                       for k, v := range v.(map[string]interface{}) {
+                               nv[k] = v.(string)
+                       }
+                       p.SetCounterparam(nv)
+               }
+       }
+
+       if d.HasChange("user_data") {
+               if v, ok := d.GetOk("user_data"); ok {
+                       p.SetUserdata(v.(string))
+               }
+       }
+
+       if d.HasChange("user_data_id") {
+               if v, ok := d.GetOk("user_data_id"); ok {
+                       p.SetUserdataid(v.(string))
+               }
+       }
+
+       if d.HasChange("user_data_details") {
+               if v, ok := d.GetOk("user_data_details"); ok {
+                       nv := make(map[string]string)
+                       for k, v := range v.(map[string]interface{}) {
+                               nv[k] = v.(string)
+                       }
+                       p.SetUserdatadetails(nv)
+               }
+       }
+
+       if d.HasChange("autoscale_user_id") {
+               if v, ok := d.GetOk("autoscale_user_id"); ok {
+                       p.SetAutoscaleuserid(v.(string))
+               }
+       }
+
+       if d.HasChange("display") {
+               if v, ok := d.GetOk("display"); ok {
+                       p.SetFordisplay(v.(bool))
                }
-               p.SetExpungevmgraceperiod(int(duration.Seconds()))
        }
 
        _, err := cs.AutoScale.UpdateAutoScaleVmProfile(p)
@@ -220,10 +396,8 @@ func resourceCloudStackAutoScaleVMProfileUpdate(d 
*schema.ResourceData, meta int
 func resourceCloudStackAutoScaleVMProfileDelete(d *schema.ResourceData, meta 
interface{}) error {
        cs := meta.(*cloudstack.CloudStackClient)
 
-       // Create a new parameter struct
        p := cs.AutoScale.NewDeleteAutoScaleVmProfileParams(d.Id())
 
-       // Delete the template
        log.Printf("[INFO] Deleting AutoScaleVmProfile: %s", d.Id())
        _, err := cs.AutoScale.DeleteAutoScaleVmProfile(p)
        if err != nil {
diff --git a/cloudstack/resource_cloudstack_condition.go 
b/cloudstack/resource_cloudstack_condition.go
new file mode 100644
index 0000000..7af09a1
--- /dev/null
+++ b/cloudstack/resource_cloudstack_condition.go
@@ -0,0 +1,172 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+       "fmt"
+       "log"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceCloudStackCondition() *schema.Resource {
+       return &schema.Resource{
+               Create: resourceCloudStackConditionCreate,
+               Read:   resourceCloudStackConditionRead,
+               Update: resourceCloudStackConditionUpdate,
+               Delete: resourceCloudStackConditionDelete,
+
+               Schema: map[string]*schema.Schema{
+                       "counter_id": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "The ID of the counter to be used 
in the condition.",
+                               ForceNew:    true,
+                       },
+                       "relational_operator": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "Relational Operator to be used 
with threshold. Valid values are EQ, GT, LT, GE, LE.",
+                       },
+                       "threshold": {
+                               Type:        schema.TypeFloat,
+                               Required:    true,
+                               Description: "Value for which the Counter will 
be evaluated with the Operator selected.",
+                       },
+                       "account_name": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "the account of the condition. 
Must be used with the domainId parameter.",
+                               ForceNew:    true,
+                       },
+                       "domain_id": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "the domain ID of the account.",
+                               ForceNew:    true,
+                       },
+                       "project_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               Description: "optional project for the 
condition",
+                               ForceNew:    true,
+                       },
+               },
+       }
+}
+
+func resourceCloudStackConditionRead(d *schema.ResourceData, meta interface{}) 
error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewListConditionsParams()
+       p.SetId(d.Id())
+
+       resp, err := cs.AutoScale.ListConditions(p)
+       if err != nil {
+               return fmt.Errorf("Error retrieving condition: %s", err)
+       }
+
+       if resp.Count == 0 {
+               log.Printf("[DEBUG] Condition %s no longer exists", d.Id())
+               d.SetId("")
+               return nil
+       }
+
+       condition := resp.Conditions[0]
+       d.Set("counter_id", condition.Counterid)
+       d.Set("relational_operator", condition.Relationaloperator)
+       d.Set("threshold", condition.Threshold)
+       d.Set("account_name", condition.Account)
+       d.Set("domain_id", condition.Domainid)
+       if condition.Projectid != "" {
+               d.Set("project_id", condition.Projectid)
+       }
+
+       return nil
+}
+
+func resourceCloudStackConditionUpdate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       if d.HasChange("relational_operator") || d.HasChange("threshold") {
+               log.Printf("[DEBUG] Updating condition: %s", d.Id())
+
+               relationaloperator := d.Get("relational_operator").(string)
+               threshold := d.Get("threshold").(float64)
+
+               p := cs.AutoScale.NewUpdateConditionParams(d.Id(), 
relationaloperator, int64(threshold))
+
+               _, err := cs.AutoScale.UpdateCondition(p)
+               if err != nil {
+                       return fmt.Errorf("Error updating condition: %s", err)
+               }
+
+               log.Printf("[DEBUG] Condition updated successfully: %s", d.Id())
+       }
+
+       return resourceCloudStackConditionRead(d, meta)
+}
+
+func resourceCloudStackConditionDelete(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewDeleteConditionParams(d.Id())
+
+       log.Printf("[DEBUG] Deleting condition: %s", d.Id())
+       _, err := cs.AutoScale.DeleteCondition(p)
+       if err != nil {
+               return fmt.Errorf("Error deleting condition: %s", err)
+       }
+
+       return nil
+}
+func resourceCloudStackConditionCreate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+       counterid := d.Get("counter_id")
+       relationaloperator := d.Get("relational_operator").(string)
+       threshold := d.Get("threshold").(float64)
+
+       account, accountOk := d.GetOk("account_name")
+       domainid, domainOk := d.GetOk("domain_id")
+
+       if !accountOk || !domainOk {
+               return fmt.Errorf("account_name and domain_id are required 
fields")
+       }
+
+       p := cs.AutoScale.NewCreateConditionParams(counterid.(string), 
relationaloperator, int64(threshold))
+       p.SetAccount(account.(string))
+       p.SetDomainid(domainid.(string))
+
+       if v, ok := d.GetOk("project_id"); ok {
+               p.SetProjectid(v.(string))
+       }
+
+       log.Printf("[DEBUG] Creating condition")
+       resp, err := cs.AutoScale.CreateCondition(p)
+       if err != nil {
+               return fmt.Errorf("Error creating condition: %s", err)
+       }
+
+       d.SetId(resp.Id)
+       log.Printf("[DEBUG] Condition created with ID: %s", resp.Id)
+
+       return resourceCloudStackConditionRead(d, meta)
+}
diff --git a/cloudstack/resource_cloudstack_counter.go 
b/cloudstack/resource_cloudstack_counter.go
new file mode 100644
index 0000000..ea3f70f
--- /dev/null
+++ b/cloudstack/resource_cloudstack_counter.go
@@ -0,0 +1,126 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+       "fmt"
+       "log"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceCloudStackCounter() *schema.Resource {
+       return &schema.Resource{
+               Create: resourceCloudStackCounterCreate,
+               Read:   resourceCloudStackCounterRead,
+               Delete: resourceCloudStackCounterDelete,
+
+               Schema: map[string]*schema.Schema{
+                       "name": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "Name of the counter",
+                               ForceNew:    true,
+                       },
+
+                       "source": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "Source of the counter",
+                               ForceNew:    true,
+                       },
+                       "value": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "Value of the counter e.g. oid in 
case of snmp",
+                               ForceNew:    true,
+                       },
+                       "provider": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               Description: "Provider of the counter",
+                               ForceNew:    true,
+                       },
+               },
+       }
+}
+
+func resourceCloudStackCounterCreate(d *schema.ResourceData, meta interface{}) 
error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       name := d.Get("name").(string)
+       source := d.Get("source").(string)
+       value := d.Get("value").(string)
+       provider := d.Get("provider").(string)
+
+       p := cs.AutoScale.NewCreateCounterParams(name, provider, source, value)
+
+       log.Printf("[DEBUG] Creating counter: %s", name)
+       resp, err := cs.AutoScale.CreateCounter(p)
+       if err != nil {
+               return fmt.Errorf("Error creating counter: %s", err)
+       }
+
+       d.SetId(resp.Id)
+       log.Printf("[DEBUG] Counter created with ID: %s", resp.Id)
+
+       return resourceCloudStackCounterRead(d, meta)
+}
+
+func resourceCloudStackCounterRead(d *schema.ResourceData, meta interface{}) 
error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewListCountersParams()
+       p.SetId(d.Id())
+
+       resp, err := cs.AutoScale.ListCounters(p)
+       if err != nil {
+               return fmt.Errorf("Error retrieving counter: %s", err)
+       }
+
+       if resp.Count == 0 {
+               log.Printf("[DEBUG] Counter %s no longer exists", d.Id())
+               d.SetId("")
+               return nil
+       }
+
+       counter := resp.Counters[0]
+       d.Set("name", counter.Name)
+       d.Set("source", counter.Source)
+       d.Set("value", counter.Value)
+       d.Set("provider", counter.Provider)
+
+       return nil
+}
+
+func resourceCloudStackCounterDelete(d *schema.ResourceData, meta interface{}) 
error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       p := cs.AutoScale.NewDeleteCounterParams(d.Id())
+
+       log.Printf("[DEBUG] Deleting counter: %s", d.Id())
+       _, err := cs.AutoScale.DeleteCounter(p)
+       if err != nil {
+               return fmt.Errorf("Error deleting counter: %s", err)
+       }
+
+       return nil
+}


Reply via email to