feat: export metadata-less YAML resources (#96829)
* feat: export metadata-less YAML resources * feat: add option to prefer YAML
This commit is contained in:
@@ -87,6 +87,11 @@ type RepositorySpec struct {
|
||||
// The value is a reference to the Kubernetes metadata name of the folder in the same namespace.
|
||||
Folder string `json:"folder,omitempty"`
|
||||
|
||||
// Should we prefer emitting YAML for this repository, e.g. upon export?
|
||||
// Editing existing dashboards will continue to emit the file format used in the repository. (TODO: implement this)
|
||||
// If you delete and then recreate a dashboard, it will switch to the preferred format.
|
||||
PreferYAML bool `json:"preferYaml,omitempty"`
|
||||
|
||||
// Edit options within the repository
|
||||
Editing EditingOptions `json:"editing"`
|
||||
|
||||
|
||||
@@ -305,6 +305,13 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref common.ReferenceCa
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"preferYaml": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Should we prefer emitting YAML for this repository, e.g. upon export? Editing existing dashboards will continue to emit the file format used in the repository. (TODO: implement this) If you delete and then recreate a dashboard, it will switch to the preferred format.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"editing": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Edit options within the repository",
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ResourceWrapper,Errors
|
||||
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitHub
|
||||
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositorySpec,PreferYAML
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
apiutils "github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
|
||||
"gopkg.in/yaml.v3"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -132,22 +133,21 @@ func (c *exportConnector) Connect(
|
||||
|
||||
folder := folders[item.GetAnnotations()[apiutils.AnnoKeyFolder]]
|
||||
|
||||
// TODO: Drop the metadata field before writing?
|
||||
// TODO: Do we want this to export YAML instead maybe?
|
||||
json, err := json.MarshalIndent(item.Object, "", "\t")
|
||||
delete(item.Object, "metadata")
|
||||
marshalledBody, baseFileName, err := c.marshalPreferredFormat(item.Object, name, repo)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "failed to marshal dashboard into JSON",
|
||||
slog.ErrorContext(ctx, "failed to marshal dashboard into preferred format",
|
||||
"err", err,
|
||||
"dashboard", name,
|
||||
"namespace", ns)
|
||||
responder.Error(apierrors.NewInternalError(fmt.Errorf("failed to marshal dashboard %s into json: %w", name, err)))
|
||||
responder.Error(apierrors.NewInternalError(fmt.Errorf("failed to marshal dashboard %s: %w", name, err)))
|
||||
return
|
||||
}
|
||||
|
||||
fileName := filepath.Join(folder.CreatePath(), name+".json")
|
||||
fileName := filepath.Join(folder.CreatePath(), baseFileName)
|
||||
// TODO: Upsert
|
||||
if err := repo.Create(ctx, fileName, json, "export of dashboard "+name+" in ns "+ns); err != nil {
|
||||
slog.ErrorContext(ctx, "failed to write dashboard JSON to repository",
|
||||
if err := repo.Create(ctx, fileName, marshalledBody, "export of dashboard "+name+" in namespace "+ns); err != nil {
|
||||
slog.ErrorContext(ctx, "failed to write dashboard model to repository",
|
||||
"err", err,
|
||||
"repository", repo.Config().GetName(),
|
||||
"dashboard", name,
|
||||
@@ -226,6 +226,16 @@ func (c *exportConnector) fetchFolderInfo(
|
||||
return folders, nil
|
||||
}
|
||||
|
||||
func (c *exportConnector) marshalPreferredFormat(obj any, name string, repo Repository) (body []byte, fileName string, err error) {
|
||||
if repo.Config().Spec.PreferYAML {
|
||||
body, err = yaml.Marshal(obj)
|
||||
return body, name + ".yaml", err
|
||||
} else {
|
||||
body, err := json.MarshalIndent(obj, "", " ")
|
||||
return body, name + ".json", err
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_ rest.Connecter = (*exportConnector)(nil)
|
||||
_ rest.Storage = (*exportConnector)(nil)
|
||||
|
||||
Reference in New Issue
Block a user