Skip to content

Commit fd1c896

Browse files
committed
[cli/gateway] Add gateway crud
1 parent dd4d7c1 commit fd1c896

File tree

5 files changed

+816
-9
lines changed

5 files changed

+816
-9
lines changed

api/core/v1alpha2/domain_types.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ type Domain struct {
3636
Status DomainStatus `json:"status,omitempty"`
3737
}
3838

39+
var (
40+
_ runtime.Object = &Domain{}
41+
_ resource.Object = &Domain{}
42+
_ resource.ObjectWithStatusSubResource = &Domain{}
43+
_ rest.SingularNameProvider = &Domain{}
44+
_ resourcestrategy.TableConverter = &Domain{}
45+
)
46+
3947
type DomainSpec struct {
4048
// The zone this domain is managed under.
4149
// +kubebuilder:validation:Required
@@ -279,12 +287,6 @@ func (as *DomainStatus) CopyTo(obj resource.ObjectWithStatusSubResource) {
279287
}
280288
}
281289

282-
var _ runtime.Object = &Domain{}
283-
var _ resource.Object = &Domain{}
284-
var _ resource.ObjectWithStatusSubResource = &Domain{}
285-
var _ rest.SingularNameProvider = &Domain{}
286-
var _ resourcestrategy.TableConverter = &Domain{}
287-
288290
func (a *Domain) GetObjectMeta() *metav1.ObjectMeta {
289291
return &a.ObjectMeta
290292
}
@@ -331,8 +333,10 @@ type DomainList struct {
331333
Items []Domain `json:"items"`
332334
}
333335

334-
var _ resource.ObjectList = &DomainList{}
335-
var _ resourcestrategy.TableConverter = &DomainList{}
336+
var (
337+
_ resource.ObjectList = &DomainList{}
338+
_ resourcestrategy.TableConverter = &DomainList{}
339+
)
336340

337341
func (pl *DomainList) GetListMeta() *metav1.ListMeta {
338342
return &pl.ListMeta

api/core/v1alpha2/proxy_types.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"k8s.io/apimachinery/pkg/runtime/schema"
1111
"k8s.io/apiserver/pkg/registry/rest"
1212
"sigs.k8s.io/apiserver-runtime/pkg/builder/resource"
13+
"sigs.k8s.io/apiserver-runtime/pkg/builder/resource/resourcestrategy"
1314
)
1415

1516
const (
@@ -245,6 +246,7 @@ var (
245246
_ resource.Object = &Proxy{}
246247
_ resource.ObjectWithStatusSubResource = &Proxy{}
247248
_ rest.SingularNameProvider = &Proxy{}
249+
_ resourcestrategy.TableConverter = &Proxy{}
248250
)
249251

250252
func (p *Proxy) GetObjectMeta() *metav1.ObjectMeta {
@@ -371,7 +373,10 @@ type ProxyList struct {
371373
Items []Proxy `json:"items"`
372374
}
373375

374-
var _ resource.ObjectList = &ProxyList{}
376+
var (
377+
_ resource.ObjectList = &ProxyList{}
378+
_ resourcestrategy.TableConverter = &ProxyList{}
379+
)
375380

376381
func (pl *ProxyList) GetListMeta() *metav1.ListMeta {
377382
return &pl.ListMeta

api/gateway/v1/gateway_types.go

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package v1
22

33
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"time"
8+
49
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
510
"k8s.io/apimachinery/pkg/runtime"
611
"k8s.io/apimachinery/pkg/runtime/schema"
12+
"k8s.io/apimachinery/pkg/util/duration"
713
"k8s.io/apiserver/pkg/registry/rest"
814
"sigs.k8s.io/apiserver-runtime/pkg/builder/resource"
15+
"sigs.k8s.io/apiserver-runtime/pkg/builder/resource/resourcestrategy"
916
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
1017
)
1118

@@ -365,3 +372,279 @@ var _ resource.ObjectList = &GRPCRouteList{}
365372
func (pl *GRPCRouteList) GetListMeta() *metav1.ListMeta {
366373
return &pl.ListMeta
367374
}
375+
376+
// formatAge formats a time as a Kubernetes-style age string.
377+
func formatAge(t time.Time) string {
378+
if t.IsZero() {
379+
return "<unknown>"
380+
}
381+
return duration.ShortHumanDuration(time.Since(t))
382+
}
383+
384+
// getListenersSummary returns a summary of gateway listeners.
385+
func getListenersSummary(listeners []gwapiv1.Listener) string {
386+
if len(listeners) == 0 {
387+
return "None"
388+
}
389+
var parts []string
390+
for _, l := range listeners {
391+
parts = append(parts, fmt.Sprintf("%s/%d", l.Protocol, l.Port))
392+
}
393+
return strings.Join(parts, ",")
394+
}
395+
396+
// getParentRefsSummary returns a summary of parent references.
397+
func getParentRefsSummary(refs []gwapiv1.ParentReference) string {
398+
if len(refs) == 0 {
399+
return "None"
400+
}
401+
var parts []string
402+
for _, ref := range refs {
403+
parts = append(parts, string(ref.Name))
404+
}
405+
return strings.Join(parts, ",")
406+
}
407+
408+
// getHostnamesSummary returns a summary of hostnames
409+
func getHostnamesSummary(hostnames []gwapiv1.Hostname) string {
410+
if len(hostnames) == 0 {
411+
return "*"
412+
}
413+
var parts []string
414+
for _, h := range hostnames {
415+
parts = append(parts, string(h))
416+
}
417+
return strings.Join(parts, ",")
418+
}
419+
420+
var _ resourcestrategy.TableConverter = &GatewayClass{}
421+
422+
func (gc *GatewayClass) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
423+
return gatewayClassToTable(gc, tableOptions)
424+
}
425+
426+
func gatewayClassToTable(gc *GatewayClass, tableOptions runtime.Object) (*metav1.Table, error) {
427+
table := &metav1.Table{}
428+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
429+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
430+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the gateway class"},
431+
{Name: "Controller", Type: "string", Description: "Controller that manages this class"},
432+
{Name: "Age", Type: "string", Description: "Time since creation"},
433+
}
434+
}
435+
table.Rows = append(table.Rows, metav1.TableRow{
436+
Cells: []interface{}{
437+
gc.Name,
438+
string(gc.Spec.ControllerName),
439+
formatAge(gc.CreationTimestamp.Time),
440+
},
441+
Object: runtime.RawExtension{Object: gc},
442+
})
443+
table.ResourceVersion = gc.ResourceVersion
444+
return table, nil
445+
}
446+
447+
var _ resourcestrategy.TableConverter = &GatewayClassList{}
448+
449+
func (l *GatewayClassList) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
450+
table := &metav1.Table{}
451+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
452+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
453+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the gateway class"},
454+
{Name: "Controller", Type: "string", Description: "Controller that manages this class"},
455+
{Name: "Age", Type: "string", Description: "Time since creation"},
456+
}
457+
}
458+
for i := range l.Items {
459+
gc := &l.Items[i]
460+
table.Rows = append(table.Rows, metav1.TableRow{
461+
Cells: []interface{}{
462+
gc.Name,
463+
string(gc.Spec.ControllerName),
464+
formatAge(gc.CreationTimestamp.Time),
465+
},
466+
Object: runtime.RawExtension{Object: gc},
467+
})
468+
}
469+
table.ResourceVersion = l.ResourceVersion
470+
table.Continue = l.Continue
471+
table.RemainingItemCount = l.RemainingItemCount
472+
return table, nil
473+
}
474+
475+
var _ resourcestrategy.TableConverter = &Gateway{}
476+
477+
func (g *Gateway) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
478+
return gatewayToTable(g, tableOptions)
479+
}
480+
481+
func gatewayToTable(g *Gateway, tableOptions runtime.Object) (*metav1.Table, error) {
482+
table := &metav1.Table{}
483+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
484+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
485+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the gateway"},
486+
{Name: "Class", Type: "string", Description: "Gateway class"},
487+
{Name: "Listeners", Type: "string", Description: "Listener configuration"},
488+
{Name: "Age", Type: "string", Description: "Time since creation"},
489+
}
490+
}
491+
table.Rows = append(table.Rows, metav1.TableRow{
492+
Cells: []interface{}{
493+
g.Name,
494+
string(g.Spec.GatewayClassName),
495+
getListenersSummary(g.Spec.Listeners),
496+
formatAge(g.CreationTimestamp.Time),
497+
},
498+
Object: runtime.RawExtension{Object: g},
499+
})
500+
table.ResourceVersion = g.ResourceVersion
501+
return table, nil
502+
}
503+
504+
var _ resourcestrategy.TableConverter = &GatewayList{}
505+
506+
func (l *GatewayList) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
507+
table := &metav1.Table{}
508+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
509+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
510+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the gateway"},
511+
{Name: "Class", Type: "string", Description: "Gateway class"},
512+
{Name: "Listeners", Type: "string", Description: "Listener configuration"},
513+
{Name: "Age", Type: "string", Description: "Time since creation"},
514+
}
515+
}
516+
for i := range l.Items {
517+
g := &l.Items[i]
518+
table.Rows = append(table.Rows, metav1.TableRow{
519+
Cells: []interface{}{
520+
g.Name,
521+
string(g.Spec.GatewayClassName),
522+
getListenersSummary(g.Spec.Listeners),
523+
formatAge(g.CreationTimestamp.Time),
524+
},
525+
Object: runtime.RawExtension{Object: g},
526+
})
527+
}
528+
table.ResourceVersion = l.ResourceVersion
529+
table.Continue = l.Continue
530+
table.RemainingItemCount = l.RemainingItemCount
531+
return table, nil
532+
}
533+
534+
var _ resourcestrategy.TableConverter = &HTTPRoute{}
535+
536+
func (r *HTTPRoute) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
537+
return httpRouteToTable(r, tableOptions)
538+
}
539+
540+
func httpRouteToTable(r *HTTPRoute, tableOptions runtime.Object) (*metav1.Table, error) {
541+
table := &metav1.Table{}
542+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
543+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
544+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the HTTP route"},
545+
{Name: "Hostnames", Type: "string", Description: "Hostnames for the route"},
546+
{Name: "Parents", Type: "string", Description: "Parent gateway references"},
547+
{Name: "Age", Type: "string", Description: "Time since creation"},
548+
}
549+
}
550+
table.Rows = append(table.Rows, metav1.TableRow{
551+
Cells: []interface{}{
552+
r.Name,
553+
getHostnamesSummary(r.Spec.Hostnames),
554+
getParentRefsSummary(r.Spec.ParentRefs),
555+
formatAge(r.CreationTimestamp.Time),
556+
},
557+
Object: runtime.RawExtension{Object: r},
558+
})
559+
table.ResourceVersion = r.ResourceVersion
560+
return table, nil
561+
}
562+
563+
var _ resourcestrategy.TableConverter = &HTTPRouteList{}
564+
565+
func (l *HTTPRouteList) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
566+
table := &metav1.Table{}
567+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
568+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
569+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the HTTP route"},
570+
{Name: "Hostnames", Type: "string", Description: "Hostnames for the route"},
571+
{Name: "Parents", Type: "string", Description: "Parent gateway references"},
572+
{Name: "Age", Type: "string", Description: "Time since creation"},
573+
}
574+
}
575+
for i := range l.Items {
576+
r := &l.Items[i]
577+
table.Rows = append(table.Rows, metav1.TableRow{
578+
Cells: []interface{}{
579+
r.Name,
580+
getHostnamesSummary(r.Spec.Hostnames),
581+
getParentRefsSummary(r.Spec.ParentRefs),
582+
formatAge(r.CreationTimestamp.Time),
583+
},
584+
Object: runtime.RawExtension{Object: r},
585+
})
586+
}
587+
table.ResourceVersion = l.ResourceVersion
588+
table.Continue = l.Continue
589+
table.RemainingItemCount = l.RemainingItemCount
590+
return table, nil
591+
}
592+
593+
var _ resourcestrategy.TableConverter = &GRPCRoute{}
594+
595+
func (r *GRPCRoute) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
596+
return grpcRouteToTable(r, tableOptions)
597+
}
598+
599+
func grpcRouteToTable(r *GRPCRoute, tableOptions runtime.Object) (*metav1.Table, error) {
600+
table := &metav1.Table{}
601+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
602+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
603+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the gRPC route"},
604+
{Name: "Hostnames", Type: "string", Description: "Hostnames for the route"},
605+
{Name: "Parents", Type: "string", Description: "Parent gateway references"},
606+
{Name: "Age", Type: "string", Description: "Time since creation"},
607+
}
608+
}
609+
table.Rows = append(table.Rows, metav1.TableRow{
610+
Cells: []interface{}{
611+
r.Name,
612+
getHostnamesSummary(r.Spec.Hostnames),
613+
getParentRefsSummary(r.Spec.ParentRefs),
614+
formatAge(r.CreationTimestamp.Time),
615+
},
616+
Object: runtime.RawExtension{Object: r},
617+
})
618+
table.ResourceVersion = r.ResourceVersion
619+
return table, nil
620+
}
621+
622+
var _ resourcestrategy.TableConverter = &GRPCRouteList{}
623+
624+
func (l *GRPCRouteList) ConvertToTable(ctx context.Context, tableOptions runtime.Object) (*metav1.Table, error) {
625+
table := &metav1.Table{}
626+
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
627+
table.ColumnDefinitions = []metav1.TableColumnDefinition{
628+
{Name: "Name", Type: "string", Format: "name", Description: "Name of the gRPC route"},
629+
{Name: "Hostnames", Type: "string", Description: "Hostnames for the route"},
630+
{Name: "Parents", Type: "string", Description: "Parent gateway references"},
631+
{Name: "Age", Type: "string", Description: "Time since creation"},
632+
}
633+
}
634+
for i := range l.Items {
635+
r := &l.Items[i]
636+
table.Rows = append(table.Rows, metav1.TableRow{
637+
Cells: []interface{}{
638+
r.Name,
639+
getHostnamesSummary(r.Spec.Hostnames),
640+
getParentRefsSummary(r.Spec.ParentRefs),
641+
formatAge(r.CreationTimestamp.Time),
642+
},
643+
Object: runtime.RawExtension{Object: r},
644+
})
645+
}
646+
table.ResourceVersion = l.ResourceVersion
647+
table.Continue = l.Continue
648+
table.RemainingItemCount = l.RemainingItemCount
649+
return table, nil
650+
}

0 commit comments

Comments
 (0)