unstructured spec

This commit is contained in:
Ryan McKinley
2025-08-20 10:38:52 +03:00
parent 76b4c687b0
commit b0c9350580
6 changed files with 52 additions and 145 deletions
-72
View File
@@ -1,72 +0,0 @@
package v0alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
)
// +k8s:deepcopy-gen=true
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DataSource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
// generic config
Spec DataSourceSpec `json:"spec"`
// Secure values placeholder (true for fields that exist)
Secure common.InlineSecureValues `json:"secure,omitempty"`
}
// DsAccess represents how the datasource connects to the remote service
// +k8s:openapi-gen=true
// +enum
type DsAccess string
const (
// The frontend can connect directly to the remote URL
// This method is discouraged
DsAccessDirect DsAccess = "direct"
// Connect to the remote datasource through the grafana backend
DsAccessProxy DsAccess = "proxy"
)
func (dsa DsAccess) String() string {
return string(dsa)
}
// +k8s:deepcopy-gen=true
// +k8s:openapi-gen=true
type DataSourceSpec struct {
// The diplay name (previously saved as the "name" property)
Title string `json:"title"`
Access DsAccess `json:"access,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
IsDefault bool `json:"isDefault,omitempty"`
// Server URL
URL string `json:"url,omitempty"`
User string `json:"user,omitempty"`
Database string `json:"database,omitempty"`
BasicAuth bool `json:"basicAuth,omitempty"`
BasicAuthUser string `json:"basicAuthUser,omitempty"`
WithCredentials bool `json:"withCredentials,omitempty"`
// Generic unstructured configuration settings
JsonData common.Unstructured `json:"jsonData,omitzero"`
}
// +k8s:deepcopy-gen=true
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DataSourceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []DataSource `json:"items"`
}
+1 -1
View File
@@ -32,7 +32,7 @@ var DataSourceResourceInfo = utils.NewResourceInfo(GROUP, VERSION,
}
return []any{
m.Name,
m.Spec.Title,
m.Spec.Object["title"],
m.CreationTimestamp.UTC().Format(time.RFC3339),
}, nil
},
@@ -79,23 +79,6 @@ func (in *DataSourceList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataSourceSpec) DeepCopyInto(out *DataSourceSpec) {
*out = *in
in.JsonData.DeepCopyInto(&out.JsonData)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSourceSpec.
func (in *DataSourceSpec) DeepCopy() *DataSourceSpec {
if in == nil {
return nil
}
out := new(DataSourceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HealthCheckResult) DeepCopyInto(out *HealthCheckResult) {
*out = *in
@@ -14,10 +14,11 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSource": schema_pkg_apis_datasource_v0alpha1_DataSource(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSourceList": schema_pkg_apis_datasource_v0alpha1_DataSourceList(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSourceSpec": schema_pkg_apis_datasource_v0alpha1_DataSourceSpec(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.HealthCheckResult": schema_pkg_apis_datasource_v0alpha1_HealthCheckResult(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSource": schema_pkg_apis_datasource_v0alpha1_DataSource(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSourceList": schema_pkg_apis_datasource_v0alpha1_DataSourceList(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.GenericDataSourceSpec": schema_pkg_apis_datasource_v0alpha1_GenericDataSourceSpec(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.HealthCheckResult": schema_pkg_apis_datasource_v0alpha1_HealthCheckResult(ref),
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.UnstructuredSpec": UnstructuredSpec{}.OpenAPIDefinition(),
}
}
@@ -49,14 +50,13 @@ func schema_pkg_apis_datasource_v0alpha1_DataSource(ref common.ReferenceCallback
},
"spec": {
SchemaProps: spec.SchemaProps{
Description: "generic config",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSourceSpec"),
Description: "DataSource configuration -- these properties are all visible to anyone able to query the data source from their browser",
Ref: ref("github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.UnstructuredSpec"),
},
},
"secure": {
SchemaProps: spec.SchemaProps{
Description: "Secure values placeholder (true for fields that exist)",
Description: "Secure values allows setting values that are never shown to users The returned properties are only the names of the configured values",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
@@ -74,7 +74,7 @@ func schema_pkg_apis_datasource_v0alpha1_DataSource(ref common.ReferenceCallback
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.InlineSecureValue", "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.DataSourceSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.InlineSecureValue", "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1.UnstructuredSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
@@ -126,7 +126,7 @@ func schema_pkg_apis_datasource_v0alpha1_DataSourceList(ref common.ReferenceCall
}
}
func schema_pkg_apis_datasource_v0alpha1_DataSourceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_datasource_v0alpha1_GenericDataSourceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -134,7 +134,7 @@ func schema_pkg_apis_datasource_v0alpha1_DataSourceSpec(ref common.ReferenceCall
Properties: map[string]spec.Schema{
"title": {
SchemaProps: spec.SchemaProps{
Description: "The diplay name (previously saved as the \"name\" property)",
Description: "The display name (previously saved as the \"name\" property)",
Default: "",
Type: []string{"string"},
Format: "",
@@ -1 +1,2 @@
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/datasource/v0alpha1,UnstructuredSpec,Object
API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/pkg/apis/datasource/v0alpha1,DataSourceList,ListMeta
+39 -44
View File
@@ -36,21 +36,22 @@ func (r *converter) asDataSource(ds *datasources.DataSource) (*datasourceV0.Data
ResourceVersion: fmt.Sprintf("%d", ds.Updated.UnixMilli()),
Generation: int64(ds.Version),
},
Spec: datasourceV0.DataSourceSpec{
Title: ds.Name,
Access: datasourceV0.DsAccess(ds.Access),
URL: ds.URL,
User: ds.User,
Database: ds.Database,
BasicAuth: ds.BasicAuth,
BasicAuthUser: ds.BasicAuthUser,
WithCredentials: ds.WithCredentials,
IsDefault: ds.IsDefault,
ReadOnly: ds.ReadOnly,
},
Spec: datasourceV0.UnstructuredSpec{},
Secure: ToInlineSecureValues(ds.Type, ds.UID, maps.Keys(ds.SecureJsonData)),
}
cfg.UID = gapiutil.CalculateClusterWideUID(cfg)
cfg.Spec.SetTitle(ds.Name).
SetAccess(string(ds.Access)).
SetURL(ds.URL).
SetDatabase(ds.Database).
SetUser(ds.User).
SetDatabase(ds.Database).
SetBasicAuth(ds.BasicAuth).
SetBasicAuthUser(ds.BasicAuthUser).
SetWithCredentials(ds.WithCredentials).
SetIsDefault(ds.IsDefault).
SetReadOnly(ds.ReadOnly).
SetJSONData(ds.JsonData)
if ds.ID > 0 {
cfg.Labels = map[string]string{
@@ -58,14 +59,6 @@ func (r *converter) asDataSource(ds *datasources.DataSource) (*datasourceV0.Data
}
}
if ds.JsonData != nil {
val, ok := ds.JsonData.Interface().(map[string]any)
if !ok {
return nil, fmt.Errorf("expected map[string]any jsondata")
}
cfg.Spec.JsonData.Object = val
}
return cfg, nil
}
@@ -101,24 +94,25 @@ func (r *converter) toAddCommand(ds *datasourceV0.DataSource) (*datasources.AddD
}
cmd := &datasources.AddDataSourceCommand{
Name: ds.Spec.Title,
Name: ds.Spec.Title(),
UID: ds.Name,
OrgID: info.OrgID,
Type: r.dstype,
Access: datasources.DsAccess(ds.Spec.Access),
URL: ds.Spec.URL,
Database: ds.Spec.Database,
User: ds.Spec.User,
BasicAuth: ds.Spec.BasicAuth,
BasicAuthUser: ds.Spec.BasicAuthUser,
WithCredentials: ds.Spec.WithCredentials,
IsDefault: ds.Spec.IsDefault,
ReadOnly: ds.Spec.ReadOnly,
Access: datasources.DsAccess(ds.Spec.Access()),
URL: ds.Spec.URL(),
Database: ds.Spec.Database(),
User: ds.Spec.User(),
BasicAuth: ds.Spec.BasicAuth(),
BasicAuthUser: ds.Spec.BasicAuthUser(),
WithCredentials: ds.Spec.WithCredentials(),
IsDefault: ds.Spec.IsDefault(),
ReadOnly: ds.Spec.ReadOnly(),
}
if len(ds.Spec.JsonData.Object) > 0 {
cmd.JsonData = simplejson.NewFromAny(ds.Spec.JsonData.Object)
jsonData := ds.Spec.JSONData()
if jsonData != nil {
cmd.JsonData = simplejson.NewFromAny(jsonData)
}
cmd.SecureJsonData, err = toSecureJsonData(ds)
@@ -135,27 +129,28 @@ func (r *converter) toUpdateCommand(ds *datasourceV0.DataSource) (*datasources.U
}
cmd := &datasources.UpdateDataSourceCommand{
Name: ds.Spec.Title,
Name: ds.Spec.Title(),
UID: ds.Name,
OrgID: info.OrgID,
Type: r.dstype,
Access: datasources.DsAccess(ds.Spec.Access),
URL: ds.Spec.URL,
Database: ds.Spec.Database,
User: ds.Spec.User,
BasicAuth: ds.Spec.BasicAuth,
BasicAuthUser: ds.Spec.BasicAuthUser,
WithCredentials: ds.Spec.WithCredentials,
IsDefault: ds.Spec.IsDefault,
ReadOnly: ds.Spec.ReadOnly,
Access: datasources.DsAccess(ds.Spec.Access()),
URL: ds.Spec.URL(),
Database: ds.Spec.Database(),
User: ds.Spec.User(),
BasicAuth: ds.Spec.BasicAuth(),
BasicAuthUser: ds.Spec.BasicAuthUser(),
WithCredentials: ds.Spec.WithCredentials(),
IsDefault: ds.Spec.IsDefault(),
ReadOnly: ds.Spec.ReadOnly(),
// The only field different than add
Version: int(ds.Generation),
}
if len(ds.Spec.JsonData.Object) > 0 {
cmd.JsonData = simplejson.NewFromAny(ds.Spec.JsonData.Object)
jsonData := ds.Spec.JSONData()
if jsonData != nil {
cmd.JsonData = simplejson.NewFromAny(jsonData)
}
cmd.SecureJsonData, err = toSecureJsonData(ds)
return cmd, err