first pass scroll jitter

mine
derailed 2019-03-28 00:03:16 -06:00
parent 437e73ae6b
commit 6001b004d1
16 changed files with 83 additions and 35 deletions

View File

@ -0,0 +1,43 @@
# Release v0.4.0
## Notes
Thank you to all that contributed with flushing out issues with K9s! I'll try
to mark some of these issues as fixed. But if you don't mind grab the latest
rev and see if we're happier with some of the fixes!
If you've filed an issue please help me verify and close.
Thank you so much for your support and awesome suggestions to make K9s better!!
---
## Change Logs
1. [Feature #82](https://github.com/derailed/k9s/issues/82)
1. Added ability to view RBAC policies while in clusterrole or role view.
1. 😃 The RBAC view will auto-refresh just like any K9s views hence showing live RBAC updates!
1. RBAC view supports standard K8s verbs ie get,list,deletecollection,watch,create,patch,update,delete.
1. Any verbs not in this standard K8s verb list, will end up in the EXTRAS column.
1. For non resource URLS, we map standard REST verbs to K8s verbs ie post=create patch=update, etc..
1. Added initial sorts by name and group while in RBAC view.
1. Usage: To activate, enter command mode via `:cr` or `:ro` for clusterole(cr)/role(ro), select a row and press `<enter>`
1. To bail out of the view and return to previous use `p` or `<esc>`
1. One feature that was mentioned in the comments for the RBAC feature above Tx [faheem-cliqz](https://github.com/faheem-cliqz)! was the ability to check RBAC rules for a given user. Namely reverse RBAC lookup
1. Added a new view, code name *Fu* view to show all the clusterroles/roles associated with a given user.
1. The view also supports for checking RBAC Fu for a user, a group or an app via a serviceaccount.
1. To activate: Enter command mode via `:fu` followed by u|g|s:subject + `<enter>`.
For example: To view user *fred* Fu enter `:fu u:fred` + `<enter>` will show all clusterroles/roles and verbs associated
with the user *fred*
1. For group Fu lookup, use the same command as above and substitute `u:fred` with `g:fred`
1. For ServiceAccount *fred* Fu check: use `s:fred`
1. Try to eliminate a tad of a jitter while scrolling on most views. Please report back if that's not the case
> NOTE!: This feature is very much an alpha feature right now.
> I find it really powerful and useful, hopefully I am not the only one hunanimous on that??
---
## Resolved Bugs
+ None

View File

@ -72,7 +72,7 @@ func (r *ClusterRole) Fields(ns string) Row {
i := r.instance
return append(ff,
Pad(i.Name, 70),
toAge(i.ObjectMeta.CreationTimestamp),
Pad(i.Name, RBACPad),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -2,7 +2,6 @@ package resource_test
import (
"fmt"
"strings"
"testing"
"time"
@ -42,12 +41,12 @@ func TestCRListAccess(t *testing.T) {
func TestCRFields(t *testing.T) {
r := newClusterRole().Fields("blee")
assert.Equal(t, "fred"+strings.Repeat(" ", 66), r[0])
assert.Equal(t, resource.Pad("fred", resource.RBACPad), r[0])
}
func TestCRFieldsAllNS(t *testing.T) {
r := newClusterRole().Fields(resource.AllNamespaces)
assert.Equal(t, "fred"+strings.Repeat(" ", 66), r[0])
assert.Equal(t, resource.Pad("fred", resource.RBACPad), r[0])
}
func TestCRMarshal(t *testing.T) {
@ -85,7 +84,7 @@ func TestCRListData(t *testing.T) {
for _, d := range row.Deltas {
assert.Equal(t, "", d)
}
assert.Equal(t, resource.Row{"fred" + strings.Repeat(" ", 66)}, row.Fields[:1])
assert.Equal(t, resource.Row{resource.Pad("fred", resource.RBACPad)}, row.Fields[:1])
}
// Helpers...

View File

@ -102,7 +102,7 @@ func (r *CronJob) Fields(ns string) Row {
i := r.instance
if ns == AllNamespaces {
ff = append(ff, i.Namespace)
ff = append(ff, Pad(i.Namespace, NSPad))
}
lastScheduled := "<none>"
@ -111,11 +111,11 @@ func (r *CronJob) Fields(ns string) Row {
}
return append(ff,
i.Name,
Pad(i.Name, NamePad),
i.Spec.Schedule,
boolPtrToStr(i.Spec.Suspend),
strconv.Itoa(len(i.Status.Active)),
lastScheduled,
toAge(i.ObjectMeta.CreationTimestamp),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -39,7 +39,7 @@ func TestCronJobListAccess(t *testing.T) {
func TestCronJobFields(t *testing.T) {
r := newCronJob().Fields("blee")
assert.Equal(t, "fred", r[0])
assert.Equal(t, resource.Pad("fred", resource.NamePad), r[0])
}
func TestCronJobMarshal(t *testing.T) {
@ -75,7 +75,7 @@ func TestCronJobListData(t *testing.T) {
for _, d := range row.Deltas {
assert.Equal(t, "", d)
}
assert.Equal(t, resource.Row{"fred"}, row.Fields[:1])
assert.Equal(t, resource.Row{resource.Pad("fred", resource.NamePad)}, row.Fields[:1])
}
// Helpers...

View File

@ -36,6 +36,14 @@ const (
NAValue = "<n/a>"
)
// Columns Padding...
const (
NSPad = 13
NamePad = 50
AgePad = 5
RBACPad = 80
)
func asPerc(f float64) string {
return fmt.Sprintf("%d%%", int(f))
}

View File

@ -132,18 +132,18 @@ func (r *Job) Fields(ns string) Row {
i := r.instance
if ns == AllNamespaces {
ff = append(ff, i.Namespace)
ff = append(ff, Pad(i.Namespace, NSPad))
}
cc, ii := r.toContainers(i.Spec.Template.Spec)
return append(ff,
i.Name,
Pad(i.Name, NamePad),
r.toCompletion(i.Spec, i.Status),
r.toDuration(i.Status),
cc,
ii,
toAge(i.ObjectMeta.CreationTimestamp),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -38,7 +38,7 @@ func TestJobListAccess(t *testing.T) {
func TestJobFields(t *testing.T) {
r := newJob().Fields("blee")
assert.Equal(t, "fred", r[0])
assert.Equal(t, resource.Pad("fred", resource.NamePad), r[0])
}
func TestJobMarshal(t *testing.T) {
@ -74,7 +74,7 @@ func TestJobListData(t *testing.T) {
for _, d := range row.Deltas {
assert.Equal(t, "", d)
}
assert.Equal(t, resource.Row{"fred"}, row.Fields[:1])
assert.Equal(t, resource.Row{resource.Pad("fred", resource.NamePad)}, row.Fields[:1])
}
// Helpers...

View File

@ -203,14 +203,14 @@ func (r *Pod) Fields(ns string) Row {
i := r.instance
if ns == AllNamespaces {
ff = append(ff, FixCol(i.Namespace, 13))
ff = append(ff, FixCol(i.Namespace, NSPad))
}
ss := i.Status.ContainerStatuses
cr, _, rc := r.statuses(ss)
return append(ff,
FixCol(i.ObjectMeta.Name, 50),
FixCol(i.ObjectMeta.Name, NamePad),
strconv.Itoa(cr)+"/"+strconv.Itoa(len(ss)),
r.phase(i.Status),
strconv.Itoa(rc),
@ -219,7 +219,7 @@ func (r *Pod) Fields(ns string) Row {
i.Status.PodIP,
i.Spec.NodeName,
r.mapQOS(i.Status.QOSClass),
toAge(i.ObjectMeta.CreationTimestamp),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -79,12 +79,12 @@ func (r *Role) Fields(ns string) Row {
i := r.instance
if ns == AllNamespaces {
ff = append(ff, i.Namespace)
ff = append(ff, Pad(i.Namespace, NSPad))
}
return append(ff,
i.Name,
toAge(i.ObjectMeta.CreationTimestamp),
Pad(i.Name, RBACPad),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -54,7 +54,7 @@ func TestRoleListData(t *testing.T) {
for _, d := range row.Deltas {
assert.Equal(t, "", d)
}
assert.Equal(t, resource.Row{"fred"}, row.Fields[:1])
assert.Equal(t, resource.Row{resource.Pad("fred", resource.RBACPad)}, row.Fields[:1])
}
// Helpers...

View File

@ -77,16 +77,16 @@ func (*ReplicaSet) Header(ns string) Row {
func (r *ReplicaSet) Fields(ns string) Row {
ff := make(Row, 0, len(r.Header(ns)))
if ns == AllNamespaces {
ff = append(ff, r.instance.Namespace)
ff = append(ff, Pad(r.instance.Namespace, NSPad))
}
i := r.instance
return append(ff,
i.Name,
Pad(i.Name, NamePad),
strconv.Itoa(int(*i.Spec.Replicas)),
strconv.Itoa(int(i.Status.Replicas)),
strconv.Itoa(int(i.Status.ReadyReplicas)),
toAge(i.ObjectMeta.CreationTimestamp),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -54,7 +54,7 @@ func TestReplicaSetListData(t *testing.T) {
for _, d := range row.Deltas {
assert.Equal(t, "", d)
}
assert.Equal(t, resource.Row{"fred"}, row.Fields[:1])
assert.Equal(t, resource.Row{resource.Pad("fred", resource.NamePad)}, row.Fields[:1])
}
// Helpers...

View File

@ -91,16 +91,16 @@ func (r *Service) Fields(ns string) Row {
i := r.instance
if ns == AllNamespaces {
ff = append(ff, i.Namespace)
ff = append(ff, Pad(i.Namespace, NSPad))
}
return append(ff,
i.ObjectMeta.Name,
Pad(i.ObjectMeta.Name, NamePad),
string(i.Spec.Type),
i.Spec.ClusterIP,
r.toIPs(i.Spec.Type, r.getSvcExtIPS(i)),
r.toPorts(i.Spec.Ports),
toAge(i.ObjectMeta.CreationTimestamp),
Pad(toAge(i.ObjectMeta.CreationTimestamp), AgePad),
)
}

View File

@ -52,8 +52,8 @@ func TestSvcFields(t *testing.T) {
{
i: newSvc(),
e: resource.Row{
"blee",
"fred",
resource.Pad("blee", resource.NSPad),
resource.Pad("fred", resource.NamePad),
"ClusterIP",
"1.1.1.1",
"2.2.2.2",
@ -102,7 +102,7 @@ func TestSVCListData(t *testing.T) {
for _, d := range row.Deltas {
assert.Equal(t, "", d)
}
assert.Equal(t, resource.Row{"fred"}, row.Fields[:1])
assert.Equal(t, resource.Row{resource.Pad("fred", 50)}, row.Fields[:1])
}
// Helpers...

View File

@ -115,7 +115,6 @@ func (v *fuView) hints() hints {
}
func (v *fuView) reconcile() (resource.TableData, error) {
log.Debug().Msg("ClusterRoles...")
evts, errs := v.clusterPolicies()
if len(errs) > 0 {
for _, err := range errs {
@ -124,7 +123,6 @@ func (v *fuView) reconcile() (resource.TableData, error) {
return resource.TableData{}, errs[0]
}
log.Debug().Msg("Roles...")
nevts, errs := v.namespacePolicies()
if len(errs) > 0 {
for _, err := range errs {