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

Commit 7ebcf7a

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 008eb45 commit 7ebcf7a

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

internal/kubectl/get.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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/apimachinery/pkg/runtime/schema"
11+
"k8s.io/cli-runtime/pkg/printers"
12+
"k8s.io/client-go/dynamic"
13+
"k8s.io/client-go/kubernetes/scheme"
14+
)
15+
16+
var (
17+
watch bool
18+
namespace string
19+
allNamespaces bool
20+
GroupVersion = schema.GroupVersion{Group: "resources.hnc.x-k8s.io", Version: "v1alpha2"}
21+
)
22+
23+
var getCmd = &cobra.Command{
24+
Use: "get",
25+
Short: "list resources",
26+
RunE: func(c *cobra.Command, args []string) error {
27+
if len(args) == 0 {
28+
return fmt.Errorf("not enough arguments to 'get'")
29+
}
30+
if len(args) > 1 {
31+
return fmt.Errorf("too many arguments to 'get'")
32+
}
33+
d := newDoer(args[0])
34+
rv, err := d.get(args[0])
35+
if err != nil {
36+
return err
37+
}
38+
if watch {
39+
return d.watch(args[0], rv)
40+
}
41+
return nil
42+
},
43+
}
44+
45+
func newGetCmd() *cobra.Command {
46+
return getCmd
47+
}
48+
49+
func init() {
50+
getCmd.Flags().BoolVarP(&watch, "watch", "w", false, "watch for changes")
51+
getCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "parent namespace to scope request to")
52+
getCmd.PersistentFlags().BoolVarP(&allNamespaces, "all-namespaces", "A", false, "list across all namespaces")
53+
}
54+
55+
type doer struct {
56+
client dynamic.ResourceInterface
57+
printer printers.ResourcePrinter
58+
}
59+
60+
func newDoer(resource string) doer {
61+
client := getClient(resource)
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 := GroupVersion.WithResource(resource)
71+
gvr, _ = mapper.ResourceFor(gvr)
72+
resourceClient := dynamicClient.Resource(gvr)
73+
if allNamespaces {
74+
return resourceClient
75+
}
76+
return resourceClient.Namespace(namespace)
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 len(unst.Items) == 0 {
86+
fmt.Printf("No resources found in %s namespace\n", namespace)
87+
return rv, nil
88+
}
89+
unst.SetAPIVersion("resources.hnc.x-k8s.io/v1alpha2")
90+
kind := unst.Items[0].GetKind()
91+
unst.SetKind(kind + "List")
92+
if err = d.printer.PrintObj(unst, os.Stdout); err != nil {
93+
return rv, err
94+
}
95+
return rv, nil
96+
}
97+
98+
func (d doer) watch(resource, rv string) error {
99+
if rv == "" {
100+
rv = "0"
101+
}
102+
opts := metav1.ListOptions{
103+
ResourceVersion: rv,
104+
}
105+
watcher, err := d.client.Watch(context.TODO(), opts)
106+
if err != nil {
107+
return err
108+
}
109+
for event := range watcher.ResultChan() {
110+
if err = d.printer.PrintObj(event.Object, os.Stdout); err != nil {
111+
return err
112+
}
113+
}
114+
return nil
115+
}

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)