ResourceServer: Add resource server protobuf and wrapper (#90007)

This commit is contained in:
Ryan McKinley
2024-07-09 15:08:13 -07:00
committed by GitHub
parent 05ce16cf7b
commit 079f0715aa
40 changed files with 5852 additions and 62 deletions
+126
View File
@@ -1,9 +1,12 @@
package utils
import (
"bytes"
"fmt"
"mime"
"reflect"
"strconv"
"strings"
"time"
"k8s.io/apimachinery/pkg/api/meta"
@@ -20,6 +23,8 @@ const AnnoKeyUpdatedTimestamp = "grafana.app/updatedTimestamp"
const AnnoKeyUpdatedBy = "grafana.app/updatedBy"
const AnnoKeyFolder = "grafana.app/folder"
const AnnoKeySlug = "grafana.app/slug"
const AnnoKeyBlob = "grafana.app/blob"
const AnnoKeyMessage = "grafana.app/message"
// Identify where values came from
@@ -53,6 +58,7 @@ type GrafanaMetaAccessor interface {
metav1.Object
GetGroupVersionKind() schema.GroupVersionKind
GetRuntimeObject() (runtime.Object, bool)
// Helper to get resource versions as int64, however this is not required
// See: https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions
@@ -68,11 +74,16 @@ type GrafanaMetaAccessor interface {
SetUpdatedBy(user string)
GetFolder() string
SetFolder(uid string)
GetMessage() string
SetMessage(msg string)
SetAnnotation(key string, val string)
GetSlug() string
SetSlug(v string)
SetBlob(v *BlobInfo)
GetBlob() *BlobInfo
GetOriginInfo() (*ResourceOriginInfo, error)
SetOriginInfo(info *ResourceOriginInfo)
GetOriginName() string
@@ -80,6 +91,8 @@ type GrafanaMetaAccessor interface {
GetOriginHash() string
GetOriginTimestamp() (*time.Time, error)
GetSpec() (any, error)
// Find a title in the object
// This will reflect the object and try to get:
// * spec.title
@@ -123,6 +136,11 @@ func (m *grafanaMetaAccessor) GetResourceVersionInt64() (int64, error) {
return strconv.ParseInt(v, 10, 64)
}
func (m *grafanaMetaAccessor) GetRuntimeObject() (runtime.Object, bool) {
obj, ok := m.raw.(runtime.Object)
return obj, ok
}
func (m *grafanaMetaAccessor) SetResourceVersionInt64(rv int64) {
m.obj.SetResourceVersion(strconv.FormatInt(rv, 10))
}
@@ -192,6 +210,17 @@ func (m *grafanaMetaAccessor) SetUpdatedBy(user string) {
m.SetAnnotation(AnnoKeyUpdatedBy, user)
}
func (m *grafanaMetaAccessor) GetBlob() *BlobInfo {
return ParseBlobInfo(m.get(AnnoKeyBlob))
}
func (m *grafanaMetaAccessor) SetBlob(info *BlobInfo) {
if info == nil {
m.SetAnnotation(AnnoKeyBlob, "") // delete
}
m.SetAnnotation(AnnoKeyBlob, info.String())
}
func (m *grafanaMetaAccessor) GetFolder() string {
return m.get(AnnoKeyFolder)
}
@@ -200,6 +229,14 @@ func (m *grafanaMetaAccessor) SetFolder(uid string) {
m.SetAnnotation(AnnoKeyFolder, uid)
}
func (m *grafanaMetaAccessor) GetMessage() string {
return m.get(AnnoKeyMessage)
}
func (m *grafanaMetaAccessor) SetMessage(uid string) {
m.SetAnnotation(AnnoKeyMessage, uid)
}
func (m *grafanaMetaAccessor) GetSlug() string {
return m.get(AnnoKeySlug)
}
@@ -457,6 +494,16 @@ func (m *grafanaMetaAccessor) GetGroupVersionKind() schema.GroupVersionKind {
return gvk
}
func (m *grafanaMetaAccessor) GetSpec() (spec any, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("error reading spec")
}
}()
spec = m.r.FieldByName("Spec").Interface()
return
}
func (m *grafanaMetaAccessor) FindTitle(defaultTitle string) string {
// look for Spec.Title or Spec.Name
spec := m.r.FieldByName("Spec")
@@ -477,3 +524,82 @@ func (m *grafanaMetaAccessor) FindTitle(defaultTitle string) string {
}
return defaultTitle
}
type BlobInfo struct {
UID string `json:"uid"`
Size int64 `json:"size,omitempty"`
Hash string `json:"hash,omitempty"`
MimeType string `json:"mime,omitempty"`
Charset string `json:"charset,omitempty"` // content type = mime+charset
}
// Content type is mime + charset
func (b *BlobInfo) SetContentType(v string) {
var params map[string]string
var err error
b.Charset = ""
b.MimeType, params, err = mime.ParseMediaType(v)
if err != nil {
return
}
b.Charset = params["charset"]
}
// Content type is mime + charset
func (b *BlobInfo) ContentType() string {
sb := bytes.NewBufferString(b.MimeType)
if b.Charset != "" {
sb.WriteString("; charset=")
sb.WriteString(b.Charset)
}
return sb.String()
}
func (b *BlobInfo) String() string {
sb := bytes.NewBufferString(b.UID)
if b.Size > 0 {
sb.WriteString(fmt.Sprintf("; size=%d", b.Size))
}
if b.Hash != "" {
sb.WriteString("; hash=")
sb.WriteString(b.Hash)
}
if b.MimeType != "" {
sb.WriteString("; mime=")
sb.WriteString(b.MimeType)
}
if b.Charset != "" {
sb.WriteString("; charset=")
sb.WriteString(b.Charset)
}
return sb.String()
}
func ParseBlobInfo(v string) *BlobInfo {
if v == "" {
return nil
}
info := &BlobInfo{}
for i, part := range strings.Split(v, ";") {
if i == 0 {
info.UID = part
continue
}
kv := strings.Split(strings.TrimSpace(part), "=")
if len(kv) == 2 {
val := kv[1]
switch kv[0] {
case "size":
info.Size, _ = strconv.ParseInt(val, 10, 64)
case "hash":
info.Hash = val
case "mime":
info.MimeType = val
case "charset":
info.Charset = val
}
}
}
return info
}
+16
View File
@@ -172,6 +172,14 @@ func TestMetaAccessor(t *testing.T) {
require.Equal(t, int64(12345), rv)
})
t.Run("blob info", func(t *testing.T) {
info := &utils.BlobInfo{UID: "AAA", Size: 123, Hash: "xyz", MimeType: "application/json", Charset: "utf-8"}
anno := info.String()
require.Equal(t, "AAA; size=123; hash=xyz; mime=application/json; charset=utf-8", anno)
copy := utils.ParseBlobInfo(anno)
require.Equal(t, info, copy)
})
t.Run("find titles", func(t *testing.T) {
// with a k8s object that has Spec.Title
obj := &TestResource{
@@ -220,5 +228,13 @@ func TestMetaAccessor(t *testing.T) {
}, obj2.GetAnnotations())
require.Equal(t, "xxx", meta.FindTitle("xxx"))
rt, ok := meta.GetRuntimeObject()
require.Equal(t, obj2, rt)
require.True(t, ok)
spec, err := meta.GetSpec()
require.Equal(t, obj2.Spec, spec)
require.NoError(t, err)
})
}