...

Source file src/github.com/emissary-ingress/emissary/v3/cmd/kubestatus/main.go

Documentation: github.com/emissary-ingress/emissary/v3/cmd/kubestatus

     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/dlib/dlog"
    13  	"github.com/emissary-ingress/emissary/v3/pkg/k8s"
    14  	"github.com/emissary-ingress/emissary/v3/pkg/kates"
    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  		// Special case and supply the name argument so we use Get instead of List if we can
    61  		// tell the FieldSelector is equivalent to a Get. This appeared to show a
    62  		// performance improvement at one point, but it was later discovered that the
    63  		// improvement actually came from the kates client doing discovery caching.
    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  				// The user is asking for the status, so print it.
   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  				// The user is asking for a status update.
   127  				// log.Debugf doesn't exist.
   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