diff --git a/pkg/apimachinery/utils/meta.go b/pkg/apimachinery/utils/meta.go index 508263b87f4..17f69da01a5 100644 --- a/pkg/apimachinery/utils/meta.go +++ b/pkg/apimachinery/utils/meta.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "strconv" + "strings" "time" "k8s.io/apimachinery/pkg/api/meta" @@ -884,9 +885,38 @@ func (m *grafanaMetaAccessor) GetSecureValues() (vals common.InlineSecureValues, return vals, nil } - fmt.Printf("TODO PROPERTY: (%t) %+v\n", property, property) + if f.Kind() == reflect.Struct { + num := f.NumField() + vals = make(common.InlineSecureValues, num) + for i := 0; i < f.NumField(); i++ { + val := f.Field(i) + if val.IsValid() && val.CanInterface() { + property = val.Interface() + inline, ok := property.(common.InlineSecureValue) + if !ok { + return nil, fmt.Errorf("secure property must be InlineSecureValue (found: %T)", property) + } - return nil, fmt.Errorf("support: %t", property) + if inline.IsZero() { + continue // nothing + } + + field := f.Type().Field(i) + fname := field.Tag.Get("json") + if fname == "" { + fname = field.Name + } else { + fname, _ = strings.CutSuffix(fname, ",omitempty") + } + vals[fname] = inline + continue + } + return nil, fmt.Errorf("value not an interface") + } + return vals, nil + } + + return nil, fmt.Errorf("secure value saved in unsupported type: %T", property) } // SetSecureValues implements GrafanaMetaAccessor. diff --git a/pkg/apimachinery/utils/meta_test.go b/pkg/apimachinery/utils/meta_test.go index fa58489b768..7bc63884699 100644 --- a/pkg/apimachinery/utils/meta_test.go +++ b/pkg/apimachinery/utils/meta_test.go @@ -90,7 +90,7 @@ type TestResource2 struct { Status *Spec `json:"status,omitempty"` // This time defined with a strict struct - SecureValues ExplictSecureValues `json:"secure,omitempty"` + Secure ExplicitSecureValues `json:"secure,omitempty"` } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -120,9 +120,12 @@ func (in *TestResource2) DeepCopyObject() runtime.Object { } // Spec defines model for Spec. -type ExplictSecureValues struct { - // Sample token value - Prop common.InlineSecureValue `json:"token,omitempty"` +type ExplicitSecureValues struct { + // Non-pointer + Value1 common.InlineSecureValue `json:"v1,omitempty"` + + // Pointer value + Value2 common.InlineSecureValue `json:"v2,omitempty"` } // Spec defines model for Spec. @@ -348,6 +351,9 @@ func TestMetaAccessor(t *testing.T) { res := &TestResource2{ Spec: Spec2{}, Status: &Spec{Title: "X"}, + Secure: ExplicitSecureValues{ + Value1: common.InlineSecureValue{Name: "hello"}, + }, } meta, err := utils.MetaAccessor(res) require.NoError(t, err) @@ -390,6 +396,10 @@ func TestMetaAccessor(t *testing.T) { require.NoError(t, err) require.Equal(t, res.Status, status) require.Equal(t, "ZZ", res.Status.Title) + + secure, err := meta.GetSecureValues() + require.NoError(t, err) + require.JSONEq(t, `{"v1": {"name": "hello"}}`, asJSON(secure, true)) }) t.Run("test reading old repo fields (now manager+source)", func(t *testing.T) {