106 lines
2.6 KiB
Go
106 lines
2.6 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"
|
|
)
|
|
|
|
// apiClient holds configuration and auth token for talking to the backend API.
|
|
type apiClient struct {
|
|
BaseURL string
|
|
Token string
|
|
}
|
|
|
|
// loginRequest represents the request body for /login.
|
|
type loginRequest struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// loginResponse represents the response body from /login.
|
|
type loginResponse struct {
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// Provider defines the vcluster Terraform provider.
|
|
func Provider() *schema.Provider {
|
|
return &schema.Provider{
|
|
Schema: map[string]*schema.Schema{
|
|
"base_url": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Description: "Base URL of vcluster API, e.g. http://localhost:8082",
|
|
},
|
|
"username": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Description: "Username for login to vcluster API",
|
|
},
|
|
"password": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Sensitive: true,
|
|
Description: "Password for login to vcluster API",
|
|
},
|
|
},
|
|
ResourcesMap: map[string]*schema.Resource{
|
|
"vcluster_cluster": resourceCluster(),
|
|
},
|
|
ConfigureContextFunc: func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
|
|
baseURL := d.Get("base_url").(string)
|
|
username := d.Get("username").(string)
|
|
password := d.Get("password").(string)
|
|
|
|
client := &apiClient{
|
|
BaseURL: baseURL,
|
|
}
|
|
|
|
// Perform login to obtain token.
|
|
reqBody, err := json.Marshal(loginRequest{
|
|
Username: username,
|
|
Password: password,
|
|
})
|
|
if err != nil {
|
|
return nil, diag.FromErr(err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/login", baseURL), bytes.NewReader(reqBody))
|
|
if err != nil {
|
|
return nil, diag.FromErr(err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return nil, diag.FromErr(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
b, _ := io.ReadAll(resp.Body)
|
|
return nil, diag.Errorf("login failed: %s: %s", resp.Status, string(b))
|
|
}
|
|
|
|
var lr loginResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&lr); err != nil {
|
|
return nil, diag.FromErr(err)
|
|
}
|
|
if lr.Token == "" {
|
|
return nil, diag.Errorf("login succeeded but no token returned")
|
|
}
|
|
|
|
client.Token = lr.Token
|
|
return client, nil
|
|
},
|
|
}
|
|
}
|
|
|
|
|