~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
129 lines · 4.6 KB Raw History
package compose

import (
	"context"
	"errors"
	"strings"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	commonv1 "github.com/johnandersen777/socialweb-computer-kcp/api/common/v1alpha1"
	exposurev1alpha1 "github.com/johnandersen777/socialweb-computer-kcp/api/exposure/v1alpha1"
	pdsv1alpha1 "github.com/johnandersen777/socialweb-computer-kcp/api/pds/v1alpha1"
	"github.com/johnandersen777/socialweb-computer-kcp/api/v1alpha1"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/events"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/market"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/eventstream"
)

type Owner struct {
	DID string

	PdsURL string

	Identifier string

	Password string

	CARef *commonv1.ObjectRef

	Vault string

	Mount string
}

func OwnerIdentityName(did string) string {
	return market.SessionOwnerName(market.SessionOwnerIdentityPrefix, did)
}

func (o Owner) pdsURL() string {
	return strings.TrimRight(strings.TrimSpace(o.PdsURL), "/")
}

func (o Owner) keysPath() string {
	return "identity/" + OwnerIdentityName(o.DID) + "/keys"
}

func (o Owner) sessionPath() string {
	return "identity/" + OwnerIdentityName(o.DID) + "/pds-session"
}

func (o Owner) pdsName() string {
	return ownerPdsName(o.pdsURL())
}

func (o Owner) tls() bool {
	return strings.HasPrefix(o.pdsURL(), "https://")
}

func OwnerRecordSources(ws string, network *v1alpha1.MarketNetworkValue) []commonv1.ObjectRef {
	refs := WatchEventSources(SourceInput{Network: network})
	for i := range refs {
		refs[i].Workspace = ws
	}
	return refs
}

func RecordWatchStreamLinks(contracts string, sources []commonv1.ObjectRef) []Link {
	sel := streamSelector(contracts, nil, []exposurev1alpha1.ComponentLinkSelectorRequirement{
		{Key: eventstream.RecordWatchLabel, Operator: exposurev1alpha1.ComponentLinkSelectorExists}})
	out := make([]Link, 0, len(sources))
	for _, s := range sources {
		out = append(out, SelectorLink(LinkName("infra-watch", contracts, s.Workspace, s.Name), sel, s, Cap(events.CapabilitySubscribe, events.ScopeAll)))
	}
	return out
}

func OwnerRepoLinks(ws, contracts string, o Owner) []Link {
	repo := RepoRefIn(o.DID, ws)
	remote := AppRef(KindRemoteRepo, repo.Name, ws)
	identity := AppRef(KindMarketIdentity, OwnerIdentityName(o.DID), ws)
	pdsRef := RemotePDSRefIn(o.pdsName(), ws)
	links := append([]Link{RepoBackendLink(repo, remote)}, RemoteRepoLinks(remote, pdsRef, identity, o.DID)...)
	if o.CARef != nil && o.tls() {
		links = append(links, TrustLink(identity, *o.CARef), TrustLink(pdsRef, *o.CARef))
	}
	return append(links, InfraLinks(contracts, repo)...)
}

func (c *Composer) ApplyOwnerRepo(ctx context.Context, r Root, ws string, o Owner) error {
	if strings.TrimSpace(o.DID) == "" || o.pdsURL() == "" || strings.TrimSpace(o.Identifier) == "" || o.Password == "" {
		return errors.New("compose: the owner account names no DID, PDS URL, identifier or password")
	}
	kv, err := c.KV(ctx, r, o.Vault, o.Mount+"/identity/*")
	if err != nil {
		return err
	}
	data, err := readKV(ctx, kv, o.Mount, o.keysPath())
	if err != nil {
		return err
	}
	if data["password"] != o.Password {
		data["password"] = o.Password
		if err := kv.Write(ctx, o.Mount, o.keysPath(), data); err != nil {
			return err
		}
	}
	remote := pdsv1alpha1.RemotePDSSpec{URL: o.pdsURL(), DID: pdsServiceDID(o.pdsURL())}
	vault := &commonv1.ObjectRef{Kind: v1alpha1.KindOpenBaoServer, Name: o.Vault, Workspace: r.Workspace}
	identity := v1alpha1.MarketIdentitySpec{Mode: v1alpha1.MarketIdentityModePdsAccount, Handle: strings.TrimSpace(o.Identifier), PdsURL: o.pdsURL(),
		Association: v1alpha1.AssociationSkip,
		KeysRef:     &commonv1.SecretRef{Vault: vault, Mount: o.Mount, Path: o.keysPath()},
		SessionRef:  &commonv1.SecretRef{Vault: vault, Mount: o.Mount, Path: o.sessionPath()}}
	if o.CARef != nil && o.tls() {
		ca := *o.CARef
		remote.TLS = pdsv1alpha1.RemotePDSTLS{Enabled: true, CARef: &ca}
		identity.CARef = &ca
	}
	if _, err := c.ApplyRemotePDS(ctx, r, ws, &pdsv1alpha1.RemotePDS{ObjectMeta: metav1.ObjectMeta{Name: o.pdsName()}, Spec: remote}); err != nil {
		return err
	}
	name := OwnerIdentityName(o.DID)
	if err := c.ApplyIdentitySpec(ctx, r, ws, name, identity); err != nil {
		return err
	}
	repo := RepoRefIn(o.DID, ws).Name
	spec := v1alpha1.RemoteRepoSpec{DID: strings.TrimSpace(o.DID), PdsRef: RemotePDSRefIn(o.pdsName(), ""),
		CredentialsRef: commonv1.CredentialsRef{ObjectRef: commonv1.ObjectRef{Group: v1alpha1.GroupName, Kind: KindMarketIdentity, Name: name}}}
	return c.ApplyRepo(ctx, r, ws, repo, KindRemoteRepo, v1alpha1.RemoteRepoGVR, &v1alpha1.RemoteRepo{ObjectMeta: metav1.ObjectMeta{Name: repo}, Spec: spec})
}