|
|
|
@ -1,14 +1,14 @@ |
|
|
|
|
package utils_test |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"encoding/json" |
|
|
|
|
"testing" |
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/apimachinery/utils" |
|
|
|
|
"github.com/stretchr/testify/require" |
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" |
|
|
|
|
"k8s.io/apimachinery/pkg/runtime" |
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/apimachinery/utils" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type TestResource struct { |
|
|
|
@ -19,6 +19,9 @@ type TestResource struct { |
|
|
|
|
metav1.ObjectMeta `json:"metadata,omitempty"` |
|
|
|
|
|
|
|
|
|
Spec Spec `json:"spec,omitempty"` |
|
|
|
|
|
|
|
|
|
// Read/write raw status
|
|
|
|
|
Status Spec `json:"status,omitempty"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
|
|
@ -76,6 +79,9 @@ type TestResource2 struct { |
|
|
|
|
metav1.ObjectMeta `json:"metadata,omitempty"` |
|
|
|
|
|
|
|
|
|
Spec Spec2 `json:"spec,omitempty"` |
|
|
|
|
|
|
|
|
|
// Exercise read/write pointer status
|
|
|
|
|
Status *Spec `json:"status,omitempty"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
|
|
@ -147,10 +153,29 @@ func TestMetaAccessor(t *testing.T) { |
|
|
|
|
require.NoError(t, err) // Must be a pointer
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
t.Run("get and set grafana metadata", func(t *testing.T) { |
|
|
|
|
res := &unstructured.Unstructured{} |
|
|
|
|
t.Run("get and set grafana metadata (unstructured)", func(t *testing.T) { |
|
|
|
|
// Error reading spec+status when missing
|
|
|
|
|
res := &unstructured.Unstructured{ |
|
|
|
|
Object: map[string]any{}, |
|
|
|
|
} |
|
|
|
|
meta, err := utils.MetaAccessor(res) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
spec, err := meta.GetSpec() |
|
|
|
|
require.Error(t, err) |
|
|
|
|
require.Nil(t, spec) |
|
|
|
|
status, err := meta.GetStatus() |
|
|
|
|
require.Error(t, err) |
|
|
|
|
require.Nil(t, status) |
|
|
|
|
|
|
|
|
|
// Now set a spec and status
|
|
|
|
|
res.Object = map[string]any{ |
|
|
|
|
"spec": map[string]any{ |
|
|
|
|
"hello": "world", |
|
|
|
|
}, |
|
|
|
|
"status": map[string]any{ |
|
|
|
|
"sloth": "🦥", |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
meta.SetOriginInfo(originInfo) |
|
|
|
|
meta.SetFolder("folderUID") |
|
|
|
@ -170,6 +195,130 @@ func TestMetaAccessor(t *testing.T) { |
|
|
|
|
rv, err := meta.GetResourceVersionInt64() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, int64(12345), rv) |
|
|
|
|
|
|
|
|
|
// Make sure access to spec works for Unstructured
|
|
|
|
|
spec, err = meta.GetSpec() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Object["spec"], spec) |
|
|
|
|
spec = &map[string]string{"a": "b"} |
|
|
|
|
err = meta.SetSpec(spec) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
spec, err = meta.GetSpec() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Object["spec"], spec) |
|
|
|
|
|
|
|
|
|
// Make sure access to spec works for Unstructured
|
|
|
|
|
status, err = meta.GetStatus() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Object["status"], status) |
|
|
|
|
status = &map[string]string{"a": "b"} |
|
|
|
|
err = meta.SetStatus(status) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
status, err = meta.GetStatus() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Object["status"], status) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
t.Run("get and set grafana metadata (TestResource)", func(t *testing.T) { |
|
|
|
|
res := &TestResource{ |
|
|
|
|
Spec: Spec{ |
|
|
|
|
Title: "test", |
|
|
|
|
}, |
|
|
|
|
// Status is empty, but not nil!
|
|
|
|
|
} |
|
|
|
|
meta, err := utils.MetaAccessor(res) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
meta.SetOriginInfo(originInfo) |
|
|
|
|
meta.SetFolder("folderUID") |
|
|
|
|
|
|
|
|
|
require.Equal(t, map[string]string{ |
|
|
|
|
"grafana.app/originName": "test", |
|
|
|
|
"grafana.app/originPath": "a/b/c", |
|
|
|
|
"grafana.app/originHash": "kkk", |
|
|
|
|
"grafana.app/folder": "folderUID", |
|
|
|
|
}, res.GetAnnotations()) |
|
|
|
|
|
|
|
|
|
meta.SetNamespace("aaa") |
|
|
|
|
meta.SetResourceVersionInt64(12345) |
|
|
|
|
require.Equal(t, "aaa", res.GetNamespace()) |
|
|
|
|
require.Equal(t, "aaa", meta.GetNamespace()) |
|
|
|
|
|
|
|
|
|
rv, err := meta.GetResourceVersionInt64() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, int64(12345), rv) |
|
|
|
|
|
|
|
|
|
// Make sure access to spec works for Unstructured
|
|
|
|
|
spec, err := meta.GetSpec() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Spec, spec) |
|
|
|
|
err = meta.SetSpec(Spec{Title: "t2"}) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
spec, err = meta.GetSpec() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Spec, spec) |
|
|
|
|
require.Equal(t, `{"title":"t2"}`, asJSON(spec, false)) |
|
|
|
|
|
|
|
|
|
// Check read/write status
|
|
|
|
|
status, err := meta.GetStatus() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.NotNil(t, status) |
|
|
|
|
err = meta.SetStatus(Spec{Title: "111"}) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
status, err = meta.GetStatus() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Status, status) |
|
|
|
|
require.Equal(t, "111", res.Status.Title) |
|
|
|
|
require.Equal(t, `{"title":"111"}`, asJSON(status, false)) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
t.Run("get and set grafana metadata (TestResource2)", func(t *testing.T) { |
|
|
|
|
res := &TestResource2{ |
|
|
|
|
Spec: Spec2{}, |
|
|
|
|
Status: &Spec{Title: "X"}, |
|
|
|
|
} |
|
|
|
|
meta, err := utils.MetaAccessor(res) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
meta.SetOriginInfo(originInfo) |
|
|
|
|
meta.SetFolder("folderUID") |
|
|
|
|
|
|
|
|
|
require.Equal(t, map[string]string{ |
|
|
|
|
"grafana.app/originName": "test", |
|
|
|
|
"grafana.app/originPath": "a/b/c", |
|
|
|
|
"grafana.app/originHash": "kkk", |
|
|
|
|
"grafana.app/folder": "folderUID", |
|
|
|
|
}, res.GetAnnotations()) |
|
|
|
|
|
|
|
|
|
meta.SetNamespace("aaa") |
|
|
|
|
meta.SetResourceVersionInt64(12345) |
|
|
|
|
require.Equal(t, "aaa", res.GetNamespace()) |
|
|
|
|
require.Equal(t, "aaa", meta.GetNamespace()) |
|
|
|
|
|
|
|
|
|
rv, err := meta.GetResourceVersionInt64() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, int64(12345), rv) |
|
|
|
|
|
|
|
|
|
// Make sure access to spec works for TestResource2
|
|
|
|
|
spec, err := meta.GetSpec() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Spec, spec) |
|
|
|
|
err = meta.SetSpec(Spec2{}) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
spec, err = meta.GetSpec() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Spec, spec) |
|
|
|
|
|
|
|
|
|
// Make sure access to spec works for TestResource2
|
|
|
|
|
status, err := meta.GetStatus() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Status, status) |
|
|
|
|
err = meta.SetStatus(&Spec{Title: "ZZ"}) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
status, err = meta.GetStatus() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, res.Status, status) |
|
|
|
|
require.Equal(t, "ZZ", res.Status.Title) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
t.Run("blob info", func(t *testing.T) { |
|
|
|
@ -238,3 +387,15 @@ func TestMetaAccessor(t *testing.T) { |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func asJSON(v any, pretty bool) string { |
|
|
|
|
if v == nil { |
|
|
|
|
return "" |
|
|
|
|
} |
|
|
|
|
if pretty { |
|
|
|
|
bytes, _ := json.MarshalIndent(v, "", " ") |
|
|
|
|
return string(bytes) |
|
|
|
|
} |
|
|
|
|
bytes, _ := json.Marshal(v) |
|
|
|
|
return string(bytes) |
|
|
|
|
} |
|
|
|
|