Skip to content

Commit

Permalink
Support output formats (#309)
Browse files Browse the repository at this point in the history
* Support configurable output formats

* Remove legacy, support --only-spec
  • Loading branch information
malcolmholmes authored Jan 23, 2024
1 parent 3dba642 commit 1646298
Show file tree
Hide file tree
Showing 17 changed files with 186 additions and 129 deletions.
31 changes: 22 additions & 9 deletions cmd/grr/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ func getCmd() *cli.Command {
Short: "retrieve resource",
Args: cli.ArgsExact(1),
}
var opts grizzly.LoggingOpts
var opts grizzly.Opts

cmd.Run = func(cmd *cli.Command, args []string) error {
uid := args[0]
return grizzly.Get(uid)
return grizzly.Get(uid, opts)
}
return initialiseLogging(cmd, &opts)
cmd = initialiseOnlySpec(cmd, &opts)
return initialiseCmd(cmd, &opts)
}

func listCmd() *cli.Command {
Expand Down Expand Up @@ -77,7 +78,7 @@ func pullCmd() *cli.Command {
return grizzly.Pull(args[0], opts)
}

cmd.Flags().BoolVarP(&opts.JSONSpec, "only-spec", "s", false, "this flag is only used for dashboards to output the spec")
cmd = initialiseOnlySpec(cmd, &opts)
return initialiseCmd(cmd, &opts)
}

Expand All @@ -94,7 +95,7 @@ func showCmd() *cli.Command {
if err != nil {
return err
}
return grizzly.Show(resources)
return grizzly.Show(resources, opts)
}
return initialiseCmd(cmd, &opts)
}
Expand All @@ -112,7 +113,7 @@ func diffCmd() *cli.Command {
if err != nil {
return err
}
return grizzly.Diff(resources)
return grizzly.Diff(resources, opts)
}
return initialiseCmd(cmd, &opts)
}
Expand All @@ -139,7 +140,7 @@ func applyCmd() *cli.Command {
}

cmd.Flags().StringVarP(&opts.FolderUID, "folder", "f", generalFolderUID, "folder to push dashboards to")
cmd.Flags().BoolVarP(&opts.JSONSpec, "only-spec", "s", false, "this flag is only used for dashboards to output the spec")
cmd = initialiseOnlySpec(cmd, &opts)
return initialiseCmd(cmd, &opts)
}

Expand All @@ -157,7 +158,7 @@ func targetsOfKind(kind string, opts grizzly.Opts) bool {
// checkDashboardTarget ensures that the specified targets are of dashboards kind
func checkDashboardTarget(opts grizzly.Opts) error {
ok := targetsOfKind("Dashboard", opts)
if opts.JSONSpec && !ok {
if opts.OnlySpec && !ok {
return fmt.Errorf("-s flag is only supported for dashboards")
}

Expand Down Expand Up @@ -236,7 +237,7 @@ func exportCmd() *cli.Command {
if err != nil {
return err
}
return grizzly.Export(dashboardDir, resources)
return grizzly.Export(dashboardDir, resources, opts)
}
return initialiseCmd(cmd, &opts)
}
Expand Down Expand Up @@ -287,10 +288,22 @@ func initialiseCmd(cmd *cli.Command, opts *grizzly.Opts) *cli.Command {

cmd.Flags().StringSliceVarP(&opts.Targets, "target", "t", nil, "resources to target")
cmd.Flags().StringSliceVarP(&opts.JsonnetPaths, "jpath", "J", getDefaultJsonnetFolders(), "Specify an additional library search dir (right-most wins)")
cmd.Flags().StringVarP(&opts.OutputFormat, "output", "o", "", "Output format")

return initialiseLogging(cmd, &opts.LoggingOpts)
}

func initialiseOnlySpec(cmd *cli.Command, opts *grizzly.Opts) *cli.Command {
cmd.Flags().BoolVarP(&opts.OnlySpec, "only-spec", "s", false, "this flag is only used for dashboards to output the spec")
cmdRun := cmd.Run
cmd.Run = func(cmd *cli.Command, args []string) error {
opts.HasOnlySpec = cmd.Flags().Changed("only-spec")
return cmdRun(cmd, args)
}

return cmd
}

func initialiseLogging(cmd *cli.Command, loggingOpts *grizzly.LoggingOpts) *cli.Command {
cmd.Flags().StringVarP(&loggingOpts.LogLevel, "log-level", "l", log.InfoLevel.String(), "info, debug, warning, error")
cmdRun := cmd.Run
Expand Down
6 changes: 6 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ var acceptableKeys = map[string]string{
"synthetic-monitoring.metrics-id": "string",
"synthetic-monitoring.logs-id": "string",
"targets": "[]string",
"output-format": "string",
"only-spec": "bool",
}

func Set(path string, value string) error {
Expand All @@ -168,6 +170,10 @@ func Set(path string, value string) error {
val = value
case "[]string":
val = strings.Split(value, ",")
case "bool":
val = strings.ToLower(value) == "true"
default:
return fmt.Errorf("Unknown config key type %s for key %s", typ, key)
}
viper.Set(fullPath, val)
return Write()
Expand Down
32 changes: 17 additions & 15 deletions pkg/config/model.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
package config

type GrafanaConfig struct {
URL string `yaml:"url"`
User string `yaml:"user"`
Token string `yaml:"token"`
URL string `yaml:"url" mapstructure:"url"`
User string `yaml:"user" mapstructure:"user"`
Token string `yaml:"token" mapstructure:"token"`
}

type MimirConfig struct {
Address string `yaml:"address"`
TenantID int64 `yaml:"tenant-id"`
ApiKey string `yaml:"api-key"`
Address string `yaml:"address" mapstructure:"address"`
TenantID int64 `yaml:"tenant-id" mapstructure:"tenant-id"`
ApiKey string `yaml:"api-key" mapstructure:"api-key"`
}

type SyntheticMonitoringConfig struct {
Token string `yaml:"token"`
StackID int64 `yaml:"stack-id"`
LogsID int64 `yaml:"logs-id"`
MetricsID int64 `yaml:"metrics-id"`
Token string `yaml:"token" mapstructure:"token"`
StackID int64 `yaml:"stack-id" mapstructure:"stack-id"`
LogsID int64 `yaml:"logs-id" mapstructure:"logs-id"`
MetricsID int64 `yaml:"metrics-id" mapstructure:"metrics-id"`
}

type Context struct {
Name string `yaml:"name"`
Grafana GrafanaConfig `yaml:"grafana"`
Mimir MimirConfig `yaml:"mimir"`
SyntheticMonitoring SyntheticMonitoringConfig `yaml:"synthetic-monitoring"`
Targets []string `yaml:"targets"`
Name string `yaml:"name" mapstructure:"name"`
Grafana GrafanaConfig `yaml:"grafana" mapstructure:"grafana"`
Mimir MimirConfig `yaml:"mimir" mapstructure:"mimir"`
SyntheticMonitoring SyntheticMonitoringConfig `yaml:"synthetic-monitoring" mapstructure:"synthetic-monitoring"`
Targets []string `yaml:"targets" mapstructure:"targets"`
OutputFormat string `yaml:"output-format" mapstructure:"output-format"`
OnlySpec bool `yaml:"only-spec" mapstructure:"only-spec"`
}
5 changes: 0 additions & 5 deletions pkg/grafana/alertgroup-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ func (h *AlertRuleGroupHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a alertRuleGroup
func (h *AlertRuleGroupHandler) GetExtension() string {
return "json"
}

const (
alertRuleGroupGlob = "alert-rules/alertRuleGroup-*"
alertRuleGroupPattern = "alert-rules/alertRuleGroup-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/contactpoint-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ func (h *AlertContactPointHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a contactPoint
func (h *AlertContactPointHandler) GetExtension() string {
return "json"
}

const (
contactPointGlob = "alert-contact-points/contactPoint-*"
contactPointPattern = "alert-contact-points/contactPoint-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/dashboard-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ func (h *DashboardHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a dashboard
func (h *DashboardHandler) GetExtension() string {
return "json"
}

const (
dashboardGlob = "dashboards/*/dashboard-*"
dashboardPattern = "dashboards/%s/dashboard-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/datasource-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ func (h *DatasourceHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a datasource
func (h *DatasourceHandler) GetExtension() string {
return "json"
}

const (
datasourceGlob = "datasources/datasource-*"
datasourcePattern = "datasources/datasource-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/folder-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ func (h *FolderHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a dashboard
func (h *FolderHandler) GetExtension() string {
return "json"
}

const (
folderGlob = "folders/folder-*"
folderPattern = "folders/folder-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/library-elements-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ func (h *LibraryElementHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a library element
func (h *LibraryElementHandler) GetExtension() string {
return "json"
}

const (
libraryElementGlob = "library-elements/*-*"
libraryElementPattern = "library-elements/%s-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/notificationpolicy-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ func (h *AlertNotificationPolicyHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a alertNotificationPolicy
func (h *AlertNotificationPolicyHandler) GetExtension() string {
return "json"
}

const (
alertNotificationPolicyFile = "alertNotificationPolicy.yaml"
)
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/rules-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ func (h *RuleHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a rule grouping
func (h *RuleHandler) GetExtension() string {
return "yaml"
}

const (
prometheusRuleGroupGlob = "prometheus/rules-*"
prometheusRuleGroupPattern = "prometheus/rules-%s.%s"
Expand Down
5 changes: 0 additions & 5 deletions pkg/grafana/synthetic-monitoring-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ func (h *SyntheticMonitoringHandler) APIVersion() string {
return h.Provider.APIVersion()
}

// GetExtension returns the file name extension for a check
func (h *SyntheticMonitoringHandler) GetExtension() string {
return "json"
}

const (
syntheticMonitoringCheckGlob = "synthetic-monitoring/check-*"
syntheticMonitoringPattern = "synthetic-monitoring/check-%s.%s"
Expand Down
6 changes: 4 additions & 2 deletions pkg/grizzly/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ type Opts struct {
Directory bool // Deprecated: now is gathered with os.Stat(<resource-path>)
JsonnetPaths []string
Targets []string
OutputFormat string

// Used for supporting commands that output dashboard JSON
FolderUID string
JSONSpec bool
FolderUID string
OnlySpec bool
HasOnlySpec bool
}

// PreviewOpts contains options to configure a preview
Expand Down
65 changes: 65 additions & 0 deletions pkg/grizzly/formatting.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package grizzly

import (
"os"
"path/filepath"
)

func Format(resourcePath string, resource *Resource, format string, onlySpec bool) ([]byte, string, string, error) {
var content string
var filename string
var extension string
var err error

spec := resource
if onlySpec {
s := Resource(resource.Spec())
spec = &s
}

switch format {
case "yaml":
extension = "yaml"
filename, err = getFilename(resourcePath, resource, extension)
if err != nil {
return nil, "", "", err
}
content, err = spec.YAML()
case "json":
extension = "json"
filename, err = getFilename(resourcePath, resource, extension)
if err != nil {
return nil, "", "", err
}
content, err = spec.JSON()
default:
extension = "yaml"
filename, err = getFilename(resourcePath, resource, extension)
if err != nil {
return nil, "", "", err
}
content, err = spec.YAML()
}
return []byte(content), filename, extension, err
}

func getFilename(resourcePath string, resource *Resource, extension string) (string, error) {
handler, err := Registry.GetHandler(resource.Kind())
if err != nil {
return "", err
}
return filepath.Join(resourcePath, handler.ResourceFilePath(*resource, extension)), nil
}

func WriteFile(filename string, content []byte) error {
dir := filepath.Dir(filename)
err := os.MkdirAll(dir, 0755)
if err != nil {
return err
}
err = os.WriteFile(filename, content, 0644)
if err != nil {
return err
}
return nil
}
Loading

0 comments on commit 1646298

Please sign in to comment.