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

Commit 671b533

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 37ac5c9 commit 671b533

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

internal/kubectl/get.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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+
// See https://iximiuz.com/en/posts/kubernetes-api-go-cli/#pretty-print-kubernetes-object-as-yamljsontables for information on k8s printers
62+
printOpts := printers.PrintOptions{WithNamespace: true}
63+
return doer{
64+
client: client,
65+
printer: printers.NewTypeSetter(scheme.Scheme).ToPrinter(printers.NewTablePrinter(printOpts)),
66+
}
67+
}
68+
69+
func getClient(resource string) dynamic.ResourceInterface {
70+
gvr := api.ResourcesGroupVersion.WithResource(resource)
71+
gvr, _ = mapper.ResourceFor(gvr)
72+
resourceClient := dynamicClient.Resource(gvr)
73+
if allNamespaces {
74+
return resourceClient
75+
}
76+
return resourceClient.Namespace(parent)
77+
}
78+
79+
func (d doer) get(resource string) (string, error) {
80+
unst, err := d.client.List(context.TODO(), metav1.ListOptions{})
81+
if err != nil {
82+
return "", err
83+
}
84+
rv := unst.GetResourceVersion()
85+
if err = d.printer.PrintObj(unst, os.Stdout); err != nil {
86+
return rv, err
87+
}
88+
return rv, nil
89+
}
90+
91+
func (d doer) watch(resource, rv string) error {
92+
if rv == "" {
93+
rv = "0"
94+
}
95+
opts := metav1.ListOptions{
96+
ResourceVersion: rv,
97+
}
98+
watcher, err := d.client.Watch(context.TODO(), opts)
99+
if err != nil {
100+
return err
101+
}
102+
for event := range watcher.ResultChan() {
103+
if err = d.printer.PrintObj(event.Object, os.Stdout); err != nil {
104+
return err
105+
}
106+
}
107+
return nil
108+
}

internal/kubectl/root.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ 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"
@@ -41,6 +43,8 @@ var k8sClient *kubernetes.Clientset
4143
var hncClient *rest.RESTClient
4244
var rootCmd *cobra.Command
4345
var client Client
46+
var dynamicClient dynamic.Interface
47+
var mapper meta.RESTMapper
4448

4549
type realClient struct{}
4650
type anchorStatus map[string]string
@@ -93,6 +97,16 @@ func init() {
9397
return err
9498
}
9599

100+
mapper, err = kubecfgFlags.ToRESTMapper()
101+
if err != nil {
102+
return err
103+
}
104+
105+
dynamicClient, err = dynamic.NewForConfig(config)
106+
if err != nil {
107+
return err
108+
}
109+
96110
return nil
97111
},
98112
}
@@ -105,6 +119,7 @@ func init() {
105119
rootCmd.AddCommand(newConfigCmd())
106120
rootCmd.AddCommand(newVersionCmd())
107121
rootCmd.AddCommand(newHrqCmd())
122+
rootCmd.AddCommand(newGetCmd())
108123
}
109124

110125
func Execute() {

0 commit comments

Comments
 (0)