|
|
@ -22,6 +22,7 @@ import (
|
|
|
|
"encoding/json"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
@ -36,8 +37,10 @@ import (
|
|
|
|
|
|
|
|
|
|
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
|
|
|
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
|
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
|
|
|
|
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
"k8s.io/apimachinery/pkg/types"
|
|
|
|
"k8s.io/apimachinery/pkg/types"
|
|
|
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
|
|
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
|
|
@ -110,17 +113,46 @@ func (c *Client) Create(resources ResourceList) (*Result, error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func transformRequests(req *rest.Request) {
|
|
|
|
func transformRequests(req *rest.Request) {
|
|
|
|
group := metav1beta1.GroupName
|
|
|
|
tableParam := strings.Join([]string{
|
|
|
|
version := metav1beta1.SchemeGroupVersion.Version
|
|
|
|
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),
|
|
|
|
tableParam := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group)
|
|
|
|
"application/json",
|
|
|
|
|
|
|
|
}, ",")
|
|
|
|
req.SetHeader("Accept", tableParam)
|
|
|
|
req.SetHeader("Accept", tableParam)
|
|
|
|
|
|
|
|
|
|
|
|
// if sorting, ensure we receive the full object in order to introspect its fields via jsonpath
|
|
|
|
// if sorting, ensure we receive the full object in order to introspect its fields via jsonpath
|
|
|
|
req.Param("includeObject", "Object")
|
|
|
|
req.Param("includeObject", "Object")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (c *Client) Get(resources ResourceList) (string, error) {
|
|
|
|
func sortTableSlice(objs []runtime.Object) []runtime.Object {
|
|
|
|
|
|
|
|
if len(objs) < 2 {
|
|
|
|
|
|
|
|
return objs
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ntbl := &metav1.Table{}
|
|
|
|
|
|
|
|
// Sort the list of objects
|
|
|
|
|
|
|
|
var newObjs []runtime.Object
|
|
|
|
|
|
|
|
namesCache := make(map[string]runtime.Object, len(objs))
|
|
|
|
|
|
|
|
var names []string
|
|
|
|
|
|
|
|
for _, obj := range objs {
|
|
|
|
|
|
|
|
unstr, ok := obj.(*unstructured.Unstructured)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return objs
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, ntbl); err != nil {
|
|
|
|
|
|
|
|
return objs
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namesCache[ntbl.GetSelfLink()] = obj
|
|
|
|
|
|
|
|
names = append(names, ntbl.GetSelfLink())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(names)
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
|
|
|
|
newObjs = append(newObjs, namesCache[name])
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return newObjs
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (c *Client) Get(resources ResourceList, reader io.Reader) (string, error) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
printFlags := get.NewHumanPrintFlags()
|
|
|
|
printFlags := get.NewHumanPrintFlags()
|
|
|
|
typePrinter, _ := printFlags.ToPrinter("")
|
|
|
|
typePrinter, _ := printFlags.ToPrinter("")
|
|
|
@ -133,6 +165,7 @@ func (c *Client) Get(resources ResourceList) (string, error) {
|
|
|
|
gvk := info.ResourceMapping().GroupVersionKind
|
|
|
|
gvk := info.ResourceMapping().GroupVersionKind
|
|
|
|
vk := gvk.Version + "/" + gvk.Kind
|
|
|
|
vk := gvk.Version + "/" + gvk.Kind
|
|
|
|
obj, err := getResource(info)
|
|
|
|
obj, err := getResource(info)
|
|
|
|
|
|
|
|
info.Object = obj
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -142,13 +175,30 @@ func (c *Client) Get(resources ResourceList) (string, error) {
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for t, ot := range objs {
|
|
|
|
infos, err := c.Build(reader, false)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return "", err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, info := range infos {
|
|
|
|
|
|
|
|
objs, err = c.getSelectRelationPod(info, objs)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
c.Log("Warning: get the relation pod is failed, err:%s", err.Error())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
var keys []string
|
|
|
|
|
|
|
|
for key := range objs {
|
|
|
|
|
|
|
|
keys = append(keys, key)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
|
|
|
for _, t := range keys {
|
|
|
|
if _, err = fmt.Fprintf(buf, "==> %s\n", t); err != nil {
|
|
|
|
if _, err = fmt.Fprintf(buf, "==> %s\n", t); err != nil {
|
|
|
|
return "", err
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, o := range ot {
|
|
|
|
vk := objs[t]
|
|
|
|
if err := printer.PrintObj(o, buf); err != nil {
|
|
|
|
vk = sortTableSlice(vk)
|
|
|
|
c.Log("failed to print object type %s, object: %q :\n %v", t, o, err)
|
|
|
|
for _, resource := range vk {
|
|
|
|
|
|
|
|
if err := printer.PrintObj(resource, buf); err != nil {
|
|
|
|
|
|
|
|
c.Log("failed to print object type %s: %v", t, err)
|
|
|
|
return "", err
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -159,6 +209,47 @@ func (c *Client) Get(resources ResourceList) (string, error) {
|
|
|
|
return buf.String(), nil
|
|
|
|
return buf.String(), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (c *Client) getSelectRelationPod(info *resource.Info, objs map[string][]runtime.Object) (map[string][]runtime.Object, error) {
|
|
|
|
|
|
|
|
if info == nil {
|
|
|
|
|
|
|
|
return objs, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Log("get relation pod of object: %s/%s/%s", info.Namespace, info.Mapping.GroupVersionKind.Kind, info.Name)
|
|
|
|
|
|
|
|
selector, ok, _ := getSelectorFromObject(info.Object)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return objs, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
infos, err := c.Factory.NewBuilder().
|
|
|
|
|
|
|
|
Unstructured().
|
|
|
|
|
|
|
|
ContinueOnError().
|
|
|
|
|
|
|
|
NamespaceParam(info.Namespace).
|
|
|
|
|
|
|
|
DefaultNamespace().
|
|
|
|
|
|
|
|
ResourceTypes("pods").
|
|
|
|
|
|
|
|
LabelSelector(labels.Set(selector).AsSelector().String()).
|
|
|
|
|
|
|
|
TransformRequests(transformRequests).
|
|
|
|
|
|
|
|
Do().Infos()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return objs, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, info := range infos {
|
|
|
|
|
|
|
|
vk := "v1/Pod(related)"
|
|
|
|
|
|
|
|
objs[vk] = append(objs[vk], info.Object)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return objs, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func getSelectorFromObject(obj runtime.Object) (map[string]string, bool, error) {
|
|
|
|
|
|
|
|
typed := obj.(*unstructured.Unstructured)
|
|
|
|
|
|
|
|
kind := typed.Object["kind"]
|
|
|
|
|
|
|
|
switch kind {
|
|
|
|
|
|
|
|
case "ReplicaSet", "Deployment", "StatefulSet", "DaemonSet", "Job":
|
|
|
|
|
|
|
|
return unstructured.NestedStringMap(typed.Object, "spec", "selector", "matchLabels")
|
|
|
|
|
|
|
|
case "ReplicationController":
|
|
|
|
|
|
|
|
return unstructured.NestedStringMap(typed.Object, "spec", "selector")
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return nil, false, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func getResource(info *resource.Info) (runtime.Object, error) {
|
|
|
|
func getResource(info *resource.Info) (runtime.Object, error) {
|
|
|
|
obj, err := resource.NewHelper(info.Client, info.Mapping).Get(info.Namespace, info.Name, false)
|
|
|
|
obj, err := resource.NewHelper(info.Client, info.Mapping).Get(info.Namespace, info.Name, false)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
@ -206,12 +297,21 @@ func (c *Client) Build(reader io.Reader, validate bool) (ResourceList, error) {
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result, err := c.newBuilder().
|
|
|
|
var result ResourceList
|
|
|
|
|
|
|
|
if validate {
|
|
|
|
|
|
|
|
result, err = c.newBuilder().
|
|
|
|
Unstructured().
|
|
|
|
Unstructured().
|
|
|
|
Schema(schema).
|
|
|
|
Schema(schema).
|
|
|
|
Stream(reader, "").
|
|
|
|
Stream(reader, "").
|
|
|
|
TransformRequests(transformRequests).
|
|
|
|
TransformRequests(transformRequests).
|
|
|
|
Do().Infos()
|
|
|
|
Do().Infos()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
result, err = c.newBuilder().
|
|
|
|
|
|
|
|
Unstructured().
|
|
|
|
|
|
|
|
Schema(schema).
|
|
|
|
|
|
|
|
Stream(reader, "").
|
|
|
|
|
|
|
|
Do().Infos()
|
|
|
|
|
|
|
|
}
|
|
|
|
return result, scrubValidationError(err)
|
|
|
|
return result, scrubValidationError(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|