constellation/internal/cloud/qemu/qemu.go

114 lines
3.0 KiB
Go
Raw Normal View History

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
This package provides an interface to fake a CSP API for QEMU instances.
*/
package qemu
import (
"context"
"encoding/json"
2022-11-26 13:44:34 -05:00
"fmt"
"io"
"net/http"
"net/url"
"strconv"
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
"github.com/edgelesssys/constellation/v2/internal/constants"
)
const qemuMetadataEndpoint = "10.42.0.1:8080"
// Cloud provides an interface to fake a CSP API for QEMU instances.
type Cloud struct{}
// New returns a new Cloud instance.
func New() *Cloud {
return &Cloud{}
}
// List retrieves all instances belonging to the current constellation.
func (c *Cloud) List(ctx context.Context) ([]metadata.InstanceMetadata, error) {
instancesRaw, err := c.retrieveMetadata(ctx, "/peers")
if err != nil {
return nil, err
}
2022-06-28 10:08:05 -04:00
var instances []metadata.InstanceMetadata
err = json.Unmarshal(instancesRaw, &instances)
return instances, err
}
// Self retrieves the current instance.
func (c *Cloud) Self(ctx context.Context) (metadata.InstanceMetadata, error) {
instanceRaw, err := c.retrieveMetadata(ctx, "/self")
if err != nil {
2022-06-28 10:08:05 -04:00
return metadata.InstanceMetadata{}, err
}
2022-06-28 10:08:05 -04:00
var instance metadata.InstanceMetadata
err = json.Unmarshal(instanceRaw, &instance)
return instance, err
}
2022-08-01 10:51:34 -04:00
// GetLoadBalancerEndpoint returns the endpoint of the load balancer.
// For QEMU, the load balancer is the first control plane node returned by the metadata API.
func (c *Cloud) GetLoadBalancerEndpoint(ctx context.Context) (host, port string, err error) {
host, err = c.getLoadBalancerHost(ctx)
if err != nil {
return "", "", fmt.Errorf("getting load balancer host: %w", err)
}
return host, strconv.FormatInt(constants.KubernetesPort, 10), nil
}
func (c *Cloud) getLoadBalancerHost(ctx context.Context) (string, error) {
endpointRaw, err := c.retrieveMetadata(ctx, "/endpoint")
if err != nil {
return "", err
}
var endpoint string
err = json.Unmarshal(endpointRaw, &endpoint)
return endpoint, err
2022-05-24 04:04:42 -04:00
}
2022-11-26 13:44:34 -05:00
// InitSecretHash returns the hash of the init secret.
func (c *Cloud) InitSecretHash(ctx context.Context) ([]byte, error) {
initSecretHash, err := c.retrieveMetadata(ctx, "/initsecrethash")
if err != nil {
return nil, fmt.Errorf("could not retrieve init secret hash: %w", err)
}
return initSecretHash, nil
}
// UID returns the UID of the constellation.
func (c *Cloud) UID(_ context.Context) (string, error) {
// We expect only one constellation to be deployed in the same QEMU / libvirt environment.
// the UID can be an empty string.
return "", nil
}
func (c *Cloud) retrieveMetadata(ctx context.Context, uri string) ([]byte, error) {
url := &url.URL{
Scheme: "http",
Host: qemuMetadataEndpoint,
Path: uri,
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url.String(), nil)
if err != nil {
return nil, err
}
res, err := (&http.Client{}).Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
return io.ReadAll(res.Body)
2022-05-24 04:04:42 -04:00
}