Skip to content

Commit bfac91b

Browse files
authored
Add missing columns to gwctl get httproutes (#2805)
Signed-off-by: Jongwoo Han <[email protected]>
1 parent f610278 commit bfac91b

File tree

3 files changed

+227
-12
lines changed

3 files changed

+227
-12
lines changed

gwctl/pkg/cmd/get/get.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func runGet(args []string, params *utils.CmdParams, flags *getFlags) {
6565
realClock := clock.RealClock{}
6666
gwPrinter := &printer.GatewaysPrinter{Out: params.Out, Clock: realClock}
6767
policiesPrinter := &printer.PoliciesPrinter{Out: params.Out}
68-
httpRoutesPrinter := &printer.HTTPRoutesPrinter{Out: params.Out}
68+
httpRoutesPrinter := &printer.HTTPRoutesPrinter{Out: params.Out, Clock: realClock}
6969

7070
switch kind {
7171
case "gateway", "gateways":

gwctl/pkg/printer/httproutes.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,66 @@ package printer
1919
import (
2020
"fmt"
2121
"io"
22+
"sort"
2223
"strings"
2324
"text/tabwriter"
2425

2526
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
26-
"sigs.k8s.io/yaml"
27-
2827
"sigs.k8s.io/gateway-api/gwctl/pkg/policymanager"
2928
"sigs.k8s.io/gateway-api/gwctl/pkg/resourcediscovery"
29+
"sigs.k8s.io/yaml"
30+
31+
"k8s.io/apimachinery/pkg/util/duration"
32+
"k8s.io/utils/clock"
3033
)
3134

3235
type HTTPRoutesPrinter struct {
33-
Out io.Writer
36+
Out io.Writer
37+
Clock clock.Clock
3438
}
3539

3640
func (hp *HTTPRoutesPrinter) Print(resourceModel *resourcediscovery.ResourceModel) {
3741
tw := tabwriter.NewWriter(hp.Out, 0, 0, 2, ' ', 0)
38-
row := []string{"NAME", "HOSTNAMES"}
42+
row := []string{"NAMESPACE", "NAME", "HOSTNAMES", "PARENT REFS", "AGE"}
3943
tw.Write([]byte(strings.Join(row, "\t") + "\n"))
4044

45+
httpRouteNodes := make([]*resourcediscovery.HTTPRouteNode, 0, len(resourceModel.HTTPRoutes))
4146
for _, httpRouteNode := range resourceModel.HTTPRoutes {
47+
httpRouteNodes = append(httpRouteNodes, httpRouteNode)
48+
}
49+
50+
sort.Slice(httpRouteNodes, func(i, j int) bool {
51+
if httpRouteNodes[i].HTTPRoute.GetNamespace() != httpRouteNodes[j].HTTPRoute.GetNamespace() {
52+
return httpRouteNodes[i].HTTPRoute.GetNamespace() < httpRouteNodes[j].HTTPRoute.GetNamespace()
53+
}
54+
return httpRouteNodes[i].HTTPRoute.GetName() < httpRouteNodes[j].HTTPRoute.GetName()
55+
})
56+
57+
for _, httpRouteNode := range httpRouteNodes {
4258
var hostNames []string
4359
for _, hostName := range httpRouteNode.HTTPRoute.Spec.Hostnames {
4460
hostNames = append(hostNames, string(hostName))
4561
}
46-
hostNamesOutput := strings.Join(hostNames, ",")
47-
if cnt := len(hostNames); cnt > 2 {
48-
hostNamesOutput = fmt.Sprintf("%v + %v more", strings.Join(hostNames[:2], ","), cnt-2)
62+
hostNamesOutput := "None"
63+
if hostNamesCount := len(hostNames); hostNamesCount > 0 {
64+
if hostNamesCount > 2 {
65+
hostNamesOutput = fmt.Sprintf("%v + %v more", strings.Join(hostNames[:2], ","), hostNamesCount-2)
66+
} else {
67+
hostNamesOutput = strings.Join(hostNames, ",")
68+
}
4969
}
5070

51-
row := []string{httpRouteNode.HTTPRoute.Name, hostNamesOutput}
71+
parentRefsCount := fmt.Sprintf("%d", len(httpRouteNode.HTTPRoute.Spec.ParentRefs))
72+
73+
age := duration.HumanDuration(hp.Clock.Since(httpRouteNode.HTTPRoute.GetCreationTimestamp().Time))
74+
75+
row := []string{
76+
httpRouteNode.HTTPRoute.GetNamespace(),
77+
httpRouteNode.HTTPRoute.GetName(),
78+
hostNamesOutput,
79+
parentRefsCount,
80+
age,
81+
}
5282
tw.Write([]byte(strings.Join(row, "\t") + "\n"))
5383
}
5484
tw.Flush()

gwctl/pkg/printer/httproutes_test.go

Lines changed: 188 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,205 @@ package printer
1919
import (
2020
"bytes"
2121
"testing"
22+
"time"
23+
24+
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
25+
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
2226

2327
"github.com/google/go-cmp/cmp"
2428
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2529
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2630
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2731
"k8s.io/apimachinery/pkg/runtime"
28-
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
29-
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
32+
testingclock "k8s.io/utils/clock/testing"
3033

3134
"sigs.k8s.io/gateway-api/gwctl/pkg/cmd/utils"
3235
"sigs.k8s.io/gateway-api/gwctl/pkg/common"
3336
"sigs.k8s.io/gateway-api/gwctl/pkg/resourcediscovery"
3437
)
3538

39+
func TestHTTPRoutesPrinter_Print(t *testing.T) {
40+
fakeClock := testingclock.NewFakeClock(time.Now())
41+
objects := []runtime.Object{
42+
&gatewayv1.GatewayClass{
43+
ObjectMeta: metav1.ObjectMeta{
44+
Name: "demo-gatewayclass-1",
45+
},
46+
Spec: gatewayv1.GatewayClassSpec{
47+
ControllerName: "example.net/gateway-controller",
48+
Description: common.PtrTo("random"),
49+
},
50+
},
51+
&gatewayv1.GatewayClass{
52+
ObjectMeta: metav1.ObjectMeta{
53+
Name: "demo-gatewayclass-2",
54+
},
55+
Spec: gatewayv1.GatewayClassSpec{
56+
ControllerName: "example.net/gateway-controller",
57+
Description: common.PtrTo("random"),
58+
},
59+
},
60+
&gatewayv1.Gateway{
61+
ObjectMeta: metav1.ObjectMeta{
62+
Name: "demo-gateway-1",
63+
Namespace: "default",
64+
},
65+
Spec: gatewayv1.GatewaySpec{
66+
GatewayClassName: "demo-gatewayclass-1",
67+
},
68+
},
69+
&gatewayv1.Gateway{
70+
ObjectMeta: metav1.ObjectMeta{
71+
Name: "demo-gateway-2",
72+
Namespace: "ns2",
73+
},
74+
Spec: gatewayv1.GatewaySpec{
75+
GatewayClassName: "demo-gatewayclass-2",
76+
},
77+
},
78+
&gatewayv1.Gateway{
79+
ObjectMeta: metav1.ObjectMeta{
80+
Name: "demo-gateway-200",
81+
Namespace: "default",
82+
},
83+
Spec: gatewayv1.GatewaySpec{
84+
GatewayClassName: "demo-gatewayclass-1",
85+
},
86+
},
87+
&gatewayv1.Gateway{
88+
ObjectMeta: metav1.ObjectMeta{
89+
Name: "demo-gateway-345",
90+
Namespace: "ns1",
91+
},
92+
Spec: gatewayv1.GatewaySpec{
93+
GatewayClassName: "demo-gatewayclass-2",
94+
},
95+
},
96+
&gatewayv1.HTTPRoute{
97+
ObjectMeta: metav1.ObjectMeta{
98+
Name: "foo-httproute-1",
99+
Namespace: "default",
100+
CreationTimestamp: metav1.Time{
101+
Time: fakeClock.Now().Add(-24 * time.Hour),
102+
},
103+
},
104+
Spec: gatewayv1.HTTPRouteSpec{
105+
Hostnames: []gatewayv1.Hostname{"example.com", "example2.com", "example3.com"},
106+
CommonRouteSpec: gatewayv1.CommonRouteSpec{
107+
ParentRefs: []gatewayv1.ParentReference{
108+
{
109+
Kind: common.PtrTo(gatewayv1.Kind("Gateway")),
110+
Group: common.PtrTo(gatewayv1.Group("gateway.networking.k8s.io")),
111+
Namespace: common.PtrTo(gatewayv1.Namespace("ns2")),
112+
Name: "demo-gateway-2",
113+
},
114+
},
115+
},
116+
},
117+
},
118+
&gatewayv1.HTTPRoute{
119+
ObjectMeta: metav1.ObjectMeta{
120+
Name: "qmn-httproute-100",
121+
Namespace: "default",
122+
CreationTimestamp: metav1.Time{
123+
Time: fakeClock.Now().Add(-11 * time.Hour),
124+
},
125+
},
126+
Spec: gatewayv1.HTTPRouteSpec{
127+
Hostnames: []gatewayv1.Hostname{"example.com"},
128+
CommonRouteSpec: gatewayv1.CommonRouteSpec{
129+
ParentRefs: []gatewayv1.ParentReference{
130+
{
131+
Kind: common.PtrTo(gatewayv1.Kind("Gateway")),
132+
Group: common.PtrTo(gatewayv1.Group("gateway.networking.k8s.io")),
133+
Name: "demo-gateway-1",
134+
},
135+
{
136+
Kind: common.PtrTo(gatewayv1.Kind("Gateway")),
137+
Group: common.PtrTo(gatewayv1.Group("gateway.networking.k8s.io")),
138+
Name: "demo-gateway-200",
139+
},
140+
},
141+
},
142+
},
143+
},
144+
&gatewayv1.HTTPRoute{
145+
ObjectMeta: metav1.ObjectMeta{
146+
Name: "bar-route-21",
147+
Namespace: "ns1",
148+
CreationTimestamp: metav1.Time{
149+
Time: fakeClock.Now().Add(-9 * time.Hour),
150+
},
151+
},
152+
Spec: gatewayv1.HTTPRouteSpec{
153+
Hostnames: []gatewayv1.Hostname{"foo.com", "bar.com", "example.com", "example2.com", "example3.com", "example4.com", "example5.com"},
154+
CommonRouteSpec: gatewayv1.CommonRouteSpec{
155+
ParentRefs: []gatewayv1.ParentReference{
156+
{
157+
Kind: common.PtrTo(gatewayv1.Kind("Gateway")),
158+
Group: common.PtrTo(gatewayv1.Group("gateway.networking.k8s.io")),
159+
Namespace: common.PtrTo(gatewayv1.Namespace("default")),
160+
Name: "demo-gateway-200",
161+
},
162+
},
163+
},
164+
},
165+
},
166+
&gatewayv1.HTTPRoute{
167+
ObjectMeta: metav1.ObjectMeta{
168+
Name: "bax-httproute-18777",
169+
Namespace: "ns2",
170+
CreationTimestamp: metav1.Time{
171+
Time: fakeClock.Now().Add(-5 * time.Minute),
172+
},
173+
},
174+
Spec: gatewayv1.HTTPRouteSpec{
175+
CommonRouteSpec: gatewayv1.CommonRouteSpec{
176+
ParentRefs: []gatewayv1.ParentReference{
177+
{
178+
Kind: common.PtrTo(gatewayv1.Kind("Gateway")),
179+
Group: common.PtrTo(gatewayv1.Group("gateway.networking.k8s.io")),
180+
Namespace: common.PtrTo(gatewayv1.Namespace("ns1")),
181+
Name: "demo-gateway-345",
182+
},
183+
},
184+
},
185+
},
186+
},
187+
}
188+
189+
params := utils.MustParamsForTest(t, common.MustClientsForTest(t, objects...))
190+
discoverer := resourcediscovery.Discoverer{
191+
K8sClients: params.K8sClients,
192+
PolicyManager: params.PolicyManager,
193+
}
194+
resourceModel, err := discoverer.DiscoverResourcesForHTTPRoute(resourcediscovery.Filter{})
195+
if err != nil {
196+
t.Fatalf("Failed to construct resourceModel: %v", resourceModel)
197+
}
198+
199+
hp := &HTTPRoutesPrinter{
200+
Out: params.Out,
201+
Clock: fakeClock,
202+
}
203+
204+
hp.Print(resourceModel)
205+
206+
got := params.Out.(*bytes.Buffer).String()
207+
want := `
208+
NAMESPACE NAME HOSTNAMES PARENT REFS AGE
209+
default foo-httproute-1 example.com,example2.com + 1 more 1 24h
210+
default qmn-httproute-100 example.com 2 11h
211+
ns1 bar-route-21 foo.com,bar.com + 5 more 1 9h
212+
ns2 bax-httproute-18777 None 1 5m
213+
`
214+
if diff := cmp.Diff(common.YamlString(want), common.YamlString(got), common.YamlStringTransformer); diff != "" {
215+
t.Errorf("Unexpected diff\ngot=\n%v\nwant=\n%v\ndiff (-want +got)=\n%v", got, want, diff)
216+
}
217+
}
218+
36219
func TestHTTPRoutesPrinter_PrintDescribeView(t *testing.T) {
220+
fakeClock := testingclock.NewFakeClock(time.Now())
37221
objects := []runtime.Object{
38222
&gatewayv1.GatewayClass{
39223
ObjectMeta: metav1.ObjectMeta{
@@ -202,7 +386,8 @@ func TestHTTPRoutesPrinter_PrintDescribeView(t *testing.T) {
202386
}
203387

204388
hp := &HTTPRoutesPrinter{
205-
Out: params.Out,
389+
Out: params.Out,
390+
Clock: fakeClock,
206391
}
207392
hp.PrintDescribeView(resourceModel)
208393

0 commit comments

Comments
 (0)