Skip to content

Commit

Permalink
Implement gwctl get namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
jongwooo committed Mar 28, 2024
1 parent 9183329 commit 79333e3
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 4 deletions.
11 changes: 10 additions & 1 deletion gwctl/cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func NewGetCommand() *cobra.Command {
var allNamespacesFlag bool

cmd := &cobra.Command{
Use: "get {gateways|gatewayclasses|policies|policycrds|httproutes}",
Use: "get {namespaces|gateways|gatewayclasses|policies|policycrds|httproutes}",
Short: "Display one or many resources",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -72,12 +72,21 @@ func runGet(cmd *cobra.Command, args []string, params *utils.CmdParams) {
PolicyManager: params.PolicyManager,
}
realClock := clock.RealClock{}
nsPrinter := &printer.NamespacesPrinter{Out: params.Out, Clock: realClock}
gwPrinter := &printer.GatewaysPrinter{Out: params.Out, Clock: realClock}
gwcPrinter := &printer.GatewayClassesPrinter{Out: params.Out, Clock: realClock}
policiesPrinter := &printer.PoliciesPrinter{Out: params.Out, Clock: realClock}
httpRoutesPrinter := &printer.HTTPRoutesPrinter{Out: params.Out, Clock: realClock}

switch kind {
case "namespace", "namespaces":
resourceModel, err := discoverer.DiscoverResourcesForNamespace(resourcediscovery.Filter{})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to discover Namespace resources: %v\n", err)
os.Exit(1)
}
nsPrinter.Print(resourceModel)

case "gateway", "gateways":
filter := resourcediscovery.Filter{Namespace: ns}
if len(args) > 1 {
Expand Down
34 changes: 33 additions & 1 deletion gwctl/pkg/printer/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@ import (
"io"
"os"
"sort"
"strings"
"text/tabwriter"

"k8s.io/apimachinery/pkg/util/duration"
"k8s.io/utils/clock"

"sigs.k8s.io/gateway-api/gwctl/pkg/policymanager"
"sigs.k8s.io/gateway-api/gwctl/pkg/resourcediscovery"
"sigs.k8s.io/yaml"
)

type NamespacesPrinter struct {
Out io.Writer
Out io.Writer
Clock clock.Clock
}

type namespaceDescribeView struct {
Expand All @@ -39,6 +45,32 @@ type namespaceDescribeView struct {
DirectlyAttachedPolicies []policymanager.ObjRef `json:",omitempty"`
}

func (nsp *NamespacesPrinter) Print(resourceModel *resourcediscovery.ResourceModel) {
tw := tabwriter.NewWriter(nsp.Out, 0, 0, 2, ' ', 0)
row := []string{"NAME", "STATUS", "AGE"}
tw.Write([]byte(strings.Join(row, "\t") + "\n"))

namespaceNodes := make([]*resourcediscovery.NamespaceNode, 0, len(resourceModel.Namespaces))
for _, namespaceNode := range resourceModel.Namespaces {
namespaceNodes = append(namespaceNodes, namespaceNode)
}

sort.Slice(namespaceNodes, func(i, j int) bool {
return namespaceNodes[i].Namespace.Name < namespaceNodes[j].Namespace.Name
})

for _, namespaceNode := range namespaceNodes {
age := duration.HumanDuration(nsp.Clock.Since(namespaceNode.Namespace.CreationTimestamp.Time))
row := []string{
namespaceNode.Namespace.Name,
string(namespaceNode.Namespace.Status.Phase),
age,
}
tw.Write([]byte(strings.Join(row, "\t") + "\n"))
}
tw.Flush()
}

func (nsp *NamespacesPrinter) PrintDescribeView(resourceModel *resourcediscovery.ResourceModel) {
namespaceNodes := make([]*resourcediscovery.NamespaceNode, 0, len(resourceModel.Namespaces))

Expand Down
77 changes: 75 additions & 2 deletions gwctl/pkg/printer/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,92 @@ package printer
import (
"bytes"
"testing"
"time"

"github.com/google/go-cmp/cmp"

corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
testingclock "k8s.io/utils/clock/testing"

gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
"sigs.k8s.io/gateway-api/gwctl/pkg/utils"
"sigs.k8s.io/gateway-api/gwctl/pkg/common"
"sigs.k8s.io/gateway-api/gwctl/pkg/resourcediscovery"
"sigs.k8s.io/gateway-api/gwctl/pkg/utils"
)

func TestNamespacePrinter_Print(t *testing.T) {
fakeClock := testingclock.NewFakeClock(time.Now())
objects := []runtime.Object{
&corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
CreationTimestamp: metav1.Time{
Time: fakeClock.Now().Add(-46 * 24 * time.Hour),
},
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceActive,
},
},
&corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kube-system",
CreationTimestamp: metav1.Time{
Time: fakeClock.Now().Add(-46 * 24 * time.Hour),
},
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceActive,
},
},
&corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "ns1",
CreationTimestamp: metav1.Time{
Time: fakeClock.Now().Add(-10 * time.Minute),
},
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceTerminating,
},
},
}

params := utils.MustParamsForTest(t, common.MustClientsForTest(t, objects...))
discoverer := resourcediscovery.Discoverer{
K8sClients: params.K8sClients,
PolicyManager: params.PolicyManager,
}
resourceModel, err := discoverer.DiscoverResourcesForNamespace(resourcediscovery.Filter{})
if err != nil {
t.Fatalf("Failed to construct resourceModel: %v", resourceModel)
}

nsp := &NamespacesPrinter{
Out: params.Out,
Clock: fakeClock,
}
nsp.Print(resourceModel)

got := params.Out.(*bytes.Buffer).String()
want := `
NAME STATUS AGE
default Active 46d
kube-system Active 46d
ns1 Terminating 10m
`

if diff := cmp.Diff(common.YamlString(want), common.YamlString(got), common.YamlStringTransformer); diff != "" {
t.Errorf("Unexpected diff\ngot=\n%v\nwant=\n%v\ndiff (-want +got)=\n%v", got, want, diff)
}
}

func TestNamespacePrinter_PrintDescribeView(t *testing.T) {
fakeClock := testingclock.NewFakeClock(time.Now())
objects := []runtime.Object{
// Defining a Namespace called development
&corev1.Namespace{
Expand Down Expand Up @@ -153,7 +225,8 @@ func TestNamespacePrinter_PrintDescribeView(t *testing.T) {
}

nsp := &NamespacesPrinter{
Out: params.Out,
Out: params.Out,
Clock: fakeClock,
}
nsp.PrintDescribeView(resourceModel)

Expand Down

0 comments on commit 79333e3

Please sign in to comment.