aboutsummaryrefslogtreecommitdiff
path: root/pkg/k9p/session.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/k9p/session.go')
-rw-r--r--pkg/k9p/session.go205
1 files changed, 205 insertions, 0 deletions
diff --git a/pkg/k9p/session.go b/pkg/k9p/session.go
new file mode 100644
index 0000000..471a6bc
--- /dev/null
+++ b/pkg/k9p/session.go
@@ -0,0 +1,205 @@
+package k9p
+
+import (
+ "context"
+ "runtime"
+ "sync"
+
+ "github.com/docker/go-p9p"
+ "go.terinstock.com/k9p/pkg/resources"
+ "k8s.io/client-go/informers"
+ "k8s.io/client-go/kubernetes"
+)
+
+type Session struct {
+ sync.Mutex
+ aname string
+ uname string
+
+ client kubernetes.Interface
+ sharedInformer informers.SharedInformerFactory
+ refs map[p9p.Fid]resources.Ref
+}
+
+func New(ctx context.Context, client kubernetes.Interface) *Session {
+ sharedInformer := informers.NewSharedInformerFactory(client, 0)
+
+ sharedInformer.Core().V1().Namespaces().Informer()
+ sharedInformer.Apps().V1().Deployments().Informer()
+
+ go sharedInformer.Start(ctx.Done())
+ runtime.Gosched()
+
+ return &Session{
+ client: client,
+ sharedInformer: sharedInformer,
+ refs: make(map[p9p.Fid]resources.Ref),
+ }
+}
+
+func (k *Session) getRef(fid p9p.Fid) (resources.Ref, error) {
+ k.Lock()
+ defer k.Unlock()
+
+ if fid == p9p.NOFID {
+ return nil, p9p.ErrUnknownfid
+ }
+
+ ref, found := k.refs[fid]
+ if !found {
+ return nil, p9p.ErrUnknownfid
+ }
+
+ return ref, nil
+}
+
+func (k *Session) newRef(fid p9p.Fid, resource resources.Ref) (resources.Ref, error) {
+ k.Lock()
+ defer k.Unlock()
+
+ if fid == p9p.NOFID {
+ return nil, p9p.ErrUnknownfid
+ }
+
+ _, ok := k.refs[fid]
+ if ok {
+ return nil, p9p.ErrDupfid
+ }
+
+ ref := resource
+ k.refs[fid] = ref
+ return ref, nil
+}
+
+func (k *Session) Auth(ctx context.Context, afid p9p.Fid, uname string, aname string) (p9p.Qid, error) {
+ return p9p.Qid{}, nil
+}
+
+func (k *Session) Attach(ctx context.Context, fid p9p.Fid, afid p9p.Fid, uname string, aname string) (p9p.Qid, error) {
+ if uname == "" {
+ return p9p.Qid{}, p9p.MessageRerror{Ename: "no user"}
+ }
+
+ if aname == "" {
+ aname = "/"
+ }
+
+ k.uname = uname
+ k.aname = aname
+
+ ref, err := k.newRef(fid, resources.NewDirRef("/", k, map[string]resources.Ref{
+ "namespaces": resources.NewNamespacesRef(k.client, k),
+ "cluster": resources.NewDirRef("cluster", k, map[string]resources.Ref{}),
+ }))
+ if err != nil {
+ return p9p.Qid{}, err
+ }
+
+ return ref.Info().Qid, nil
+}
+
+func (k *Session) Clunk(ctx context.Context, fid p9p.Fid) error {
+ _, err := k.getRef(fid)
+ if err != nil {
+ return err
+ }
+
+ k.Lock()
+ defer k.Unlock()
+ delete(k.refs, fid)
+
+ return nil
+}
+
+func (k *Session) Remove(ctx context.Context, fid p9p.Fid) error {
+ return p9p.ErrUnknownMsg
+}
+
+func (k *Session) Walk(ctx context.Context, fid p9p.Fid, newfid p9p.Fid, names ...string) ([]p9p.Qid, error) {
+ var qids []p9p.Qid
+
+ ref, err := k.getRef(fid)
+ if err != nil {
+ return qids, err
+ }
+
+ current := ref
+ for _, name := range names {
+ newResource, err := current.Get(name)
+ if err != nil {
+ break
+ }
+
+ qids = append(qids, newResource.Info().Qid)
+ current = newResource
+ }
+
+ if len(qids) != len(names) {
+ return qids, nil
+ }
+
+ _, err = k.newRef(newfid, current)
+ if err != nil {
+ return qids, err
+ }
+
+ return qids, nil
+}
+
+func (k *Session) Read(ctx context.Context, fid p9p.Fid, p []byte, offset int64) (n int, err error) {
+ ref, err := k.getRef(fid)
+ if err != nil {
+ return 0, err
+ }
+
+ return ref.Read(ctx, p, offset)
+}
+
+func (k *Session) Write(ctx context.Context, fid p9p.Fid, p []byte, offset int64) (n int, err error) {
+ return 0, p9p.ErrUnknownMsg
+}
+
+func (k *Session) Open(ctx context.Context, fid p9p.Fid, mode p9p.Flag) (p9p.Qid, uint32, error) {
+ ref, err := k.getRef(fid)
+ if err != nil {
+ return p9p.Qid{}, 0, err
+ }
+
+ return ref.Info().Qid, 0, nil
+}
+
+func (k *Session) Create(ctx context.Context, parent p9p.Fid, name string, perm uint32, mode p9p.Flag) (p9p.Qid, uint32, error) {
+ return p9p.Qid{}, 0, p9p.ErrUnknownMsg
+}
+
+func (k *Session) Stat(ctx context.Context, fid p9p.Fid) (p9p.Dir, error) {
+ ref, err := k.getRef(fid)
+ if err != nil {
+ return p9p.Dir{}, err
+ }
+
+ return ref.Info(), nil
+}
+
+func (k *Session) WStat(ctx context.Context, fid p9p.Fid, dir p9p.Dir) error {
+ return p9p.ErrUnknownMsg
+}
+
+// Version returns the supported version and msize of the session. This
+// can be affected by negotiating or the level of support provided by the
+// session implementation.
+func (k *Session) Version() (msize int, version string) {
+ return p9p.DefaultMSize, p9p.DefaultVersion
+}
+
+func (k *Session) WaitForCacheSync(stopCh <-chan struct{}) {
+ k.sharedInformer.WaitForCacheSync(stopCh)
+}
+
+func (k *Session) GetAuth() (uname, aname string) {
+ return k.uname, k.aname
+}
+
+func (k *Session) Informer() informers.SharedInformerFactory {
+ return k.sharedInformer
+}