1 package kubestatus
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "os"
8 "strings"
9
10 "github.com/spf13/cobra"
11
12 "github.com/datawire/ambassador/v2/pkg/k8s"
13 "github.com/datawire/ambassador/v2/pkg/kates"
14 "github.com/datawire/dlib/dlog"
15 )
16
17 func Main(ctx context.Context, version string, args ...string) error {
18 var st = &cobra.Command{
19 Use: "kubestatus <kind> [<name>]",
20 Short: "get and set status of kubernetes resources",
21 Args: cobra.RangeArgs(1, 2),
22 SilenceErrors: true,
23 SilenceUsage: true,
24 }
25
26 info := k8s.NewKubeInfoFromFlags(st.Flags())
27 fields := st.Flags().StringP("field-selector", "f", "", "field selector")
28 labels := st.Flags().StringP("label-selector", "l", "", "label selector")
29 statusFile := st.Flags().StringP("update", "u", "", "update with new status from file (must be json)")
30
31 st.RunE = func(cmd *cobra.Command, args []string) error {
32 ctx := cmd.Context()
33 var status map[string]interface{}
34
35 if *statusFile != "" {
36 rawStatus, err := os.Open(*statusFile)
37 if err != nil {
38 return err
39 }
40 defer rawStatus.Close()
41
42 dec := json.NewDecoder(rawStatus)
43 err = dec.Decode(&status)
44 if err != nil {
45 return err
46 }
47 }
48
49 kind := args[0]
50 namespace, err := info.Namespace()
51 if err != nil {
52 return err
53 }
54
55 name := ""
56 if len(args) == 2 {
57 name = args[1]
58 }
59
60
61
62
63
64 if *labels == "" {
65 parts := strings.Split(*fields, ",")
66 if len(parts) == 1 {
67 parts = strings.Split(parts[0], "=")
68 if len(parts) == 2 {
69 lhs := strings.TrimSpace(parts[0])
70 if lhs == "metadata.name" {
71 name = strings.TrimSpace(parts[1])
72 }
73 }
74 }
75 }
76
77 client, err := kates.NewClientFromConfigFlags(info.GetConfigFlags())
78 if err != nil {
79 return err
80 }
81
82 if name != "" {
83 obj := kates.NewUnstructured(kind, "")
84 obj.SetName(name)
85 if namespace != "" {
86 obj.SetNamespace(namespace)
87 }
88 err = client.Get(ctx, obj, obj)
89 if err != nil {
90 return err
91 }
92
93 if *statusFile == "" {
94 fmt.Println("Status of", obj.GetKind(), obj.GetName(), "in namespace",
95 obj.GetNamespace())
96 fmt.Printf(" %v\n", obj.Object["status"])
97 return nil
98 } else {
99 obj.Object["status"] = status
100 return client.UpdateStatus(ctx, obj, obj)
101 }
102 }
103
104 var items []*kates.Unstructured
105
106 err = client.List(ctx,
107 kates.Query{
108 Kind: kind,
109 Namespace: namespace,
110 FieldSelector: *fields,
111 LabelSelector: *labels,
112 },
113 &items)
114
115 if err != nil {
116 return err
117 }
118
119 for _, obj := range items {
120 if *statusFile == "" {
121
122 fmt.Println("Status of", obj.GetKind(), obj.GetName(), "in namespace",
123 obj.GetNamespace())
124 fmt.Printf(" %v\n", obj.Object["status"])
125 } else {
126
127
128 if false {
129 fmt.Println("Updating", obj.GetName(), "in namespace", obj.GetNamespace())
130 }
131
132 obj.Object["status"] = status
133 err = client.UpdateStatus(ctx, obj, nil)
134 if err != nil {
135 dlog.Debugf(ctx, "error updating resource: %v", err)
136 }
137 }
138 }
139
140 return nil
141 }
142
143 st.SetArgs(args)
144 return st.ExecuteContext(ctx)
145 }
146
View as plain text