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 e4ecc98  Add support for the new parameters added to CKS cluster 
deployement (#230)
e4ecc98 is described below

commit e4ecc98ee38ca5f93d43fc529a5d2fb917d0f5f4
Author: Pearl Dsilva <[email protected]>
AuthorDate: Mon Sep 29 08:35:35 2025 -0400

    Add support for the new parameters added to CKS cluster deployement (#230)
    
    Co-authored-by: vishesh92 <[email protected]>
---
 cloudstack/provider.go                             |   1 +
 .../resource_cloudstack_cni_configuration.go       | 222 +++++++++++++++++++++
 .../resource_cloudstack_cni_configuration_test.go  | 153 ++++++++++++++
 .../resource_cloudstack_kubernetes_cluster.go      | 148 +++++++++++++-
 .../resource_cloudstack_kubernetes_version.go      |   2 +-
 cloudstack/resource_cloudstack_static_route.go     |   5 +-
 cloudstack/resource_cloudstack_template.go         |  12 ++
 go.mod                                             |   2 +-
 go.sum                                             |   4 +-
 website/docs/r/cni_configuration.html.markdown     | 172 ++++++++++++++++
 website/docs/r/kubernetes_cluster.html.markdown    | 178 +++++++++++++----
 website/docs/r/template.html.markdown              | 117 +++++++++--
 12 files changed, 952 insertions(+), 64 deletions(-)

diff --git a/cloudstack/provider.go b/cloudstack/provider.go
index 277dfae..0e0f6cf 100644
--- a/cloudstack/provider.go
+++ b/cloudstack/provider.go
@@ -109,6 +109,7 @@ func Provider() *schema.Provider {
                        "cloudstack_autoscale_policy":               
resourceCloudStackAutoScalePolicy(),
                        "cloudstack_autoscale_vm_group":             
resourceCloudStackAutoScaleVMGroup(),
                        "cloudstack_autoscale_vm_profile":           
resourceCloudStackAutoScaleVMProfile(),
+                       "cloudstack_cni_configuration":              
resourceCloudStackCniConfiguration(),
                        "cloudstack_condition":                      
resourceCloudStackCondition(),
                        "cloudstack_configuration":                  
resourceCloudStackConfiguration(),
                        "cloudstack_counter":                        
resourceCloudStackCounter(),
diff --git a/cloudstack/resource_cloudstack_cni_configuration.go 
b/cloudstack/resource_cloudstack_cni_configuration.go
new file mode 100644
index 0000000..60b320c
--- /dev/null
+++ b/cloudstack/resource_cloudstack_cni_configuration.go
@@ -0,0 +1,222 @@
+//
+// 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 resourceCloudStackCniConfiguration() *schema.Resource {
+       return &schema.Resource{
+               Create: resourceCloudStackCniConfigurationCreate,
+               Read:   resourceCloudStackCniConfigurationRead,
+               Delete: resourceCloudStackCniConfigurationDelete,
+               Importer: &schema.ResourceImporter{
+                       State: importStatePassthrough,
+               },
+
+               Schema: map[string]*schema.Schema{
+                       "name": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               ForceNew:    true,
+                               Description: "Name of the CNI configuration",
+                       },
+
+                       "cni_config": {
+                               Type:        schema.TypeString,
+                               Required:    true,
+                               ForceNew:    true,
+                               Description: "CNI Configuration content to be 
registered",
+                       },
+
+                       "account": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional account for the CNI 
configuration. Must be used with domain_id.",
+                       },
+
+                       "domain_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional domain ID for the CNI 
configuration. If the account parameter is used, domain_id must also be used.",
+                       },
+
+                       "project_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional project for the CNI 
configuration",
+                       },
+
+                       "params": {
+                               Type:        schema.TypeSet,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "List of variables declared in CNI 
configuration content",
+                               Elem: &schema.Schema{
+                                       Type: schema.TypeString,
+                               },
+                       },
+               },
+       }
+}
+
+func resourceCloudStackCniConfigurationCreate(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       name := d.Get("name").(string)
+       log.Printf("[DEBUG] Creating CNI configuration: %s", name)
+
+       p := cs.Configuration.NewRegisterCniConfigurationParams(name)
+
+       if v, ok := d.GetOk("cni_config"); ok {
+               cniConfig := v.(string)
+               log.Printf("[DEBUG] CNI config data length: %d bytes", 
len(cniConfig))
+               p.SetCniconfig(cniConfig)
+       } else {
+               return fmt.Errorf("CNI configuration content is required but 
not provided")
+       }
+
+       if account := d.Get("account").(string); account != "" {
+               log.Printf("[DEBUG] Setting account: %s", account)
+               p.SetAccount(account)
+       }
+
+       if domainID := d.Get("domain_id").(string); domainID != "" {
+               log.Printf("[DEBUG] Setting domain ID: %s", domainID)
+               p.SetDomainid(domainID)
+       }
+
+       if projectID := d.Get("project_id").(string); projectID != "" {
+               log.Printf("[DEBUG] Setting project ID: %s", projectID)
+               p.SetProjectid(projectID)
+       }
+
+       if params, ok := d.GetOk("params"); ok {
+               paramsList := []string{}
+               for _, param := range params.(*schema.Set).List() {
+                       paramsList = append(paramsList, param.(string))
+               }
+               if len(paramsList) > 0 {
+                       paramsStr := strings.Join(paramsList, ",")
+                       log.Printf("[DEBUG] Setting params: %s", paramsStr)
+                       p.SetParams(paramsStr)
+               }
+       }
+
+       resp, err := cs.Configuration.RegisterCniConfiguration(p)
+       if err != nil {
+               return fmt.Errorf("Error creating CNI configuration %s: %s", 
name, err)
+       }
+
+       log.Printf("[DEBUG] CNI configuration creation response: %+v", resp)
+
+       // List configurations to find the created one by name since direct ID 
access is not available
+       listParams := cs.Configuration.NewListCniConfigurationParams()
+       listParams.SetName(name)
+
+       // Add context parameters if available
+       if account := d.Get("account").(string); account != "" {
+               listParams.SetAccount(account)
+       }
+       if domainID := d.Get("domain_id").(string); domainID != "" {
+               listParams.SetDomainid(domainID)
+       }
+       if projectID := d.Get("project_id").(string); projectID != "" {
+               listParams.SetProjectid(projectID)
+       }
+
+       listResp, err := cs.Configuration.ListCniConfiguration(listParams)
+       if err != nil {
+               return fmt.Errorf("Error listing CNI configurations after 
creation: %s", err)
+       }
+
+       if listResp.Count == 0 {
+               return fmt.Errorf("CNI configuration %s was created but could 
not be found", name)
+       }
+
+       // Use the first (and should be only) result
+       config := listResp.CniConfiguration[0]
+       d.SetId(config.Id)
+       log.Printf("[DEBUG] CNI configuration %s successfully created with ID: 
%s", name, d.Id())
+
+       return resourceCloudStackCniConfigurationRead(d, meta)
+}
+
+func resourceCloudStackCniConfigurationRead(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       log.Printf("[DEBUG] Reading CNI configuration: %s", d.Id())
+
+       p := cs.Configuration.NewListCniConfigurationParams()
+       p.SetId(d.Id())
+
+       config, err := cs.Configuration.ListCniConfiguration(p)
+       if err != nil {
+               return fmt.Errorf("Error listing CNI configuration: %s", err)
+       }
+       if config.Count == 0 {
+               log.Printf("[DEBUG] CNI configuration %s no longer exists", 
d.Id())
+               d.SetId("")
+               return nil
+       }
+
+       d.Set("name", config.CniConfiguration[0].Name)
+       d.Set("cni_config", config.CniConfiguration[0].Userdata)
+       d.Set("account", config.CniConfiguration[0].Account)
+       d.Set("domain_id", config.CniConfiguration[0].Domainid)
+       d.Set("project_id", config.CniConfiguration[0].Projectid)
+
+       if config.CniConfiguration[0].Params != "" {
+               paramsList := strings.Split(config.CniConfiguration[0].Params, 
",")
+               d.Set("params", paramsList)
+       }
+
+       return nil
+}
+
+func resourceCloudStackCniConfigurationDelete(d *schema.ResourceData, meta 
interface{}) error {
+       cs := meta.(*cloudstack.CloudStackClient)
+
+       log.Printf("[DEBUG] Deleting CNI configuration: %s", d.Id())
+
+       p := cs.Configuration.NewDeleteCniConfigurationParams(d.Id())
+
+       _, err := cs.Configuration.DeleteCniConfiguration(p)
+       if err != nil {
+               if strings.Contains(err.Error(), "does not exist") ||
+                       strings.Contains(err.Error(), "not found") {
+                       log.Printf("[DEBUG] CNI configuration %s already 
deleted", d.Id())
+                       return nil
+               }
+               return fmt.Errorf("Error deleting CNI configuration %s: %s", 
d.Id(), err)
+       }
+
+       log.Printf("[DEBUG] CNI configuration %s deleted", d.Id())
+       return nil
+}
diff --git a/cloudstack/resource_cloudstack_cni_configuration_test.go 
b/cloudstack/resource_cloudstack_cni_configuration_test.go
new file mode 100644
index 0000000..96b2692
--- /dev/null
+++ b/cloudstack/resource_cloudstack_cni_configuration_test.go
@@ -0,0 +1,153 @@
+//
+// 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"
+       "testing"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+       "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+func TestAccCloudStackCniConfiguration_basic(t *testing.T) {
+       var cniConfig cloudstack.UserData
+
+       resource.Test(t, resource.TestCase{
+               PreCheck:     func() { testAccPreCheck(t); 
testAccPreCheckCniSupport(t) },
+               Providers:    testAccProviders,
+               CheckDestroy: testAccCheckCloudStackCniConfigurationDestroy,
+               Steps: []resource.TestStep{
+                       {
+                               Config: testAccCloudStackCniConfiguration_basic,
+                               Check: resource.ComposeTestCheckFunc(
+                                       
testAccCheckCloudStackCniConfigurationExists("cloudstack_cni_configuration.foo",
 &cniConfig),
+                                       
resource.TestCheckResourceAttr("cloudstack_cni_configuration.foo", "name", 
"test-cni-config"),
+                                       
resource.TestCheckResourceAttr("cloudstack_cni_configuration.foo", "params.#", 
"2"),
+                               ),
+                       },
+               },
+       })
+}
+
+func testAccCheckCloudStackCniConfigurationExists(n string, cniConfig 
*cloudstack.UserData) resource.TestCheckFunc {
+       return func(s *terraform.State) error {
+               rs, ok := s.RootModule().Resources[n]
+               if !ok {
+                       return fmt.Errorf("Not found: %s", n)
+               }
+
+               if rs.Primary.ID == "" {
+                       return fmt.Errorf("No CNI configuration ID is set")
+               }
+
+               cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
+               p := cs.Configuration.NewListCniConfigurationParams()
+               p.SetId(rs.Primary.ID)
+
+               resp, err := cs.Configuration.ListCniConfiguration(p)
+               if err != nil {
+                       return err
+               }
+
+               if resp.Count != 1 {
+                       return fmt.Errorf("CNI configuration not found")
+               }
+
+               config := resp.CniConfiguration[0]
+               if config.Id != rs.Primary.ID {
+                       return fmt.Errorf("CNI configuration not found")
+               }
+
+               *cniConfig = *config
+               return nil
+       }
+}
+
+func testAccCheckCloudStackCniConfigurationDestroy(s *terraform.State) error {
+       cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
+
+       for _, rs := range s.RootModule().Resources {
+               if rs.Type != "cloudstack_cni_configuration" {
+                       continue
+               }
+
+               if rs.Primary.ID == "" {
+                       return fmt.Errorf("No CNI configuration ID is set")
+               }
+
+               p := cs.Configuration.NewListCniConfigurationParams()
+               p.SetId(rs.Primary.ID)
+
+               resp, err := cs.Configuration.ListCniConfiguration(p)
+               if err == nil && resp.Count > 0 {
+                       return fmt.Errorf("CNI configuration %s still exists", 
rs.Primary.ID)
+               }
+       }
+
+       return nil
+}
+
+const testAccCloudStackCniConfiguration_basic = `
+resource "cloudstack_cni_configuration" "foo" {
+  name       = "test-cni-config"
+  cni_config = base64encode(jsonencode({
+    "name": "test-network",
+    "cniVersion": "0.4.0",
+    "plugins": [
+      {
+        "type": "calico",
+        "log_level": "info",
+        "datastore_type": "kubernetes",
+        "nodename": "KUBERNETES_NODE_NAME",
+        "mtu": "CNI_MTU",
+        "ipam": {
+          "type": "calico-ipam"
+        },
+        "policy": {
+          "type": "k8s"
+        },
+        "kubernetes": {
+          "kubeconfig": "KUBECONFIG_FILEPATH"
+        }
+      },
+      {
+        "type": "portmap",
+        "snat": true,
+        "capabilities": {"portMappings": true}
+      }
+    ]
+  }))
+  
+  params = ["KUBERNETES_NODE_NAME", "CNI_MTU"]
+}
+`
+
+func testAccPreCheckCniSupport(t *testing.T) {
+       cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
+
+       // Try to list CNI configurations to check if the feature is available
+       p := cs.Configuration.NewListCniConfigurationParams()
+       _, err := cs.Configuration.ListCniConfiguration(p)
+       if err != nil {
+               t.Skipf("CNI configuration not supported in this CloudStack 
version (requires 4.21.0+): %v", err)
+       }
+}
diff --git a/cloudstack/resource_cloudstack_kubernetes_cluster.go 
b/cloudstack/resource_cloudstack_kubernetes_cluster.go
index 44b500f..7333c25 100644
--- a/cloudstack/resource_cloudstack_kubernetes_cluster.go
+++ b/cloudstack/resource_cloudstack_kubernetes_cluster.go
@@ -121,6 +121,20 @@ func resourceCloudStackKubernetesCluster() 
*schema.Resource {
                                // Default:  "Running",
                        },
 
+                       "account": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional account for the 
Kubernetes cluster. Must be used with domain_id.",
+                       },
+
+                       "domain_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional domain ID for the 
Kubernetes cluster. If the account parameter is used, domain_id must also be 
used. Hosts dedicated to the specified domain will be used for deploying the 
cluster",
+                       },
+
                        "project": {
                                Type:     schema.TypeString,
                                Optional: true,
@@ -151,6 +165,55 @@ func resourceCloudStackKubernetesCluster() 
*schema.Resource {
                                ForceNew:  true,
                                Sensitive: true,
                        },
+
+                       "as_number": {
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional as number for the 
Kubernetes cluster",
+                       },
+
+                       "cni_config_details": {
+                               Type:        schema.TypeMap,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional map of CNI 
configuration details. It is used to specify the parameters values for the 
variables in userdata",
+                       },
+
+                       "cni_configuration_id": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional CNI configuration ID 
for the Kubernetes cluster. If not specified, the default CNI configuration 
will be used",
+                       },
+
+                       "etcd_nodes_size": {
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true, // For now
+                               Description: "Number of etcd nodes in the 
Kubernetes cluster. Default is 0",
+                       },
+
+                       "hypervisor": {
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "The hypervisor on which to deploy 
the cluster.",
+                       },
+
+                       "node_offerings": {
+                               Type:        schema.TypeMap,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional map of node roles to 
service offerings. If not specified, the service_offering parameter will be 
used for all node roles. Valid roles are: worker, control, etcd",
+                       },
+
+                       "node_templates": {
+                               Type:        schema.TypeMap,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Description: "An optional map of node roles to 
instance templates. If not specified, system VM template will be used. Valid 
roles are: worker, control, etcd",
+                       },
                },
        }
 }
@@ -214,6 +277,69 @@ func resourceCloudStackKubernetesClusterCreate(d 
*schema.ResourceData, meta inte
                return err
        }
 
+       if account, ok := d.GetOk("account"); ok {
+               p.SetAccount(account.(string))
+       }
+       if domainID, ok := d.GetOk("domain_id"); ok {
+               p.SetDomainid(domainID.(string))
+       }
+
+       if asNumber, ok := d.GetOk("as_number"); ok {
+               p.SetAsnumber(int64(asNumber.(int)))
+       }
+
+       if etcdNodesSize, ok := d.GetOk("etcd_nodes_size"); ok {
+               p.SetEtcdnodes(int64(etcdNodesSize.(int)))
+       }
+
+       if hypervisor, ok := d.GetOk("hypervisor"); ok {
+               p.SetHypervisor(hypervisor.(string))
+       }
+
+       if cniConfigID, ok := d.GetOk("cni_configuration_id"); ok {
+               p.SetCniconfigurationid(cniConfigID.(string))
+       }
+
+       if nodeOfferings, ok := d.GetOk("node_offerings"); ok {
+               nodeOfferingsMap := nodeOfferings.(map[string]interface{})
+               nodeOfferingsFormatted := make(map[string]string)
+               for nodeType, offeringName := range nodeOfferingsMap {
+                       // Retrieve the offering ID
+                       offeringID, e := retrieveID(cs, "service_offering", 
offeringName.(string))
+                       if e != nil {
+                               return e.Error()
+                       }
+                       nodeOfferingsFormatted[nodeType] = offeringID
+               }
+               p.SetNodeofferings(nodeOfferingsFormatted)
+       }
+
+       if nodeTemplates, ok := d.GetOk("node_templates"); ok {
+               nodeTemplatesMap := nodeTemplates.(map[string]interface{})
+               nodeTemplatesFormatted := make(map[string]string)
+               for nodeType, templateName := range nodeTemplatesMap {
+                       zoneID, err := retrieveID(cs, "zone", 
d.Get("zone").(string))
+                       if err != nil {
+                               return err.Error()
+                       }
+                       templateID, e := retrieveTemplateID(cs, zoneID, 
templateName.(string))
+                       if e != nil {
+                               return e.Error()
+                       }
+                       nodeTemplatesFormatted[nodeType] = templateID
+               }
+               p.SetNodetemplates(nodeTemplatesFormatted)
+       }
+
+       if cniConfigDetails, ok := d.GetOk("cni_config_details"); ok {
+               cniConfigDetailsMap := cniConfigDetails.(map[string]interface{})
+               cniConfigDetailsFormatted := make(map[string]string)
+               for key, value := range cniConfigDetailsMap {
+                       cniConfigDetailsFormatted[key] = value.(string)
+               }
+               p.SetCniconfigdetails(cniConfigDetailsFormatted)
+       }
+
        log.Printf("[DEBUG] Creating Kubernetes Cluster %s", name)
        r, err := cs.Kubernetes.CreateKubernetesCluster(p)
        if err != nil {
@@ -273,6 +399,10 @@ func resourceCloudStackKubernetesClusterRead(d 
*schema.ResourceData, meta interf
        d.Set("network_id", cluster.Networkid)
        d.Set("ip_address", cluster.Ipaddress)
        d.Set("state", cluster.State)
+       d.Set("account", cluster.Account)
+       d.Set("domain_id", cluster.Domainid)
+       d.Set("etcd_nodes_size", cluster.Etcdnodes)
+       d.Set("cni_configuration_id", cluster.Cniconfigurationid)
 
        setValueOrID(d, "kubernetes_version", cluster.Kubernetesversionname, 
cluster.Kubernetesversionid)
        setValueOrID(d, "service_offering", cluster.Serviceofferingname, 
cluster.Serviceofferingid)
@@ -295,7 +425,7 @@ func autoscaleKubernetesCluster(d *schema.ResourceData, 
meta interface{}) error
 func resourceCloudStackKubernetesClusterUpdate(d *schema.ResourceData, meta 
interface{}) error {
        cs := meta.(*cloudstack.CloudStackClient)
 
-       if d.HasChange("service_offering") || d.HasChange("size") {
+       if d.HasChange("service_offering") || d.HasChange("size") || 
d.HasChange("node_offerings") {
                p := cs.Kubernetes.NewScaleKubernetesClusterParams(d.Id())
                serviceOfferingID, e := retrieveID(cs, "service_offering", 
d.Get("service_offering").(string))
                if e != nil {
@@ -303,6 +433,22 @@ func resourceCloudStackKubernetesClusterUpdate(d 
*schema.ResourceData, meta inte
                }
                p.SetServiceofferingid(serviceOfferingID)
                p.SetSize(int64(d.Get("size").(int)))
+
+               // Handle node offerings if they changed
+               if nodeOfferings, ok := d.GetOk("node_offerings"); ok {
+                       nodeOfferingsMap := 
nodeOfferings.(map[string]interface{})
+                       nodeOfferingsFormatted := make(map[string]string)
+                       for nodeType, offeringName := range nodeOfferingsMap {
+                               // Retrieve the offering ID
+                               offeringID, e := retrieveID(cs, 
"service_offering", offeringName.(string))
+                               if e != nil {
+                                       return e.Error()
+                               }
+                               nodeOfferingsFormatted[nodeType] = offeringID
+                       }
+                       p.SetNodeofferings(nodeOfferingsFormatted)
+               }
+
                _, err := cs.Kubernetes.ScaleKubernetesCluster(p)
                if err != nil {
                        return fmt.Errorf(
diff --git a/cloudstack/resource_cloudstack_kubernetes_version.go 
b/cloudstack/resource_cloudstack_kubernetes_version.go
index a389d3a..b1e6d1f 100644
--- a/cloudstack/resource_cloudstack_kubernetes_version.go
+++ b/cloudstack/resource_cloudstack_kubernetes_version.go
@@ -115,7 +115,7 @@ func resourceCloudStackKubernetesVersionCreate(d 
*schema.ResourceData, meta inte
                p.SetName(name.(string))
        }
        if checksum, ok := d.GetOk("checksum"); ok {
-               p.SetName(checksum.(string))
+               p.SetChecksum(checksum.(string))
        }
        if zone, ok := d.GetOk("zone"); ok {
                zoneID, e := retrieveID(cs, "zone", zone.(string))
diff --git a/cloudstack/resource_cloudstack_static_route.go 
b/cloudstack/resource_cloudstack_static_route.go
index 0970532..d9240b7 100644
--- a/cloudstack/resource_cloudstack_static_route.go
+++ b/cloudstack/resource_cloudstack_static_route.go
@@ -56,9 +56,12 @@ func resourceCloudStackStaticRouteCreate(d 
*schema.ResourceData, meta interface{
        // Create a new parameter struct
        p := cs.VPC.NewCreateStaticRouteParams(
                d.Get("cidr").(string),
-               d.Get("gateway_id").(string),
        )
 
+       if v, ok := d.GetOk("gateway_id"); ok {
+               p.SetGatewayid(v.(string))
+       }
+
        // Create the new private gateway
        r, err := cs.VPC.CreateStaticRoute(p)
        if err != nil {
diff --git a/cloudstack/resource_cloudstack_template.go 
b/cloudstack/resource_cloudstack_template.go
index edf41c1..4316c7e 100644
--- a/cloudstack/resource_cloudstack_template.go
+++ b/cloudstack/resource_cloudstack_template.go
@@ -126,6 +126,13 @@ func resourceCloudStackTemplate() *schema.Resource {
                                Default:  300,
                        },
 
+                       "for_cks": {
+                               Type:     schema.TypeBool,
+                               Optional: true,
+                               Computed: true,
+                               ForceNew: true,
+                       },
+
                        "tags": tagsSchema(),
                },
        }
@@ -182,6 +189,10 @@ func resourceCloudStackTemplateCreate(d 
*schema.ResourceData, meta interface{})
                p.SetPasswordenabled(v.(bool))
        }
 
+       if v, ok := d.GetOk("for_cks"); ok {
+               p.SetForcks(v.(bool))
+       }
+
        // Retrieve the zone ID
        if v, ok := d.GetOk("zone"); ok {
                if v.(string) != "all" {
@@ -277,6 +288,7 @@ func resourceCloudStackTemplateRead(d *schema.ResourceData, 
meta interface{}) er
        d.Set("is_public", t.Ispublic)
        d.Set("password_enabled", t.Passwordenabled)
        d.Set("is_ready", t.Isready)
+       d.Set("for_cks", t.Forcks)
 
        tags := make(map[string]interface{})
        for _, tag := range t.Tags {
diff --git a/go.mod b/go.mod
index 339e856..6e69966 100644
--- a/go.mod
+++ b/go.mod
@@ -18,7 +18,7 @@
 module github.com/terraform-providers/terraform-provider-cloudstack
 
 require (
-       github.com/apache/cloudstack-go/v2 v2.17.2
+       github.com/apache/cloudstack-go/v2 v2.18.1
        github.com/go-ini/ini v1.67.0
        github.com/hashicorp/go-multierror v1.1.1
        github.com/hashicorp/terraform-plugin-framework v1.12.0
diff --git a/go.sum b/go.sum
index 4b49b66..d60bbe4 100644
--- a/go.sum
+++ b/go.sum
@@ -6,8 +6,8 @@ github.com/ProtonMail/go-crypto v1.1.0-alpha.0 
h1:nHGfwXmFvJrSR9xu8qL7BkO4DqTHXE
 github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod 
h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
 github.com/agext/levenshtein v1.2.2 
h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
 github.com/agext/levenshtein v1.2.2/go.mod 
h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
-github.com/apache/cloudstack-go/v2 v2.17.2 
h1:fMqLUTpHZeJoSVQiD2hDBSoqOvGJ9QMoOaWABW8lc/0=
-github.com/apache/cloudstack-go/v2 v2.17.2/go.mod 
h1:p/YBUwIEkQN6CQxFhw8Ff0wzf1MY0qRRRuGYNbcb1F8=
+github.com/apache/cloudstack-go/v2 v2.18.1 
h1:SgdRUEj5x17wSPfwAacjWgTqbtS/u7iaqnbpILWzE1c=
+github.com/apache/cloudstack-go/v2 v2.18.1/go.mod 
h1:p/YBUwIEkQN6CQxFhw8Ff0wzf1MY0qRRRuGYNbcb1F8=
 github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod 
h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
 github.com/apparentlymart/go-textseg/v15 v15.0.0 
h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
 github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod 
h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
diff --git a/website/docs/r/cni_configuration.html.markdown 
b/website/docs/r/cni_configuration.html.markdown
new file mode 100644
index 0000000..de80a76
--- /dev/null
+++ b/website/docs/r/cni_configuration.html.markdown
@@ -0,0 +1,172 @@
+---
+layout: default
+page_title: "CloudStack: cloudstack_cni_configuration"
+sidebar_current: "docs-cloudstack-resource-cni_configuration"
+description: |-
+    Creates and manages a CloudStack CNI (Container Network Interface) 
configuration
+---
+
+# CloudStack: cloudstack_cni_configuration
+
+A `cloudstack_cni_configuration` resource manages a Container Network 
Interface (CNI) configuration for CloudStack Kubernetes Service (CKS) clusters. 
CNI configurations define how network connectivity is provided to Kubernetes 
pods.
+
+## Example Usage
+
+### Basic Calico CNI Configuration
+
+```hcl
+resource "cloudstack_cni_configuration" "calico" {
+  name       = "calico-cni-config"
+  cni_config = base64encode(jsonencode({
+    "name"       = "k8s-pod-network",
+    "cniVersion" = "0.3.1",
+    "plugins" = [
+      {
+        "type"           = "calico",
+        "log_level"      = "info",
+        "datastore_type" = "kubernetes",
+        "nodename"       = "KUBERNETES_NODE_NAME",
+        "mtu"            = "CNI_MTU",
+        "ipam" = {
+          "type" = "calico-ipam"
+        },
+        "policy" = {
+          "type" = "k8s"
+        },
+        "kubernetes" = {
+          "kubeconfig" = "KUBECONFIG_FILEPATH"
+        }
+      },
+      {
+        "type" = "portmap",
+        "snat" = true,
+        "capabilities" = { "portMappings" = true }
+      }
+    ]
+  }))
+  
+  params = [
+    "KUBERNETES_NODE_NAME",
+    "CNI_MTU",
+    "KUBECONFIG_FILEPATH"
+  ]
+}
+```
+
+### Flannel CNI Configuration
+
+```hcl
+resource "cloudstack_cni_configuration" "flannel" {
+  name       = "flannel-cni-config"
+  cni_config = base64encode(jsonencode({
+    "name"       = "cbr0",
+    "cniVersion" = "0.3.1",
+    "plugins" = [
+      {
+        "type"   = "flannel",
+        "delegate" = {
+          "hairpinMode" = true,
+          "isDefaultGateway" = true
+        }
+      },
+      {
+        "type" = "portmap",
+        "capabilities" = {
+          "portMappings" = true
+        }
+      }
+    ]
+  }))
+  
+  params = ["FLANNEL_NETWORK", "FLANNEL_SUBNET"]
+  
+  domain_id = "domain-uuid"
+  account   = "admin"
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+### Required Arguments
+
+* `name` - (Required) The name of the CNI configuration. Must be unique within 
the account/domain.
+* `cni_config` - (Required) The CNI configuration in base64-encoded JSON 
format. This should contain the complete CNI plugin configuration according to 
the CNI specification.
+
+### Optional Arguments
+
+* `params` - (Optional) A list of parameter names that can be substituted in 
the CNI configuration. These parameters can be provided with actual values when 
creating a Kubernetes cluster using `cni_config_details`.
+* `domain_id` - (Optional) The domain ID for the CNI configuration. If not 
specified, uses the default domain.
+* `account` - (Optional) The account name for the CNI configuration. If not 
specified, uses the account of the authenticated user.
+* `project_id` - (Optional) The project ID to assign the CNI configuration to.
+
+## Attributes Reference
+
+In addition to all arguments above, the following attributes are exported:
+
+* `id` - The ID of the CNI configuration.
+* `created` - The timestamp when the CNI configuration was created.
+* `domain` - The domain name where the CNI configuration belongs.
+* `project` - The project name if the CNI configuration is assigned to a 
project.
+
+## CNI Configuration Format
+
+The `cni_config` should be a base64-encoded JSON string that follows the CNI 
specification. The configuration supports parameter substitution using 
placeholder names that can be defined in the `params` list.
+
+### Parameter Substitution
+
+Parameters in the CNI configuration can be specified as placeholders and will 
be replaced with actual values when the configuration is used in a Kubernetes 
cluster:
+
+```json
+{
+  "name": "k8s-pod-network",
+  "cniVersion": "0.3.1",
+  "plugins": [
+    {
+      "type": "calico",
+      "nodename": "KUBERNETES_NODE_NAME",
+      "mtu": "CNI_MTU"
+    }
+  ]
+}
+```
+
+The `KUBERNETES_NODE_NAME` and `CNI_MTU` placeholders will be replaced when 
creating a cluster using this configuration.
+
+### Supported CNI Plugins
+
+CloudStack supports various CNI plugins including:
+
+* **Calico** - Provides networking and network policy for Kubernetes
+* **Flannel** - Simple overlay network for Kubernetes
+* **Weave** - Container networking solution
+* **Custom plugins** - Any CNI-compliant plugin can be configured
+
+## Usage with Kubernetes Clusters
+
+CNI configurations are used with Kubernetes clusters by referencing the 
configuration ID:
+
+```hcl
+resource "cloudstack_kubernetes_cluster" "example" {
+  name                 = "example-cluster"
+  zone                 = "zone1"
+  kubernetes_version   = "1.25.0"
+  service_offering     = "Medium Instance"
+  
+  cni_configuration_id = cloudstack_cni_configuration.calico.id
+  cni_config_details = {
+    "CNI_MTU"               = "1450"
+    "KUBERNETES_NODE_NAME"  = "spec.nodeName"
+    "KUBECONFIG_FILEPATH"   = "/etc/cni/net.d/calico-kubeconfig"
+  }
+}
+```
+
+## Import
+
+CNI configurations can be imported using the configuration ID:
+
+```shell
+$ terraform import cloudstack_cni_configuration.example <CNI_CONFIGURATION_ID>
+```
diff --git a/website/docs/r/kubernetes_cluster.html.markdown 
b/website/docs/r/kubernetes_cluster.html.markdown
index 8bb61c8..ac2ec62 100644
--- a/website/docs/r/kubernetes_cluster.html.markdown
+++ b/website/docs/r/kubernetes_cluster.html.markdown
@@ -3,31 +3,103 @@ layout: default
 page_title: "CloudStack: cloudstack_kubernetes_cluster"
 sidebar_current: "docs-cloudstack-resource-kubernetes_cluster"
 description: |-
-    Creates a Kubernetes Cluster
+    Creates and manages a CloudStack Kubernetes Service (CKS) cluster
 ---
 
 # CloudStack: cloudstack_kubernetes_cluster
 
-A `cloudstack_kubernetes_cluster` resource manages a Kubernetes cluster within 
CloudStack.
+A `cloudstack_kubernetes_cluster` resource manages a CloudStack Kubernetes 
Service (CKS) cluster within CloudStack. This resource supports advanced 
features including mixed node types, custom templates, CNI configurations, and 
autoscaling.
 
 ## Example Usage
 
+### Basic Cluster
+
 ```hcl
-resource "cloudstack_kubernetes_cluster" "example" {
-    name = "example-cluster"
-    zone = "zone-id"
-    kubernetes_version = "1.18.6"
-    service_offering = "small"
-    size = 1
-    autoscaling_enabled = true
-    min_size = 1
-    max_size = 5
-    control_nodes_size = 1
-    description = "An example Kubernetes cluster"
-    keypair = "my-ssh-key"
-    network_id = "net-id"
-    state = "Running"
-    project = "my-project"
+resource "cloudstack_kubernetes_cluster" "basic" {
+  name               = "basic-cluster"
+  zone               = "zone1"
+  kubernetes_version = "1.25.0"
+  service_offering   = "Medium Instance"
+  size               = 3
+  description        = "Basic Kubernetes cluster"
+}
+```
+
+### Advanced Cluster with CKS Features
+
+```hcl
+# Kubernetes version resource
+resource "cloudstack_kubernetes_version" "k8s_v1_25" {
+  semantic_version = "1.25.0"
+  name             = "Kubernetes v1.25.0 with Calico"
+  url              = "http://example.com/k8s-setup-v1.25.0.iso";
+  min_cpu          = 2
+  min_memory       = 2048
+  zone             = "zone1"
+  state            = "Enabled"
+}
+
+# CNI configuration
+resource "cloudstack_cni_configuration" "calico" {
+  name       = "calico-cni-config"
+  cni_config = base64encode(jsonencode({
+    "name"       = "k8s-pod-network",
+    "cniVersion" = "0.3.1",
+    "plugins" = [
+      {
+        "type"           = "calico",
+        "datastore_type" = "kubernetes",
+        "nodename"       = "KUBERNETES_NODE_NAME",
+        "mtu"            = "CNI_MTU"
+      }
+    ]
+  }))
+  
+  params = ["KUBERNETES_NODE_NAME", "CNI_MTU"]
+}
+
+# Advanced cluster with mixed node types
+resource "cloudstack_kubernetes_cluster" "advanced" {
+  name               = "production-cluster"
+  zone               = "zone1"
+  kubernetes_version = cloudstack_kubernetes_version.k8s_v1_25.semantic_version
+  service_offering   = "Medium Instance"
+
+  # Cluster configuration
+  size               = 3
+  control_nodes_size = 3
+  etcd_nodes_size    = 3
+
+  # Autoscaling
+  autoscaling_enabled = true
+  min_size            = 2
+  max_size            = 10
+
+  # Node configuration
+  noderootdisksize = 50
+
+  # Mixed node offerings
+  node_offerings = {
+    "control" = "Large Instance"
+    "worker"  = "Medium Instance"
+    "etcd"    = "Medium Instance"
+  }
+
+  # Custom templates
+  node_templates = {
+    "control" = "ubuntu-20.04-k8s-template"
+    "worker"  = "ubuntu-20.04-k8s-template"
+  }
+
+  # CNI Configuration
+  cni_configuration_id = cloudstack_cni_configuration.calico.id
+  cni_config_details = {
+    "CNI_MTU"               = "1450"
+    "KUBERNETES_NODE_NAME"  = "spec.nodeName"
+  }
+
+  description = "Production cluster with mixed node types"
+  hypervisor  = "KVM"
 }
 ```
 
@@ -36,43 +108,67 @@ resource "cloudstack_kubernetes_cluster" "example" {
 
 The following arguments are supported:
 
+### Required Arguments
+
 * `name` - (Required) The name of the Kubernetes cluster.
 * `zone` - (Required) The zone where the Kubernetes cluster will be deployed.
 * `kubernetes_version` - (Required) The Kubernetes version for the cluster.
 * `service_offering` - (Required) The service offering for the nodes in the 
cluster.
-* `size` - (Optional) The initial size of the Kubernetes cluster. Defaults to 
`1`.
-* `autoscaling_enabled` - (Optional) Whether autoscaling is enabled for the 
cluster.
-* `min_size` - (Optional) The minimum size of the Kubernetes cluster when 
autoscaling is enabled.
-* `max_size` - (Optional) The maximum size of the Kubernetes cluster when 
autoscaling is enabled.
-* `control_nodes_size` - (Optional) The size of the control nodes in the 
cluster.
+
+### Basic Configuration
+
+* `size` - (Optional) The number of worker nodes in the Kubernetes cluster. 
Defaults to `1`.
+* `control_nodes_size` - (Optional) The number of control plane nodes in the 
cluster. Defaults to `1`.
+* `etcd_nodes_size` - (Optional) The number of etcd nodes in the cluster. 
Defaults to `0` (uses control nodes for etcd).
 * `description` - (Optional) A description for the Kubernetes cluster.
-* `keypair` - (Optional) The SSH key pair to use for the nodes in the cluster.
-* `network_id` - (Optional) The network ID to connect the Kubernetes cluster 
to.
-* `ip_address` - (Computed) The IP address of the Kubernetes cluster.
-* `state` - (Optional) The state of the Kubernetes cluster. Defaults to 
`"Running"`.
-* `project` - (Optional) The project to assign the Kubernetes cluster to.
-* `noderootdisksize` - (Optional) root disk size in GB for each node.
+* `hypervisor` - (Optional) The hypervisor type for the cluster nodes. 
Defaults to `"KVM"`.
 * `docker_registry_url` - (Optional) URL for the docker image private registry
 * `docker_registry_username` - (Optional) password for the docker image 
private registry
 * `docker_registry_password"` - (Optional) user name for the docker image 
private registry
 
+### Autoscaling Configuration
+
+* `autoscaling_enabled` - (Optional) Whether autoscaling is enabled for the 
cluster. Defaults to `false`.
+* `min_size` - (Optional) The minimum number of worker nodes when autoscaling 
is enabled.
+* `max_size` - (Optional) The maximum number of worker nodes when autoscaling 
is enabled.
+
+### Node Configuration
+
+* `noderootdisksize` - (Optional) Root disk size in GB for each node. Defaults 
to `20`.
+* `node_offerings` - (Optional) A map of node roles to service offerings. 
Valid roles are `control`, `worker`, and `etcd`. If not specified, the main 
`service_offering` is used for all nodes.
+* `node_templates` - (Optional) A map of node roles to instance templates. 
Valid roles are `control`, `worker`, and `etcd`. If not specified, system VM 
template will be used.
+
+### CNI Configuration
+
+* `cni_configuration_id` - (Optional) The ID of a CNI configuration to use for 
the cluster. If not specified, the default CNI configuration will be used.
+* `cni_config_details` - (Optional) A map of CNI configuration parameter 
values to substitute in the CNI configuration.
+
+### Network and Security
+
+* `keypair` - (Optional) The SSH key pair to use for the nodes in the cluster.
+* `network_id` - (Optional) The network ID to connect the Kubernetes cluster 
to.
+
+### Project and Domain
+
+* `project` - (Optional) The project to assign the Kubernetes cluster to.
+* `domain_id` - (Optional) The domain ID for the cluster.
+* `account` - (Optional) The account name for the cluster.
+
 ## Attributes Reference
 
-The following attributes are exported:
+In addition to all arguments above, the following attributes are exported:
 
 * `id` - The ID of the Kubernetes cluster.
-* `name` - The name of the Kubernetes cluster.
-* `description` - The description of the Kubernetes cluster.
-* `control_nodes_size` - The size of the control nodes in the cluster.
-* `size` - The size of the Kubernetes cluster.
-* `autoscaling_enabled` - Whether autoscaling is enabled for the cluster.
-* `min_size` - The minimum size of the Kubernetes cluster when autoscaling is 
enabled.
-* `max_size` - The maximum size of the Kubernetes cluster when autoscaling is 
enabled.
-* `keypair` - The SSH key pair used for the nodes in the cluster.
-* `network_id` - The network ID connected to the Kubernetes cluster.
-* `ip_address` - The IP address of the Kubernetes cluster.
-* `state` - The state of the Kubernetes cluster.
-* `project` - The project assigned to the Kubernetes cluster.
+* `ip_address` - The IP address of the Kubernetes cluster API server.
+* `state` - The current state of the Kubernetes cluster.
+* `created` - The timestamp when the cluster was created.
+* `zone_id` - The zone ID where the cluster is deployed.
+* `zone_name` - The zone name where the cluster is deployed.
+* `kubernetes_version_id` - The ID of the Kubernetes version used.
+* `service_offering_id` - The ID of the service offering used.
+* `master_nodes` - The number of master/control nodes in the cluster.
+* `cpu_number` - The number of CPUs allocated to the cluster.
+* `memory` - The amount of memory (in MB) allocated to the cluster.
 
 ## Import
 
diff --git a/website/docs/r/template.html.markdown 
b/website/docs/r/template.html.markdown
index 1b2f8a6..52eb7fa 100644
--- a/website/docs/r/template.html.markdown
+++ b/website/docs/r/template.html.markdown
@@ -3,51 +3,98 @@ layout: "cloudstack"
 page_title: "CloudStack: cloudstack_template"
 sidebar_current: "docs-cloudstack-resource-template"
 description: |-
-  Registers an existing template into the CloudStack cloud.
+  Registers a template into the CloudStack cloud, including support for 
CloudStack Kubernetes Service (CKS) templates.
 ---
 
 # cloudstack_template
 
-Registers an existing template into the CloudStack cloud.
+Registers a template into the CloudStack cloud. This resource supports both 
regular VM templates and specialized templates for CloudStack Kubernetes 
Service (CKS) clusters.
 
 ## Example Usage
 
+### Basic Template
+
 ```hcl
 resource "cloudstack_template" "centos64" {
   name       = "CentOS 6.4 x64"
   format     = "VHD"
   hypervisor = "XenServer"
   os_type    = "CentOS 6.4 (64bit)"
-  url        = "http://someurl.com/template.vhd";
+  url        = "http://example.com/template.vhd";
   zone       = "zone-1"
 }
 ```
 
+### CKS Template for Kubernetes
+
+```hcl
+resource "cloudstack_template" "cks_ubuntu_template" {
+  name         = "cks-ubuntu-2204-template"
+  display_text = "CKS Ubuntu 22.04 Template for Kubernetes"
+  url          = "http://example.com/cks-ubuntu-2204-kvm.qcow2.bz2";
+  format       = "QCOW2"
+  hypervisor   = "KVM"
+  os_type      = "Ubuntu 22.04 LTS"
+  zone         = "zone1"
+
+  # CKS specific flag
+  for_cks = true
+
+  # Template properties
+  is_extractable          = false
+  is_featured             = false
+  is_public               = false
+  password_enabled        = true
+  is_dynamically_scalable = true
+
+  # Wait for template to be ready
+  is_ready_timeout = 1800
+
+  tags = {
+    Environment = "CKS"
+    Purpose     = "Kubernetes"
+    OS          = "Ubuntu-22.04"
+  }
+}
+```
+
 ## Argument Reference
 
 The following arguments are supported:
 
+### Required Arguments
+
 * `name` - (Required) The name of the template.
+* `format` - (Required) The format of the template. Valid values are `QCOW2`, 
`RAW`, `VHD`, `OVA`, and `ISO`.
+* `hypervisor` - (Required) The target hypervisor for the template. Valid 
values include `KVM`, `XenServer`, `VMware`, `Hyperv`, and `LXC`. Changing this 
forces a new resource to be created.
+* `os_type` - (Required) The OS Type that best represents the OS of this 
template.
+* `url` - (Required) The URL of where the template is hosted. Changing this 
forces a new resource to be created.
 
-* `display_text` - (Optional) The display name of the template.
+### Optional Arguments
 
-* `format` - (Required) The format of the template. Valid values are `QCOW2`,
-    `RAW`, and `VHD`.
+* `display_text` - (Optional) The display name of the template. If not 
specified, defaults to the `name`.
+* `zone` - (Optional) The name or ID of the zone where this template will be 
created. Changing this forces a new resource to be created.
+* `project` - (Optional) The name or ID of the project to create this template 
for. Changing this forces a new resource to be created.
+* `account` - (Optional) The account name for the template.
+* `domain_id` - (Optional) The domain ID for the template.
 
-* `hypervisor` - (Required) The target hypervisor for the template. Changing
-    this forces a new resource to be created.
+### CKS-Specific Arguments
 
-* `os_type` - (Required) The OS Type that best represents the OS of this
-    template.
+* `for_cks` - (Optional) Set to `true` to indicate this template is for 
CloudStack Kubernetes Service (CKS). CKS templates have special requirements 
and capabilities. Defaults to `false`.
 
-* `url` - (Required) The URL of where the template is hosted. Changing this
-    forces a new resource to be created.
+### Template Properties
 
-* `project` - (Optional) The name or ID of the project to create this template 
for.
-    Changing this forces a new resource to be created.
+* `is_dynamically_scalable` - (Optional) Set to indicate if the template 
contains tools to support dynamic scaling of VM cpu/memory. Defaults to `false`.
+* `is_extractable` - (Optional) Set to indicate if the template is 
extractable. Defaults to `false`.
+* `is_featured` - (Optional) Set to indicate if the template is featured. 
Defaults to `false`.
+* `is_public` - (Optional) Set to indicate if the template is available for 
all accounts. Defaults to `true`.
+* `password_enabled` - (Optional) Set to indicate if the template should be 
password enabled. Defaults to `false`.
+* `sshkey_enabled` - (Optional) Set to indicate if the template supports SSH 
key injection. Defaults to `false`.
+* `is_ready_timeout` - (Optional) The maximum time in seconds to wait until 
the template is ready for use. Defaults to `300` seconds.
 
-* `zone` - (Optional) The name or ID of the zone where this template will be 
created.
-    Changing this forces a new resource to be created.
+### Metadata and Tagging
+
+* `tags` - (Optional) A mapping of tags to assign to the template.
 
 * `is_dynamically_scalable` - (Optional) Set to indicate if the template 
contains
     tools to support dynamic scaling of VM cpu/memory (defaults false)
@@ -78,4 +125,40 @@ The following attributes are exported:
 * `is_featured` - Set to "true" if the template is featured.
 * `is_public` - Set to "true" if the template is public.
 * `password_enabled` - Set to "true" if the template is password enabled.
-* `is_ready` - Set to "true" once the template is ready for use.
+* `is_ready` - Set to `true` once the template is ready for use.
+* `created` - The timestamp when the template was created.
+* `size` - The size of the template in bytes.
+* `checksum` - The checksum of the template.
+* `status` - The current status of the template.
+* `zone_id` - The zone ID where the template is registered.
+* `zone_name` - The zone name where the template is registered.
+* `account` - The account name owning the template.
+* `domain` - The domain name where the template belongs.
+* `project` - The project name if the template is assigned to a project.
+
+### Example CKS Template Usage
+
+```hcl
+# Data source to use existing CKS template
+data "cloudstack_template" "cks_template" {
+  template_filter = "executable"
+
+  filter {
+    name  = "name" 
+    value = "cks-ubuntu-2204-template"
+  }
+}
+
+# Use in Kubernetes cluster
+resource "cloudstack_kubernetes_cluster" "example" {
+  name               = "example-cluster"
+  zone               = "zone1"
+  kubernetes_version = "1.25.0"
+  service_offering   = "Medium Instance"
+  
+  node_templates = {
+    "control" = data.cloudstack_template.cks_template.name
+    "worker"  = data.cloudstack_template.cks_template.name
+  }
+}
+```


Reply via email to