mirror of
https://github.com/rancher/k3k.git
synced 2026-08-18 03:46:31 +00:00
* Adding new k3s function to get the config * Adding a new way to get the bootstrap data directly from the server Pod * Gate the bootstrap fetch if external datastore is in use --------- Signed-off-by: galal-hussein <hussein.galal.ahmed.11@gmail.com>
131 lines
2.5 KiB
Go
131 lines
2.5 KiB
Go
package k3s
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
type ClientConfig struct {
|
|
AgentIP string
|
|
NodeName string
|
|
PodIP string
|
|
ServerIP string
|
|
Token string
|
|
}
|
|
type Client struct {
|
|
config ClientConfig
|
|
httpClient *http.Client
|
|
staticHeaders http.Header
|
|
}
|
|
|
|
var ErrServerNotReady = errors.New("server not ready")
|
|
|
|
const (
|
|
k3sNodePasswordHeader = "k3s-Node-Password"
|
|
k3sNodeIPHeader = "k3s-Node-IP"
|
|
k3sNodeNameHeader = "k3s-Node-Name"
|
|
)
|
|
|
|
func New(config ClientConfig) *Client {
|
|
httpClient := &http.Client{
|
|
Transport: http.DefaultTransport,
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
|
|
// skip TLS verify for k3s server
|
|
if transport, ok := httpClient.Transport.(*http.Transport); ok {
|
|
transport.TLSClientConfig = &tls.Config{
|
|
// This is insecure because the K3s CA hasn't been setup yet.
|
|
InsecureSkipVerify: true,
|
|
}
|
|
}
|
|
|
|
headers := http.Header{}
|
|
|
|
if config.Token != "" {
|
|
headers.Set(k3sNodePasswordHeader, config.Token)
|
|
}
|
|
|
|
if config.NodeName != "" {
|
|
headers.Set(k3sNodeNameHeader, config.NodeName)
|
|
}
|
|
|
|
var nodeIPs []string
|
|
if config.AgentIP != "" {
|
|
nodeIPs = append(nodeIPs, config.AgentIP)
|
|
}
|
|
|
|
if config.PodIP != "" {
|
|
nodeIPs = append(nodeIPs, config.PodIP)
|
|
}
|
|
|
|
if len(nodeIPs) > 0 {
|
|
headers.Set("k3s-Node-IP", strings.Join(nodeIPs, ","))
|
|
}
|
|
|
|
return &Client{
|
|
httpClient: httpClient,
|
|
config: config,
|
|
staticHeaders: headers,
|
|
}
|
|
}
|
|
|
|
func do[T any](c *Client, endpoint, user, method string) (T, error) {
|
|
var response T
|
|
|
|
respBody, err := c.do(endpoint, user, method)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
// unmarshal the json data to the generic struct
|
|
if err := json.Unmarshal(respBody, &response); err != nil {
|
|
return response, err
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (c *Client) do(endpoint, user, method string) ([]byte, error) {
|
|
url := "https://" + c.config.ServerIP + endpoint
|
|
|
|
req, err := http.NewRequest(method, url, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.SetBasicAuth(user, c.config.Token)
|
|
|
|
for headerName, headerValues := range c.staticHeaders {
|
|
for _, headerValue := range headerValues {
|
|
req.Header.Add(headerName, headerValue)
|
|
}
|
|
}
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
if errors.Is(err, syscall.ECONNREFUSED) {
|
|
return nil, ErrServerNotReady
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode >= http.StatusBadRequest {
|
|
return nil, fmt.Errorf("failed executing '%s' request to k3s server: status code: %s", endpoint, resp.Status)
|
|
}
|
|
|
|
defer func() {
|
|
_ = resp.Body.Close()
|
|
}()
|
|
|
|
return io.ReadAll(resp.Body)
|
|
}
|