Fix karmadactl get -o yaml|json
Signed-off-by: lonelyCZ <531187475@qq.com>
This commit is contained in:
parent
74838ccce0
commit
f488d6be90
|
@ -2,6 +2,7 @@ package karmadactl
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -10,6 +11,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -95,8 +97,9 @@ type CommandGetOptions struct {
|
|||
|
||||
Clusters []string
|
||||
|
||||
PrintFlags *get.PrintFlags
|
||||
ToPrinter func(*meta.RESTMapping, *bool, bool, bool) (printers.ResourcePrinterFunc, error)
|
||||
PrintFlags *get.PrintFlags
|
||||
ToPrinter func(*meta.RESTMapping, *bool, bool, bool) (printers.ResourcePrinterFunc, error)
|
||||
IsHumanReadablePrinter bool
|
||||
|
||||
CmdParent string
|
||||
|
||||
|
@ -113,6 +116,8 @@ type CommandGetOptions struct {
|
|||
Namespace string
|
||||
ExplicitNamespace bool
|
||||
|
||||
ServerPrint bool
|
||||
|
||||
NoHeaders bool
|
||||
Sort bool
|
||||
IgnoreNotFound bool
|
||||
|
@ -124,10 +129,11 @@ type CommandGetOptions struct {
|
|||
// NewCommandGetOptions returns a GetOptions with default chunk size 500.
|
||||
func NewCommandGetOptions(parent string, streams genericclioptions.IOStreams) *CommandGetOptions {
|
||||
return &CommandGetOptions{
|
||||
PrintFlags: get.NewGetPrintFlags(),
|
||||
CmdParent: parent,
|
||||
IOStreams: streams,
|
||||
ChunkSize: 500,
|
||||
PrintFlags: get.NewGetPrintFlags(),
|
||||
CmdParent: parent,
|
||||
IOStreams: streams,
|
||||
ChunkSize: 500,
|
||||
ServerPrint: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,8 +141,19 @@ func NewCommandGetOptions(parent string, streams genericclioptions.IOStreams) *C
|
|||
func (g *CommandGetOptions) Complete(cmd *cobra.Command, args []string) error {
|
||||
newScheme := gclient.NewSchema()
|
||||
|
||||
if g.AllNamespaces {
|
||||
g.ExplicitNamespace = false
|
||||
outputOption := cmd.Flags().Lookup("output").Value.String()
|
||||
if strings.Contains(outputOption, "custom-columns") || outputOption == "yaml" || strings.Contains(outputOption, "json") {
|
||||
g.ServerPrint = false
|
||||
}
|
||||
|
||||
templateArg := ""
|
||||
if g.PrintFlags.TemplateFlags != nil && g.PrintFlags.TemplateFlags.TemplateArgument != nil {
|
||||
templateArg = *g.PrintFlags.TemplateFlags.TemplateArgument
|
||||
}
|
||||
|
||||
// human readable printers have special conversion rules, so we determine if we're using one.
|
||||
if (len(*g.PrintFlags.OutputFormat) == 0 && len(templateArg) == 0) || *g.PrintFlags.OutputFormat == "wide" {
|
||||
g.IsHumanReadablePrinter = true
|
||||
}
|
||||
|
||||
g.ToPrinter = func(mapping *meta.RESTMapping, outputObjects *bool, withNamespace bool, withKind bool) (printers.ResourcePrinterFunc, error) {
|
||||
|
@ -163,7 +180,9 @@ func (g *CommandGetOptions) Complete(cmd *cobra.Command, args []string) error {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
printer = &get.TablePrinter{Delegate: printer}
|
||||
if g.ServerPrint {
|
||||
printer = &get.TablePrinter{Delegate: printer}
|
||||
}
|
||||
|
||||
return printer.PrintObj, nil
|
||||
}
|
||||
|
@ -196,6 +215,10 @@ func (g *CommandGetOptions) Run(karmadaConfig KarmadaConfig, cmd *cobra.Command,
|
|||
clusterInfos := make(map[string]*ClusterInfo)
|
||||
RBInfo = make(map[string]*OtherPrint)
|
||||
|
||||
if g.AllNamespaces {
|
||||
g.ExplicitNamespace = false
|
||||
}
|
||||
|
||||
karmadaclient, err := clusterInfoInit(g, karmadaConfig, clusterInfos)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -339,6 +362,13 @@ func (g *CommandGetOptions) getObjInfo(wg *sync.WaitGroup, mux *sync.Mutex, f cm
|
|||
|
||||
r.IgnoreErrors(apierrors.IsNotFound)
|
||||
|
||||
if !g.IsHumanReadablePrinter {
|
||||
err := g.printGeneric(r)
|
||||
|
||||
*allErrs = append(*allErrs, err)
|
||||
return
|
||||
}
|
||||
|
||||
infos, err := r.Infos()
|
||||
if err != nil {
|
||||
*allErrs = append(*allErrs, err)
|
||||
|
@ -386,6 +416,110 @@ func (g *CommandGetOptions) reconstructionRow(objs []Obj, table *metav1.Table) (
|
|||
return allTableRows, mapping, nil
|
||||
}
|
||||
|
||||
func (g *CommandGetOptions) printGeneric(r *resource.Result) error {
|
||||
// we flattened the data from the builder, so we have individual items, but now we'd like to either:
|
||||
// 1. if there is more than one item, combine them all into a single list
|
||||
// 2. if there is a single item and that item is a list, leave it as its specific list
|
||||
// 3. if there is a single item and it is not a list, leave it as a single item
|
||||
var errs []error
|
||||
singleItemImplied := false
|
||||
|
||||
infos, err := g.extractInfosFromResource(r, &errs, &singleItemImplied)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printer, err := g.ToPrinter(nil, nil, false, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var obj runtime.Object
|
||||
if !singleItemImplied || len(infos) != 1 {
|
||||
// we have zero or multple items, so coerce all items into a list.
|
||||
// we don't want an *unstructured.Unstructured list yet, as we
|
||||
// may be dealing with non-unstructured objects. Compose all items
|
||||
// into an corev1.List, and then decode using an unstructured scheme.
|
||||
list := corev1.List{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "List",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ListMeta: metav1.ListMeta{},
|
||||
}
|
||||
for _, info := range infos {
|
||||
list.Items = append(list.Items, runtime.RawExtension{Object: info.Object})
|
||||
}
|
||||
|
||||
listData, err := json.Marshal(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, listData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj = converted
|
||||
} else {
|
||||
obj = infos[0].Object
|
||||
}
|
||||
|
||||
isList := meta.IsListType(obj)
|
||||
if isList {
|
||||
items, err := meta.ExtractList(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// take the items and create a new list for display
|
||||
list := &unstructured.UnstructuredList{
|
||||
Object: map[string]interface{}{
|
||||
"kind": "List",
|
||||
"apiVersion": "v1",
|
||||
"metadata": map[string]interface{}{},
|
||||
},
|
||||
}
|
||||
if listMeta, err := meta.ListAccessor(obj); err == nil {
|
||||
list.Object["metadata"] = map[string]interface{}{
|
||||
"selfLink": listMeta.GetSelfLink(),
|
||||
"resourceVersion": listMeta.GetResourceVersion(),
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
list.Items = append(list.Items, *item.(*unstructured.Unstructured))
|
||||
}
|
||||
if err := printer.PrintObj(list, g.Out); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs)))
|
||||
}
|
||||
|
||||
if printErr := printer.PrintObj(obj, g.Out); printErr != nil {
|
||||
errs = append(errs, printErr)
|
||||
}
|
||||
|
||||
return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs)))
|
||||
}
|
||||
|
||||
func (g *CommandGetOptions) extractInfosFromResource(r *resource.Result, errs *[]error, singleItemImplied *bool) ([]*resource.Info, error) {
|
||||
infos, err := r.IntoSingleItemImplied(singleItemImplied).Infos()
|
||||
if err != nil {
|
||||
if *singleItemImplied {
|
||||
return nil, err
|
||||
}
|
||||
*errs = append(*errs, err)
|
||||
}
|
||||
|
||||
if len(infos) == 0 && g.IgnoreNotFound {
|
||||
return nil, utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(*errs)))
|
||||
}
|
||||
|
||||
return infos, nil
|
||||
}
|
||||
|
||||
type trackingWriterWrapper struct {
|
||||
Delegate io.Writer
|
||||
Written int
|
||||
|
@ -461,6 +595,10 @@ func getFactory(clusterName string, clusterInfos map[string]*ClusterInfo) cmduti
|
|||
}
|
||||
|
||||
func (g *CommandGetOptions) transformRequests(req *rest.Request) {
|
||||
if !g.ServerPrint || !g.IsHumanReadablePrinter {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetHeader("Accept", strings.Join([]string{
|
||||
fmt.Sprintf("application/json;as=Table;v=%s;g=%s", metav1.SchemeGroupVersion.Version, metav1.GroupName),
|
||||
fmt.Sprintf("application/json;as=Table;v=%s;g=%s", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName),
|
||||
|
@ -615,7 +753,10 @@ func getExample(parentCommand string) string {
|
|||
fmt.Sprintf("%s get replicasets nginx", parentCommand) + `
|
||||
|
||||
# List deployments in JSON output format, in the "v1" version of the "apps" API group ` + "\n" +
|
||||
fmt.Sprintf("%s get deployments.v1.apps ", parentCommand) + `
|
||||
fmt.Sprintf("%s get deployments.v1.apps -o json", parentCommand) + `
|
||||
|
||||
# Return only the phase value of the specified resource ` + "\n" +
|
||||
fmt.Sprintf("%s get -o template deployment/nginx -C member1 --template={{.spec.replicas}}", parentCommand) + `
|
||||
|
||||
# List all replication controllers and services together in ps output format ` + "\n" +
|
||||
fmt.Sprintf("%s get rs,services", parentCommand) + `
|
||||
|
|
Loading…
Reference in New Issue