mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
K8s: Rename origin.key to origin.hash (#89337)
This commit is contained in:
parent
b0c043de5f
commit
9b7f9ae22e
@ -25,7 +25,7 @@ const AnnoKeySlug = "grafana.app/slug"
|
|||||||
|
|
||||||
const AnnoKeyOriginName = "grafana.app/originName"
|
const AnnoKeyOriginName = "grafana.app/originName"
|
||||||
const AnnoKeyOriginPath = "grafana.app/originPath"
|
const AnnoKeyOriginPath = "grafana.app/originPath"
|
||||||
const AnnoKeyOriginKey = "grafana.app/originKey"
|
const AnnoKeyOriginHash = "grafana.app/originHash"
|
||||||
const AnnoKeyOriginTimestamp = "grafana.app/originTimestamp"
|
const AnnoKeyOriginTimestamp = "grafana.app/originTimestamp"
|
||||||
|
|
||||||
// ResourceOriginInfo is saved in annotations. This is used to identify where the resource came from
|
// ResourceOriginInfo is saved in annotations. This is used to identify where the resource came from
|
||||||
@ -37,8 +37,8 @@ type ResourceOriginInfo struct {
|
|||||||
// The path within the named origin above (external_id in the existing dashboard provisioing)
|
// The path within the named origin above (external_id in the existing dashboard provisioing)
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
|
|
||||||
// Verification/identification key (check_sum in existing dashboard provisioning)
|
// Verification/identification hash (check_sum in existing dashboard provisioning)
|
||||||
Key string `json:"key,omitempty"`
|
Hash string `json:"hash,omitempty"`
|
||||||
|
|
||||||
// Origin modification timestamp when the resource was saved
|
// Origin modification timestamp when the resource was saved
|
||||||
// This will be before the resource updated time
|
// This will be before the resource updated time
|
||||||
@ -77,7 +77,7 @@ type GrafanaMetaAccessor interface {
|
|||||||
SetOriginInfo(info *ResourceOriginInfo)
|
SetOriginInfo(info *ResourceOriginInfo)
|
||||||
GetOriginName() string
|
GetOriginName() string
|
||||||
GetOriginPath() string
|
GetOriginPath() string
|
||||||
GetOriginKey() string
|
GetOriginHash() string
|
||||||
GetOriginTimestamp() (*time.Time, error)
|
GetOriginTimestamp() (*time.Time, error)
|
||||||
|
|
||||||
// Find a title in the object
|
// Find a title in the object
|
||||||
@ -219,15 +219,15 @@ func (m *grafanaMetaAccessor) SetOriginInfo(info *ResourceOriginInfo) {
|
|||||||
|
|
||||||
delete(anno, AnnoKeyOriginName)
|
delete(anno, AnnoKeyOriginName)
|
||||||
delete(anno, AnnoKeyOriginPath)
|
delete(anno, AnnoKeyOriginPath)
|
||||||
delete(anno, AnnoKeyOriginKey)
|
delete(anno, AnnoKeyOriginHash)
|
||||||
delete(anno, AnnoKeyOriginTimestamp)
|
delete(anno, AnnoKeyOriginTimestamp)
|
||||||
if info != nil && info.Name != "" {
|
if info != nil && info.Name != "" {
|
||||||
anno[AnnoKeyOriginName] = info.Name
|
anno[AnnoKeyOriginName] = info.Name
|
||||||
if info.Path != "" {
|
if info.Path != "" {
|
||||||
anno[AnnoKeyOriginPath] = info.Path
|
anno[AnnoKeyOriginPath] = info.Path
|
||||||
}
|
}
|
||||||
if info.Key != "" {
|
if info.Hash != "" {
|
||||||
anno[AnnoKeyOriginKey] = info.Key
|
anno[AnnoKeyOriginHash] = info.Hash
|
||||||
}
|
}
|
||||||
if info.Timestamp != nil {
|
if info.Timestamp != nil {
|
||||||
anno[AnnoKeyOriginTimestamp] = info.Timestamp.UTC().Format(time.RFC3339)
|
anno[AnnoKeyOriginTimestamp] = info.Timestamp.UTC().Format(time.RFC3339)
|
||||||
@ -245,7 +245,7 @@ func (m *grafanaMetaAccessor) GetOriginInfo() (*ResourceOriginInfo, error) {
|
|||||||
return &ResourceOriginInfo{
|
return &ResourceOriginInfo{
|
||||||
Name: v,
|
Name: v,
|
||||||
Path: m.GetOriginPath(),
|
Path: m.GetOriginPath(),
|
||||||
Key: m.GetOriginKey(),
|
Hash: m.GetOriginHash(),
|
||||||
Timestamp: t,
|
Timestamp: t,
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
@ -258,8 +258,8 @@ func (m *grafanaMetaAccessor) GetOriginPath() string {
|
|||||||
return m.get(AnnoKeyOriginPath)
|
return m.get(AnnoKeyOriginPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *grafanaMetaAccessor) GetOriginKey() string {
|
func (m *grafanaMetaAccessor) GetOriginHash() string {
|
||||||
return m.get(AnnoKeyOriginKey)
|
return m.get(AnnoKeyOriginHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *grafanaMetaAccessor) GetOriginTimestamp() (*time.Time, error) {
|
func (m *grafanaMetaAccessor) GetOriginTimestamp() (*time.Time, error) {
|
||||||
|
@ -126,7 +126,7 @@ func TestMetaAccessor(t *testing.T) {
|
|||||||
originInfo := &utils.ResourceOriginInfo{
|
originInfo := &utils.ResourceOriginInfo{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Path: "a/b/c",
|
Path: "a/b/c",
|
||||||
Key: "kkk",
|
Hash: "kkk",
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("fails for non resource objects", func(t *testing.T) {
|
t.Run("fails for non resource objects", func(t *testing.T) {
|
||||||
@ -158,7 +158,7 @@ func TestMetaAccessor(t *testing.T) {
|
|||||||
require.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"grafana.app/originName": "test",
|
"grafana.app/originName": "test",
|
||||||
"grafana.app/originPath": "a/b/c",
|
"grafana.app/originPath": "a/b/c",
|
||||||
"grafana.app/originKey": "kkk",
|
"grafana.app/originHash": "kkk",
|
||||||
"grafana.app/folder": "folderUID",
|
"grafana.app/folder": "folderUID",
|
||||||
}, res.GetAnnotations())
|
}, res.GetAnnotations())
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ func TestMetaAccessor(t *testing.T) {
|
|||||||
require.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"grafana.app/originName": "test",
|
"grafana.app/originName": "test",
|
||||||
"grafana.app/originPath": "a/b/c",
|
"grafana.app/originPath": "a/b/c",
|
||||||
"grafana.app/originKey": "kkk",
|
"grafana.app/originHash": "kkk",
|
||||||
"grafana.app/folder": "folderUID",
|
"grafana.app/folder": "folderUID",
|
||||||
}, obj.GetAnnotations())
|
}, obj.GetAnnotations())
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ func TestMetaAccessor(t *testing.T) {
|
|||||||
require.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"grafana.app/originName": "test",
|
"grafana.app/originName": "test",
|
||||||
"grafana.app/originPath": "a/b/c",
|
"grafana.app/originPath": "a/b/c",
|
||||||
"grafana.app/originKey": "kkk",
|
"grafana.app/originHash": "kkk",
|
||||||
"grafana.app/folder": "folderUID",
|
"grafana.app/folder": "folderUID",
|
||||||
}, obj2.GetAnnotations())
|
}, obj2.GetAnnotations())
|
||||||
|
|
||||||
|
@ -4,16 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/selection"
|
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DualWriterMode2 struct {
|
type DualWriterMode2 struct {
|
||||||
@ -317,29 +316,15 @@ func parseList(legacyList []runtime.Object) (metainternalversion.ListOptions, ma
|
|||||||
indexMap := map[string]int{}
|
indexMap := map[string]int{}
|
||||||
|
|
||||||
for i, obj := range legacyList {
|
for i, obj := range legacyList {
|
||||||
metaAccessor, err := utils.MetaAccessor(obj)
|
accessor, err := utils.MetaAccessor(obj)
|
||||||
if err != nil {
|
|
||||||
return options, nil, err
|
|
||||||
}
|
|
||||||
originKeys = append(originKeys, metaAccessor.GetOriginKey())
|
|
||||||
|
|
||||||
accessor, err := meta.Accessor(obj)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return options, nil, err
|
return options, nil, err
|
||||||
}
|
}
|
||||||
indexMap[accessor.GetName()] = i
|
indexMap[accessor.GetName()] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(originKeys) == 0 {
|
if len(originKeys) == 0 {
|
||||||
return options, nil, nil
|
return options, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := labels.NewRequirement(utils.AnnoKeyOriginKey, selection.In, originKeys)
|
|
||||||
if err != nil {
|
|
||||||
return options, nil, err
|
|
||||||
}
|
|
||||||
options.LabelSelector = labels.NewSelector().Add(*r)
|
|
||||||
|
|
||||||
return options, indexMap, nil
|
return options, indexMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +100,6 @@ func (a *dashboardSqlAccess) getRows(ctx context.Context, query *DashboardQuery,
|
|||||||
if query.Requirements.ListDeleted {
|
if query.Requirements.ListDeleted {
|
||||||
return nil, 0, fmt.Errorf("ListDeleted not yet supported")
|
return nil, 0, fmt.Errorf("ListDeleted not yet supported")
|
||||||
}
|
}
|
||||||
if len(query.Requirements.ListOriginKeys) > 0 {
|
|
||||||
return nil, 0, fmt.Errorf("ListOriginKeys not yet supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := readContinueToken(query)
|
token, err := readContinueToken(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -318,7 +315,7 @@ func (a *dashboardSqlAccess) scanRow(rows *sql.Rows) (*dashboardRow, error) {
|
|||||||
var origin_name sql.NullString
|
var origin_name sql.NullString
|
||||||
var origin_path sql.NullString
|
var origin_path sql.NullString
|
||||||
var origin_ts sql.NullInt64
|
var origin_ts sql.NullInt64
|
||||||
var origin_key sql.NullString
|
var origin_hash sql.NullString
|
||||||
var data []byte // the dashboard JSON
|
var data []byte // the dashboard JSON
|
||||||
var version int64
|
var version int64
|
||||||
|
|
||||||
@ -327,7 +324,7 @@ func (a *dashboardSqlAccess) scanRow(rows *sql.Rows) (*dashboardRow, error) {
|
|||||||
&created, &createdByID, &createdByName,
|
&created, &createdByID, &createdByName,
|
||||||
&updated, &updatedByID, &updatedByName,
|
&updated, &updatedByID, &updatedByName,
|
||||||
&plugin_id,
|
&plugin_id,
|
||||||
&origin_name, &origin_path, &origin_key, &origin_ts,
|
&origin_name, &origin_path, &origin_hash, &origin_ts,
|
||||||
&version,
|
&version,
|
||||||
&row.Title, &data,
|
&row.Title, &data,
|
||||||
)
|
)
|
||||||
@ -370,7 +367,7 @@ func (a *dashboardSqlAccess) scanRow(rows *sql.Rows) (*dashboardRow, error) {
|
|||||||
meta.SetOriginInfo(&utils.ResourceOriginInfo{
|
meta.SetOriginInfo(&utils.ResourceOriginInfo{
|
||||||
Name: origin_name.String,
|
Name: origin_name.String,
|
||||||
Path: originPath,
|
Path: originPath,
|
||||||
Key: origin_key.String,
|
Hash: origin_hash.String,
|
||||||
Timestamp: &ts,
|
Timestamp: &ts,
|
||||||
})
|
})
|
||||||
} else if plugin_id != "" {
|
} else if plugin_id != "" {
|
||||||
|
@ -33,7 +33,7 @@ func convertToK8sResource(v *folder.Folder, namespacer request.NamespaceMapper)
|
|||||||
if v.ID > 0 { // nolint:staticcheck
|
if v.ID > 0 { // nolint:staticcheck
|
||||||
meta.SetOriginInfo(&utils.ResourceOriginInfo{
|
meta.SetOriginInfo(&utils.ResourceOriginInfo{
|
||||||
Name: "SQL",
|
Name: "SQL",
|
||||||
Key: fmt.Sprintf("%d", v.ID), // nolint:staticcheck
|
Path: fmt.Sprintf("%d", v.ID), // nolint:staticcheck
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if v.CreatedBy > 0 {
|
if v.CreatedBy > 0 {
|
||||||
|
@ -95,7 +95,7 @@ func convertToK8sResource(v *playlistsvc.PlaylistDTO, namespacer request.Namespa
|
|||||||
createdAt := time.UnixMilli(v.CreatedAt).UTC()
|
createdAt := time.UnixMilli(v.CreatedAt).UTC()
|
||||||
meta.SetOriginInfo(&utils.ResourceOriginInfo{
|
meta.SetOriginInfo(&utils.ResourceOriginInfo{
|
||||||
Name: "SQL",
|
Name: "SQL",
|
||||||
Key: fmt.Sprintf("%d", v.Id),
|
Path: fmt.Sprintf("%d", v.Id),
|
||||||
Timestamp: &createdAt,
|
Timestamp: &createdAt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ func getLegacyID(item *unstructured.Unstructured) int64 {
|
|||||||
}
|
}
|
||||||
info, _ := meta.GetOriginInfo()
|
info, _ := meta.GetOriginInfo()
|
||||||
if info != nil && info.Name == "SQL" {
|
if info != nil && info.Name == "SQL" {
|
||||||
i, err := strconv.ParseInt(info.Key, 10, 64)
|
i, err := strconv.ParseInt(info.Path, 10, 64)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ func TestPlaylistConversion(t *testing.T) {
|
|||||||
"resourceVersion": "54321",
|
"resourceVersion": "54321",
|
||||||
"creationTimestamp": "1970-01-01T00:00:12Z",
|
"creationTimestamp": "1970-01-01T00:00:12Z",
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"grafana.app/originKey": "123",
|
"grafana.app/originPath": "123",
|
||||||
"grafana.app/originName": "SQL",
|
"grafana.app/originName": "SQL",
|
||||||
"grafana.app/originTimestamp":"1970-01-01T00:00:12Z",
|
"grafana.app/originTimestamp":"1970-01-01T00:00:12Z",
|
||||||
"grafana.app/updatedTimestamp": "1970-01-01T00:00:54Z"
|
"grafana.app/updatedTimestamp": "1970-01-01T00:00:54Z"
|
||||||
|
@ -21,8 +21,6 @@ type Requirements struct {
|
|||||||
ListDeleted bool
|
ListDeleted bool
|
||||||
// ListHistory is a resource name to list the history of
|
// ListHistory is a resource name to list the history of
|
||||||
ListHistory string
|
ListHistory string
|
||||||
// ListOriginKeys needs to include the origin key of a given entity in order for it to be selected.
|
|
||||||
ListOriginKeys []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadLabelSelectors(selector labels.Selector) (Requirements, labels.Selector, error) {
|
func ReadLabelSelectors(selector labels.Selector) (Requirements, labels.Selector, error) {
|
||||||
@ -48,11 +46,6 @@ func ReadLabelSelectors(selector labels.Selector) (Requirements, labels.Selector
|
|||||||
return requirements, newSelector, apierrors.NewBadRequest(SortByKey + " label selector only supports in")
|
return requirements, newSelector, apierrors.NewBadRequest(SortByKey + " label selector only supports in")
|
||||||
}
|
}
|
||||||
requirements.SortBy = r.Values().List()
|
requirements.SortBy = r.Values().List()
|
||||||
case utils.AnnoKeyOriginKey:
|
|
||||||
if r.Operator() != selection.In {
|
|
||||||
return requirements, newSelector, apierrors.NewBadRequest(SortByKey + " label selector only supports in")
|
|
||||||
}
|
|
||||||
requirements.ListOriginKeys = r.Values().List()
|
|
||||||
case ListDeletedKey:
|
case ListDeletedKey:
|
||||||
if r.Operator() != selection.Equals {
|
if r.Operator() != selection.Equals {
|
||||||
return requirements, newSelector, apierrors.NewBadRequest(ListDeletedKey + " label selector only supports equality")
|
return requirements, newSelector, apierrors.NewBadRequest(ListDeletedKey + " label selector only supports equality")
|
||||||
|
@ -442,9 +442,6 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti
|
|||||||
if len(requirements.SortBy) > 0 {
|
if len(requirements.SortBy) > 0 {
|
||||||
req.Sort = requirements.SortBy
|
req.Sort = requirements.SortBy
|
||||||
}
|
}
|
||||||
if len(requirements.ListOriginKeys) > 0 {
|
|
||||||
req.OriginKeys = requirements.ListOriginKeys
|
|
||||||
}
|
|
||||||
if requirements.ListDeleted {
|
if requirements.ListDeleted {
|
||||||
req.Deleted = true
|
req.Deleted = true
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func entityToResource(rsp *entityStore.Entity, res runtime.Object, codec runtime
|
|||||||
originTime := time.UnixMilli(rsp.Origin.Time).UTC()
|
originTime := time.UnixMilli(rsp.Origin.Time).UTC()
|
||||||
grafanaAccessor.SetOriginInfo(&utils.ResourceOriginInfo{
|
grafanaAccessor.SetOriginInfo(&utils.ResourceOriginInfo{
|
||||||
Name: rsp.Origin.Source,
|
Name: rsp.Origin.Source,
|
||||||
Key: rsp.Origin.Key,
|
Path: rsp.Origin.Key, // Using "key" in the
|
||||||
// Path: rsp.Origin.Path,
|
// Path: rsp.Origin.Path,
|
||||||
Timestamp: &originTime,
|
Timestamp: &originTime,
|
||||||
})
|
})
|
||||||
@ -136,8 +136,8 @@ func resourceToEntity(res runtime.Object, requestInfo *request.RequestInfo, code
|
|||||||
Title: grafanaAccessor.FindTitle(metaAccessor.GetName()),
|
Title: grafanaAccessor.FindTitle(metaAccessor.GetName()),
|
||||||
Origin: &entityStore.EntityOriginInfo{
|
Origin: &entityStore.EntityOriginInfo{
|
||||||
Source: grafanaAccessor.GetOriginName(),
|
Source: grafanaAccessor.GetOriginName(),
|
||||||
Key: grafanaAccessor.GetOriginKey(),
|
// Deprecated: Keeping "key" in the protobuf to avoid migrations while a bigger one is in place
|
||||||
// Path: grafanaAccessor.GetOriginPath(),
|
Key: grafanaAccessor.GetOriginPath(),
|
||||||
},
|
},
|
||||||
Labels: metaAccessor.GetLabels(),
|
Labels: metaAccessor.GetLabels(),
|
||||||
}
|
}
|
||||||
|
@ -311,7 +311,7 @@ message EntityListRequest {
|
|||||||
// list deleted entities instead of active ones
|
// list deleted entities instead of active ones
|
||||||
bool deleted = 12;
|
bool deleted = 12;
|
||||||
|
|
||||||
// Limit to a set of origin keys (empty is all)
|
// Deprecated: Limit to a set of origin keys (empty is all)
|
||||||
repeated string origin_keys = 13;
|
repeated string origin_keys = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,8 +143,11 @@ func (c *K8sResourceClient) SanitizeJSON(v *unstructured.Unstructured) string {
|
|||||||
|
|
||||||
deep := v.DeepCopy()
|
deep := v.DeepCopy()
|
||||||
anno := deep.GetAnnotations()
|
anno := deep.GetAnnotations()
|
||||||
if anno["grafana.app/originKey"] != "" {
|
if anno["grafana.app/originPath"] != "" {
|
||||||
anno["grafana.app/originKey"] = "${originKey}"
|
anno["grafana.app/originPath"] = "${originPath}"
|
||||||
|
}
|
||||||
|
if anno["grafana.app/originHash"] != "" {
|
||||||
|
anno["grafana.app/originHash"] = "${originHash}"
|
||||||
}
|
}
|
||||||
if anno["grafana.app/updatedTimestamp"] != "" {
|
if anno["grafana.app/updatedTimestamp"] != "" {
|
||||||
anno["grafana.app/updatedTimestamp"] = "${updatedTimestamp}"
|
anno["grafana.app/updatedTimestamp"] = "${updatedTimestamp}"
|
||||||
|
@ -360,7 +360,7 @@ func doPlaylistTests(t *testing.T, helper *apis.K8sTestHelper) *apis.K8sTestHelp
|
|||||||
"kind": "Playlist",
|
"kind": "Playlist",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"grafana.app/originKey": "${originKey}",
|
"grafana.app/originPath": "${originPath}",
|
||||||
"grafana.app/originName": "SQL",
|
"grafana.app/originName": "SQL",
|
||||||
"grafana.app/updatedTimestamp": "${updatedTimestamp}"
|
"grafana.app/updatedTimestamp": "${updatedTimestamp}"
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user