Skip to content

Commit

Permalink
Updating Context Logic and moving context into the apphelpers package (
Browse files Browse the repository at this point in the history
…#40)

* Updating Context Logic and moving context into the apphelpers package

* Updating documentation to reflect context changes.

* Adding a walk through wizard to create a new context.

Fixes #39

* Adding a context clear functionality
  • Loading branch information
safaci2000 authored Aug 4, 2021
1 parent 64e3804 commit 67fb8d6
Show file tree
Hide file tree
Showing 44 changed files with 513 additions and 147 deletions.
28 changes: 26 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
"version": "0.2.0",
"configurations": [
{
"name": "dash list",
"name": "Dash list",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go",
"args": [
"dash",
"ds",
"list",
]
},
Expand Down Expand Up @@ -95,6 +95,30 @@
"org",
"list",
]
},
{
"name": "ctx cp",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go",
"args": [
"ctx",
"cp",
"qa",
"foobar"
]
},
{
"name": "ctx clear",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go",
"args": [
"ctx",
"clear"
]
}
]
}
6 changes: 3 additions & 3 deletions api/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"strings"

"github.com/gosimple/slug"
"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/grafana-tools/sdk"
"github.com/netsage-project/grafana-dashboard-manager/apphelpers"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -49,9 +49,9 @@ func buildDataSourcePath(conf *viper.Viper, name string) string {
//getResourcePath for a gven resource type: ["dashboard", "ds"] it'll return the configured location
func getResourcePath(conf *viper.Viper, resourceType string) string {
if resourceType == "dashboard" {
return config.GetDefaultGrafanaConfig().OutputDashboard
return apphelpers.GetCtxDefaultGrafanaConfig().OutputDashboard
} else if resourceType == "ds" {
return config.GetDefaultGrafanaConfig().OutputDataSource
return apphelpers.GetCtxDefaultGrafanaConfig().OutputDataSource
}
return ""
}
Expand Down
3 changes: 2 additions & 1 deletion api/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"github.com/grafana-tools/sdk"
"github.com/netsage-project/grafana-dashboard-manager/apphelpers"
"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -36,7 +37,7 @@ type DashNGoImpl struct {
}

func (s *DashNGoImpl) init() {
s.grafanaConf = config.GetDefaultGrafanaConfig()
s.grafanaConf = apphelpers.GetCtxDefaultGrafanaConfig()
s.configRef = config.Config().ViperConfig()
s.client = s.Login()
s.adminClient = s.AdminLogin()
Expand Down
4 changes: 2 additions & 2 deletions api/datasources.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"strings"

"github.com/gosimple/slug"
"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/grafana-tools/sdk"
"github.com/netsage-project/grafana-dashboard-manager/config"
log "github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -101,7 +101,7 @@ func (s *DashNGoImpl) ExportDataSources(filter Filter) []string {
if !filter.Validate(map[string]string{Name: GetSlug(newDS.Name)}) {
continue
}
dsConfig := config.GetDefaultGrafanaConfig()
dsConfig := s.grafanaConf
var creds *config.GrafanaDataSource

if *newDS.BasicAuth {
Expand Down
4 changes: 2 additions & 2 deletions api/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"regexp"
"strings"

"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/netsage-project/grafana-dashboard-manager/apphelpers"
"github.com/thoas/go-funk"
)

Expand Down Expand Up @@ -71,7 +71,7 @@ func (s *DashboardFilter) init() {
//GetFolders splits the comma delimited folder list and returns a slice
func (s *DashboardFilter) GetFolders() []string {
if s.GetFilter(FolderFilter) == "" {
return config.GetDefaultGrafanaConfig().GetMonitoredFolders()
return apphelpers.GetCtxDefaultGrafanaConfig().GetMonitoredFolders()
}
folderFilter := s.GetFilter(FolderFilter)
folderFilter = s.quoteRegex.ReplaceAllString(folderFilter, "")
Expand Down
4 changes: 2 additions & 2 deletions api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import (
"fmt"
"os"

"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/grafana-tools/sdk"
"github.com/netsage-project/grafana-dashboard-manager/apphelpers"
"github.com/sirupsen/logrus"
)

func validateUserAPI(client *sdk.Client) {
if client == nil || !config.GetDefaultGrafanaConfig().AdminEnabled {
if client == nil || !apphelpers.GetCtxDefaultGrafanaConfig().AdminEnabled {
logrus.Fatal("Missing Admin client, please check your config and ensure basic auth is configured")
os.Exit(1)
}
Expand Down
225 changes: 225 additions & 0 deletions apphelpers/contextHelper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package apphelpers

import (
"fmt"
"os"
"strings"

// "github.com/labstack/gommon/log"
"github.com/AlecAivazis/survey/v2"
"github.com/netsage-project/grafana-dashboard-manager/config"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
"github.com/thoas/go-funk"
"gopkg.in/yaml.v2"
)

//GetContext returns the name of the selected context
func GetContext() string {
name := config.Config().ViperConfig().GetString("context_name")
return name
}

func NewContext(name string) {
answers := config.GrafanaConfig{
DataSourceSettings: make(map[string]*config.GrafanaDataSource),
}
promptAnswers := struct {
AuthType string
Folders string
DSUser string
DSPassword string
}{}
//Setup question that drive behavior
var behaviorQuestions = []*survey.Question{
{
Name: "AuthType",
Prompt: &survey.Select{
Message: "Will you be using a Token, BasicAuth, or both?",
Options: []string{"token", "basicauth", "both"},
Default: "basicauth",
},
},
{
Name: "Folders",
Prompt: &survey.Input{Message: "List the folders you wish to manage (example: folder1,folder2)? (Blank for General)?"},
},
{
Name: "DSUser",
Prompt: &survey.Input{Message: "Please enter your datasource default username"},
},
{
Name: "DSPassword",
Prompt: &survey.Password{Message: "Please enter your datasource default password"},
},
}
err := survey.Ask(behaviorQuestions, &promptAnswers)
if err != nil {
log.Fatal("Failed to get valid answers to generate a new context")
}

//Set Watched Folders
foldersList := strings.Split(promptAnswers.Folders, ",")
if len(foldersList) > 0 && foldersList[0] != "" {
answers.MonitoredFolders = foldersList
} else {
answers.MonitoredFolders = []string{"General"}
}
//Set Default Datasource
if promptAnswers.DSUser != "" && promptAnswers.DSPassword != "" {
ds := config.GrafanaDataSource{
User: promptAnswers.DSUser,
Password: promptAnswers.DSPassword,
}
answers.DataSourceSettings["default"] = &ds
}

//Setup grafana required field based on responses
var questions = []*survey.Question{
{
Name: "URL",
Prompt: &survey.Input{Message: "What is the Grafana URL include http(s)?"},
},
{
Name: "OutputDashboard",
Prompt: &survey.Input{Message: "Dashboard destination folder?"},
},
{
Name: "OutputDataSource",
Prompt: &survey.Input{Message: "Datasource destination folder?"},
},
}

if promptAnswers.AuthType == "both" || promptAnswers.AuthType == "token" {
questions = append(questions, &survey.Question{
Name: "APIToken",
Prompt: &survey.Input{Message: "Please enter your API Token"},
Validate: survey.Required,
})
}

if promptAnswers.AuthType == "both" || promptAnswers.AuthType == "basicauth" {
answers.AdminEnabled = true
questions = append(questions, &survey.Question{
Name: "UserName",
Prompt: &survey.Input{Message: "Please enter your admin UserName"},
Validate: survey.Required,
})
questions = append(questions, &survey.Question{
Name: "Password",
Prompt: &survey.Password{Message: "Please enter your admin Password"},
Validate: survey.Required,
})

}

err = survey.Ask(questions, &answers)
if err != nil {
log.Fatal(err.Error())
}

v := config.Config().ViperConfig()
contextMap := config.Config().Contexts()

contextMap[name] = &answers
v.Set("contexts", contextMap)
v.WriteConfig()
SetContext(name)
log.Infof("New configuration %s has been created", name)

}

//ShowContext displays the selected context
func ShowContext(ctx string) {
grafana := GetCtxGrafanaConfig(ctx)
d, err := yaml.Marshal(grafana)
if err != nil {
log.Info("Failed to serialize context")
os.Exit(1)
}
fmt.Printf("---%s:\n%s\n\n", ctx, string(d))

}

//ClearContexts clear all contexts except a simple running example
// (required for app not to error out)
func ClearContexts() {
v := config.Config().ViperConfig()
newContext := make(map[string]*config.GrafanaConfig)
newContext["example"] = &config.GrafanaConfig{
APIToken: "dummy",
}
v.Set("context_name", "example")
v.Set("contexts", newContext)
v.WriteConfig()
}

func CopyContext(src, dest string) {
v, contexts := getContextReferences()
srcCtx := v.GetStringMap(fmt.Sprintf("contexts.%s", src))
//Validate context
if len(contexts) == 0 {
log.Fatal("Cannot set context. No valid configuration found in importer.yml")
}
contexts[dest] = srcCtx
v.Set("contexts", contexts)
SetContext(dest)
log.Infof("Copied %s context to %s please check your config to confirm", src, dest)
}

//SetContext will try to find the specified context, if it exists in the file, will re-write the importer.yml
//with the selected context
func SetContext(context string) {
v, _ := getContextReferences()
m := config.Config().Contexts()
if len(m) == 0 {
log.Fatal("Cannot set context. No valid configuration found in importer.yml")
}
v.Set("context_name", context)
v.WriteConfig()
}

//getContextReferences Helper method to get viper and context map
func getContextReferences() (*viper.Viper, map[string]interface{}) {
v := config.Config().ViperConfig()
contexts := config.Config().ViperConfig().GetStringMap("contexts")

return v, contexts

}

//DeleteContext Delete a specific
func DeleteContext(context string) {
activeCtx := GetContext()
if activeCtx == context {
log.Fatalf("Cannot delete context since it's currently active, please change context before deleting %s", context)
}
v, contextMap := getContextReferences()
delete(contextMap, context)
v.Set("contexts", contextMap)
v.WriteConfig()
}

//GetContexts returns all available contexts
func GetContexts() []string {
contextMap := config.Config().ViperConfig().GetStringMap("contexts")
return funk.Keys(contextMap).([]string)
}

//GetCtxGrafanaConfig returns the selected context or terminates app if not found
func GetCtxGrafanaConfig(name string) *config.GrafanaConfig {
val, ok := config.Config().Contexts()[name]
if ok {
return val
} else {
log.Error("Context is not found. Please check your config")
os.Exit(1)
}

return nil
}

//GetCtxDefaultGrafanaConfig returns the default aka. selected grafana config
func GetCtxDefaultGrafanaConfig() *config.GrafanaConfig {
return GetCtxGrafanaConfig(GetContext())
}
21 changes: 21 additions & 0 deletions cmd/contextClear.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cmd

import (
"github.com/netsage-project/grafana-dashboard-manager/apphelpers"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var contextClear = &cobra.Command{
Use: "clear",
Short: "clear all context",
Long: `clear all contexts`,
Run: func(cmd *cobra.Command, args []string) {
apphelpers.ClearContexts()
log.Info("Successfully deleted all configured contexts")
},
}

func init() {
context.AddCommand(contextClear)
}
Loading

0 comments on commit 67fb8d6

Please sign in to comment.