Commit 0b6e0e2b authored by k8s-merge-robot's avatar k8s-merge-robot

Merge pull request #26749 from Clarifai/describe-svc

Automatic merge from submit-queue AWS: kubectl get service should print hostnames for LB services Fixes #21526 Also test wide outputs. We only guarantee the first IP to be fully printed if multiple ingresses are present. For AWS, which has no ingress IPs, but only hostnames, the ELB hostname will be truncated, unless -o=wide is specified.
parents aa008ab0 40f76a95
...@@ -1294,7 +1294,7 @@ func (i *IngressDescriber) describeIngress(ing *extensions.Ingress, describerSet ...@@ -1294,7 +1294,7 @@ func (i *IngressDescriber) describeIngress(ing *extensions.Ingress, describerSet
return tabbedString(func(out io.Writer) error { return tabbedString(func(out io.Writer) error {
fmt.Fprintf(out, "Name:\t%v\n", ing.Name) fmt.Fprintf(out, "Name:\t%v\n", ing.Name)
fmt.Fprintf(out, "Namespace:\t%v\n", ing.Namespace) fmt.Fprintf(out, "Namespace:\t%v\n", ing.Namespace)
fmt.Fprintf(out, "Address:\t%v\n", loadBalancerStatusStringer(ing.Status.LoadBalancer)) fmt.Fprintf(out, "Address:\t%v\n", loadBalancerStatusStringer(ing.Status.LoadBalancer, true))
def := ing.Spec.Backend def := ing.Spec.Backend
ns := ing.Namespace ns := ing.Namespace
if def == nil { if def == nil {
......
...@@ -53,6 +53,7 @@ const ( ...@@ -53,6 +53,7 @@ const (
tabwriterPadding = 3 tabwriterPadding = 3
tabwriterPadChar = ' ' tabwriterPadChar = ' '
tabwriterFlags = 0 tabwriterFlags = 0
loadBalancerWidth = 16
) )
// 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
...@@ -930,19 +931,26 @@ func printJobList(list *batch.JobList, w io.Writer, options PrintOptions) error ...@@ -930,19 +931,26 @@ func printJobList(list *batch.JobList, w io.Writer, options PrintOptions) error
return nil return nil
} }
// loadBalancerStatusStringer behaves just like a string interface and converts the given status to a string. // loadBalancerStatusStringer behaves mostly like a string interface and converts the given status to a string.
func loadBalancerStatusStringer(s api.LoadBalancerStatus) string { // `wide` indicates whether the returned value is meant for --o=wide output. If not, it's clipped to 16 bytes.
func loadBalancerStatusStringer(s api.LoadBalancerStatus, wide bool) string {
ingress := s.Ingress ingress := s.Ingress
result := []string{} result := []string{}
for i := range ingress { for i := range ingress {
if ingress[i].IP != "" { if ingress[i].IP != "" {
result = append(result, ingress[i].IP) result = append(result, ingress[i].IP)
} else if ingress[i].Hostname != "" {
result = append(result, ingress[i].Hostname)
} }
} }
return strings.Join(result, ",") r := strings.Join(result, ",")
if !wide && len(r) > loadBalancerWidth {
r = r[0:(loadBalancerWidth-3)] + "..."
}
return r
} }
func getServiceExternalIP(svc *api.Service) string { func getServiceExternalIP(svc *api.Service, wide bool) string {
switch svc.Spec.Type { switch svc.Spec.Type {
case api.ServiceTypeClusterIP: case api.ServiceTypeClusterIP:
if len(svc.Spec.ExternalIPs) > 0 { if len(svc.Spec.ExternalIPs) > 0 {
...@@ -955,7 +963,7 @@ func getServiceExternalIP(svc *api.Service) string { ...@@ -955,7 +963,7 @@ func getServiceExternalIP(svc *api.Service) string {
} }
return "<nodes>" return "<nodes>"
case api.ServiceTypeLoadBalancer: case api.ServiceTypeLoadBalancer:
lbIps := loadBalancerStatusStringer(svc.Status.LoadBalancer) lbIps := loadBalancerStatusStringer(svc.Status.LoadBalancer, wide)
if len(svc.Spec.ExternalIPs) > 0 { if len(svc.Spec.ExternalIPs) > 0 {
result := append(strings.Split(lbIps, ","), svc.Spec.ExternalIPs...) result := append(strings.Split(lbIps, ","), svc.Spec.ExternalIPs...)
return strings.Join(result, ",") return strings.Join(result, ",")
...@@ -982,7 +990,7 @@ func printService(svc *api.Service, w io.Writer, options PrintOptions) error { ...@@ -982,7 +990,7 @@ func printService(svc *api.Service, w io.Writer, options PrintOptions) error {
namespace := svc.Namespace namespace := svc.Namespace
internalIP := svc.Spec.ClusterIP internalIP := svc.Spec.ClusterIP
externalIP := getServiceExternalIP(svc) externalIP := getServiceExternalIP(svc, options.Wide)
if options.WithNamespace { if options.WithNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
...@@ -1069,7 +1077,7 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, options PrintOptions ...@@ -1069,7 +1077,7 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, options PrintOptions
if _, err := fmt.Fprintf(w, "%s\t%v\t%v\t%v\t%s", if _, err := fmt.Fprintf(w, "%s\t%v\t%v\t%v\t%s",
name, name,
formatHosts(ingress.Spec.Rules), formatHosts(ingress.Spec.Rules),
loadBalancerStatusStringer(ingress.Status.LoadBalancer), loadBalancerStatusStringer(ingress.Status.LoadBalancer, options.Wide),
formatPorts(ingress.Spec.TLS), formatPorts(ingress.Spec.TLS),
translateTimestamp(ingress.CreationTimestamp), translateTimestamp(ingress.CreationTimestamp),
); err != nil { ); err != nil {
......
...@@ -706,7 +706,7 @@ func TestPrintHumanReadableService(t *testing.T) { ...@@ -706,7 +706,7 @@ func TestPrintHumanReadableService(t *testing.T) {
}, },
{ {
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
ClusterIP: "1.2.3.4", ClusterIP: "1.3.4.5",
Ports: []api.ServicePort{ Ports: []api.ServicePort{
{ {
Port: 80, Port: 80,
...@@ -725,7 +725,7 @@ func TestPrintHumanReadableService(t *testing.T) { ...@@ -725,7 +725,7 @@ func TestPrintHumanReadableService(t *testing.T) {
}, },
{ {
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
ClusterIP: "1.2.3.4", ClusterIP: "1.4.5.6",
Type: "LoadBalancer", Type: "LoadBalancer",
Ports: []api.ServicePort{ Ports: []api.ServicePort{
{ {
...@@ -754,7 +754,7 @@ func TestPrintHumanReadableService(t *testing.T) { ...@@ -754,7 +754,7 @@ func TestPrintHumanReadableService(t *testing.T) {
}, },
{ {
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
ClusterIP: "1.2.3.4", ClusterIP: "1.5.6.7",
Type: "LoadBalancer", Type: "LoadBalancer",
Ports: []api.ServicePort{ Ports: []api.ServicePort{
{ {
...@@ -791,30 +791,33 @@ func TestPrintHumanReadableService(t *testing.T) { ...@@ -791,30 +791,33 @@ func TestPrintHumanReadableService(t *testing.T) {
} }
for _, svc := range tests { for _, svc := range tests {
buff := bytes.Buffer{} for _, wide := range []bool{false, true} {
printService(&svc, &buff, PrintOptions{false, false, false, false, false, false, []string{}}) buff := bytes.Buffer{}
output := string(buff.Bytes()) printService(&svc, &buff, PrintOptions{false, false, wide, false, false, false, []string{}})
ip := svc.Spec.ClusterIP output := string(buff.Bytes())
if !strings.Contains(output, ip) { ip := svc.Spec.ClusterIP
t.Errorf("expected to contain ClusterIP %s, but doesn't: %s", ip, output)
}
for _, ingress := range svc.Status.LoadBalancer.Ingress {
ip = ingress.IP
if !strings.Contains(output, ip) { if !strings.Contains(output, ip) {
t.Errorf("expected to contain ingress ip %s, but doesn't: %s", ip, output) t.Errorf("expected to contain ClusterIP %s, but doesn't: %s", ip, output)
} }
}
for _, port := range svc.Spec.Ports { for n, ingress := range svc.Status.LoadBalancer.Ingress {
portSpec := fmt.Sprintf("%d/%s", port.Port, port.Protocol) ip = ingress.IP
if !strings.Contains(output, portSpec) { // For non-wide output, we only guarantee the first IP to be printed
t.Errorf("expected to contain port: %s, but doesn't: %s", portSpec, output) if (n == 0 || wide) && !strings.Contains(output, ip) {
t.Errorf("expected to contain ingress ip %s with wide=%v, but doesn't: %s", ip, wide, output)
}
}
for _, port := range svc.Spec.Ports {
portSpec := fmt.Sprintf("%d/%s", port.Port, port.Protocol)
if !strings.Contains(output, portSpec) {
t.Errorf("expected to contain port: %s, but doesn't: %s", portSpec, output)
}
}
// Each service should print on one line
if 1 != strings.Count(output, "\n") {
t.Errorf("expected a single newline, found %d", strings.Count(output, "\n"))
} }
}
// Each service should print on one line
if 1 != strings.Count(output, "\n") {
t.Errorf("expected a single newline, found %d", strings.Count(output, "\n"))
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment