mirror of
https://github.com/grafana/grafana.git
synced 2024-12-02 05:29:42 -06:00
89f3b70e17
* add support for listing resource history * make watch handle custom label selectors properly * fix tests * Apply suggestions from code review Co-authored-by: Diego Augusto Molina <diegoaugustomolina@gmail.com> * properly handle special characters in json label matcher * tidy up --------- Co-authored-by: Diego Augusto Molina <diegoaugustomolina@gmail.com>
184 lines
4.5 KiB
Go
184 lines
4.5 KiB
Go
package entity
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
"time"
|
|
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/apiserver/pkg/endpoints/request"
|
|
|
|
"github.com/grafana/grafana/pkg/services/apiserver/utils"
|
|
entityStore "github.com/grafana/grafana/pkg/services/store/entity"
|
|
)
|
|
|
|
func entityToResource(rsp *entityStore.Entity, res runtime.Object, codec runtime.Codec) error {
|
|
var err error
|
|
|
|
// Read the body first -- it includes old resourceVersion!
|
|
if len(rsp.Body) > 0 {
|
|
decoded, _, err := codec.Decode(rsp.Body, &schema.GroupVersionKind{Group: rsp.Group, Version: rsp.GroupVersion}, res)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res = decoded
|
|
}
|
|
|
|
metaAccessor, err := meta.Accessor(res)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(rsp.Meta) > 0 {
|
|
err = json.Unmarshal(rsp.Meta, res)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
metaAccessor.SetName(rsp.Name)
|
|
metaAccessor.SetNamespace(rsp.Namespace)
|
|
metaAccessor.SetUID(types.UID(rsp.Guid))
|
|
metaAccessor.SetResourceVersion(fmt.Sprintf("%d", rsp.ResourceVersion))
|
|
metaAccessor.SetCreationTimestamp(metav1.Unix(rsp.CreatedAt/1000, rsp.CreatedAt%1000*1000000))
|
|
|
|
grafanaAccessor, err := utils.MetaAccessor(metaAccessor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rsp.Folder != "" {
|
|
grafanaAccessor.SetFolder(rsp.Folder)
|
|
}
|
|
if rsp.CreatedBy != "" {
|
|
grafanaAccessor.SetCreatedBy(rsp.CreatedBy)
|
|
}
|
|
if rsp.UpdatedBy != "" {
|
|
grafanaAccessor.SetUpdatedBy(rsp.UpdatedBy)
|
|
}
|
|
if rsp.UpdatedAt != 0 {
|
|
updatedAt := time.UnixMilli(rsp.UpdatedAt).UTC()
|
|
grafanaAccessor.SetUpdatedTimestamp(&updatedAt)
|
|
}
|
|
grafanaAccessor.SetSlug(rsp.Slug)
|
|
grafanaAccessor.SetAction(rsp.Action.String())
|
|
|
|
if rsp.Origin != nil {
|
|
originTime := time.UnixMilli(rsp.Origin.Time).UTC()
|
|
grafanaAccessor.SetOriginInfo(&utils.ResourceOriginInfo{
|
|
Name: rsp.Origin.Source,
|
|
Key: rsp.Origin.Key,
|
|
// Path: rsp.Origin.Path,
|
|
Timestamp: &originTime,
|
|
})
|
|
}
|
|
|
|
if len(rsp.Labels) > 0 {
|
|
metaAccessor.SetLabels(rsp.Labels)
|
|
}
|
|
|
|
// TODO fields?
|
|
|
|
if len(rsp.Status) > 0 {
|
|
status := reflect.ValueOf(res).Elem().FieldByName("Status")
|
|
if status != (reflect.Value{}) && status.CanSet() {
|
|
err = json.Unmarshal(rsp.Status, status.Addr().Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceToEntity(res runtime.Object, requestInfo *request.RequestInfo, codec runtime.Codec) (*entityStore.Entity, error) {
|
|
metaAccessor, err := meta.Accessor(res)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
grafanaAccessor, err := utils.MetaAccessor(metaAccessor)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rv, _ := strconv.ParseInt(metaAccessor.GetResourceVersion(), 10, 64)
|
|
|
|
k := &entityStore.Key{
|
|
Group: requestInfo.APIGroup,
|
|
Resource: requestInfo.Resource,
|
|
Namespace: requestInfo.Namespace,
|
|
Name: metaAccessor.GetName(),
|
|
Subresource: requestInfo.Subresource,
|
|
}
|
|
|
|
rsp := &entityStore.Entity{
|
|
Group: k.Group,
|
|
GroupVersion: requestInfo.APIVersion,
|
|
Resource: k.Resource,
|
|
Subresource: k.Subresource,
|
|
Namespace: k.Namespace,
|
|
Key: k.String(),
|
|
Name: k.Name,
|
|
Guid: string(metaAccessor.GetUID()),
|
|
ResourceVersion: rv,
|
|
Folder: grafanaAccessor.GetFolder(),
|
|
CreatedAt: metaAccessor.GetCreationTimestamp().Time.UnixMilli(),
|
|
CreatedBy: grafanaAccessor.GetCreatedBy(),
|
|
UpdatedBy: grafanaAccessor.GetUpdatedBy(),
|
|
Slug: grafanaAccessor.GetSlug(),
|
|
Title: grafanaAccessor.FindTitle(metaAccessor.GetName()),
|
|
Origin: &entityStore.EntityOriginInfo{
|
|
Source: grafanaAccessor.GetOriginName(),
|
|
Key: grafanaAccessor.GetOriginKey(),
|
|
// Path: grafanaAccessor.GetOriginPath(),
|
|
},
|
|
Labels: metaAccessor.GetLabels(),
|
|
}
|
|
|
|
t, err := grafanaAccessor.GetUpdatedTimestamp()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if t != nil {
|
|
rsp.UpdatedAt = t.UnixMilli()
|
|
}
|
|
|
|
t, err = grafanaAccessor.GetOriginTimestamp()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if t != nil {
|
|
rsp.Origin.Time = t.UnixMilli()
|
|
}
|
|
|
|
rsp.Meta, err = json.Marshal(meta.AsPartialObjectMetadata(metaAccessor))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
err = codec.Encode(res, &buf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rsp.Body = buf.Bytes()
|
|
|
|
status := reflect.ValueOf(res).Elem().FieldByName("Status")
|
|
if status != (reflect.Value{}) {
|
|
rsp.Status, err = json.Marshal(status.Interface())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return rsp, nil
|
|
}
|