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

dahn 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 5191290  add cloudstack_cluster data source and documentation (#222)
5191290 is described below

commit 5191290128f0b785eb43bd78bd3010d01c6ae284
Author: Ian <[email protected]>
AuthorDate: Tue Sep 16 05:47:22 2025 -0700

    add cloudstack_cluster data source and documentation (#222)
---
 cloudstack/data_source_cloudstack_cluster.go      | 357 ++++++++++++++++++++++
 cloudstack/data_source_cloudstack_cluster_test.go |  75 +++++
 cloudstack/provider.go                            |   1 +
 website/docs/d/cluster.html.markdown              |  88 ++++++
 4 files changed, 521 insertions(+)

diff --git a/cloudstack/data_source_cloudstack_cluster.go 
b/cloudstack/data_source_cloudstack_cluster.go
new file mode 100644
index 0000000..35bdfe6
--- /dev/null
+++ b/cloudstack/data_source_cloudstack_cluster.go
@@ -0,0 +1,357 @@
+//
+// 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"
+       "reflect"
+       "regexp"
+       "strings"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func dataSourceCloudstackCluster() *schema.Resource {
+       return &schema.Resource{
+               Read: datasourceCloudStackClusterRead,
+               Schema: map[string]*schema.Schema{
+                       "filter": dataSourceFiltersSchema(),
+
+                       //Computed values
+                       "id": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "allocation_state": {
+                               Description: "Allocation state of this cluster 
for allocation of new resources",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "cluster_name": {
+                               Description: "the cluster name",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "name": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "cluster_type": {
+                               Description: "Type of the cluster: 
CloudManaged, ExternalManaged",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "guest_vswitch_name": {
+                               Description: "Name of virtual switch used for 
guest traffic in the cluster. This would override zone wide traffic label 
setting.",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "guest_vswitch_type": {
+                               Description: "Type of virtual switch used for 
guest traffic in the cluster. Allowed values are, vmwaresvs (for VMware 
standard vSwitch) and vmwaredvs (for VMware distributed vSwitch)",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "hypervisor": {
+                               Description: "hypervisor type of the cluster: 
XenServer,KVM,VMware,Hyperv,BareMetal,Simulator,Ovm3",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "ovm3_cluster": {
+                               Description: "Ovm3 native OCFS2 clustering 
enabled for cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "ovm3_pool": {
+                               Description: "Ovm3 native pooling enabled for 
cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "ovm3_vip": {
+                               Description: "Ovm3 vip to use for pool (and 
cluster)",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "ovm3vip": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "password": {
+                               Description: "the password for the host",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                               Sensitive:   true,
+                       },
+                       "public_vswitch_name": {
+                               Description: "Name of virtual switch used for 
public traffic in the cluster. This would override zone wide traffic label 
setting.",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "public_vswitch_type": {
+                               Description: "Type of virtual switch used for 
public traffic in the cluster. Allowed values are, vmwaresvs (for VMware 
standard vSwitch) and vmwaredvs (for VMware distributed vSwitch)",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "pod_id": {
+                               Description: "The Pod ID for the cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "pod_name": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "url": {
+                               Description: "the URL",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "username": {
+                               Description: "the username for the cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "vsm_ip_address": {
+                               Description: "the ipaddress of the VSM 
associated with this cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "vsm_password": {
+                               Description: "the password for the VSM 
associated with this cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                               Sensitive:   true,
+                       },
+                       "vsm_username": {
+                               Description: "the username for the VSM 
associated with this cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "zone_id": {
+                               Description: "the Zone ID for the cluster",
+                               Type:        schema.TypeString,
+                               Computed:    true,
+                       },
+                       "zone_name": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "managed_state": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "cpu_overcommit_ratio": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "memory_overcommit_ratio": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "arch": {
+                               Type:     schema.TypeString,
+                               Computed: true,
+                       },
+                       "capacity": {
+                               Type:     schema.TypeList,
+                               Computed: true,
+                               Elem: &schema.Resource{
+                                       Schema: map[string]*schema.Schema{
+                                               "capacity_allocated": {
+                                                       Type:     
schema.TypeInt,
+                                                       Computed: true,
+                                               },
+                                               "capacity_total": {
+                                                       Type:     
schema.TypeInt,
+                                                       Computed: true,
+                                               },
+                                               "capacity_used": {
+                                                       Type:     
schema.TypeInt,
+                                                       Computed: true,
+                                               },
+                                               "cluster_id": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "cluster_name": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "name": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "percent_used": {
+                                                       Type:     
schema.TypeInt,
+                                                       Computed: true,
+                                               },
+                                               "pod_id": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "pod_name": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "type": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "zone_id": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                               "zone_name": {
+                                                       Type:     
schema.TypeString,
+                                                       Computed: true,
+                                               },
+                                       },
+                               },
+                       },
+               },
+       }
+}
+
+func dsFlattenClusterCapacity(capacity []cloudstack.ClusterCapacity) 
[]map[string]interface{} {
+       cap := make([]map[string]interface{}, len(capacity))
+       for i, c := range capacity {
+               cap[i] = map[string]interface{}{
+                       "capacity_allocated": c.Capacityallocated,
+                       "capacity_total":     c.Capacitytotal,
+                       "capacity_used":      c.Capacityused,
+                       "cluster_id":         c.Clusterid,
+                       "cluster_name":       c.Clustername,
+                       "name":               c.Name,
+                       "percent_used":       c.Percentused,
+                       "pod_id":             c.Podid,
+                       "pod_name":           c.Podname,
+                       "type":               c.Type,
+                       "zone_id":            c.Zoneid,
+                       "zone_name":          c.Zonename,
+               }
+       }
+       return cap
+}
+
+func datasourceCloudStackClusterRead(d *schema.ResourceData, meta interface{}) 
error {
+       cs := meta.(*cloudstack.CloudStackClient)
+       p := cs.Cluster.NewListClustersParams()
+
+       csClusters, err := cs.Cluster.ListClusters(p)
+       if err != nil {
+               return fmt.Errorf("failed to list clusters: %s", err)
+       }
+
+       filters := d.Get("filter")
+
+       for _, cluster := range csClusters.Clusters {
+               match, err := applyClusterFilters(cluster, 
filters.(*schema.Set))
+               if err != nil {
+                       return err
+               }
+               if match {
+                       return clusterDescriptionAttributes(d, cluster)
+               }
+       }
+
+       return fmt.Errorf("no clusters found")
+}
+
+func clusterDescriptionAttributes(d *schema.ResourceData, cluster 
*cloudstack.Cluster) error {
+       d.SetId(cluster.Id)
+
+       fields := map[string]interface{}{
+               "id":                      cluster.Id,
+               "allocation_state":        cluster.Allocationstate,
+               "cluster_name":            cluster.Name,
+               "name":                    cluster.Name,
+               "cluster_type":            cluster.Clustertype,
+               "hypervisor":              cluster.Hypervisortype,
+               "ovm3_vip":                cluster.Ovm3vip,
+               "ovm3vip":                 cluster.Ovm3vip,
+               "pod_id":                  cluster.Podid,
+               "pod_name":                cluster.Podname,
+               "zone_id":                 cluster.Zoneid,
+               "zone_name":               cluster.Zonename,
+               "managed_state":           cluster.Managedstate,
+               "cpu_overcommit_ratio":    cluster.Cpuovercommitratio,
+               "memory_overcommit_ratio": cluster.Memoryovercommitratio,
+               "arch":                    cluster.Arch,
+               "capacity":                
dsFlattenClusterCapacity(cluster.Capacity),
+       }
+
+       // Set fields that may not be available in all cluster responses to 
empty strings
+       // These are typically only available during cluster 
creation/configuration
+       emptyStringFields := []string{
+               "guest_vswitch_name",
+               "guest_vswitch_type",
+               "ovm3_cluster",
+               "ovm3_pool",
+               "password",
+               "public_vswitch_name",
+               "public_vswitch_type",
+               "url",
+               "username",
+               "vsm_ip_address",
+               "vsm_password",
+               "vsm_username",
+       }
+
+       for k, v := range fields {
+               if err := d.Set(k, v); err != nil {
+                       log.Printf("[WARN] Error setting %s: %s", k, err)
+               }
+       }
+
+       for _, field := range emptyStringFields {
+               if err := d.Set(field, ""); err != nil {
+                       log.Printf("[WARN] Error setting %s: %s", field, err)
+               }
+       }
+
+       return nil
+}
+
+func applyClusterFilters(cluster *cloudstack.Cluster, filters *schema.Set) 
(bool, error) {
+       val := reflect.ValueOf(cluster).Elem()
+
+       for _, f := range filters.List() {
+               filter := f.(map[string]interface{})
+               r, err := regexp.Compile(filter["value"].(string))
+               if err != nil {
+                       return false, fmt.Errorf("invalid regex: %s", err)
+               }
+               updatedName := strings.ReplaceAll(filter["name"].(string), "_", 
"")
+               clusterField := val.FieldByNameFunc(func(fieldName string) bool 
{
+                       if strings.EqualFold(fieldName, updatedName) {
+                               updatedName = fieldName
+                               return true
+                       }
+                       return false
+               }).String()
+
+               if r.MatchString(clusterField) {
+                       return true, nil
+               }
+       }
+
+       return false, nil
+}
diff --git a/cloudstack/data_source_cloudstack_cluster_test.go 
b/cloudstack/data_source_cloudstack_cluster_test.go
new file mode 100644
index 0000000..96fbfd9
--- /dev/null
+++ b/cloudstack/data_source_cloudstack_cluster_test.go
@@ -0,0 +1,75 @@
+//
+// 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 (
+       "testing"
+
+       "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+func TestAccClusterDataSource_basic(t *testing.T) {
+       resource.Test(t, resource.TestCase{
+               PreCheck:  func() { testAccPreCheck(t) },
+               Providers: testAccProviders,
+               Steps: []resource.TestStep{
+                       {
+                               Config: testClusterDataSourceConfig_basic,
+                               Check: resource.ComposeTestCheckFunc(
+                                       
resource.TestCheckResourceAttr("data.cloudstack_cluster.test", "name", 
"terraform-test-cluster"),
+                               ),
+                       },
+               },
+       })
+}
+
+const testClusterDataSourceConfig_basic = `
+data "cloudstack_zone" "zone" {
+  filter {
+    name = "name"
+    value = "Sandbox-simulator"
+  }
+}
+
+data "cloudstack_pod" "pod" {
+  filter {
+    name = "name"
+    value = "POD0"
+  }
+}
+
+# Create a cluster first
+resource "cloudstack_cluster" "test_cluster" {
+  cluster_name = "terraform-test-cluster"
+  cluster_type = "CloudManaged"
+  hypervisor = "KVM"
+  pod_id = data.cloudstack_pod.pod.id
+  zone_id = data.cloudstack_zone.zone.id
+}
+
+# Then query it with the data source
+data "cloudstack_cluster" "test" {
+  filter {
+    name = "name"
+    value = "terraform-test-cluster"
+  }
+  depends_on = [cloudstack_cluster.test_cluster]
+}
+`
diff --git a/cloudstack/provider.go b/cloudstack/provider.go
index b52b3d3..f4eedc1 100644
--- a/cloudstack/provider.go
+++ b/cloudstack/provider.go
@@ -93,6 +93,7 @@ func Provider() *schema.Provider {
                        "cloudstack_domain":           
dataSourceCloudstackDomain(),
                        "cloudstack_physical_network": 
dataSourceCloudStackPhysicalNetwork(),
                        "cloudstack_role":             
dataSourceCloudstackRole(),
+                       "cloudstack_cluster":          
dataSourceCloudstackCluster(),
                },
 
                ResourcesMap: map[string]*schema.Resource{
diff --git a/website/docs/d/cluster.html.markdown 
b/website/docs/d/cluster.html.markdown
new file mode 100644
index 0000000..901a3ca
--- /dev/null
+++ b/website/docs/d/cluster.html.markdown
@@ -0,0 +1,88 @@
+---
+subcategory: "Cluster"
+layout: "cloudstack"
+page_title: "CloudStack: cloudstack_cluster"
+description: |-
+  Gets information about a cluster.
+---
+
+# cloudstack_cluster
+
+Use this data source to get information about a cluster for use in other 
resources.
+
+## Example Usage
+
+```hcl
+data "cloudstack_cluster" "cluster" {
+  filter {
+    name = "name"
+    value = "cluster-1"
+  }
+}
+
+output "cluster_id" {
+  value = data.cloudstack_cluster.cluster.id
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `filter` - (Required) One or more name/value pairs to filter off of. See 
detailed documentation below.
+
+### Filter Arguments
+
+* `name` - (Required) The name of the field to filter on. This can be any of 
the fields returned by the CloudStack API.
+* `value` - (Required) The value to filter on. This should be a regular 
expression.
+
+## Attributes Reference
+
+The following attributes are exported:
+
+* `id` - The ID of the cluster.
+* `allocation_state` - Allocation state of this cluster for allocation of new 
resources.
+* `cluster_name` - The cluster name.
+* `name` - The name of the cluster.
+* `cluster_type` - Type of the cluster: CloudManaged, ExternalManaged.
+* `guest_vswitch_name` - Name of virtual switch used for guest traffic in the 
cluster. This would override zone wide traffic label setting.
+* `guest_vswitch_type` - Type of virtual switch used for guest traffic in the 
cluster. Allowed values are, vmwaresvs (for VMware standard vSwitch) and 
vmwaredvs (for VMware distributed vSwitch).
+* `hypervisor` - Hypervisor type of the cluster: XenServer, KVM, VMware, 
Hyperv, BareMetal, Simulator, Ovm3.
+* `ovm3_cluster` - Ovm3 native OCFS2 clustering enabled for cluster.
+* `ovm3_pool` - Ovm3 native pooling enabled for cluster.
+* `ovm3_vip` - Ovm3 vip to use for pool (and cluster).
+* `ovm3vip` - Ovm3 vip used for pool (and cluster).
+* `password` - The password for the host.
+* `public_vswitch_name` - Name of virtual switch used for public traffic in 
the cluster. This would override zone wide traffic label setting.
+* `public_vswitch_type` - Type of virtual switch used for public traffic in 
the cluster. Allowed values are, vmwaresvs (for VMware standard vSwitch) and 
vmwaredvs (for VMware distributed vSwitch).
+* `pod_id` - The Pod ID for the cluster.
+* `pod_name` - The name of the pod where the cluster is created.
+* `url` - The URL.
+* `username` - The username for the cluster.
+* `vsm_ip_address` - The ipaddress of the VSM associated with this cluster.
+* `vsm_password` - The password for the VSM associated with this cluster.
+* `vsm_username` - The username for the VSM associated with this cluster.
+* `zone_id` - The Zone ID for the cluster.
+* `zone_name` - The name of the zone where the cluster is created.
+* `managed_state` - The managed state of the cluster.
+* `cpu_overcommit_ratio` - The CPU overcommit ratio of the cluster.
+* `memory_overcommit_ratio` - The memory overcommit ratio of the cluster.
+* `arch` - The CPU arch of the cluster.
+* `capacity` - The capacity information of the cluster. See Capacity below for 
more details.
+
+### Capacity
+
+The `capacity` attribute supports the following:
+
+* `capacity_allocated` - The capacity allocated.
+* `capacity_total` - The total capacity.
+* `capacity_used` - The capacity used.
+* `cluster_id` - The ID of the cluster.
+* `cluster_name` - The name of the cluster.
+* `name` - The name of the capacity.
+* `percent_used` - The percentage of capacity used.
+* `pod_id` - The ID of the pod.
+* `pod_name` - The name of the pod.
+* `type` - The type of the capacity.
+* `zone_id` - The ID of the zone.
+* `zone_name` - The name of the zone.

Reply via email to