checkpoint

mine
derailed 2019-12-28 12:49:14 -07:00
parent c26c80e170
commit 9d23488ff5
12 changed files with 87 additions and 54 deletions

View File

@ -87,20 +87,17 @@ func IsK9sMeta(m metav1.APIResource) bool {
// Load hydrates server preferred+CRDs resource metadata. // Load hydrates server preferred+CRDs resource metadata.
func LoadResources(f Factory) error { func LoadResources(f Factory) error {
log.Debug().Msgf("LOAD RES")
resMetas = make(ResourceMetas, 100) resMetas = make(ResourceMetas, 100)
if err := loadPreferred(f, resMetas); err != nil { if err := loadPreferred(f, resMetas); err != nil {
return err return err
} }
if err := loadNonResource(resMetas); err != nil { loadNonResource(resMetas)
return err
}
return loadCRDs(f, resMetas) return loadCRDs(f, resMetas)
} }
// BOZO!! Need contermeasure for direct commands! // BOZO!! Need contermeasure for direct commands!
func loadNonResource(m ResourceMetas) error { func loadNonResource(m ResourceMetas) {
m["aliases"] = metav1.APIResource{ m["aliases"] = metav1.APIResource{
Name: "aliases", Name: "aliases",
Kind: "Aliases", Kind: "Aliases",
@ -134,6 +131,16 @@ func loadNonResource(m ResourceMetas) error {
Verbs: []string{"delete"}, Verbs: []string{"delete"},
Categories: []string{"k9s"}, Categories: []string{"k9s"},
} }
m["containers"] = metav1.APIResource{
Name: "containers",
Kind: "Containers",
Categories: []string{"k9s"},
}
loadRBAC(m)
}
func loadRBAC(m ResourceMetas) {
m["rbac"] = metav1.APIResource{ m["rbac"] = metav1.APIResource{
Name: "rbacs", Name: "rbacs",
Kind: "Rules", Kind: "Rules",
@ -145,11 +152,6 @@ func loadNonResource(m ResourceMetas) error {
Namespaced: true, Namespaced: true,
Categories: []string{"k9s"}, Categories: []string{"k9s"},
} }
m["containers"] = metav1.APIResource{
Name: "containers",
Kind: "Containers",
Categories: []string{"k9s"},
}
m["users"] = metav1.APIResource{ m["users"] = metav1.APIResource{
Name: "users", Name: "users",
Kind: "User", Kind: "User",
@ -160,8 +162,6 @@ func loadNonResource(m ResourceMetas) error {
Kind: "Group", Kind: "Group",
Categories: []string{"k9s"}, Categories: []string{"k9s"},
} }
return nil
} }
func loadPreferred(f Factory, m ResourceMetas) error { func loadPreferred(f Factory, m ResourceMetas) error {
@ -221,8 +221,8 @@ func extractMeta(o runtime.Object) (metav1.APIResource, []error) {
var meta map[string]interface{} var meta map[string]interface{}
meta, errs = extractMap(crd.Object, "metadata", errs) meta, errs = extractMap(crd.Object, "metadata", errs)
m.Name, errs = extractStr(meta, "name", errs) m.Name, errs = extractStr(meta, "name", errs)
m.Group, errs = extractStr(spec, "group", errs) m.Group, errs = extractStr(spec, "group", errs)
m.Version, errs = extractStr(spec, "version", errs) m.Version, errs = extractStr(spec, "version", errs)

View File

@ -6,19 +6,19 @@ type ContextKey string
// A collection of context keys. // A collection of context keys.
const ( const (
KeyFactory ContextKey = "factory" KeyFactory ContextKey = "factory"
KeyLabels = "labels" KeyLabels ContextKey = "labels"
KeyFields = "fields" KeyFields ContextKey = "fields"
KeyTable = "table" KeyTable ContextKey = "table"
KeyDir = "dir" KeyDir ContextKey = "dir"
KeyPath = "path" KeyPath ContextKey = "path"
KeySubject = "subject" KeySubject ContextKey = "subject"
KeyGVR = "gvr" KeyGVR ContextKey = "gvr"
KeyForwards = "forwards" KeyForwards ContextKey = "forwards"
KeyContainers = "containers" KeyContainers ContextKey = "containers"
KeyBenchCfg = "benchcfg" KeyBenchCfg ContextKey = "benchcfg"
KeyAliases = "aliases" KeyAliases ContextKey = "aliases"
KeyUID = "uid" KeyUID ContextKey = "uid"
KeySubjectKind = "subjectKind" KeySubjectKind ContextKey = "subjectKind"
KeySubjectName = "subjectName" KeySubjectName ContextKey = "subjectName"
KeyNamespace = "namespace" KeyNamespace ContextKey = "namespace"
) )

View File

@ -60,12 +60,6 @@ func (c *Job) List(ctx context.Context) ([]runtime.Object, error) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Helpers... // Helpers...
func isControlledBy(cuid, id string) bool {
tokens := strings.Split(cuid, "-")
root := strings.Join(tokens[2:], "-")
return strings.Contains(id, root)
}
func isNamedAfter(p, n string) bool { func isNamedAfter(p, n string) bool {
tokens := strings.Split(n, "-") tokens := strings.Split(n, "-")
if len(tokens) == 0 || tokens[0] != p { if len(tokens) == 0 || tokens[0] != p {

View File

@ -30,8 +30,8 @@ func (n *Node) List(_ context.Context) ([]runtime.Object, error) {
} }
oo := make([]runtime.Object, len(nn.Items)) oo := make([]runtime.Object, len(nn.Items))
for i, n := range nn.Items { for i := range nn.Items {
o, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&n) o, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&nn.Items[i])
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -21,10 +21,25 @@ func (s *Subject) List(ctx context.Context) ([]runtime.Object, error) {
return nil, errors.New("expecting a SubjectKind") return nil, errors.New("expecting a SubjectKind")
} }
crbs, err := s.listClusterRoleBindings(kind)
if err != nil {
return nil, err
}
rbs, err := s.listRoleBindings(kind)
if err != nil {
return nil, err
}
return append(crbs, rbs...), nil
}
func (s *Subject) listClusterRoleBindings(kind string) ([]runtime.Object, error) {
crbs, err := fetchClusterRoleBindings(s.factory) crbs, err := fetchClusterRoleBindings(s.factory)
if err != nil { if err != nil {
return nil, err return nil, err
} }
oo := make([]runtime.Object, 0, len(crbs)) oo := make([]runtime.Object, 0, len(crbs))
for _, crb := range crbs { for _, crb := range crbs {
for _, su := range crb.Subjects { for _, su := range crb.Subjects {
@ -39,10 +54,16 @@ func (s *Subject) List(ctx context.Context) ([]runtime.Object, error) {
} }
} }
return oo, nil
}
func (s *Subject) listRoleBindings(kind string) ([]runtime.Object, error) {
rbs, err := fetchRoleBindings(s.factory) rbs, err := fetchRoleBindings(s.factory)
if err != nil { if err != nil {
return nil, err return nil, err
} }
oo := make([]runtime.Object, 0, len(rbs))
for _, rb := range rbs { for _, rb := range rbs {
for _, su := range rb.Subjects { for _, su := range rb.Subjects {
if su.Kind != kind || inSubjectRes(oo, su.Name) { if su.Kind != kind || inSubjectRes(oo, su.Name) {

View File

@ -34,8 +34,8 @@ func NewTable(gvr string) *Table {
} }
} }
// Start initiates model updates. // Watch initiates model updates.
func (t *Table) Start(ctx context.Context) { func (t *Table) Watch(ctx context.Context) {
t.Refresh(ctx) t.Refresh(ctx)
go t.updater(ctx) go t.updater(ctx)
} }

View File

@ -57,10 +57,6 @@ func (v *CmdView) write(s string) {
fmt.Fprintf(v, defaultPrompt, v.icon, s) fmt.Fprintf(v, defaultPrompt, v.icon, s)
} }
func (v *CmdView) reset() {
v.update("")
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Event Listener protocol... // Event Listener protocol...

View File

@ -10,16 +10,39 @@ import (
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
) )
type Tabular interface { // Namespaceable represents a namespaceable model.
Empty() bool type Namespaceable interface {
Peek() render.TableData // ClusterWide returns true if the model represents resource in all namespaces.
ClusterWide() bool ClusterWide() bool
// GetNamespace returns the model namespace.
GetNamespace() string GetNamespace() string
// SetNamespace changes the model namespace.
SetNamespace(string) SetNamespace(string)
AddListener(model.TableListener)
Start(context.Context) // InNamespace check if current namespace matches models.
InNamespace(string) bool InNamespace(string) bool
}
// Tabular represents a tabular model.
type Tabular interface {
Namespaceable
// Empty returns true if model has no data.
Empty() bool
// Peek returns current model data.
Peek() render.TableData
// Watch watches a given resource for changes.
Watch(context.Context)
// SetRefreshRate sets the model watch loop rate.
SetRefreshRate(time.Duration) SetRefreshRate(time.Duration)
// AddListener registers a model listener.
AddListener(model.TableListener)
} }
// Selectable represents a table with selections. // Selectable represents a table with selections.

View File

@ -67,7 +67,7 @@ func (t *testModel) ClusterWide() bool { return false }
func (t *testModel) GetNamespace() string { return "blee" } func (t *testModel) GetNamespace() string { return "blee" }
func (t *testModel) SetNamespace(string) {} func (t *testModel) SetNamespace(string) {}
func (t *testModel) AddListener(model.TableListener) {} func (t *testModel) AddListener(model.TableListener) {}
func (t *testModel) Start(context.Context) {} func (t *testModel) Watch(context.Context) {}
func (t *testModel) InNamespace(string) bool { return true } func (t *testModel) InNamespace(string) bool { return true }
func (t *testModel) SetRefreshRate(time.Duration) {} func (t *testModel) SetRefreshRate(time.Duration) {}

View File

@ -104,7 +104,7 @@ func (t *testModel) ClusterWide() bool { return false }
func (t *testModel) GetNamespace() string { return "blee" } func (t *testModel) GetNamespace() string { return "blee" }
func (t *testModel) SetNamespace(string) {} func (t *testModel) SetNamespace(string) {}
func (t *testModel) AddListener(model.TableListener) {} func (t *testModel) AddListener(model.TableListener) {}
func (t *testModel) Start(context.Context) {} func (t *testModel) Watch(context.Context) {}
func (t *testModel) InNamespace(string) bool { return true } func (t *testModel) InNamespace(string) bool { return true }
func (t *testModel) SetRefreshRate(time.Duration) {} func (t *testModel) SetRefreshRate(time.Duration) {}

View File

@ -63,8 +63,8 @@ func (b *Browser) Init(ctx context.Context) error {
return err return err
} }
if !dao.IsK9sMeta(b.meta) { if !dao.IsK9sMeta(b.meta) {
if _, err := b.app.factory.CanForResource(b.app.Config.ActiveNamespace(), b.GVR()); err != nil { if _, e := b.app.factory.CanForResource(b.app.Config.ActiveNamespace(), b.GVR()); e != nil {
return err return e
} }
} }
@ -105,8 +105,7 @@ func (b *Browser) Start() {
if path, ok := ctx.Value(internal.KeyPath).(string); ok && path != "" { if path, ok := ctx.Value(internal.KeyPath).(string); ok && path != "" {
b.Path = path b.Path = path
} }
b.GetModel().Watch(ctx)
b.GetModel().Start(ctx)
} }
// Stop terminates browser updates. // Stop terminates browser updates.

View File

@ -96,7 +96,7 @@ func (t *testTableModel) ClusterWide() bool { return false }
func (t *testTableModel) GetNamespace() string { return "blee" } func (t *testTableModel) GetNamespace() string { return "blee" }
func (t *testTableModel) SetNamespace(string) {} func (t *testTableModel) SetNamespace(string) {}
func (t *testTableModel) AddListener(model.TableListener) {} func (t *testTableModel) AddListener(model.TableListener) {}
func (t *testTableModel) Start(context.Context) {} func (t *testTableModel) Watch(context.Context) {}
func (t *testTableModel) InNamespace(string) bool { return true } func (t *testTableModel) InNamespace(string) bool { return true }
func (t *testTableModel) SetRefreshRate(time.Duration) {} func (t *testTableModel) SetRefreshRate(time.Duration) {}