mirror of https://github.com/grafana/grafana
K8s: Update grafana resource metadata accessor (#89074)
parent
58f7032b39
commit
3ae95a6eb1
@ -0,0 +1,463 @@ |
||||
package utils |
||||
|
||||
import ( |
||||
"fmt" |
||||
"reflect" |
||||
"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" |
||||
) |
||||
|
||||
// Annotation keys
|
||||
|
||||
const AnnoKeyCreatedBy = "grafana.app/createdBy" |
||||
const AnnoKeyUpdatedTimestamp = "grafana.app/updatedTimestamp" |
||||
const AnnoKeyUpdatedBy = "grafana.app/updatedBy" |
||||
const AnnoKeyFolder = "grafana.app/folder" |
||||
const AnnoKeySlug = "grafana.app/slug" |
||||
|
||||
// Identify where values came from
|
||||
|
||||
const AnnoKeyOriginName = "grafana.app/originName" |
||||
const AnnoKeyOriginPath = "grafana.app/originPath" |
||||
const AnnoKeyOriginKey = "grafana.app/originKey" |
||||
const AnnoKeyOriginTimestamp = "grafana.app/originTimestamp" |
||||
|
||||
// ResourceOriginInfo is saved in annotations. This is used to identify where the resource came from
|
||||
// This object can model the same data as our existing provisioning table or a more general git sync
|
||||
type ResourceOriginInfo struct { |
||||
// Name of the origin/provisioning source
|
||||
Name string `json:"name,omitempty"` |
||||
|
||||
// The path within the named origin above (external_id in the existing dashboard provisioing)
|
||||
Path string `json:"path,omitempty"` |
||||
|
||||
// Verification/identification key (check_sum in existing dashboard provisioning)
|
||||
Key string `json:"key,omitempty"` |
||||
|
||||
// Origin modification timestamp when the resource was saved
|
||||
// This will be before the resource updated time
|
||||
Timestamp *time.Time `json:"time,omitempty"` |
||||
|
||||
// Avoid extending
|
||||
_ any `json:"-"` |
||||
} |
||||
|
||||
// Accessor functions for k8s objects
|
||||
type GrafanaMetaAccessor interface { |
||||
metav1.Object |
||||
|
||||
GetGroupVersionKind() schema.GroupVersionKind |
||||
|
||||
GetUpdatedTimestamp() (*time.Time, error) |
||||
SetUpdatedTimestamp(v *time.Time) |
||||
SetUpdatedTimestampMillis(unix int64) |
||||
GetCreatedBy() string |
||||
SetCreatedBy(user string) |
||||
GetUpdatedBy() string |
||||
SetUpdatedBy(user string) |
||||
GetFolder() string |
||||
SetFolder(uid string) |
||||
GetSlug() string |
||||
SetSlug(v string) |
||||
|
||||
GetOriginInfo() (*ResourceOriginInfo, error) |
||||
SetOriginInfo(info *ResourceOriginInfo) |
||||
GetOriginName() string |
||||
GetOriginPath() string |
||||
GetOriginKey() string |
||||
GetOriginTimestamp() (*time.Time, error) |
||||
|
||||
// Find a title in the object
|
||||
// This will reflect the object and try to get:
|
||||
// * spec.title
|
||||
// * spec.name
|
||||
// * title
|
||||
// and return an empty string if nothing was found
|
||||
FindTitle(defaultTitle string) string |
||||
} |
||||
|
||||
var _ GrafanaMetaAccessor = (*grafanaMetaAccessor)(nil) |
||||
|
||||
type grafanaMetaAccessor struct { |
||||
raw interface{} // the original object (it implements metav1.Object)
|
||||
obj metav1.Object |
||||
r reflect.Value |
||||
} |
||||
|
||||
// Accessor takes an arbitrary object pointer and returns meta.Interface.
|
||||
// obj must be a pointer to an API type. An error is returned if the minimum
|
||||
// required fields are missing. Fields that are not required return the default
|
||||
// value and are a no-op if set.
|
||||
func MetaAccessor(raw interface{}) (GrafanaMetaAccessor, error) { |
||||
obj, err := meta.Accessor(raw) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
// look for Spec.Title or Spec.Name
|
||||
r := reflect.ValueOf(raw) |
||||
if r.Kind() == reflect.Ptr || r.Kind() == reflect.Interface { |
||||
r = r.Elem() |
||||
} |
||||
return &grafanaMetaAccessor{raw, obj, r}, nil |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) Object() metav1.Object { |
||||
return m.obj |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) set(key string, val string) { |
||||
anno := m.obj.GetAnnotations() |
||||
if val == "" { |
||||
if anno != nil { |
||||
delete(anno, key) |
||||
} |
||||
} else { |
||||
if anno == nil { |
||||
anno = make(map[string]string) |
||||
} |
||||
anno[key] = val |
||||
} |
||||
m.obj.SetAnnotations(anno) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) get(key string) string { |
||||
return m.obj.GetAnnotations()[key] |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetUpdatedTimestamp() (*time.Time, error) { |
||||
v, ok := m.obj.GetAnnotations()[AnnoKeyUpdatedTimestamp] |
||||
if !ok || v == "" { |
||||
return nil, nil |
||||
} |
||||
t, err := time.Parse(time.RFC3339, v) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("invalid updated timestamp: %s", err.Error()) |
||||
} |
||||
t = t.UTC() |
||||
return &t, nil |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetUpdatedTimestampMillis(v int64) { |
||||
if v > 0 { |
||||
t := time.UnixMilli(v) |
||||
m.SetUpdatedTimestamp(&t) |
||||
} else { |
||||
m.set(AnnoKeyUpdatedTimestamp, "") // will clear the annotation
|
||||
} |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetUpdatedTimestamp(v *time.Time) { |
||||
txt := "" |
||||
if v != nil && v.Unix() != 0 { |
||||
txt = v.UTC().Format(time.RFC3339) |
||||
} |
||||
m.set(AnnoKeyUpdatedTimestamp, txt) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetCreatedBy() string { |
||||
return m.get(AnnoKeyCreatedBy) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetCreatedBy(user string) { |
||||
m.set(AnnoKeyCreatedBy, user) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetUpdatedBy() string { |
||||
return m.get(AnnoKeyUpdatedBy) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetUpdatedBy(user string) { |
||||
m.set(AnnoKeyUpdatedBy, user) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetFolder() string { |
||||
return m.get(AnnoKeyFolder) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetFolder(uid string) { |
||||
m.set(AnnoKeyFolder, uid) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetSlug() string { |
||||
return m.get(AnnoKeySlug) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetSlug(v string) { |
||||
m.set(AnnoKeySlug, v) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) SetOriginInfo(info *ResourceOriginInfo) { |
||||
anno := m.obj.GetAnnotations() |
||||
if anno == nil { |
||||
if info == nil { |
||||
return |
||||
} |
||||
anno = make(map[string]string, 0) |
||||
} |
||||
|
||||
delete(anno, AnnoKeyOriginName) |
||||
delete(anno, AnnoKeyOriginPath) |
||||
delete(anno, AnnoKeyOriginKey) |
||||
delete(anno, AnnoKeyOriginTimestamp) |
||||
if info != nil && info.Name != "" { |
||||
anno[AnnoKeyOriginName] = info.Name |
||||
if info.Path != "" { |
||||
anno[AnnoKeyOriginPath] = info.Path |
||||
} |
||||
if info.Key != "" { |
||||
anno[AnnoKeyOriginKey] = info.Key |
||||
} |
||||
if info.Timestamp != nil { |
||||
anno[AnnoKeyOriginTimestamp] = info.Timestamp.UTC().Format(time.RFC3339) |
||||
} |
||||
} |
||||
m.obj.SetAnnotations(anno) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetOriginInfo() (*ResourceOriginInfo, error) { |
||||
v, ok := m.obj.GetAnnotations()[AnnoKeyOriginName] |
||||
if !ok { |
||||
return nil, nil |
||||
} |
||||
t, err := m.GetOriginTimestamp() |
||||
return &ResourceOriginInfo{ |
||||
Name: v, |
||||
Path: m.GetOriginPath(), |
||||
Key: m.GetOriginKey(), |
||||
Timestamp: t, |
||||
}, err |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetOriginName() string { |
||||
return m.get(AnnoKeyOriginName) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetOriginPath() string { |
||||
return m.get(AnnoKeyOriginPath) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetOriginKey() string { |
||||
return m.get(AnnoKeyOriginKey) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetOriginTimestamp() (*time.Time, error) { |
||||
v, ok := m.obj.GetAnnotations()[AnnoKeyOriginTimestamp] |
||||
if !ok || v == "" { |
||||
return nil, nil |
||||
} |
||||
t, err := time.Parse(time.RFC3339, v) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("invalid origin timestamp: %s", err.Error()) |
||||
} |
||||
return &t, nil |
||||
} |
||||
|
||||
// GetAnnotations implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetAnnotations() map[string]string { |
||||
return m.obj.GetAnnotations() |
||||
} |
||||
|
||||
// GetCreationTimestamp implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetCreationTimestamp() metav1.Time { |
||||
return m.obj.GetCreationTimestamp() |
||||
} |
||||
|
||||
// GetDeletionGracePeriodSeconds implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetDeletionGracePeriodSeconds() *int64 { |
||||
return m.obj.GetDeletionGracePeriodSeconds() |
||||
} |
||||
|
||||
// GetDeletionTimestamp implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetDeletionTimestamp() *metav1.Time { |
||||
return m.obj.GetDeletionTimestamp() |
||||
} |
||||
|
||||
// GetFinalizers implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetFinalizers() []string { |
||||
return m.obj.GetFinalizers() |
||||
} |
||||
|
||||
// GetGenerateName implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetGenerateName() string { |
||||
return m.obj.GetGenerateName() |
||||
} |
||||
|
||||
// GetGeneration implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetGeneration() int64 { |
||||
return m.obj.GetGeneration() |
||||
} |
||||
|
||||
// GetLabels implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetLabels() map[string]string { |
||||
return m.obj.GetLabels() |
||||
} |
||||
|
||||
// GetManagedFields implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetManagedFields() []metav1.ManagedFieldsEntry { |
||||
return m.obj.GetManagedFields() |
||||
} |
||||
|
||||
// GetName implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetName() string { |
||||
return m.obj.GetName() |
||||
} |
||||
|
||||
// GetNamespace implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetNamespace() string { |
||||
return m.obj.GetNamespace() |
||||
} |
||||
|
||||
// GetOwnerReferences implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetOwnerReferences() []metav1.OwnerReference { |
||||
return m.obj.GetOwnerReferences() |
||||
} |
||||
|
||||
// GetResourceVersion implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetResourceVersion() string { |
||||
return m.obj.GetResourceVersion() |
||||
} |
||||
|
||||
// GetSelfLink implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetSelfLink() string { |
||||
return m.obj.GetSelfLink() |
||||
} |
||||
|
||||
// GetUID implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) GetUID() types.UID { |
||||
return m.obj.GetUID() |
||||
} |
||||
|
||||
// SetAnnotations implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetAnnotations(annotations map[string]string) { |
||||
m.obj.SetAnnotations(annotations) |
||||
} |
||||
|
||||
// SetCreationTimestamp implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetCreationTimestamp(timestamp metav1.Time) { |
||||
m.obj.SetCreationTimestamp(timestamp) |
||||
} |
||||
|
||||
// SetDeletionGracePeriodSeconds implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetDeletionGracePeriodSeconds(v *int64) { |
||||
m.obj.SetDeletionGracePeriodSeconds(v) |
||||
} |
||||
|
||||
// SetDeletionTimestamp implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetDeletionTimestamp(timestamp *metav1.Time) { |
||||
m.obj.SetDeletionTimestamp(timestamp) |
||||
} |
||||
|
||||
// SetFinalizers implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetFinalizers(finalizers []string) { |
||||
m.obj.SetFinalizers(finalizers) |
||||
} |
||||
|
||||
// SetGenerateName implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetGenerateName(name string) { |
||||
m.obj.SetGenerateName(name) |
||||
} |
||||
|
||||
// SetGeneration implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetGeneration(generation int64) { |
||||
m.obj.SetGeneration(generation) |
||||
} |
||||
|
||||
// SetLabels implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetLabels(labels map[string]string) { |
||||
m.obj.SetLabels(labels) |
||||
} |
||||
|
||||
// SetManagedFields implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetManagedFields(managedFields []metav1.ManagedFieldsEntry) { |
||||
m.obj.SetManagedFields(managedFields) |
||||
} |
||||
|
||||
// SetName implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetName(name string) { |
||||
m.obj.SetName(name) |
||||
} |
||||
|
||||
// SetNamespace implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetNamespace(namespace string) { |
||||
m.obj.SetNamespace(namespace) |
||||
} |
||||
|
||||
// SetOwnerReferences implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetOwnerReferences(v []metav1.OwnerReference) { |
||||
m.obj.SetOwnerReferences(v) |
||||
} |
||||
|
||||
// SetResourceVersion implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetResourceVersion(version string) { |
||||
m.obj.SetResourceVersion(version) |
||||
} |
||||
|
||||
// SetSelfLink implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetSelfLink(selfLink string) { |
||||
m.obj.SetSelfLink(selfLink) |
||||
} |
||||
|
||||
// SetUID implements GrafanaMetaAccessor.
|
||||
func (m *grafanaMetaAccessor) SetUID(uid types.UID) { |
||||
m.obj.SetUID(uid) |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) GetGroupVersionKind() schema.GroupVersionKind { |
||||
obj, ok := m.raw.(runtime.Object) |
||||
if ok { |
||||
return obj.GetObjectKind().GroupVersionKind() |
||||
} |
||||
|
||||
gvk := schema.GroupVersionKind{} |
||||
apiVersion := "" |
||||
|
||||
typ, ok := m.raw.(metav1.Type) |
||||
if ok { |
||||
apiVersion = typ.GetAPIVersion() |
||||
gvk.Kind = typ.GetKind() |
||||
} else { |
||||
val := m.r.FieldByName("APIVersion") |
||||
if val.IsValid() && val.Kind() == reflect.String { |
||||
apiVersion = val.String() |
||||
} |
||||
val = m.r.FieldByName("Kind") |
||||
if val.IsValid() && val.Kind() == reflect.String { |
||||
gvk.Kind = val.String() |
||||
} |
||||
} |
||||
if apiVersion != "" { |
||||
gv, err := schema.ParseGroupVersion(apiVersion) |
||||
if err == nil { |
||||
gvk.Group = gv.Group |
||||
gvk.Version = gv.Version |
||||
} |
||||
} |
||||
return gvk |
||||
} |
||||
|
||||
func (m *grafanaMetaAccessor) FindTitle(defaultTitle string) string { |
||||
// look for Spec.Title or Spec.Name
|
||||
spec := m.r.FieldByName("Spec") |
||||
if spec.Kind() == reflect.Struct { |
||||
title := spec.FieldByName("Title") |
||||
if title.IsValid() && title.Kind() == reflect.String { |
||||
return title.String() |
||||
} |
||||
name := spec.FieldByName("Name") |
||||
if name.IsValid() && name.Kind() == reflect.String { |
||||
return name.String() |
||||
} |
||||
} |
||||
|
||||
title := m.r.FieldByName("Title") |
||||
if title.IsValid() && title.Kind() == reflect.String { |
||||
return title.String() |
||||
} |
||||
return defaultTitle |
||||
} |
||||
@ -1,268 +0,0 @@ |
||||
package utils |
||||
|
||||
import ( |
||||
"fmt" |
||||
"reflect" |
||||
"time" |
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta" |
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||
) |
||||
|
||||
// Annotation keys
|
||||
|
||||
const AnnoKeyCreatedBy = "grafana.app/createdBy" |
||||
const AnnoKeyUpdatedTimestamp = "grafana.app/updatedTimestamp" |
||||
const AnnoKeyUpdatedBy = "grafana.app/updatedBy" |
||||
const AnnoKeyFolder = "grafana.app/folder" |
||||
const AnnoKeySlug = "grafana.app/slug" |
||||
|
||||
// Identify where values came from
|
||||
|
||||
const AnnoKeyOriginName = "grafana.app/originName" |
||||
const AnnoKeyOriginPath = "grafana.app/originPath" |
||||
const AnnoKeyOriginKey = "grafana.app/originKey" |
||||
const AnnoKeyOriginTimestamp = "grafana.app/originTimestamp" |
||||
|
||||
// ResourceOriginInfo is saved in annotations. This is used to identify where the resource came from
|
||||
// This object can model the same data as our existing provisioning table or a more general git sync
|
||||
type ResourceOriginInfo struct { |
||||
// Name of the origin/provisioning source
|
||||
Name string `json:"name,omitempty"` |
||||
|
||||
// The path within the named origin above (external_id in the existing dashboard provisioing)
|
||||
Path string `json:"path,omitempty"` |
||||
|
||||
// Verification/identification key (check_sum in existing dashboard provisioning)
|
||||
Key string `json:"key,omitempty"` |
||||
|
||||
// Origin modification timestamp when the resource was saved
|
||||
// This will be before the resource updated time
|
||||
Timestamp *time.Time `json:"time,omitempty"` |
||||
|
||||
// Avoid extending
|
||||
_ any `json:"-"` |
||||
} |
||||
|
||||
// Accessor functions for k8s objects
|
||||
type GrafanaResourceMetaAccessor interface { |
||||
GetUpdatedTimestamp() (*time.Time, error) |
||||
SetUpdatedTimestamp(v *time.Time) |
||||
SetUpdatedTimestampMillis(unix int64) |
||||
GetCreatedBy() string |
||||
SetCreatedBy(user string) |
||||
GetUpdatedBy() string |
||||
SetUpdatedBy(user string) |
||||
GetFolder() string |
||||
SetFolder(uid string) |
||||
GetSlug() string |
||||
SetSlug(v string) |
||||
|
||||
GetOriginInfo() (*ResourceOriginInfo, error) |
||||
SetOriginInfo(info *ResourceOriginInfo) |
||||
GetOriginName() string |
||||
GetOriginPath() string |
||||
GetOriginKey() string |
||||
GetOriginTimestamp() (*time.Time, error) |
||||
|
||||
// Find a title in the object
|
||||
// This will reflect the object and try to get:
|
||||
// * spec.title
|
||||
// * spec.name
|
||||
// * title
|
||||
// and return an empty string if nothing was found
|
||||
FindTitle(defaultTitle string) string |
||||
} |
||||
|
||||
var _ GrafanaResourceMetaAccessor = (*grafanaResourceMetaAccessor)(nil) |
||||
|
||||
type grafanaResourceMetaAccessor struct { |
||||
raw interface{} // the original object (it implements metav1.Object)
|
||||
obj metav1.Object |
||||
} |
||||
|
||||
// Accessor takes an arbitrary object pointer and returns meta.Interface.
|
||||
// obj must be a pointer to an API type. An error is returned if the minimum
|
||||
// required fields are missing. Fields that are not required return the default
|
||||
// value and are a no-op if set.
|
||||
func MetaAccessor(raw interface{}) (GrafanaResourceMetaAccessor, error) { |
||||
obj, err := meta.Accessor(raw) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &grafanaResourceMetaAccessor{raw, obj}, nil |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) set(key string, val string) { |
||||
anno := m.obj.GetAnnotations() |
||||
if val == "" { |
||||
if anno != nil { |
||||
delete(anno, key) |
||||
} |
||||
} else { |
||||
if anno == nil { |
||||
anno = make(map[string]string) |
||||
} |
||||
anno[key] = val |
||||
} |
||||
m.obj.SetAnnotations(anno) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) get(key string) string { |
||||
return m.obj.GetAnnotations()[key] |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetUpdatedTimestamp() (*time.Time, error) { |
||||
v, ok := m.obj.GetAnnotations()[AnnoKeyUpdatedTimestamp] |
||||
if !ok || v == "" { |
||||
return nil, nil |
||||
} |
||||
t, err := time.Parse(time.RFC3339, v) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("invalid updated timestamp: %s", err.Error()) |
||||
} |
||||
t = t.UTC() |
||||
return &t, nil |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetUpdatedTimestampMillis(v int64) { |
||||
if v > 0 { |
||||
t := time.UnixMilli(v) |
||||
m.SetUpdatedTimestamp(&t) |
||||
} else { |
||||
m.set(AnnoKeyUpdatedTimestamp, "") // will clear the annotation
|
||||
} |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetUpdatedTimestamp(v *time.Time) { |
||||
txt := "" |
||||
if v != nil && v.Unix() != 0 { |
||||
txt = v.UTC().Format(time.RFC3339) |
||||
} |
||||
m.set(AnnoKeyUpdatedTimestamp, txt) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetCreatedBy() string { |
||||
return m.get(AnnoKeyCreatedBy) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetCreatedBy(user string) { |
||||
m.set(AnnoKeyCreatedBy, user) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetUpdatedBy() string { |
||||
return m.get(AnnoKeyUpdatedBy) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetUpdatedBy(user string) { |
||||
m.set(AnnoKeyUpdatedBy, user) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetFolder() string { |
||||
return m.get(AnnoKeyFolder) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetFolder(uid string) { |
||||
m.set(AnnoKeyFolder, uid) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetSlug() string { |
||||
return m.get(AnnoKeySlug) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetSlug(v string) { |
||||
m.set(AnnoKeySlug, v) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) SetOriginInfo(info *ResourceOriginInfo) { |
||||
anno := m.obj.GetAnnotations() |
||||
if anno == nil { |
||||
if info == nil { |
||||
return |
||||
} |
||||
anno = make(map[string]string, 0) |
||||
} |
||||
|
||||
delete(anno, AnnoKeyOriginName) |
||||
delete(anno, AnnoKeyOriginPath) |
||||
delete(anno, AnnoKeyOriginKey) |
||||
delete(anno, AnnoKeyOriginTimestamp) |
||||
if info != nil && info.Name != "" { |
||||
anno[AnnoKeyOriginName] = info.Name |
||||
if info.Path != "" { |
||||
anno[AnnoKeyOriginPath] = info.Path |
||||
} |
||||
if info.Key != "" { |
||||
anno[AnnoKeyOriginKey] = info.Key |
||||
} |
||||
if info.Timestamp != nil { |
||||
anno[AnnoKeyOriginTimestamp] = info.Timestamp.UTC().Format(time.RFC3339) |
||||
} |
||||
} |
||||
m.obj.SetAnnotations(anno) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetOriginInfo() (*ResourceOriginInfo, error) { |
||||
v, ok := m.obj.GetAnnotations()[AnnoKeyOriginName] |
||||
if !ok { |
||||
return nil, nil |
||||
} |
||||
t, err := m.GetOriginTimestamp() |
||||
return &ResourceOriginInfo{ |
||||
Name: v, |
||||
Path: m.GetOriginPath(), |
||||
Key: m.GetOriginKey(), |
||||
Timestamp: t, |
||||
}, err |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetOriginName() string { |
||||
return m.get(AnnoKeyOriginName) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetOriginPath() string { |
||||
return m.get(AnnoKeyOriginPath) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetOriginKey() string { |
||||
return m.get(AnnoKeyOriginKey) |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) GetOriginTimestamp() (*time.Time, error) { |
||||
v, ok := m.obj.GetAnnotations()[AnnoKeyOriginTimestamp] |
||||
if !ok || v == "" { |
||||
return nil, nil |
||||
} |
||||
t, err := time.Parse(time.RFC3339, v) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("invalid origin timestamp: %s", err.Error()) |
||||
} |
||||
return &t, nil |
||||
} |
||||
|
||||
func (m *grafanaResourceMetaAccessor) FindTitle(defaultTitle string) string { |
||||
// look for Spec.Title or Spec.Name
|
||||
r := reflect.ValueOf(m.raw) |
||||
if r.Kind() == reflect.Ptr || r.Kind() == reflect.Interface { |
||||
r = r.Elem() |
||||
} |
||||
if r.Kind() == reflect.Struct { |
||||
spec := r.FieldByName("Spec") |
||||
if spec.Kind() == reflect.Struct { |
||||
title := spec.FieldByName("Title") |
||||
if title.IsValid() && title.Kind() == reflect.String { |
||||
return title.String() |
||||
} |
||||
name := spec.FieldByName("Name") |
||||
if name.IsValid() && name.Kind() == reflect.String { |
||||
return name.String() |
||||
} |
||||
} |
||||
|
||||
title := r.FieldByName("Title") |
||||
if title.IsValid() && title.Kind() == reflect.String { |
||||
return title.String() |
||||
} |
||||
} |
||||
return defaultTitle |
||||
} |
||||
Loading…
Reference in new issue