refactor policies

mine
derailed 2019-06-20 16:06:07 -06:00
parent cd7258fa23
commit 1e0f48b9b3
7 changed files with 231 additions and 155 deletions

View File

@ -373,18 +373,15 @@ func (r *Pod) phase(po *v1.Pod) string {
status = po.Status.Reason
}
var init bool
init, status = r.initContainerPhase(po.Status, len(po.Spec.InitContainers), status)
init, status := r.initContainerPhase(po.Status, len(po.Spec.InitContainers), status)
if init {
return status
}
var running bool
running, status = r.containerPhase(po.Status, status)
if status == "Completed" && running {
running, status := r.containerPhase(po.Status, status)
if running && status == "Completed" {
status = "Running"
}
if po.DeletionTimestamp == nil {
return status
}
@ -416,32 +413,35 @@ func (*Pod) containerPhase(st v1.PodStatus, status string) (bool, string) {
}
func (*Pod) initContainerPhase(st v1.PodStatus, initCount int, status string) (bool, string) {
var init bool
for i, cs := range st.InitContainerStatuses {
switch {
case cs.State.Terminated != nil:
if cs.State.Terminated.ExitCode == 0 {
continue
}
if cs.State.Terminated.Reason != "" {
status = "Init:" + cs.State.Terminated.Reason
break
}
if cs.State.Terminated.Signal != 0 {
status = "Init:Signal:" + strconv.Itoa(int(cs.State.Terminated.Signal))
} else {
status = "Init:ExitCode:" + strconv.Itoa(int(cs.State.Terminated.ExitCode))
}
case cs.State.Waiting != nil && cs.State.Waiting.Reason != "" && cs.State.Waiting.Reason != "PodInitializing":
status = "Init:" + cs.State.Waiting.Reason
default:
status = "Init:" + strconv.Itoa(i) + "/" + strconv.Itoa(initCount)
status := checkContainerStatus(cs, i, initCount)
if status == "" {
continue
}
init = true
break
return true, status
}
return init, status
return false, status
}
func checkContainerStatus(cs v1.ContainerStatus, i, initCount int) string {
switch {
case cs.State.Terminated != nil:
if cs.State.Terminated.ExitCode == 0 {
return ""
}
if cs.State.Terminated.Reason != "" {
return "Init:" + cs.State.Terminated.Reason
}
if cs.State.Terminated.Signal != 0 {
return "Init:Signal:" + strconv.Itoa(int(cs.State.Terminated.Signal))
}
return "Init:ExitCode:" + strconv.Itoa(int(cs.State.Terminated.ExitCode))
case cs.State.Waiting != nil && cs.State.Waiting.Reason != "" && cs.State.Waiting.Reason != "PodInitializing":
return "Init:" + cs.State.Waiting.Reason
default:
return "Init:" + strconv.Itoa(i) + "/" + strconv.Itoa(initCount)
}
}
func (r *Pod) loggableContainers(s v1.PodStatus) []string {

View File

@ -88,6 +88,17 @@ func (v *logView) bindKeys() {
}
}
func (v *logView) setTitle(path, co string) {
var fmat string
if co == "" {
fmat = skinTitle(fmt.Sprintf(logFmt, path), v.app.styles.Frame())
} else {
fmat = skinTitle(fmt.Sprintf(logCoFmt, path, co), v.app.styles.Frame())
}
v.path = path
v.SetTitle(fmat)
}
// Hints show action hints
func (v *logView) hints() hints {
return v.actions.toHints()

View File

@ -85,8 +85,8 @@ func (v *logsView) stop() {
v.cancelFunc = nil
}
func (v *logsView) load(container string, showPrevious bool) {
if err := v.doLoad(v.parent.getSelection(), container, showPrevious); err != nil {
func (v *logsView) load(container string, prevLogs bool) {
if err := v.doLoad(v.parent.getSelection(), container, prevLogs); err != nil {
v.app.flash().err(err)
l := v.CurrentPage().Item.(*logView)
l.logLine("😂 Doh! No logs are available at this time. Check again later on...")
@ -95,41 +95,26 @@ func (v *logsView) load(container string, showPrevious bool) {
v.app.SetFocus(v)
}
func (v *logsView) doLoad(path, co string, showPrevious bool) error {
func (v *logsView) doLoad(path, co string, prevLogs bool) error {
v.stop()
maxBuff := int64(v.app.config.K9s.LogRequestSize)
l := v.CurrentPage().Item.(*logView)
l.logs.Clear()
l.path = path
var fmat string
if co == "" {
fmat = skinTitle(fmt.Sprintf(logFmt, path), v.app.styles.Frame())
} else {
fmat = skinTitle(fmt.Sprintf(logCoFmt, path, co), v.app.styles.Frame())
}
l.SetTitle(fmat)
l.setTitle(path, co)
c := make(chan string, 10)
go updateLogs(c, l)
ns, po := namespaced(path)
res, ok := v.parent.getList().Resource().(resource.Tailable)
if !ok {
return fmt.Errorf("Resource %T is not tailable", v.parent.getList().Resource())
}
var ctx context.Context
ctx = context.WithValue(context.Background(), resource.IKey("informer"), v.app.informer)
ctx, v.cancelFunc = context.WithCancel(ctx)
opts := resource.LogOptions{
Namespace: ns,
Name: po,
Container: co,
Lines: maxBuff,
Previous: showPrevious,
}
if err := res.Logs(ctx, c, opts); err != nil {
if err := res.Logs(ctx, c, v.logOpts(path, co, prevLogs)); err != nil {
v.cancelFunc()
return err
}
@ -137,6 +122,17 @@ func (v *logsView) doLoad(path, co string, showPrevious bool) error {
return nil
}
func (v *logsView) logOpts(path, co string, prevLogs bool) resource.LogOptions {
ns, po := namespaced(path)
return resource.LogOptions{
Namespace: ns,
Name: po,
Container: co,
Lines: int64(v.app.config.K9s.LogRequestSize),
Previous: prevLogs,
}
}
func updateLogs(c <-chan string, l *logView) {
buff, index := make([]string, logBuffSize), 0
for {

View File

@ -12,17 +12,17 @@ type (
pageView struct {
*tview.Pages
app *appView
actions keyActions
app *appView
actions keyActions
selectedItem string
selectedRow int
selectedFn func() string
}
masterDetail struct {
*pageView
currentNS string
selectedItem string
selectedRow int
selectedFn func() string
enterFn enterFn
extraActionsFn func(keyActions)
}

View File

@ -16,15 +16,21 @@ const policyTitle = "Policy"
var policyHeader = append(resource.Row{"NAMESPACE", "NAME", "API GROUP", "BINDING"}, rbacHeaderVerbs...)
type policyView struct {
*tableView
type (
namespacedRole struct {
ns, role string
}
current igniter
cancel context.CancelFunc
subjectKind string
subjectName string
cache resource.RowEvents
}
policyView struct {
*tableView
current igniter
cancel context.CancelFunc
subjectKind string
subjectName string
cache resource.RowEvents
}
)
func newPolicyView(app *appView, subject, name string) *policyView {
v := policyView{}
@ -140,6 +146,8 @@ func (v *policyView) reconcile() (resource.TableData, error) {
return buildTable(v, evts), nil
}
// Protocol...
func (v *policyView) header() resource.Row {
return policyHeader
}
@ -183,10 +191,6 @@ func (v *policyView) clusterPolicies() (resource.RowEvents, []error) {
return evts, errs
}
type namespacedRole struct {
ns, role string
}
func (v *policyView) namespacePolicies() (resource.RowEvents, []error) {
var errs []error
evts := make(resource.RowEvents)
@ -230,11 +234,11 @@ func (v *policyView) parseRules(ns, binding string, rules []rbacv1.PolicyRule) r
for _, na := range r.ResourceNames {
n := fqn(k, na)
m[fqn(ns, n)] = &resource.RowEvent{
Fields: append(v.prepRow(ns, n, grp, binding), r.Verbs...),
Fields: append(policyRow(ns, n, grp, binding), r.Verbs...),
}
}
m[fqn(ns, k)] = &resource.RowEvent{
Fields: append(v.prepRow(ns, k, grp, binding), r.Verbs...),
Fields: append(policyRow(ns, k, grp, binding), r.Verbs...),
}
}
}
@ -243,7 +247,7 @@ func (v *policyView) parseRules(ns, binding string, rules []rbacv1.PolicyRule) r
nres = "/" + nres
}
m[fqn(ns, nres)] = &resource.RowEvent{
Fields: append(v.prepRow(ns, nres, resource.NAValue, binding), r.Verbs...),
Fields: append(policyRow(ns, nres, resource.NAValue, binding), r.Verbs...),
}
}
}
@ -251,7 +255,7 @@ func (v *policyView) parseRules(ns, binding string, rules []rbacv1.PolicyRule) r
return m
}
func (v *policyView) prepRow(ns, res, grp, binding string) resource.Row {
func policyRow(ns, res, grp, binding string) resource.Row {
if grp != resource.NAValue {
grp = toGroup(grp)
}

View File

@ -16,6 +16,7 @@ type (
decorateFn func(resource.TableData) resource.TableData
crdCmd struct {
api string
version string
plural string
singular string
@ -24,7 +25,6 @@ type (
resCmd struct {
crdCmd
api string
title string
viewFn viewFn
listFn listFn
@ -57,8 +57,8 @@ func allCRDs(c k8s.Connection, m map[string]resCmd) {
res := resCmd{
title: grp.Kind,
api: grp.Group,
crdCmd: crdCmd{
api: grp.Group,
version: grp.Version,
},
}
@ -129,96 +129,124 @@ func resourceViews(c k8s.Connection, m map[string]resCmd) {
func coreRes(m map[string]resCmd) {
m["cm"] = resCmd{
title: "ConfigMaps",
api: "",
title: "ConfigMaps",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewConfigMapList,
}
m["ctx"] = resCmd{
title: "Contexts",
api: "",
title: "Contexts",
crdCmd: crdCmd{
api: "",
},
viewFn: newContextView,
listFn: resource.NewContextList,
colorerFn: ctxColorer,
}
m["ds"] = resCmd{
title: "DaemonSets",
api: "",
title: "DaemonSets",
crdCmd: crdCmd{
api: "",
},
viewFn: newDaemonSetView,
listFn: resource.NewDaemonSetList,
colorerFn: dpColorer,
}
m["ep"] = resCmd{
title: "EndPoints",
api: "",
title: "EndPoints",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewEndpointsList,
}
m["ev"] = resCmd{
title: "Events",
api: "",
title: "Events",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewEventList,
colorerFn: evColorer,
}
m["no"] = resCmd{
title: "Nodes",
api: "",
title: "Nodes",
crdCmd: crdCmd{
api: "",
},
viewFn: newNodeView,
listFn: resource.NewNodeList,
colorerFn: nsColorer,
}
m["ns"] = resCmd{
title: "Namespaces",
api: "",
title: "Namespaces",
crdCmd: crdCmd{
api: "",
},
viewFn: newNamespaceView,
listFn: resource.NewNamespaceList,
colorerFn: nsColorer,
}
m["po"] = resCmd{
title: "Pods",
api: "",
title: "Pods",
crdCmd: crdCmd{
api: "",
},
viewFn: newPodView,
listFn: resource.NewPodList,
colorerFn: podColorer,
}
m["pv"] = resCmd{
title: "PersistentVolumes",
api: "",
title: "PersistentVolumes",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewPersistentVolumeList,
colorerFn: pvColorer,
}
m["pvc"] = resCmd{
title: "PersistentVolumeClaims",
api: "",
title: "PersistentVolumeClaims",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewPersistentVolumeClaimList,
colorerFn: pvcColorer,
}
m["rc"] = resCmd{
title: "ReplicationControllers",
api: "",
title: "ReplicationControllers",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewReplicationControllerList,
colorerFn: rsColorer,
}
m["sa"] = resCmd{
title: "ServiceAccounts",
api: "",
title: "ServiceAccounts",
crdCmd: crdCmd{
api: "",
},
viewFn: newResourceView,
listFn: resource.NewServiceAccountList,
enterFn: showSAPolicy,
}
m["sec"] = resCmd{
title: "Secrets",
api: "",
title: "Secrets",
crdCmd: crdCmd{
api: "",
},
viewFn: newSecretView,
listFn: resource.NewSecretList,
}
m["svc"] = resCmd{
title: "Services",
api: "",
title: "Services",
crdCmd: crdCmd{
api: "",
},
viewFn: newSvcView,
listFn: resource.NewServiceList,
}
@ -226,58 +254,76 @@ func coreRes(m map[string]resCmd) {
func custRes(m map[string]resCmd) {
m["usr"] = resCmd{
title: "Users",
api: "",
title: "Users",
crdCmd: crdCmd{
api: "",
},
viewFn: newSubjectView,
}
m["grp"] = resCmd{
title: "Groups",
api: "",
title: "Groups",
crdCmd: crdCmd{
api: "",
},
viewFn: newSubjectView,
}
m["pf"] = resCmd{
title: "PortForward",
api: "",
title: "PortForward",
crdCmd: crdCmd{
api: "",
},
viewFn: newForwardView,
}
m["be"] = resCmd{
title: "Benchmark",
api: "",
title: "Benchmark",
crdCmd: crdCmd{
api: "",
},
viewFn: newBenchView,
}
m["sd"] = resCmd{
title: "ScreenDumps",
api: "",
title: "ScreenDumps",
crdCmd: crdCmd{
api: "",
},
viewFn: newDumpView,
}
}
func rbacRes(m map[string]resCmd) {
m["cr"] = resCmd{
title: "ClusterRoles",
api: "rbac.authorization.k8s.io",
title: "ClusterRoles",
crdCmd: crdCmd{
api: "rbac.authorization.k8s.io",
},
viewFn: newResourceView,
listFn: resource.NewClusterRoleList,
enterFn: showRBAC,
}
m["crb"] = resCmd{
title: "ClusterRoleBindings",
api: "rbac.authorization.k8s.io",
title: "ClusterRoleBindings",
crdCmd: crdCmd{
api: "rbac.authorization.k8s.io",
},
viewFn: newResourceView,
listFn: resource.NewClusterRoleBindingList,
enterFn: showClusterRole,
}
m["rb"] = resCmd{
title: "RoleBindings",
api: "rbac.authorization.k8s.io",
title: "RoleBindings",
crdCmd: crdCmd{
api: "rbac.authorization.k8s.io",
},
viewFn: newResourceView,
listFn: resource.NewRoleBindingList,
enterFn: showRole,
}
m["ro"] = resCmd{
title: "Roles",
api: "rbac.authorization.k8s.io",
title: "Roles",
crdCmd: crdCmd{
api: "rbac.authorization.k8s.io",
},
viewFn: newResourceView,
listFn: resource.NewRoleList,
enterFn: showRBAC,
@ -286,8 +332,10 @@ func rbacRes(m map[string]resCmd) {
func apiExtRes(m map[string]resCmd) {
m["crd"] = resCmd{
title: "CustomResourceDefinitions",
api: "apiextensions.k8s.io",
title: "CustomResourceDefinitions",
crdCmd: crdCmd{
api: "apiextensions.k8s.io",
},
viewFn: newResourceView,
listFn: resource.NewCustomResourceDefinitionList,
}
@ -295,14 +343,18 @@ func apiExtRes(m map[string]resCmd) {
func batchRes(m map[string]resCmd) {
m["cj"] = resCmd{
title: "CronJobs",
api: "batch",
title: "CronJobs",
crdCmd: crdCmd{
api: "batch",
},
viewFn: newCronJobView,
listFn: resource.NewCronJobList,
}
m["jo"] = resCmd{
title: "Jobs",
api: "batch",
title: "Jobs",
crdCmd: crdCmd{
api: "batch",
},
viewFn: newJobView,
listFn: resource.NewJobList,
}
@ -310,22 +362,28 @@ func batchRes(m map[string]resCmd) {
func appsRes(m map[string]resCmd) {
m["dp"] = resCmd{
title: "Deployments",
api: "apps",
title: "Deployments",
crdCmd: crdCmd{
api: "apps",
},
viewFn: newDeployView,
listFn: resource.NewDeploymentList,
colorerFn: dpColorer,
}
m["rs"] = resCmd{
title: "ReplicaSets",
api: "apps",
title: "ReplicaSets",
crdCmd: crdCmd{
api: "apps",
},
viewFn: newReplicaSetView,
listFn: resource.NewReplicaSetList,
colorerFn: rsColorer,
}
m["sts"] = resCmd{
title: "StatefulSets",
api: "apps",
title: "StatefulSets",
crdCmd: crdCmd{
api: "apps",
},
viewFn: newStatefulSetView,
listFn: resource.NewStatefulSetList,
colorerFn: stsColorer,
@ -334,8 +392,10 @@ func appsRes(m map[string]resCmd) {
func extRes(m map[string]resCmd) {
m["ing"] = resCmd{
title: "Ingress",
api: "extensions",
title: "Ingress",
crdCmd: crdCmd{
api: "extensions",
},
viewFn: newResourceView,
listFn: resource.NewIngressList,
}
@ -343,8 +403,10 @@ func extRes(m map[string]resCmd) {
func v1beta1Res(m map[string]resCmd) {
m["pdb"] = resCmd{
title: "PodDisruptionBudgets",
api: "v1.beta1",
title: "PodDisruptionBudgets",
crdCmd: crdCmd{
api: "v1.beta1",
},
viewFn: newResourceView,
listFn: resource.NewPDBList,
colorerFn: pdbColorer,
@ -365,22 +427,28 @@ func hpaRes(c k8s.Connection, cmds map[string]resCmd) {
switch rev {
case "v1":
cmds["hpa"] = resCmd{
title: "HorizontalPodAutoscalers",
api: "autoscaling",
title: "HorizontalPodAutoscalers",
crdCmd: crdCmd{
api: "autoscaling",
},
viewFn: newResourceView,
listFn: resource.NewHorizontalPodAutoscalerV1List,
}
case "v2beta1":
cmds["hpa"] = resCmd{
title: "HorizontalPodAutoscalers",
api: "autoscaling",
title: "HorizontalPodAutoscalers",
crdCmd: crdCmd{
api: "autoscaling",
},
viewFn: newResourceView,
listFn: resource.NewHorizontalPodAutoscalerV2Beta1List,
}
case "v2beta2":
cmds["hpa"] = resCmd{
title: "HorizontalPodAutoscalers",
api: "autoscaling",
title: "HorizontalPodAutoscalers",
crdCmd: crdCmd{
api: "autoscaling",
},
viewFn: newResourceView,
listFn: resource.NewHorizontalPodAutoscalerList,
}

View File

@ -196,22 +196,22 @@ func (v *subjectView) setCache(evts resource.RowEvents) {
v.cache = evts
}
func buildTable(v cachedEventer, evts resource.RowEvents) resource.TableData {
func buildTable(c cachedEventer, evts resource.RowEvents) resource.TableData {
table := resource.TableData{
Header: v.header(),
Header: c.header(),
Rows: make(resource.RowEvents, len(evts)),
Namespace: "*",
}
noDeltas := make(resource.Row, len(v.header()))
cache := v.getCache()
noDeltas := make(resource.Row, len(c.header()))
cache := c.getCache()
if len(cache) == 0 {
for k, ev := range evts {
ev.Action = resource.New
ev.Deltas = noDeltas
table.Rows[k] = ev
}
v.setCache(evts)
c.setCache(evts)
return table
}
@ -244,7 +244,7 @@ func buildTable(v cachedEventer, evts resource.RowEvents) resource.TableData {
delete(evts, k)
}
}
v.setCache(evts)
c.setCache(evts)
return table
}
@ -258,10 +258,11 @@ func (v *subjectView) clusterSubjects() (resource.RowEvents, error) {
evts := make(resource.RowEvents, len(crbs.Items))
for _, crb := range crbs.Items {
for _, s := range crb.Subjects {
if s.Kind == v.subjectKind {
evts[s.Name] = &resource.RowEvent{
Fields: v.makeRow("*", s.Name, "ClusterRoleBinding", crb.Name),
}
if s.Kind != v.subjectKind {
continue
}
evts[s.Name] = &resource.RowEvent{
Fields: resource.Row{s.Name, "ClusterRoleBinding", crb.Name},
}
}
}
@ -269,10 +270,6 @@ func (v *subjectView) clusterSubjects() (resource.RowEvents, error) {
return evts, nil
}
func (v *subjectView) makeRow(_, subject, kind, loc string) resource.Row {
return resource.Row{subject, kind, loc}
}
func (v *subjectView) namespacedSubjects() (resource.RowEvents, error) {
rbs, err := v.app.conn().DialOrDie().Rbac().RoleBindings("").List(metav1.ListOptions{})
if err != nil {
@ -284,7 +281,7 @@ func (v *subjectView) namespacedSubjects() (resource.RowEvents, error) {
for _, s := range rb.Subjects {
if s.Kind == v.subjectKind {
evts[s.Name] = &resource.RowEvent{
Fields: v.makeRow(rb.Namespace, s.Name, "RoleBinding", rb.Name),
Fields: resource.Row{s.Name, "RoleBinding", rb.Name},
}
}
}