~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
91 lines · 3.0 KB Raw History
package providermain

import (
	"context"
	"errors"
	"fmt"
	"log/slog"

	"github.com/johnandersen777/socialweb-computer-kcp/api/v1alpha1"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/clusterlink"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/clusterprovider"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/vault/openbao"
)

type clusterLinkClient interface {
	WriteClusterLink(ctx context.Context, logicalCluster string, link v1alpha1.ClusterLink) error
	WriteClusterLinkStatus(ctx context.Context, logicalCluster, name string, status v1alpha1.ClusterLinkStatus) (bool, error)
	DeleteClusterLink(ctx context.Context, logicalCluster, name string) error
}

type linkRecorder struct {
	client   clusterLinkClient
	registry clusterprovider.Clusters
}

var _ clusterprovider.LinkRecorder = linkRecorder{}

func (r linkRecorder) home(ctx context.Context, cluster string) (string, error) {
	ref, err := nodeRefFor(ctx, r.registry, cluster)
	if err != nil {
		return "", err
	}
	if ref.Home == "" {
		return "", fmt.Errorf("clusterprovider: the Cluster CR for %s was found with no home workspace, "+
			"so its ClusterLinks have nowhere to be written", cluster)
	}
	return ref.Home, nil
}

func (r linkRecorder) WriteLink(ctx context.Context, link v1alpha1.ClusterLink) error {
	home, err := r.home(ctx, link.Spec.ClusterRef.Name)
	if err != nil {
		return err
	}
	return r.client.WriteClusterLink(ctx, home, link)
}

func (r linkRecorder) WriteLinkStatus(ctx context.Context, cluster, name string, status v1alpha1.ClusterLinkStatus) error {
	home, err := r.home(ctx, cluster)
	if err != nil {
		return err
	}
	_, err = r.client.WriteClusterLinkStatus(ctx, home, name, status)
	return err
}

func (r linkRecorder) remove(ctx context.Context, home, cluster string) error {
	var errs []error
	for _, service := range clusterlink.Services {
		if err := r.client.DeleteClusterLink(ctx, home, clusterlink.Name(cluster, service)); err != nil {
			errs = append(errs, err)
		}
	}
	return errors.Join(errs...)
}

func clusterLinks(cfg Config, client clusterLinkClient, registry clusterprovider.Clusters, logins *openbao.Logins, log *slog.Logger) *clusterprovider.Links {
	if cfg.Dumbpipe == "" || cfg.ObserveOnly() || client == nil {
		return nil
	}
	return &clusterprovider.Links{
		Dumbpipe: cfg.Dumbpipe,
		Recorder: linkRecorder{client: client, registry: registry},
		Keys:     clusterprovider.VaultLinkKeys(logins),
		Log:      log,
	}
}

func (p *Provider) removeLinks(ctx context.Context, ref clusterprovider.Ref, key string) {
	if p.links == nil {
		return
	}
	if err := p.links.remove(ctx, ref.Home, key); err != nil {
		p.log.Warn("cluster provider: removing the ClusterLinks of a deleted cluster did not complete",
			"cluster", ref.Name, "key", key, "home", ref.Home, "error", err.Error(),
			"keys", "left in the cluster's own vault at "+clusterlink.Mount+", which goes with its data")
		return
	}
	p.log.Info("cluster provider: removed the ClusterLinks of a deleted cluster",
		"cluster", ref.Name, "key", key, "home", ref.Home)
}