package main import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // ClusterPayload represents the JSON body sent to /createcluster. type ClusterPayload struct { Name string `json:"Name"` ClusterID string `json:"ClusterID"` ControlPlane string `json:"ControlPlane"` Status string `json:"Status"` Cpu string `json:"Cpu"` Memory string `json:"Memory"` PlatformVersion string `json:"PlatformVersion"` HealthCheck string `json:"HealthCheck"` Alert string `json:"Alert"` EndPoint string `json:"EndPoint"` ClusterType string `json:"ClusterType"` CoreDNSCpu string `json:"CoreDNSCpu"` CoreDNSMemory string `json:"CoreDNSMemory"` ApiServerCpu string `json:"ApiServerCpu"` ApiServerMemory string `json:"ApiServerMemory"` } // resourceCluster defines the vcluster_cluster resource schema and CRUD. func resourceCluster() *schema.Resource { return &schema.Resource{ CreateContext: resourceClusterCreate, ReadContext: resourceClusterRead, UpdateContext: resourceClusterUpdate, DeleteContext: resourceClusterDelete, Schema: map[string]*schema.Schema{ "name": {Type: schema.TypeString, Required: true}, "cluster_id": {Type: schema.TypeString, Required: true}, "control_plane": {Type: schema.TypeString, Required: true}, "status": {Type: schema.TypeString, Optional: true, Default: "Progressing"}, "cpu": {Type: schema.TypeString, Required: true}, "memory": {Type: schema.TypeString, Required: true}, "platform_version": {Type: schema.TypeString, Required: true}, "health_check": {Type: schema.TypeString, Optional: true}, "alert": {Type: schema.TypeString, Optional: true}, "endpoint": {Type: schema.TypeString, Optional: true, Computed: true}, "cluster_type": {Type: schema.TypeString, Required: true}, "coredns_cpu": {Type: schema.TypeString, Required: true}, "coredns_memory": {Type: schema.TypeString, Required: true}, "apiserver_cpu": {Type: schema.TypeString, Required: true}, "apiserver_memory": {Type: schema.TypeString, Required: true}, }, } } // buildPayload converts Terraform state to API payload. func buildPayload(d *schema.ResourceData) ClusterPayload { return ClusterPayload{ Name: d.Get("name").(string), ClusterID: d.Get("cluster_id").(string), ControlPlane: d.Get("control_plane").(string), Status: d.Get("status").(string), Cpu: d.Get("cpu").(string), Memory: d.Get("memory").(string), PlatformVersion: d.Get("platform_version").(string), HealthCheck: d.Get("health_check").(string), Alert: d.Get("alert").(string), EndPoint: d.Get("endpoint").(string), ClusterType: d.Get("cluster_type").(string), CoreDNSCpu: d.Get("coredns_cpu").(string), CoreDNSMemory: d.Get("coredns_memory").(string), ApiServerCpu: d.Get("apiserver_cpu").(string), ApiServerMemory: d.Get("apiserver_memory").(string), } } // resourceClusterCreate calls POST /createcluster. func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client, ok := m.(*apiClient) if !ok || client == nil { return diag.Errorf("invalid API client configuration") } payload := buildPayload(d) body, err := json.Marshal(payload) if err != nil { return diag.FromErr(err) } req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/createcluster", client.BaseURL), bytes.NewReader(body)) if err != nil { return diag.FromErr(err) } req.Header.Set("Content-Type", "application/json") // Set Authorization header with raw token as provided by the login API usage. req.Header.Set("Authorization", client.Token) resp, err := http.DefaultClient.Do(req) if err != nil { return diag.FromErr(err) } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { b, _ := io.ReadAll(resp.Body) return diag.Errorf("createcluster failed: %s: %s", resp.Status, string(b)) } // Use ClusterID as Terraform resource ID. d.SetId(payload.ClusterID) return resourceClusterRead(ctx, d, m) } // resourceClusterRead is a stub until a read API is available. func resourceClusterRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { // TODO: Implement GET call to sync state from API if/when available. return nil } // resourceClusterUpdate is a stub; you can extend it to call an update endpoint. func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { // TODO: Implement update behavior when API supports it. return resourceClusterRead(ctx, d, m) } // resourceClusterDelete clears state; extend to call delete endpoint when available. func resourceClusterDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { // TODO: Implement delete behavior when API supports it. d.SetId("") return nil }