K8s: Rename origin.key to origin.hash (#89337)

This commit is contained in:
Ryan McKinley 2024-06-18 22:27:16 +03:00 committed by GitHub
parent b0c043de5f
commit 9b7f9ae22e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 34 additions and 59 deletions

View File

@ -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) {

View File

@ -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())

View File

@ -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
} }

View File

@ -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 != "" {

View File

@ -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 {

View File

@ -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
} }

View File

@ -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"

View File

@ -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")

View File

@ -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
} }

View File

@ -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(),
} }

View File

@ -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;
} }

View File

@ -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}"

View File

@ -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}"
}, },