117 lines
2.7 KiB
Go
117 lines
2.7 KiB
Go
package resource
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/derailed/k9s/internal/k8s"
|
|
log "github.com/sirupsen/logrus"
|
|
yaml "gopkg.in/yaml.v2"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
)
|
|
|
|
// CRD tracks a kubernetes resource.
|
|
type CRD struct {
|
|
*Base
|
|
instance *unstructured.Unstructured
|
|
}
|
|
|
|
// NewCRDList returns a new resource list.
|
|
func NewCRDList(ns string) List {
|
|
return NewCRDListWithArgs(ns, NewCRD())
|
|
}
|
|
|
|
// NewCRDListWithArgs returns a new resource list.
|
|
func NewCRDListWithArgs(ns string, res Resource) List {
|
|
return newList(NotNamespaced, "crd", res, CRUDAccess|DescribeAccess)
|
|
}
|
|
|
|
// NewCRD instantiates a new CRD.
|
|
func NewCRD() *CRD {
|
|
return NewCRDWithArgs(k8s.NewCRD())
|
|
}
|
|
|
|
// NewCRDWithArgs instantiates a new Context.
|
|
func NewCRDWithArgs(r k8s.Res) *CRD {
|
|
ctx := &CRD{
|
|
Base: &Base{
|
|
caller: r,
|
|
},
|
|
}
|
|
ctx.creator = ctx
|
|
return ctx
|
|
}
|
|
|
|
// NewInstance builds a new Context instance from a k8s resource.
|
|
func (r *CRD) NewInstance(i interface{}) Columnar {
|
|
c := NewCRD()
|
|
switch i.(type) {
|
|
case *unstructured.Unstructured:
|
|
c.instance = i.(*unstructured.Unstructured)
|
|
case unstructured.Unstructured:
|
|
ii := i.(unstructured.Unstructured)
|
|
c.instance = &ii
|
|
default:
|
|
log.Fatalf("unknown context type %#v", i)
|
|
}
|
|
meta := c.instance.Object["metadata"].(map[string]interface{})
|
|
c.path = meta["name"].(string)
|
|
|
|
return c
|
|
}
|
|
|
|
// Marshal a resource.
|
|
func (r *CRD) Marshal(path string) (string, error) {
|
|
ns, n := namespaced(path)
|
|
i, err := r.caller.Get(ns, n)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
raw, err := yaml.Marshal(i)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(raw), nil
|
|
// BOZO!! Need to figure out apiGroup+Version
|
|
// return r.marshalObject(i.(*unstructured.Unstructured))
|
|
}
|
|
|
|
// Header return the resource header.
|
|
func (*CRD) Header(ns string) Row {
|
|
return Row{"NAME", "AGE"}
|
|
}
|
|
|
|
// Fields retrieves displayable fields.
|
|
func (r *CRD) Fields(ns string) Row {
|
|
ff := make(Row, 0, len(r.Header(ns)))
|
|
|
|
i := r.instance
|
|
meta := i.Object["metadata"].(map[string]interface{})
|
|
t, err := time.Parse(time.RFC3339, meta["creationTimestamp"].(string))
|
|
if err != nil {
|
|
log.Error("Fields timestamp", err)
|
|
}
|
|
return append(ff, meta["name"].(string), toAge(metav1.Time{t}))
|
|
}
|
|
|
|
// ExtFields returns extended fields.
|
|
func (r *CRD) ExtFields() Properties {
|
|
var (
|
|
pp = Properties{}
|
|
i = r.instance
|
|
)
|
|
|
|
meta := i.Object["metadata"].(map[string]interface{})
|
|
|
|
if spec, ok := i.Object["spec"].(map[string]interface{}); ok {
|
|
pp["name"] = meta["name"]
|
|
pp["group"], pp["version"] = spec["group"], spec["version"]
|
|
names := spec["names"].(map[string]interface{})
|
|
pp["kind"] = names["kind"]
|
|
pp["singular"], pp["plural"] = names["singular"], names["plural"]
|
|
pp["aliases"] = names["shortNames"]
|
|
}
|
|
return pp
|
|
}
|