1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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...)
}