first pass scroll jitter
parent
437e73ae6b
commit
6001b004d1
|
|
@ -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
|
||||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue