~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
96 lines · 2.8 KB Raw History
package kcpclient

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"

	kcpv1alpha1 "github.com/kcp-dev/sdk/apis/tenancy/v1alpha1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"

	"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/clusterhome"
)

func (c *Client) RemoveHome(ctx context.Context, home string) (bool, error) {
	if _, err := clusterhome.Key(home); err != nil {
		return false, err
	}
	i := strings.LastIndex(home, ":")
	parent, name := home[:i], home[i+1:]
	_, err := c.readCluster(ctx, home, name)
	switch {
	case err == nil:
		return false, nil
	case !apierrors.IsNotFound(err):
		return false, fmt.Errorf("kcpclient: the cluster of %s: %w", home, err)
	}
	claims, err := c.ListNodeClaims(ctx, home)
	if err != nil && !apierrors.IsNotFound(err) {
		return false, err
	}
	if len(claims) > 0 {
		return false, nil
	}
	if _, err := c.DropAgentHome(ctx, home); err != nil {
		return false, err
	}
	r, err := c.resource(parent, tenancyResource)
	if err != nil {
		return false, err
	}
	err = r.Delete().Resource("workspaces").Name(name).Do(ctx).Error()
	if err != nil && !apierrors.IsNotFound(err) {
		return false, fmt.Errorf("kcpclient: delete the home workspace %s: %w", home, err)
	}
	return true, nil
}

// ponytail: one list per account per sweep; a wildcard list of the home workspaces once accounts reach the thousands
func (c *Client) SweepHomes(ctx context.Context, live map[string]bool, grace time.Duration) ([]string, error) {
	if c == nil {
		return nil, nil
	}
	r, err := c.resource(clusterhome.RootWorkspace, tenancyResource)
	if err != nil {
		return nil, err
	}
	var accounts kcpv1alpha1.WorkspaceList
	if err := r.Get().Resource("workspaces").Do(ctx).Into(&accounts); err != nil {
		return nil, fmt.Errorf("kcpclient: list the account workspaces: %w", err)
	}
	var removed []string
	var errs []error
	for _, account := range accounts.Items {
		if account.Spec.Type == nil || account.Spec.Type.Name != AccountWorkspaceType || account.DeletionTimestamp != nil {
			continue
		}
		path := clusterhome.RootWorkspace + ":" + account.Name
		ar, err := c.resource(path, tenancyResource)
		if err != nil {
			return removed, err
		}
		var homes kcpv1alpha1.WorkspaceList
		if err := ar.Get().Resource("workspaces").Do(ctx).Into(&homes); err != nil {
			errs = append(errs, fmt.Errorf("kcpclient: list the homes in %s: %w", path, err))
			continue
		}
		for _, ws := range homes.Items {
			home := path + ":" + ws.Name
			key, err := clusterhome.Key(home)
			if err != nil || live[key] || ws.Spec.Type == nil || ws.Spec.Type.Name != HomeWorkspaceType ||
				ws.DeletionTimestamp != nil || time.Since(ws.CreationTimestamp.Time) < grace {
				continue
			}
			ok, err := c.RemoveHome(ctx, home)
			if err != nil {
				errs = append(errs, fmt.Errorf("%s: %w", home, err))
			}
			if ok {
				removed = append(removed, home)
			}
		}
	}
	return removed, errors.Join(errs...)
}