Files
vcluster_terraform/resource_cluster.go
2025-12-01 19:38:12 +03:30

140 lines
5.1 KiB
Go

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
}