Skip to content

Commit

Permalink
Handling only-spec
Browse files Browse the repository at this point in the history
  • Loading branch information
malcolmholmes committed Jan 29, 2024
1 parent 090bc97 commit bb6fb12
Show file tree
Hide file tree
Showing 13 changed files with 73 additions and 56 deletions.
3 changes: 2 additions & 1 deletion cmd/grr/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ func applyCmd() *cli.Command {
return grizzly.Apply(resources)
}

cmd.Flags().StringVarP(&opts.FolderUID, "folder", "f", generalFolderUID, "folder to push dashboards to")
cmd = initialiseOnlySpec(cmd, &opts)
return initialiseCmd(cmd, &opts)
}
Expand Down Expand Up @@ -295,6 +294,8 @@ func initialiseCmd(cmd *cli.Command, opts *grizzly.Opts) *cli.Command {

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")
cmd.Flags().StringVarP(&opts.FolderUID, "folder", "f", generalFolderUID, "folder to push dashboards to")
cmd.Flags().StringVarP(&opts.ResourceKind, "kind", "k", "", "Kind to use for resources. Requires --only-spec")
cmdRun := cmd.Run
cmd.Run = func(cmd *cli.Command, args []string) error {
opts.HasOnlySpec = cmd.Flags().Changed("only-spec")
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/alertgroup-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ func (h *AlertRuleGroupHandler) Update(existing, resource grizzly.Resource) erro
return h.putAlertRuleGroup(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *AlertRuleGroupHandler) UsesFolders() bool {
return false
}

// getRemoteAlertRuleGroup retrieves a alertRuleGroup object from Grafana
func (h *AlertRuleGroupHandler) getRemoteAlertRuleGroup(uid string) (*grizzly.Resource, error) {
folder, group := h.splitUID(uid)
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/contactpoint-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func (h *AlertContactPointHandler) Update(existing, resource grizzly.Resource) e
return h.putContactPoint(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *AlertContactPointHandler) UsesFolders() bool {
return false
}

// getRemoteContactPoint retrieves a contactPoint object from Grafana
func (h *AlertContactPointHandler) getRemoteContactPoint(uid string) (*grizzly.Resource, error) {
client, err := h.Provider.(ClientProvider).Client()
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/dashboard-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ func (h *DashboardHandler) Preview(resource grizzly.Resource, opts *grizzly.Prev
return nil
}

// UsesFolders identifies whether this resource lives within a folder
func (h *DashboardHandler) UsesFolders() bool {
return true
}

// getRemoteDashboard retrieves a dashboard object from Grafana
func (h *DashboardHandler) getRemoteDashboard(uid string) (*grizzly.Resource, error) {
client, err := h.Provider.(ClientProvider).Client()
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/datasource-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ func (h *DatasourceHandler) Update(existing, resource grizzly.Resource) error {
return h.putDatasource(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *DatasourceHandler) UsesFolders() bool {
return false
}

// getRemoteDatasource retrieves a datasource object from Grafana
func (h *DatasourceHandler) getRemoteDatasource(uid string) (*grizzly.Resource, error) {
client, err := h.Provider.(ClientProvider).Client()
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/folder-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ func (h *FolderHandler) Update(existing, resource grizzly.Resource) error {
return h.putFolder(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *FolderHandler) UsesFolders() bool {
return false
}

// getRemoteFolder retrieves a folder object from Grafana
func (h *FolderHandler) getRemoteFolder(uid string) (*grizzly.Resource, error) {
var folder *models.Folder
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/library-elements-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ func (h *LibraryElementHandler) Update(existing, resource grizzly.Resource) erro
return h.updateElement(existing, resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *LibraryElementHandler) UsesFolders() bool {
return false
}

func (h *LibraryElementHandler) listElements() ([]string, error) {
params := library.NewGetLibraryElementsParams()
client, err := h.Provider.(ClientProvider).Client()
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/notificationpolicy-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func (h *AlertNotificationPolicyHandler) Update(existing, resource grizzly.Resou
return h.putAlertNotificationPolicy(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *AlertNotificationPolicyHandler) UsesFolders() bool {
return false
}

// getRemoteAlertNotificationPolicy retrieves a alertNotificationPolicy object from Grafana
func (h *AlertNotificationPolicyHandler) getRemoteAlertNotificationPolicy() (*grizzly.Resource, error) {
client, err := h.Provider.(ClientProvider).Client()
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/rules-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ func (h *RuleHandler) Update(existing, resource grizzly.Resource) error {
return h.writeRuleGroup(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *RuleHandler) UsesFolders() bool {
return false
}

var cortexTool = func(mimirConfig *config.MimirConfig, args ...string) ([]byte, error) {
path := os.Getenv("CORTEXTOOL_PATH")
if path == "" {
Expand Down
5 changes: 5 additions & 0 deletions pkg/grafana/synthetic-monitoring-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ func (h *SyntheticMonitoringHandler) Update(existing, resource grizzly.Resource)
return h.updateCheck(resource)
}

// UsesFolders identifies whether this resource lives within a folder
func (h *SyntheticMonitoringHandler) UsesFolders() bool {
return false
}

// NewSyntheticMonitoringClient creates a new client for synthetic monitoring go client
func (h *SyntheticMonitoringHandler) NewSyntheticMonitoringClient() (*smapi.Client, error) {
grizzlyContext, err := config.CurrentContext()
Expand Down
9 changes: 5 additions & 4 deletions pkg/grizzly/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ type Opts struct {
Targets []string
OutputFormat string

// Used for supporting commands that output dashboard JSON
FolderUID string
OnlySpec bool
HasOnlySpec bool
// Used for legacy forms that do not include the metadata envelope
OnlySpec bool
HasOnlySpec bool
FolderUID string
ResourceKind string
}

// PreviewOpts contains options to configure a preview
Expand Down
69 changes: 18 additions & 51 deletions pkg/grizzly/parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"path/filepath"
"strconv"
"strings"

"github.com/google/go-jsonnet"
"github.com/grafana/grizzly/pkg/config"
Expand Down Expand Up @@ -59,10 +60,6 @@ func FindResourceFiles(resourcePath string) ([]string, error) {
}

func ParseFile(opts Opts, resourceFile string) (Resources, error) {
if opts.OnlySpec && filepath.Ext(resourceFile) != ".json" {
return nil, fmt.Errorf("when -s flag is passed, command expects only json files as resources")
}

switch filepath.Ext(resourceFile) {
case ".json":
return ParseJSON(resourceFile, opts)
Expand All @@ -75,79 +72,49 @@ func ParseFile(opts Opts, resourceFile string) (Resources, error) {
}
}

func manifestFile(resourceFile string) (bool, error) {
if filepath.Ext(resourceFile) != ".json" {
return false, nil
}
// ParseJSON evaluates a JSON file and parses it into resources
func ParseJSON(resourceFile string, opts Opts) (Resources, error) {

m := map[string]interface{}{}

f, err := os.Open(resourceFile)
if err != nil {
return false, err
return nil, err
}

err = json.NewDecoder(f).Decode(&m)
if err != nil {
return false, err
}

if _, ok := m["spec"]; ok {
return true, nil
return nil, err
}

return false, nil
}

// ParseJSON evaluates a JSON file and parses it into resources
func ParseJSON(resourceFile string, opts Opts) (Resources, error) {
var resource Resource
if opts.OnlySpec {
return ParseDashboardJSON(resourceFile, opts)
}

isManifest, err := manifestFile(resourceFile)
if err != nil {
return Resources{}, err
}

// TODO: refactor, no need to read the file twice
if !isManifest {
return ParseDashboardJSON(resourceFile, opts)
resource = newResource(resourceFile, m, opts.ResourceKind, opts.FolderUID)
} else {
resource = Resource(m)
}

return ParseJsonnet(resourceFile, opts)
return Resources{resource}, nil
}

// ParseDashboardJSON parses a JSON file with a single dashboard object into a Resources (to align with ParseFile interface)
func ParseDashboardJSON(jsonFile string, opts Opts) (Resources, error) {
if filepath.Ext(jsonFile) != ".json" {
return nil, fmt.Errorf("when -s flag is passed, command expects only json files as resources")
}
func newResource(resourceFile string, spec map[string]any, kind, folderUID string) map[string]any {
uid := strings.ReplaceAll(filepath.Base(resourceFile), filepath.Ext(resourceFile), "")

f, err := os.Open(jsonFile)
if err != nil {
return nil, err
}

var spec map[string]interface{}
err = json.NewDecoder(f).Decode(&spec)
if err != nil {
return Resources{}, err
}

handler := Registry.Handlers["Dashboard"]
handler := Registry.Handlers[kind]

resource := Resource{
"apiVersion": handler.APIVersion(),
"kind": handler.Kind(),
"metadata": map[string]interface{}{
"folder": opts.FolderUID,
"name": spec["uid"],
"name": uid,
},
"spec": spec,
}
if handler.UsesFolders() {
resource.SetMetadata("folder", folderUID)
}

return Resources{resource}, nil
return resource
}

// ParseYAML evaluates a YAML file and parses it into resources
Expand Down
3 changes: 3 additions & 0 deletions pkg/grizzly/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ type Handler interface {

// Sort sorts resources as defined by the handler
Sort(resources Resources) Resources

// UsesFolders identifies whether this resource lives within a folder
UsesFolders() bool
}

// PreviewHandler describes a handler that has the ability to render
Expand Down

0 comments on commit bb6fb12

Please sign in to comment.