~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
134 lines · 4.6 KB Raw History
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
}