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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package gatewaykcp
import (
"io/fs"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/johnandersen777/socialweb-computer-kcp/deploy"
appgateway "github.com/johnandersen777/socialweb-computer-kcp/internal/app/gateway"
"github.com/johnandersen777/socialweb-computer-kcp/internal/devinstance"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kcpclient"
"github.com/johnandersen777/socialweb-computer-kcp/internal/pgunit"
)
const (
DefaultAudience = "did:web:socialweb.local"
DefaultPLC = "https://plc.directory"
DefaultIngress = "xrpc.fedproxy.com"
DefaultJoin = "*"
DeployDir = "deploy"
tenantGrantFile = "tenant-grant.yaml"
auditPolicyFile = "audit-policy.yaml"
esoDir = "eso"
)
type env struct{ m map[string]string }
func newEnv(environ []string) *env {
e := &env{m: map[string]string{}}
for _, kv := range environ {
k, v, ok := strings.Cut(kv, "=")
if ok {
e.m[k] = v
}
}
return e
}
func (e *env) get(k string) string { return e.m[k] }
func (e *env) set(k, v string) { e.m[k] = v }
func (e *env) dflt(k, v string) {
if strings.TrimSpace(e.m[k]) == "" {
e.m[k] = v
}
}
func materialize(dir string) (string, string, string, error) {
grant, audit, eso := filepath.Join(dir, tenantGrantFile), filepath.Join(dir, auditPolicyFile), filepath.Join(dir, esoDir)
if err := os.MkdirAll(eso, 0o700); err != nil {
return "", "", "", err
}
copyOut := func(src, dst string) error {
b, err := fs.ReadFile(deploy.FS, src)
if err != nil {
return err
}
return os.WriteFile(dst, b, 0o600)
}
for src, dst := range map[string]string{tenantGrantFile: grant, auditPolicyFile: audit} {
if err := copyOut(src, dst); err != nil {
return "", "", "", err
}
}
entries, err := fs.ReadDir(deploy.FS, esoDir)
if err != nil {
return "", "", "", err
}
for _, en := range entries {
if err := copyOut(esoDir+"/"+en.Name(), filepath.Join(eso, en.Name())); err != nil {
return "", "", "", err
}
}
return grant, audit, eso, nil
}
func (g *gateway) defaults(e *env, rec devinstance.Record, cert, key string) error {
state := g.c.StateDir
e.set("SOCIALWEB_KCP_HOST", rec.KcpURL)
e.set("SOCIALWEB_KCP_KUBECONFIG", g.memberKubeconfig())
e.set("SOCIALWEB_GATEWAY_NODECLAIM_AGENT", appgateway.WebAppAccountRef(g.ws))
e.dflt("SOCIALWEB_GATEWAY_ADDR", DefaultAddress)
e.dflt("SOCIALWEB_GATEWAY_AUDIENCES", DefaultAudience)
if n := g.c.Spec.Network; n != nil && n.PLCDirectoryURL != "" {
e.dflt("SOCIALWEB_GATEWAY_PLC_URL", n.PLCDirectoryURL)
}
e.dflt("SOCIALWEB_GATEWAY_PLC_URL", DefaultPLC)
e.set("SOCIALWEB_CLUSTERPROVIDER_UNIT_PREFIX", g.l.Names().HostProcessPrefix())
e.set("SOCIALWEB_CLUSTERPROVIDER_HOSTPROCESS_WORKSPACE", g.ws)
e.set("SOCIALWEB_CLUSTERPROVIDER_MOUNT_CONTEXT", kcpclient.ShardAdminContext)
e.dflt("SOCIALWEB_CLUSTERPROVIDER_STATE_DIR", filepath.Join(state, "clusterprovider"))
e.dflt("SOCIALWEB_CLUSTERPROVIDER_VAULT_STATE_DIR", state)
e.dflt("SOCIALWEB_GATEWAY_CLUSTER_STATE_DIR", e.get("SOCIALWEB_CLUSTERPROVIDER_STATE_DIR"))
e.dflt("SOCIALWEB_CLUSTERPROVIDER_LEASE_PATH", filepath.Join(state, "leases.json"))
e.dflt("SOCIALWEB_CLUSTERPROVIDER_JOIN", DefaultJoin)
e.dflt("SOCIALWEB_CLUSTERPROVIDER_DATASTORE_HAS_ROW", "false")
for k, v := range ClusterProviderEnv(g.c.Spec.ClusterProvider) {
e.set(k, v)
}
if q := g.c.Spec.Quota; q != nil && q.NodeClaims != 0 {
e.set("SOCIALWEB_GATEWAY_NODECLAIM_QUOTA", strconv.Itoa(int(q.NodeClaims)))
}
for env, name := range map[string]string{"SOCIALWEB_CLUSTERPROVIDER_EXTERNAL_SECRETS": ExeExternalSecrets,
"SOCIALWEB_CLUSTERPROVIDER_ESO_BUNDLE": ExeESOBundle, "SOCIALWEB_CLUSTERPROVIDER_DUMBPIPE": ExeDumbpipe,
"SOCIALWEB_CLUSTERPROVIDER_K3S": ExeK3s, "SOCIALWEB_CLUSTERPROVIDER_KINE": ExeKine, "SOCIALWEB_CLUSTERPROVIDER_BAO": ExeBao} {
if p := g.c.Executables[name].Path; p != "" {
e.dflt(env, p)
}
}
if root := g.c.Executables[ExePostgres].Path; root != "" {
in, err := pgunit.FromRoot(root)
if err != nil {
return err
}
e.dflt("SOCIALWEB_CLUSTERPROVIDER_PG_DUMP", in.Path("pg_dump"))
}
if h, err := os.Hostname(); err == nil {
e.dflt("SOCIALWEB_CLUSTERPROVIDER_HOST", h)
}
os.MkdirAll(e.get("SOCIALWEB_CLUSTERPROVIDER_STATE_DIR"), 0o700)
if grant, audit, eso, err := materialize(filepath.Join(state, DeployDir)); err == nil {
e.dflt("SOCIALWEB_CLUSTERPROVIDER_GRANT", grant)
e.dflt("SOCIALWEB_CLUSTERPROVIDER_AUDIT_POLICY", audit)
e.dflt("SOCIALWEB_CLUSTERPROVIDER_ESO_MANIFEST_DIR", eso)
} else {
g.c.log().Warn("the embedded deploy files could not be written; the clusterprovider reads its own defaults", "err", err.Error())
}
e.set("SOCIALWEB_TLS_CERT_FILE", cert)
e.set("SOCIALWEB_TLS_KEY_FILE", key)
return nil
}