Skip to content
This repository was archived by the owner on Apr 17, 2025. It is now read-only.

Commit 3dc9c35

Browse files
committed
Add new subcommand for the kubectl-hns plugin
Add a subcommand to list resources by their parent namespace: kubectl hns get -n <parent ns> <resource>
1 parent d56b15d commit 3dc9c35

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

internal/kubectl/get.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package kubectl
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/spf13/cobra"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/cli-runtime/pkg/printers"
11+
"k8s.io/client-go/dynamic"
12+
"k8s.io/client-go/kubernetes/scheme"
13+
api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2"
14+
)
15+
16+
var (
17+
watch bool
18+
parent string
19+
allNamespaces bool
20+
)
21+
22+
var getCmd = &cobra.Command{
23+
Use: "get",
24+
Short: "list resources",
25+
RunE: func(c *cobra.Command, args []string) error {
26+
if len(args) == 0 {
27+
return fmt.Errorf("not enough arguments to 'get'")
28+
}
29+
if len(args) > 1 {
30+
return fmt.Errorf("too many arguments to 'get'")
31+
}
32+
d := newDoer(args[0])
33+
rv, err := d.get(args[0])
34+
if err != nil {
35+
return err
36+
}
37+
if watch {
38+
return d.watch(args[0], rv)
39+
}
40+
return nil
41+
},
42+
}
43+
44+
func newGetCmd() *cobra.Command {
45+
return getCmd
46+
}
47+
48+
func init() {
49+
getCmd.Flags().BoolVarP(&watch, "watch", "w", false, "watch for changes")
50+
getCmd.PersistentFlags().StringVarP(&parent, "namespace", "n", "default", "parent namespace to scope request to")
51+
getCmd.PersistentFlags().BoolVarP(&allNamespaces, "all-namespaces", "A", false, "list across all namespaces")
52+
}
53+
54+
type doer struct {
55+
client dynamic.ResourceInterface
56+
printer printers.ResourcePrinter
57+
}
58+
59+
func newDoer(resource string) doer {
60+
client := getClient(resource)
61+
printOpts := printers.PrintOptions{WithNamespace: true}
62+
return doer{
63+
client: client,
64+
printer: printers.NewTypeSetter(scheme.Scheme).ToPrinter(printers.NewTablePrinter(printOpts)),
65+
}
66+
}
67+
68+
func getClient(resource string) dynamic.ResourceInterface {
69+
gvr := api.ResourcesGroupVersion.WithResource(resource)
70+
gvr, _ = mapper.ResourceFor(gvr)
71+
resourceClient := dynamicClient.Resource(gvr)
72+
if allNamespaces {
73+
return resourceClient
74+
}
75+
return resourceClient.Namespace(parent)
76+
}
77+
78+
func (d doer) get(resource string) (string, error) {
79+
unst, err := d.client.List(context.TODO(), metav1.ListOptions{})
80+
if err != nil {
81+
return "", err
82+
}
83+
rv := unst.GetResourceVersion()
84+
if err = d.printer.PrintObj(unst, os.Stdout); err != nil {
85+
return rv, err
86+
}
87+
return rv, nil
88+
}
89+
90+
func (d doer) watch(resource, rv string) error {
91+
if rv == "" {
92+
rv = "0"
93+
}
94+
opts := metav1.ListOptions{
95+
ResourceVersion: rv,
96+
}
97+
watcher, err := d.client.Watch(context.TODO(), opts)
98+
if err != nil {
99+
return err
100+
}
101+
for event := range watcher.ResultChan() {
102+
if err = d.printer.PrintObj(event.Object, os.Stdout); err != nil {
103+
return err
104+
}
105+
}
106+
return nil
107+
}

internal/kubectl/root.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,28 @@ import (
2424

2525
"github.com/spf13/cobra"
2626
"k8s.io/apimachinery/pkg/api/errors"
27+
"k8s.io/apimachinery/pkg/api/meta"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
"k8s.io/apimachinery/pkg/runtime/serializer"
2930
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3031
"k8s.io/cli-runtime/pkg/genericclioptions"
32+
"k8s.io/client-go/dynamic"
3133
"k8s.io/client-go/kubernetes"
3234
"k8s.io/client-go/kubernetes/scheme"
3335
_ "k8s.io/client-go/plugin/pkg/client/auth"
3436
"k8s.io/client-go/rest"
3537

3638
api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2"
39+
"sigs.k8s.io/hierarchical-namespaces/internal/apiextension/clients"
3740
"sigs.k8s.io/hierarchical-namespaces/internal/version"
3841
)
3942

4043
var k8sClient *kubernetes.Clientset
4144
var hncClient *rest.RESTClient
4245
var rootCmd *cobra.Command
4346
var client Client
47+
var dynamicClient dynamic.Interface
48+
var mapper meta.RESTMapper
4449

4550
type realClient struct{}
4651
type anchorStatus map[string]string
@@ -93,6 +98,20 @@ func init() {
9398
return err
9499
}
95100

101+
mapper, err = kubecfgFlags.ToRESTMapper()
102+
if err != nil {
103+
return err
104+
}
105+
106+
config, err = clients.SetMediaType(config, "application/json;as=Table;v=v1;g=meta.k8s.io")
107+
if err != nil {
108+
return err
109+
}
110+
dynamicClient, err = dynamic.NewForConfig(config)
111+
if err != nil {
112+
return err
113+
}
114+
96115
return nil
97116
},
98117
}
@@ -105,6 +124,7 @@ func init() {
105124
rootCmd.AddCommand(newConfigCmd())
106125
rootCmd.AddCommand(newVersionCmd())
107126
rootCmd.AddCommand(newHrqCmd())
127+
rootCmd.AddCommand(newGetCmd())
108128
}
109129

110130
func Execute() {

0 commit comments

Comments
 (0)