mirror of https://github.com/k3s-io/k3s
Kubectl printer
parent
9779bf68ef
commit
99b0e051fc
|
@ -292,6 +292,7 @@ _kubectl_get()
|
||||||
must_have_one_noun+=("endpoints")
|
must_have_one_noun+=("endpoints")
|
||||||
must_have_one_noun+=("event")
|
must_have_one_noun+=("event")
|
||||||
must_have_one_noun+=("horizontalpodautoscaler")
|
must_have_one_noun+=("horizontalpodautoscaler")
|
||||||
|
must_have_one_noun+=("ingress")
|
||||||
must_have_one_noun+=("job")
|
must_have_one_noun+=("job")
|
||||||
must_have_one_noun+=("limitrange")
|
must_have_one_noun+=("limitrange")
|
||||||
must_have_one_noun+=("namespace")
|
must_have_one_noun+=("namespace")
|
||||||
|
@ -462,6 +463,7 @@ _kubectl_delete()
|
||||||
must_have_one_noun+=("endpoints")
|
must_have_one_noun+=("endpoints")
|
||||||
must_have_one_noun+=("event")
|
must_have_one_noun+=("event")
|
||||||
must_have_one_noun+=("horizontalpodautoscaler")
|
must_have_one_noun+=("horizontalpodautoscaler")
|
||||||
|
must_have_one_noun+=("ingress")
|
||||||
must_have_one_noun+=("job")
|
must_have_one_noun+=("job")
|
||||||
must_have_one_noun+=("limitrange")
|
must_have_one_noun+=("limitrange")
|
||||||
must_have_one_noun+=("namespace")
|
must_have_one_noun+=("namespace")
|
||||||
|
@ -863,6 +865,7 @@ _kubectl_label()
|
||||||
must_have_one_noun+=("endpoints")
|
must_have_one_noun+=("endpoints")
|
||||||
must_have_one_noun+=("event")
|
must_have_one_noun+=("event")
|
||||||
must_have_one_noun+=("horizontalpodautoscaler")
|
must_have_one_noun+=("horizontalpodautoscaler")
|
||||||
|
must_have_one_noun+=("ingress")
|
||||||
must_have_one_noun+=("job")
|
must_have_one_noun+=("job")
|
||||||
must_have_one_noun+=("limitrange")
|
must_have_one_noun+=("limitrange")
|
||||||
must_have_one_noun+=("namespace")
|
must_have_one_noun+=("namespace")
|
||||||
|
|
|
@ -102,6 +102,7 @@ func expandResourceShortcut(resource string) string {
|
||||||
"rc": "replicationcontrollers",
|
"rc": "replicationcontrollers",
|
||||||
"ds": "daemonsets",
|
"ds": "daemonsets",
|
||||||
"svc": "services",
|
"svc": "services",
|
||||||
|
"ing": "ingress",
|
||||||
}
|
}
|
||||||
if expanded, ok := shortForms[resource]; ok {
|
if expanded, ok := shortForms[resource]; ok {
|
||||||
return expanded
|
return expanded
|
||||||
|
|
|
@ -45,6 +45,14 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
tabwriterMinWidth = 10
|
||||||
|
tabwriterWidth = 4
|
||||||
|
tabwriterPadding = 3
|
||||||
|
tabwriterPadChar = ' '
|
||||||
|
tabwriterFlags = 0
|
||||||
|
)
|
||||||
|
|
||||||
// GetPrinter takes a format type, an optional format argument. It will return true
|
// GetPrinter takes a format type, an optional format argument. It will return true
|
||||||
// if the format is generic (untyped), otherwise it will return false. The printer
|
// if the format is generic (untyped), otherwise it will return false. The printer
|
||||||
// is agnostic to schema versions, so you must send arguments to PrintObj in the
|
// is agnostic to schema versions, so you must send arguments to PrintObj in the
|
||||||
|
@ -382,6 +390,7 @@ var podTemplateColumns = []string{"TEMPLATE", "CONTAINER(S)", "IMAGE(S)", "PODLA
|
||||||
var replicationControllerColumns = []string{"CONTROLLER", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "REPLICAS", "AGE"}
|
var replicationControllerColumns = []string{"CONTROLLER", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "REPLICAS", "AGE"}
|
||||||
var jobColumns = []string{"JOB", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "SUCCESSFUL"}
|
var jobColumns = []string{"JOB", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "SUCCESSFUL"}
|
||||||
var serviceColumns = []string{"NAME", "CLUSTER_IP", "EXTERNAL_IP", "PORT(S)", "SELECTOR", "AGE"}
|
var serviceColumns = []string{"NAME", "CLUSTER_IP", "EXTERNAL_IP", "PORT(S)", "SELECTOR", "AGE"}
|
||||||
|
var ingressColumns = []string{"NAME", "RULE", "BACKEND", "ADDRESS"}
|
||||||
var endpointColumns = []string{"NAME", "ENDPOINTS", "AGE"}
|
var endpointColumns = []string{"NAME", "ENDPOINTS", "AGE"}
|
||||||
var nodeColumns = []string{"NAME", "LABELS", "STATUS", "AGE"}
|
var nodeColumns = []string{"NAME", "LABELS", "STATUS", "AGE"}
|
||||||
var daemonSetColumns = []string{"NAME", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "NODE-SELECTOR"}
|
var daemonSetColumns = []string{"NAME", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "NODE-SELECTOR"}
|
||||||
|
@ -413,6 +422,8 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
|
||||||
h.Handler(jobColumns, printJobList)
|
h.Handler(jobColumns, printJobList)
|
||||||
h.Handler(serviceColumns, printService)
|
h.Handler(serviceColumns, printService)
|
||||||
h.Handler(serviceColumns, printServiceList)
|
h.Handler(serviceColumns, printServiceList)
|
||||||
|
h.Handler(ingressColumns, printIngress)
|
||||||
|
h.Handler(ingressColumns, printIngressList)
|
||||||
h.Handler(endpointColumns, printEndpoints)
|
h.Handler(endpointColumns, printEndpoints)
|
||||||
h.Handler(endpointColumns, printEndpointsList)
|
h.Handler(endpointColumns, printEndpointsList)
|
||||||
h.Handler(nodeColumns, printNode)
|
h.Handler(nodeColumns, printNode)
|
||||||
|
@ -739,6 +750,18 @@ func printJobList(list *experimental.JobList, w io.Writer, withNamespace bool, w
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loadBalancerStatusStringer behaves just like a string interface and converts the given status to a string.
|
||||||
|
func loadBalancerStatusStringer(s api.LoadBalancerStatus) string {
|
||||||
|
ingress := s.Ingress
|
||||||
|
result := []string{}
|
||||||
|
for i := range ingress {
|
||||||
|
if ingress[i].IP != "" {
|
||||||
|
result = append(result, ingress[i].IP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(result, ",")
|
||||||
|
}
|
||||||
|
|
||||||
func getServiceExternalIP(svc *api.Service) string {
|
func getServiceExternalIP(svc *api.Service) string {
|
||||||
switch svc.Spec.Type {
|
switch svc.Spec.Type {
|
||||||
case api.ServiceTypeClusterIP:
|
case api.ServiceTypeClusterIP:
|
||||||
|
@ -752,17 +775,12 @@ func getServiceExternalIP(svc *api.Service) string {
|
||||||
}
|
}
|
||||||
return "nodes"
|
return "nodes"
|
||||||
case api.ServiceTypeLoadBalancer:
|
case api.ServiceTypeLoadBalancer:
|
||||||
ingress := svc.Status.LoadBalancer.Ingress
|
lbIps := loadBalancerStatusStringer(svc.Status.LoadBalancer)
|
||||||
result := []string{}
|
|
||||||
for i := range ingress {
|
|
||||||
if ingress[i].IP != "" {
|
|
||||||
result = append(result, ingress[i].IP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(svc.Spec.ExternalIPs) > 0 {
|
if len(svc.Spec.ExternalIPs) > 0 {
|
||||||
result = append(result, svc.Spec.ExternalIPs...)
|
result := append(strings.Split(lbIps, ","), svc.Spec.ExternalIPs...)
|
||||||
|
return strings.Join(result, ",")
|
||||||
}
|
}
|
||||||
return strings.Join(result, ",")
|
return lbIps
|
||||||
}
|
}
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
@ -813,6 +831,71 @@ func printServiceList(list *api.ServiceList, w io.Writer, withNamespace bool, wi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// backendStringer behaves just like a string interface and converts the given backend to a string.
|
||||||
|
func backendStringer(backend *experimental.IngressBackend) string {
|
||||||
|
if backend == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v:%v", backend.ServiceName, backend.ServicePort.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func printIngress(ingress *experimental.Ingress, w io.Writer, withNamespace, wide bool, showAll bool, columnLabels []string) error {
|
||||||
|
name := ingress.Name
|
||||||
|
namespace := ingress.Namespace
|
||||||
|
|
||||||
|
hostRules := ingress.Spec.Rules
|
||||||
|
if withNamespace {
|
||||||
|
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := fmt.Fprintf(w, "%s\t%v\t%v\t%v\n",
|
||||||
|
name,
|
||||||
|
"-",
|
||||||
|
backendStringer(ingress.Spec.Backend),
|
||||||
|
loadBalancerStatusStringer(ingress.Status.LoadBalancer)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lay out all the rules on separate lines.
|
||||||
|
extraLinePrefix := ""
|
||||||
|
if withNamespace {
|
||||||
|
extraLinePrefix = "\t"
|
||||||
|
}
|
||||||
|
for _, rules := range hostRules {
|
||||||
|
if rules.HTTP == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err := fmt.Fprintf(w, "%s\t%v\t", extraLinePrefix, rules.Host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, rule := range rules.HTTP.Paths {
|
||||||
|
_, err := fmt.Fprintf(w, "%s\t%v\t%v", extraLinePrefix, rule.Path, backendStringer(&rule.Backend))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printIngressList(ingressList *experimental.IngressList, w io.Writer, withNamespace, wide bool, showAll bool, columnLabels []string) error {
|
||||||
|
for _, ingress := range ingressList.Items {
|
||||||
|
if err := printIngress(&ingress, w, withNamespace, wide, true, columnLabels); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func printDaemonSet(ds *experimental.DaemonSet, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error {
|
func printDaemonSet(ds *experimental.DaemonSet, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error {
|
||||||
name := ds.Name
|
name := ds.Name
|
||||||
namespace := ds.Namespace
|
namespace := ds.Namespace
|
||||||
|
@ -1369,7 +1452,7 @@ func formatWideHeaders(wide bool, t reflect.Type) []string {
|
||||||
|
|
||||||
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
|
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
|
||||||
func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error {
|
func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error {
|
||||||
w := tabwriter.NewWriter(output, 10, 4, 3, ' ', 0)
|
w := tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags)
|
||||||
defer w.Flush()
|
defer w.Flush()
|
||||||
t := reflect.TypeOf(obj)
|
t := reflect.TypeOf(obj)
|
||||||
if handler := h.handlerMap[t]; handler != nil {
|
if handler := h.handlerMap[t]; handler != nil {
|
||||||
|
|
Loading…
Reference in New Issue