The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/apimachinery/apis/common/v0alpha1/unstructured.go

178 lines
4.5 KiB

package v0alpha1
import (
"encoding/json"
"reflect"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
runtime "k8s.io/apimachinery/pkg/runtime"
openapi "k8s.io/kube-openapi/pkg/common"
spec "k8s.io/kube-openapi/pkg/validation/spec"
)
// Unstructured allows objects that do not have Golang structs registered to be manipulated
// generically.
type Unstructured struct {
// Object is a JSON compatible map with string, float, int, bool, []interface{},
// or map[string]interface{} children.
Object map[string]interface{}
}
// Produce an API definition that represents map[string]any
func (u Unstructured) OpenAPIDefinition() openapi.OpenAPIDefinition {
return openapi.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{Allows: true},
},
VendorExtensible: spec.VendorExtensible{
Extensions: map[string]interface{}{
"x-kubernetes-preserve-unknown-fields": true,
},
},
},
}
}
func (u *Unstructured) UnstructuredContent() map[string]interface{} {
if u.Object == nil {
return make(map[string]interface{})
}
return u.Object
}
func (u *Unstructured) SetUnstructuredContent(content map[string]interface{}) {
u.Object = content
}
// MarshalJSON ensures that the unstructured object produces proper
// JSON when passed to Go's standard JSON library.
func (u *Unstructured) MarshalJSON() ([]byte, error) {
return json.Marshal(u.Object)
}
// UnmarshalJSON ensures that the unstructured object properly decodes
// JSON when passed to Go's standard JSON library.
func (u *Unstructured) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &u.Object)
}
func (u *Unstructured) DeepCopy() *Unstructured {
if u == nil {
return nil
}
out := new(Unstructured)
*out = *u
out.Object = deepCopyJSONValue(u.Object).(map[string]interface{})
return out
}
func (u *Unstructured) DeepCopyInto(out *Unstructured) {
clone := u.DeepCopy()
*out = *clone
}
// Copied from:
//
// runtime.DeepCopyJSON(u.Object)
//
// BUT this avoids panic on int
func deepCopyJSONValue(x interface{}) interface{} {
switch x := x.(type) {
case map[string]interface{}:
if x == nil {
// Typed nil - an interface{} that contains a type map[string]interface{} with a value of nil
return x
}
clone := make(map[string]interface{}, len(x))
for k, v := range x {
clone[k] = deepCopyJSONValue(v)
}
return clone
case []interface{}:
if x == nil {
// Typed nil - an interface{} that contains a type []interface{} with a value of nil
return x
}
clone := make([]interface{}, len(x))
for i, v := range x {
clone[i] = deepCopyJSONValue(v)
}
return clone
case string, int64, bool, float64, nil, json.Number:
return x
// Keep more numbers
case int, int8, int16, int32, float32, uint, uint16, uint32, uint64, uint8:
return x
case runtime.Object:
return x.DeepCopyObject()
default:
// fallback to reflection
val := reflect.ValueOf(x).Elem()
cpy := reflect.New(val.Type())
cpy.Elem().Set(val)
// Using the <obj>, <ok> for the type conversion ensures that it doesn't panic if it can't be converted
if obj, ok := cpy.Interface().(runtime.Object); ok {
return obj
}
return x
}
}
func (u *Unstructured) Set(field string, value interface{}) {
if u.Object == nil {
u.Object = make(map[string]interface{})
}
_ = unstructured.SetNestedField(u.Object, value, field)
}
func (u *Unstructured) Remove(fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
}
unstructured.RemoveNestedField(u.Object, fields...)
}
func (u *Unstructured) SetNestedField(value interface{}, fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
}
_ = unstructured.SetNestedField(u.Object, value, fields...)
}
func (u *Unstructured) GetNestedString(fields ...string) string {
val, found, err := unstructured.NestedString(u.Object, fields...)
if !found || err != nil {
return ""
}
return val
}
func (u *Unstructured) GetNestedBool(fields ...string) bool {
val, found, err := unstructured.NestedBool(u.Object, fields...)
if !found || err != nil {
return false
}
return val
}
func (u *Unstructured) GetNestedStringSlice(fields ...string) []string {
val, found, err := unstructured.NestedStringSlice(u.Object, fields...)
if !found || err != nil {
return nil
}
return val
}
func (u *Unstructured) GetNestedInt64(fields ...string) int64 {
val, found, err := unstructured.NestedInt64(u.Object, fields...)
if !found || err != nil {
return 0
}
return val
}