Ctrl K
ComunidadGuías…

iclient/incus_server.go

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package iclient

import (
	"context"
	"net/http"
	"net/url"
	"slices"
	"strings"

	"github.com/lxc/incus/v7/shared/api"
)

// GetClusterMembers returns every member of the cluster, each one whole.
func (c *Connection) GetClusterMembers(ctx context.Context) ([]api.ClusterMember, error) {
	members := []api.ClusterMember{}

	query := url.Values{}
	query.Set("recursion", "1")

	_, err := c.getStruct(ctx, "", "/cluster/members", query, &members)
	if err != nil {
		return nil, err
	}

	return members, nil
}

// GetServer returns the server's own description and its ETag.
func (c *Connection) GetServer(ctx context.Context) (*api.Server, string, error) {
	server := api.Server{}

	// The root of the API is /1.0 itself.
	etag, err := c.getStruct(ctx, "", "", nil, &server)
	if err != nil {
		return nil, "", err
	}

	return &server, etag, nil
}

// HasExtension reports whether the server carries an API extension. It asks
// every time: a memo would be the one piece of mutable state on the connection.
func (c *Connection) HasExtension(ctx context.Context, extension string) (bool, error) {
	server, _, err := c.GetServer(ctx)
	if err != nil {
		return false, err
	}

	return slices.Contains(server.APIExtensions, extension), nil
}

// IsIncusOS reports whether the server runs IncusOS, by asking incusd's /os
// proxy, which only answers there.
func (c *Connection) IsIncusOS(ctx context.Context) (bool, error) {
	_, _, err := c.doPath(ctx, http.MethodGet, "/os/1.0", nil, "")
	if err == nil {
		return true, nil
	}

	// incusd's own 400 on the proxy means not IncusOS (cmd/incusd/api_os.go),
	// and a server without the proxy (404) predates IncusOS.
	if api.StatusErrorCheck(err, http.StatusBadRequest, http.StatusNotFound) {
		return false, nil
	}

	return false, err
}

// GetConnectionInfo describes how this connection reaches the server.
func (c *Connection) GetConnectionInfo(ctx context.Context) (*ConnectionInfo, error) {
	info := &ConnectionInfo{
		Certificate: c.serverCert,
		Protocol:    "incus",
		URL:         c.baseURL,
		SocketPath:  c.socketPath,
	}

	server, _, err := c.GetServer(ctx)
	if err != nil {
		return nil, err
	}

	info.Target = server.Environment.ServerName
	info.CertificateFingerprint = server.Environment.CertificateFingerprint

	if c.socketPath == "" {
		info.Addresses = append(info.Addresses, c.baseURL)
	}

	for _, addr := range server.Environment.Addresses {
		// A wildcard address names no host, so it reaches nothing.
		if strings.HasPrefix(addr, ":") {
			continue
		}

		info.Addresses = append(info.Addresses, "https://"+addr)
	}

	return info, nil
}

// RawQuery sends a request to a path the caller built in full: the path is
// used verbatim, with no /1.0 prefix and no project.
func (c *Connection) RawQuery(ctx context.Context, method string, path string, data any, queryETag string) (*api.Response, string, error) {
	return c.doPath(ctx, method, path, data, queryETag)
}