checkpoint
parent
c26c80e170
commit
9d23488ff5
|
|
@ -87,20 +87,17 @@ func IsK9sMeta(m metav1.APIResource) bool {
|
|||
|
||||
// Load hydrates server preferred+CRDs resource metadata.
|
||||
func LoadResources(f Factory) error {
|
||||
log.Debug().Msgf("LOAD RES")
|
||||
resMetas = make(ResourceMetas, 100)
|
||||
if err := loadPreferred(f, resMetas); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := loadNonResource(resMetas); err != nil {
|
||||
return err
|
||||
}
|
||||
loadNonResource(resMetas)
|
||||
|
||||
return loadCRDs(f, resMetas)
|
||||
}
|
||||
|
||||
// BOZO!! Need contermeasure for direct commands!
|
||||
func loadNonResource(m ResourceMetas) error {
|
||||
func loadNonResource(m ResourceMetas) {
|
||||
m["aliases"] = metav1.APIResource{
|
||||
Name: "aliases",
|
||||
Kind: "Aliases",
|
||||
|
|
@ -134,6 +131,16 @@ func loadNonResource(m ResourceMetas) error {
|
|||
Verbs: []string{"delete"},
|
||||
Categories: []string{"k9s"},
|
||||
}
|
||||
m["containers"] = metav1.APIResource{
|
||||
Name: "containers",
|
||||
Kind: "Containers",
|
||||
Categories: []string{"k9s"},
|
||||
}
|
||||
|
||||
loadRBAC(m)
|
||||
}
|
||||
|
||||
func loadRBAC(m ResourceMetas) {
|
||||
m["rbac"] = metav1.APIResource{
|
||||
Name: "rbacs",
|
||||
Kind: "Rules",
|
||||
|
|
@ -145,11 +152,6 @@ func loadNonResource(m ResourceMetas) error {
|
|||
Namespaced: true,
|
||||
Categories: []string{"k9s"},
|
||||
}
|
||||
m["containers"] = metav1.APIResource{
|
||||
Name: "containers",
|
||||
Kind: "Containers",
|
||||
Categories: []string{"k9s"},
|
||||
}
|
||||
m["users"] = metav1.APIResource{
|
||||
Name: "users",
|
||||
Kind: "User",
|
||||
|
|
@ -160,8 +162,6 @@ func loadNonResource(m ResourceMetas) error {
|
|||
Kind: "Group",
|
||||
Categories: []string{"k9s"},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadPreferred(f Factory, m ResourceMetas) error {
|
||||
|
|
@ -221,8 +221,8 @@ func extractMeta(o runtime.Object) (metav1.APIResource, []error) {
|
|||
|
||||
var meta map[string]interface{}
|
||||
meta, errs = extractMap(crd.Object, "metadata", errs)
|
||||
|
||||
m.Name, errs = extractStr(meta, "name", errs)
|
||||
|
||||
m.Group, errs = extractStr(spec, "group", errs)
|
||||
m.Version, errs = extractStr(spec, "version", errs)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,19 +6,19 @@ type ContextKey string
|
|||
// A collection of context keys.
|
||||
const (
|
||||
KeyFactory ContextKey = "factory"
|
||||
KeyLabels = "labels"
|
||||
KeyFields = "fields"
|
||||
KeyTable = "table"
|
||||
KeyDir = "dir"
|
||||
KeyPath = "path"
|
||||
KeySubject = "subject"
|
||||
KeyGVR = "gvr"
|
||||
KeyForwards = "forwards"
|
||||
KeyContainers = "containers"
|
||||
KeyBenchCfg = "benchcfg"
|
||||
KeyAliases = "aliases"
|
||||
KeyUID = "uid"
|
||||
KeySubjectKind = "subjectKind"
|
||||
KeySubjectName = "subjectName"
|
||||
KeyNamespace = "namespace"
|
||||
KeyLabels ContextKey = "labels"
|
||||
KeyFields ContextKey = "fields"
|
||||
KeyTable ContextKey = "table"
|
||||
KeyDir ContextKey = "dir"
|
||||
KeyPath ContextKey = "path"
|
||||
KeySubject ContextKey = "subject"
|
||||
KeyGVR ContextKey = "gvr"
|
||||
KeyForwards ContextKey = "forwards"
|
||||
KeyContainers ContextKey = "containers"
|
||||
KeyBenchCfg ContextKey = "benchcfg"
|
||||
KeyAliases ContextKey = "aliases"
|
||||
KeyUID ContextKey = "uid"
|
||||
KeySubjectKind ContextKey = "subjectKind"
|
||||
KeySubjectName ContextKey = "subjectName"
|
||||
KeyNamespace ContextKey = "namespace"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -60,12 +60,6 @@ func (c *Job) List(ctx context.Context) ([]runtime.Object, error) {
|
|||
// ----------------------------------------------------------------------------
|
||||
// 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 {
|
||||
tokens := strings.Split(n, "-")
|
||||
if len(tokens) == 0 || tokens[0] != p {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ func (n *Node) List(_ context.Context) ([]runtime.Object, error) {
|
|||
}
|
||||
|
||||
oo := make([]runtime.Object, len(nn.Items))
|
||||
for i, n := range nn.Items {
|
||||
o, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&n)
|
||||
for i := range nn.Items {
|
||||
o, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&nn.Items[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,25 @@ func (s *Subject) List(ctx context.Context) ([]runtime.Object, error) {
|
|||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oo := make([]runtime.Object, 0, len(crbs))
|
||||
for _, crb := range crbs {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oo := make([]runtime.Object, 0, len(rbs))
|
||||
for _, rb := range rbs {
|
||||
for _, su := range rb.Subjects {
|
||||
if su.Kind != kind || inSubjectRes(oo, su.Name) {
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ func NewTable(gvr string) *Table {
|
|||
}
|
||||
}
|
||||
|
||||
// Start initiates model updates.
|
||||
func (t *Table) Start(ctx context.Context) {
|
||||
// Watch initiates model updates.
|
||||
func (t *Table) Watch(ctx context.Context) {
|
||||
t.Refresh(ctx)
|
||||
go t.updater(ctx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,10 +57,6 @@ func (v *CmdView) write(s string) {
|
|||
fmt.Fprintf(v, defaultPrompt, v.icon, s)
|
||||
}
|
||||
|
||||
func (v *CmdView) reset() {
|
||||
v.update("")
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Event Listener protocol...
|
||||
|
||||
|
|
|
|||
|
|
@ -10,16 +10,39 @@ import (
|
|||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
type Tabular interface {
|
||||
Empty() bool
|
||||
Peek() render.TableData
|
||||
// Namespaceable represents a namespaceable model.
|
||||
type Namespaceable interface {
|
||||
// ClusterWide returns true if the model represents resource in all namespaces.
|
||||
ClusterWide() bool
|
||||
|
||||
// GetNamespace returns the model namespace.
|
||||
GetNamespace() string
|
||||
|
||||
// SetNamespace changes the model namespace.
|
||||
SetNamespace(string)
|
||||
AddListener(model.TableListener)
|
||||
Start(context.Context)
|
||||
|
||||
// InNamespace check if current namespace matches models.
|
||||
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)
|
||||
|
||||
// AddListener registers a model listener.
|
||||
AddListener(model.TableListener)
|
||||
}
|
||||
|
||||
// Selectable represents a table with selections.
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func (t *testModel) ClusterWide() bool { return false }
|
|||
func (t *testModel) GetNamespace() string { return "blee" }
|
||||
func (t *testModel) SetNamespace(string) {}
|
||||
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) SetRefreshRate(time.Duration) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ func (t *testModel) ClusterWide() bool { return false }
|
|||
func (t *testModel) GetNamespace() string { return "blee" }
|
||||
func (t *testModel) SetNamespace(string) {}
|
||||
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) SetRefreshRate(time.Duration) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ func (b *Browser) Init(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
if !dao.IsK9sMeta(b.meta) {
|
||||
if _, err := b.app.factory.CanForResource(b.app.Config.ActiveNamespace(), b.GVR()); err != nil {
|
||||
return err
|
||||
if _, e := b.app.factory.CanForResource(b.app.Config.ActiveNamespace(), b.GVR()); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,8 +105,7 @@ func (b *Browser) Start() {
|
|||
if path, ok := ctx.Value(internal.KeyPath).(string); ok && path != "" {
|
||||
b.Path = path
|
||||
}
|
||||
|
||||
b.GetModel().Start(ctx)
|
||||
b.GetModel().Watch(ctx)
|
||||
}
|
||||
|
||||
// Stop terminates browser updates.
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func (t *testTableModel) ClusterWide() bool { return false }
|
|||
func (t *testTableModel) GetNamespace() string { return "blee" }
|
||||
func (t *testTableModel) SetNamespace(string) {}
|
||||
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) SetRefreshRate(time.Duration) {}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue