diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 1ef69664..fec7e90f 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -88,12 +88,8 @@ jobs: restore-keys: | ${{ runner.os }}-go- - - name: Starting SFTP Server - run: docker run -p 2222:22 -d atmoz/sftp "foo:pass:::testing" - name: Wait for Minio to come up. run: nc -z -v -w15 127.0.0.1 9000 - - name: Wait for SSH to come up. - run: nc -z -v -w15 127.0.0.1 2222 - name: Calc coverage if: "${{ matrix.go == '1.20.2' && matrix.grafana == '9.4.3' }}" run: | diff --git a/cmd/alertnotifications.go b/cmd/alertnotifications.go index 21f4003f..d4689a8c 100644 --- a/cmd/alertnotifications.go +++ b/cmd/alertnotifications.go @@ -2,7 +2,7 @@ package cmd import ( "fmt" - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" @@ -27,7 +27,7 @@ var clearAlertNotifications = &cobra.Command{ log.Warn("Alert Notifications will be deprecated as of Grafana 9.0, this API may no longer work soon") tableObj.AppendHeader(table.Row{"type", "filename"}) - log.Infof("Clearing all alert notification channels for context: '%s'", apphelpers.GetContext()) + log.Infof("Clearing all alert notification channels for context: '%s'", config.Config().AppConfig.GetContext()) deleted := grafanaSvc.DeleteAllAlertNotifications() for _, item := range deleted { tableObj.AppendRow(table.Row{"alertnotification", item}) @@ -50,7 +50,7 @@ var uploadAlertNotifications = &cobra.Command{ log.Warn("Alert Notifications will be deprecated as of Grafana 9.0, this API may no longer work soon") tableObj.AppendHeader(table.Row{"name", "id", "UID"}) - log.Infof("Exporting alert notification channels for context: '%s'", apphelpers.GetContext()) + log.Infof("Exporting alert notification channels for context: '%s'", config.Config().AppConfig.GetContext()) grafanaSvc.ExportAlertNotifications() items := grafanaSvc.ListAlertNotifications() for _, item := range items { @@ -73,7 +73,7 @@ var downloadAlertNotifications = &cobra.Command{ log.Warn("Alert Notifications will be deprecated as of Grafana 9.0, this API may no longer work soon") tableObj.AppendHeader(table.Row{"type", "filename"}) - log.Infof("Importing alert notification channels for context: '%s'", apphelpers.GetContext()) + log.Infof("Importing alert notification channels for context: '%s'", config.Config().AppConfig.GetContext()) savedFiles := grafanaSvc.ImportAlertNotifications() for _, file := range savedFiles { tableObj.AppendRow(table.Row{"alertnotification", file}) @@ -93,12 +93,12 @@ var listAlertNotifications = &cobra.Command{ tableObj.AppendHeader(table.Row{"id", "name", "slug", "type", "default", "url"}) alertnotifications := grafanaSvc.ListAlertNotifications() - log.Infof("Listing alert notifications channels for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing alert notifications channels for context: '%s'", config.Config().AppConfig.GetContext()) if len(alertnotifications) == 0 { log.Info("No alert notifications found") } else { for _, link := range alertnotifications { - url := fmt.Sprintf("%s/alerting/notification/%d/edit", apphelpers.GetCtxDefaultGrafanaConfig().URL, link.ID) + url := fmt.Sprintf("%s/alerting/notification/%d/edit", config.Config().GetDefaultGrafanaConfig().URL, link.ID) tableObj.AppendRow(table.Row{link.ID, link.Name, service.GetSlug(link.Name), link.Type, link.IsDefault, url}) } tableObj.Render() diff --git a/cmd/auth_serviceAccts.go b/cmd/auth_serviceAccts.go index a0e6c635..eeb33171 100644 --- a/cmd/auth_serviceAccts.go +++ b/cmd/auth_serviceAccts.go @@ -2,10 +2,10 @@ package cmd import ( "errors" + "github.com/esnet/gdg/internal/config" "sort" "strconv" - "github.com/esnet/gdg/internal/apphelpers" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -74,7 +74,7 @@ var deleteServiceAcctsTokensCmd = &cobra.Command{ log.Fatalf("unable to parse %s as a valid numeric value", idStr) } - log.Infof("Deleting Service Accounts Tokens for serviceID %d for context: '%s'", id, apphelpers.GetContext()) + log.Infof("Deleting Service Accounts Tokens for serviceID %d for context: '%s'", id, config.Config().AppConfig.GetContext()) savedFiles := grafanaSvc.DeleteServiceAccountTokens(id) tableObj.AppendHeader(table.Row{"serviceID", "type", "token_name"}) if len(savedFiles) == 0 { @@ -95,7 +95,7 @@ var deleteServiceAcctsCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { savedFiles := grafanaSvc.DeleteAllServiceAccounts() - log.Infof("Delete Service Accounts for context: '%s'", apphelpers.GetContext()) + log.Infof("Delete Service Accounts for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"type", "filename"}) if len(savedFiles) == 0 { log.Info("No Service Accounts found") diff --git a/cmd/auth_tokens.go b/cmd/auth_tokens.go index 8bd1c1e1..e0c1f6d2 100644 --- a/cmd/auth_tokens.go +++ b/cmd/auth_tokens.go @@ -2,7 +2,7 @@ package cmd import ( "errors" - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -54,7 +54,7 @@ var deleteTokensCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { savedFiles := grafanaSvc.DeleteAllTokens() - log.Infof("Delete Tokens for context: '%s'", apphelpers.GetContext()) + log.Infof("Delete Tokens for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"type", "filename"}) if len(savedFiles) == 0 { log.Info("No Tokens found") diff --git a/cmd/context.go b/cmd/context.go index 7676995a..360d205f 100644 --- a/cmd/context.go +++ b/cmd/context.go @@ -3,7 +3,7 @@ package cmd import ( "errors" "fmt" - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -22,7 +22,7 @@ var contextClear = &cobra.Command{ Short: "clear all context", Long: `clear all contexts`, Run: func(cmd *cobra.Command, args []string) { - apphelpers.ClearContexts() + config.Config().ClearContexts() log.Info("Successfully deleted all configured contexts") }, } @@ -42,8 +42,7 @@ var contextCopy = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { src := args[0] dest := args[1] - apphelpers.CopyContext(src, dest) - + config.Config().CopyContext(src, dest) }, } @@ -60,7 +59,7 @@ var contextDelete = &cobra.Command{ }, Run: func(cmd *cobra.Command, args []string) { ctx := args[0] - apphelpers.DeleteContext(ctx) + config.Config().DeleteContext(ctx) log.Infof("Successfully deleted context %s", ctx) }, } @@ -71,15 +70,15 @@ var contextList = &cobra.Command{ Long: `List contexts.`, Run: func(cmd *cobra.Command, args []string) { tableObj.AppendHeader(table.Row{"context", "active"}) - contexts := apphelpers.GetContexts() - activeContext := apphelpers.GetContext() - for _, item := range contexts { + contexts := config.Config().GetAppConfig().GetContexts() + activeContext := config.Config().GetAppConfig().GetContext() + for key, _ := range contexts { active := false - if item == strings.ToLower(activeContext) { - item = fmt.Sprintf("*%s", activeContext) + if key == strings.ToLower(activeContext) { + key = fmt.Sprintf("*%s", activeContext) active = true } - tableObj.AppendRow(table.Row{item, active}) + tableObj.AppendRow(table.Row{key, active}) } tableObj.Render() @@ -99,8 +98,7 @@ var contextNew = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { ctx := args[0] - apphelpers.NewContext(ctx) - + config.Config().NewContext(ctx) }, } @@ -117,7 +115,7 @@ var contextSet = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { context := args[0] - apphelpers.SetContext(context) + config.Config().ChangeContext(context) }, } @@ -127,11 +125,11 @@ var contextShow = &cobra.Command{ Short: "show optional[context]", Long: `show contexts optional[context]`, Run: func(cmd *cobra.Command, args []string) { - context := apphelpers.GetContext() - if len(args) > 1 && len(args[0]) > 0 { + context := config.Config().GetAppConfig().GetContext() + if len(args) > 0 && len(args[0]) > 0 { context = args[0] } - apphelpers.ShowContext(context) + config.Config().PrintContext(context) }, } diff --git a/cmd/dashboard.go b/cmd/dashboard.go index d3758b6b..15fe8eb2 100644 --- a/cmd/dashboard.go +++ b/cmd/dashboard.go @@ -2,7 +2,7 @@ package cmd import ( "fmt" - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service" "github.com/esnet/gdg/internal/tools" "github.com/jedib0t/go-pretty/v6/table" @@ -65,7 +65,7 @@ var uploadDashboard = &cobra.Command{ if !skipConfirmAction { tools.GetUserConfirmation(fmt.Sprintf("WARNING: this will delete all dashboards from the monitored folders: '%s' "+ "(or all folders if ignore_dashboard_filters is set to true) and upload your local copy. Do you wish to "+ - "continue (y/n) ", strings.Join(apphelpers.GetCtxDefaultGrafanaConfig().GetMonitoredFolders(), ", "), + "continue (y/n) ", strings.Join(config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders(), ", "), ), "", true) } grafanaSvc.ExportDashboards(filter) @@ -94,7 +94,7 @@ var downloadDashboard = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { filter := service.NewDashboardFilter(parseDashboardGlobalFlags(cmd)...) savedFiles := grafanaSvc.ImportDashboards(filter) - log.Infof("Importing dashboards for context: '%s'", apphelpers.GetContext()) + log.Infof("Importing dashboards for context: '%s'", config.Config().GetAppConfig().GetContext()) tableObj.AppendHeader(table.Row{"type", "filename"}) for _, file := range savedFiles { tableObj.AppendRow(table.Row{"dashboard", file}) @@ -114,9 +114,9 @@ var listDashboards = &cobra.Command{ filters := service.NewDashboardFilter(parseDashboardGlobalFlags(cmd)...) boards := grafanaSvc.ListDashboards(filters) - log.Infof("Listing dashboards for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing dashboards for context: '%s'", config.Config().GetAppConfig().GetContext()) for _, link := range boards { - url := fmt.Sprintf("%s%s", apphelpers.GetCtxDefaultGrafanaConfig().URL, link.URL) + url := fmt.Sprintf("%s%s", config.Config().GetDefaultGrafanaConfig().URL, link.URL) tableObj.AppendRow(table.Row{link.ID, link.Title, link.Slug, link.FolderTitle, link.UID, strings.Join(link.Tags, ","), url}) diff --git a/cmd/datasources.go b/cmd/datasources.go index 790a4bfa..55d889e4 100644 --- a/cmd/datasources.go +++ b/cmd/datasources.go @@ -2,7 +2,7 @@ package cmd import ( "fmt" - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" @@ -60,7 +60,7 @@ var downloadDataSources = &cobra.Command{ Long: `download all datasources from grafana to local filesystem`, Aliases: []string{"d", "import"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Importing datasources for context: '%s'", apphelpers.GetContext()) + log.Infof("Importing datasources for context: '%s'", config.Config().GetAppConfig().GetContext()) dashboardFilter, _ := cmd.Flags().GetString("datasource") filters := service.NewDataSourceFilter(dashboardFilter) savedFiles := grafanaSvc.ImportDataSources(filters) @@ -83,12 +83,12 @@ var listDataSources = &cobra.Command{ dashboardFilter, _ := cmd.Flags().GetString("datasource") filters := service.NewDataSourceFilter(dashboardFilter) dsListing := grafanaSvc.ListDataSources(filters) - log.Infof("Listing datasources for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing datasources for context: '%s'", config.Config().GetAppConfig().GetContext()) if len(dsListing) == 0 { log.Info("No datasources found") } else { for _, link := range dsListing { - url := fmt.Sprintf("%s/datasource/edit/%d", apphelpers.GetCtxDefaultGrafanaConfig().URL, link.ID) + url := fmt.Sprintf("%s/datasource/edit/%d", config.Config().GetDefaultGrafanaConfig().URL, link.ID) tableObj.AppendRow(table.Row{link.ID, link.UID, link.Name, service.GetSlug(link.Name), link.Type, link.IsDefault, url}) } tableObj.Render() diff --git a/cmd/folders.go b/cmd/folders.go index 43533484..60b439f2 100644 --- a/cmd/folders.go +++ b/cmd/folders.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service" "github.com/esnet/gdg/internal/service/filters" "github.com/jedib0t/go-pretty/v6/table" @@ -33,7 +33,7 @@ var deleteFoldersCmd = &cobra.Command{ Long: `delete Folders from grafana`, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Deleting all Folders for context: '%s'", apphelpers.GetContext()) + log.Infof("Deleting all Folders for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"title"}) folders := grafanaSvc.DeleteAllFolder(getFolderFilter()) @@ -56,7 +56,7 @@ var uploadFoldersCmd = &cobra.Command{ Aliases: []string{"export", "u"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing Folders for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing Folders for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"file"}) folders := grafanaSvc.ExportFolder(getFolderFilter()) if len(folders) == 0 { @@ -78,7 +78,7 @@ var downloadFoldersCmd = &cobra.Command{ Aliases: []string{"import", "d"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing Folders for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing Folders for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"file"}) folders := grafanaSvc.ImportFolder(getFolderFilter()) if len(folders) == 0 { @@ -100,7 +100,7 @@ var listFoldersCmd = &cobra.Command{ Aliases: []string{"l"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing Folders for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing Folders for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"id", "uid", "title"}) folders := grafanaSvc.ListFolder(getFolderFilter()) diff --git a/cmd/library.go b/cmd/library.go index c8e08b07..0d7c04ac 100644 --- a/cmd/library.go +++ b/cmd/library.go @@ -2,7 +2,7 @@ package cmd import ( "encoding/json" - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" @@ -69,7 +69,7 @@ var downloadLibary = &cobra.Command{ log.Info("exporting lib elements") //filter := parseDashboardGlobalFlags(cmd) savedFiles := grafanaSvc.ImportLibraryElements(nil) - log.Infof("Importing library for context: '%s'", apphelpers.GetContext()) + log.Infof("Importing library for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"type", "filename"}) for _, file := range savedFiles { tableObj.AppendRow(table.Row{"library", file}) @@ -89,7 +89,7 @@ var listLibraries = &cobra.Command{ elements := grafanaSvc.ListLibraryElements(nil) log.Infof("Number of elements is: %d", len(elements)) - log.Infof("Listing library for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing library for context: '%s'", config.Config().AppConfig.GetContext()) for _, link := range elements { tableObj.AppendRow(table.Row{link.ID, link.UID, link.Meta.FolderName, link.Name, link.Type}) @@ -113,7 +113,7 @@ var listLibraryConnections = &cobra.Command{ libElmentUid := args[0] elements := grafanaSvc.ListLibraryElementsConnections(nil, libElmentUid) - log.Infof("Listing library for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing library connections for context: '%s'", config.Config().AppConfig.GetContext()) for _, link := range elements { dash := link.Dashboard.(map[string]interface{}) tableObj.AppendRow(table.Row{dash["id"].(json.Number), dash["uid"].(string), link.Meta.Slug, dash["title"].(string), link.Meta.FolderTitle}) diff --git a/cmd/organizations.go b/cmd/organizations.go index 8691fe84..34e84cb4 100644 --- a/cmd/organizations.go +++ b/cmd/organizations.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -21,7 +21,7 @@ var listOrgCmd = &cobra.Command{ Aliases: []string{"l"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing organizations for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing organizations for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"id", "org"}) listOrganizations := grafanaSvc.ListOrganizations() if len(listOrganizations) == 0 { diff --git a/cmd/team.go b/cmd/team.go index 9f3458eb..e5f91c15 100644 --- a/cmd/team.go +++ b/cmd/team.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" api "github.com/esnet/gdg/internal/service" "github.com/esnet/grafana-swagger-api-golang/goclient/models" "github.com/jedib0t/go-pretty/v6/table" @@ -29,7 +29,7 @@ var downloadTeamCmd = &cobra.Command{ Aliases: []string{"import", "d"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Importing Teams for context: '%s'", apphelpers.GetContext()) + log.Infof("Importing Teams for context: '%s'", config.Config().AppConfig.GetContext()) filter := api.NewTeamFilter(parseTeamGlobalFlags(cmd)...) savedFiles := grafanaSvc.ImportTeams(filter) if len(savedFiles) == 0 { @@ -54,7 +54,7 @@ var uploadTeamCmd = &cobra.Command{ Aliases: []string{"export", "u"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Exporting Teams for context: '%s'", apphelpers.GetContext()) + log.Infof("Exporting Teams for context: '%s'", config.Config().AppConfig.GetContext()) log.Warn("Currently support for import Admin members is not support, there will be 1 admin, which is the default admin user") filter := api.NewTeamFilter(parseTeamGlobalFlags(cmd)...) savedFiles := grafanaSvc.ExportTeams(filter) @@ -90,7 +90,7 @@ var listTeamCmd = &cobra.Command{ Aliases: []string{"l"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing teams for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing teams for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"id", "name", "email", "orgID", "memberCount", "memberID", "member Permission"}) filter := api.NewTeamFilter(parseTeamGlobalFlags(cmd)...) teams := grafanaSvc.ListTeams(filter) @@ -117,7 +117,7 @@ var deleteTeamCmd = &cobra.Command{ Long: `Delete All Team from grafana`, Aliases: []string{"c"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Deleting teams for context: '%s'", apphelpers.GetContext()) + log.Infof("Deleting teams for context: '%s'", config.Config().AppConfig.GetContext()) filter := api.NewTeamFilter(parseTeamGlobalFlags(cmd)...) tableObj.AppendHeader(table.Row{"type", "team ID", "team Name"}) teams, err := grafanaSvc.DeleteTeam(filter) diff --git a/cmd/users.go b/cmd/users.go index 91a4ffa0..5c22af0a 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service" "github.com/jedib0t/go-pretty/v6/table" log "github.com/sirupsen/logrus" @@ -25,7 +25,7 @@ var promoteUser = &cobra.Command{ Aliases: []string{"godmode"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing dashboards for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing dashboards for context: '%s'", config.Config().AppConfig.GetContext()) userLogin, _ := cmd.Flags().GetString("user") msg, err := grafanaSvc.PromoteUser(userLogin) @@ -46,7 +46,7 @@ var deleteUsersCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { authLabel, _ := cmd.Flags().GetString("authlabel") savedFiles := grafanaSvc.DeleteAllUsers(service.NewUserFilter(authLabel)) - log.Infof("Delete Users for context: '%s'", apphelpers.GetContext()) + log.Infof("Delete Users for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"type", "filename"}) if len(savedFiles) == 0 { log.Info("No users found") @@ -65,10 +65,9 @@ var uploadUsersCmd = &cobra.Command{ Long: `upload users to grafana`, Aliases: []string{"export", "u"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Uploading Users to context: '%s'", apphelpers.GetContext()) + log.Infof("Uploading Users to context: '%s'", config.Config().AppConfig.GetContext()) authLabel, _ := cmd.Flags().GetString("authlabel") savedFiles := grafanaSvc.ExportUsers(service.NewUserFilter(authLabel)) - log.Infof("Exporting Users for context: '%s'", apphelpers.GetContext()) tableObj.AppendHeader(table.Row{"id", "login", "name", "email", "grafanaAdmin", "disabled", "default Password", "authLabels"}) if len(savedFiles) == 0 { log.Info("No users found") @@ -92,10 +91,9 @@ var downloadUsersCmd = &cobra.Command{ Long: `download users from grafana`, Aliases: []string{"import", "d"}, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing dashboards for context: '%s'", apphelpers.GetContext()) authLabel, _ := cmd.Flags().GetString("authlabel") savedFiles := grafanaSvc.ImportUsers(service.NewUserFilter(authLabel)) - log.Infof("Importing Users for context: '%s'", apphelpers.GetContext()) + log.Infof("Importing Users for context: '%s'", config.Config().AppConfig.GetContext()) tableObj.AppendHeader(table.Row{"type", "filename"}) if len(savedFiles) == 0 { log.Info("No users found") @@ -114,7 +112,7 @@ var listUserCmd = &cobra.Command{ Long: `list users`, Run: func(cmd *cobra.Command, args []string) { - log.Infof("Listing users for context: '%s'", apphelpers.GetContext()) + log.Infof("Listing users for context: '%s'", config.Config().AppConfig.GetContext()) authLabel, _ := cmd.Flags().GetString("authlabel") tableObj.AppendHeader(table.Row{"id", "login", "name", "email", "admin", "disabled", "default Password", "authLabels"}) users := grafanaSvc.ListUsers(service.NewUserFilter(authLabel)) diff --git a/config/testing.yml b/config/testing.yml index aed147cd..c899bb2a 100644 --- a/config/testing.yml +++ b/config/testing.yml @@ -92,3 +92,11 @@ contexts: global: debug: true ignore_ssl_errors: false ##when set to true will ignore invalid SSL errors + + +storage_engine: + test: + kind: cloud + cloud_type: s3 + bucket_name: "" + prefix: "" \ No newline at end of file diff --git a/internal/api/extended.go b/internal/api/extended.go index cf864eac..ec14194a 100644 --- a/internal/api/extended.go +++ b/internal/api/extended.go @@ -3,7 +3,6 @@ package api import ( "crypto/tls" "github.com/carlmjohnson/requests" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "net/http" ) @@ -15,7 +14,7 @@ type ExtendedApi struct { } func NewExtendedApi() *ExtendedApi { - cfg := apphelpers.GetCtxDefaultGrafanaConfig() + cfg := config.Config().GetDefaultGrafanaConfig() o := ExtendedApi{ grafanaCfg: cfg, } diff --git a/internal/apphelpers/contextHelper.go b/internal/apphelpers/contextHelper.go deleted file mode 100644 index fb385687..00000000 --- a/internal/apphelpers/contextHelper.go +++ /dev/null @@ -1,248 +0,0 @@ -package apphelpers - -import ( - "fmt" - "github.com/esnet/gdg/internal/config" - "strings" - - "github.com/AlecAivazis/survey/v2" - log "github.com/sirupsen/logrus" - "github.com/spf13/viper" - "github.com/thoas/go-funk" - "gopkg.in/yaml.v3" -) - -// GetContext returns the name of the selected context -func GetContext() string { - name := config.Config().ViperConfig().GetString("context_name") - return strings.ToLower(name) -} - -func NewContext(name string) { - name = strings.ToLower(name) // forces lowercase contexts - answers := config.GrafanaConfig{ - DataSourceSettings: &config.DataSourceSettings{ - MatchingRules: make([]config.RegexMatchesList, 0), - }, - } - 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.MatchingRules = []config.RegexMatchesList{ - { - Rules: []config.MatchingRule{ - { - Field: "name", - Regex: ".*", - }, - }, - Auth: &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: "OutputPath", - Prompt: &survey.Input{Message: "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) - err = v.WriteConfig() - if err != nil { - log.Fatal("could not save configuration.") - } - 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.WithError(err).Fatal("failed to serialize context") - } - 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) - err := v.WriteConfig() - if err != nil { - log.Fatal("could not save configuration.") - } -} - -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") - } - if funk.Contains(funk.Keys(m), context) { - v.Set("context_name", context) - err := v.WriteConfig() - if err != nil { - log.WithError(err).Fatal("could not save configuration.") - } - } else { - log.Fatal("invalid context specified. Please check config file and try again.") - } - -} - -// 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 == strings.ToLower(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) - err := v.WriteConfig() - if err != nil { - log.Fatal("could not save configuration.") - } -} - -// 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.Fatal("Context is not found. Please check your config") - } - - return nil -} - -// GetCtxDefaultGrafanaConfig returns the default aka. selected grafana config -func GetCtxDefaultGrafanaConfig() *config.GrafanaConfig { - return GetCtxGrafanaConfig(GetContext()) -} diff --git a/internal/config/config.go b/internal/config/config.go index 3fab1fba..825f61c2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,7 +1,9 @@ package config import ( + "encoding/json" "fmt" + "github.com/esnet/gdg/internal/tools" "github.com/thoas/go-funk" "os" "path/filepath" @@ -15,7 +17,165 @@ import ( type Configuration struct { defaultConfig *viper.Viper - contextMap map[string]*GrafanaConfig + AppConfig *AppConfig +} + +type AppGlobals struct { + Debug bool `mapstructure:"debug" yaml:"debug"` + IgnoreSSLErrors bool `mapstructure:"ignore_ssl_errors" yaml:"ignore_ssl_errors"` +} + +type AppConfig struct { + ContextName string `mapstructure:"context_name" yaml:"context_name"` + StorageEngine map[string]map[string]string `mapstructure:"storage_engine" yaml:"storage_engine"` + Contexts map[string]*GrafanaConfig `mapstructure:"contexts" yaml:"contexts"` + Global *AppGlobals `mapstructure:"global" yaml:"global"` +} + +func (s *Configuration) ClearContexts() { + newContext := make(map[string]*GrafanaConfig) + newContext["example"] = &GrafanaConfig{ + APIToken: "dummy", + } + appCfg := s.GetAppConfig() + appCfg.Contexts = newContext + appCfg.ContextName = "example" + err := s.SaveToDisk(false) + if err != nil { + log.Fatal("Failed to make save changes") + } + + log.Info("All contexts were cleared") + +} + +// GetDefaultGrafanaConfig returns the default aka. selected grafana config +func (s *Configuration) GetDefaultGrafanaConfig() *GrafanaConfig { + name := s.GetAppConfig().GetContext() + + val, ok := s.GetAppConfig().GetContexts()[name] + if ok { + return val + } else { + log.Fatalf("Context: '%s' is not found. Please check your config", name) + } + return nil + +} + +// CopyContext Makes a copy of the specified context and write to disk +func (s *Configuration) CopyContext(src, dest string) { + //Validate context + contexts := s.GetAppConfig().GetContexts() + if len(contexts) == 0 { + log.Fatal("Cannot set context. No valid configuration found in importer.yml") + } + cfg, ok := contexts[src] + if !ok { + log.Fatalf("Cannot find context to: '%s'. No valid configuration found in importer.yml", src) + } + newCopy, err := tools.DeepCopy(*cfg) + if err != nil { + log.Fatal("unable to make a copy of contexts") + + } + contexts[dest] = newCopy + s.GetAppConfig().ContextName = dest + err = s.SaveToDisk(false) + if err != nil { + log.Fatal("Failed to make save changes") + } + log.Infof("Copied %s context to %s please check your config to confirm", src, dest) +} + +func (s *Configuration) PrintContext(name string) { + name = strings.ToLower(name) + grafana, ok := s.GetAppConfig().GetContexts()[name] + if !ok { + log.Errorf("context %s was not found", name) + return + } + d, err := yaml.Marshal(grafana) + if err != nil { + log.WithError(err).Fatal("failed to serialize context") + } + fmt.Printf("---%s:\n%s\n\n", name, string(d)) + +} + +// DeleteContext remove a given context +func (s *Configuration) DeleteContext(name string) { + name = strings.ToLower(name) //ensure name is lower case + contexts := s.GetAppConfig().GetContexts() + _, ok := contexts[name] + if !ok { + log.Infof("Context not found, cannot delete context named '%s'", name) + return + } + delete(contexts, name) + if len(contexts) != 0 { + for key, _ := range contexts { + s.GetAppConfig().ContextName = key + break + } + } + + err := s.SaveToDisk(false) + if err != nil { + log.Fatal("Failed to make save changes") + } + log.Infof("Delete %s context and set new context to %s", name, s.GetAppConfig().ContextName) +} + +// ChangeContext +func (s *Configuration) ChangeContext(name string) { + name = strings.ToLower(name) + _, ok := s.GetAppConfig().GetContexts()[name] + if !ok { + log.Fatalf("context %s was not found", name) + } + s.GetAppConfig().ContextName = name + err := s.SaveToDisk(false) + if err != nil { + log.Fatal("Failed to make save changes") + } + log.Infof("Change context to: '%s'", name) +} + +// SaveToDisk Persists current configuration to disk +func (s *Configuration) SaveToDisk(useViper bool) error { + if useViper { + return s.ViperConfig().WriteConfig() + } + + file := s.ViperConfig().ConfigFileUsed() + data, err := yaml.Marshal(s.AppConfig) + if err == nil { + err = os.WriteFile(file, data, 0600) + } + + return err +} + +func (app *AppConfig) GetContext() string { + return strings.ToLower(app.ContextName) +} + +// Temporary function +func (app *AppConfig) GetContextMap() map[string]interface{} { + response := make(map[string]interface{}) + data, err := json.Marshal(app.Contexts) + if err != nil { + log.Errorf("could not serialize contexts") + return response + } + err = json.Unmarshal(data, &response) + if err != nil { + return make(map[string]interface{}) + } + + return response + } var ( @@ -23,14 +183,28 @@ var ( configSearchPaths = []string{".", "../../config", "../config", "conf", "config", "/etc/gdg"} ) +// GetCloudConfiguration Returns storage type and configuration +func (s *Configuration) GetCloudConfiguration(configName string) (string, map[string]string) { + appData := s.AppConfig.StorageEngine[configName] + storageType := "local" + if len(appData) != 0 { + storageType = appData["kind"] + } + return storageType, appData +} + // ViperConfig returns the loaded configuration via a viper reference func (s *Configuration) ViperConfig() *viper.Viper { return s.defaultConfig } -// Contexts returns map of all contexts -func (s *Configuration) Contexts() map[string]*GrafanaConfig { - return s.contextMap +func (app *AppConfig) GetContexts() map[string]*GrafanaConfig { + return app.Contexts +} + +// GetContexts returns map of all contexts +func (s *Configuration) GetContexts() map[string]*GrafanaConfig { + return s.GetAppConfig().GetContexts() } // IsDebug returns true if debug mode is enabled @@ -47,6 +221,10 @@ func Config() *Configuration { return configData } +func (s *Configuration) GetAppConfig() *AppConfig { + return s.AppConfig +} + // setMapValueEnvOverride recursively iterate over the keys and updates the map value accordingly func setMapValueEnvOverride(keys []string, mapValue map[string]interface{}, value interface{}) { if len(keys) > 1 { @@ -101,7 +279,7 @@ func InitConfig(override, defaultConfig string) { } var err error - configData.defaultConfig, err = readViperConfig(appName, configDirs) + configData.defaultConfig, configData.AppConfig, err = readViperConfig(appName, configDirs) if err != nil { err = os.MkdirAll("config", os.ModePerm) if err != nil { @@ -113,12 +291,15 @@ func InitConfig(override, defaultConfig string) { } appName = "importer" - configData.defaultConfig, err = readViperConfig(appName, configDirs) + configData.defaultConfig, configData.AppConfig, err = readViperConfig(appName, configDirs) if err != nil { log.Panic(err) } } + + //unmarshall struct + contexts := configData.defaultConfig.GetStringMap("contexts") contexts = applyEnvOverrides(contexts, "contexts", configData.defaultConfig) @@ -126,7 +307,7 @@ func InitConfig(override, defaultConfig string) { if err != nil { log.Fatal("Failed to decode context map, please check your configuration") } - err = yaml.Unmarshal(contextMaps, &configData.contextMap) + err = yaml.Unmarshal(contextMaps, &configData.AppConfig.Contexts) if err != nil { log.Fatal("No valid configuration file has been found") } @@ -134,7 +315,8 @@ func InitConfig(override, defaultConfig string) { } // readViperConfig utilizes the viper library to load the config from the selected paths -func readViperConfig(appName string, configDirs []string) (*viper.Viper, error) { +func readViperConfig(appName string, configDirs []string) (*viper.Viper, *AppConfig, error) { + app := &AppConfig{} v := viper.New() v.SetEnvPrefix("GDG") replacer := strings.NewReplacer(".", "__") @@ -147,10 +329,14 @@ func readViperConfig(appName string, configDirs []string) (*viper.Viper, error) v.AutomaticEnv() // global defaults - v.SetDefault("json_logs", false) - v.SetDefault("loglevel", "debug") + //v.SetDefault("globals.json_logs", false) + //v.SetDefault("loglevel", "debug") err := v.ReadInConfig() + if err == nil { + //Marshall the data read into a app struct + err = v.Unmarshal(app) + } - return v, err + return v, app, err } diff --git a/internal/config/config_model.go b/internal/config/config_model.go index 74ed11df..530078c3 100644 --- a/internal/config/config_model.go +++ b/internal/config/config_model.go @@ -19,6 +19,7 @@ const ( DashboardResource = "dashboards" DataSourceResource = "datasources" FolderResource = "folders" + FolderPermissionResource = "folders-permissions" AlertNotificationResource = "alertnotifications" LibraryElementResource = "libraryelements" ) diff --git a/internal/config/config_new_ctx.go b/internal/config/config_new_ctx.go new file mode 100644 index 00000000..92bd7f33 --- /dev/null +++ b/internal/config/config_new_ctx.go @@ -0,0 +1,128 @@ +package config + +import ( + "github.com/AlecAivazis/survey/v2" + log "github.com/sirupsen/logrus" + "strings" +) + +func (s *Configuration) NewContext(name string) { + + name = strings.ToLower(name) // forces lowercase contexts + answers := GrafanaConfig{ + DataSourceSettings: &DataSourceSettings{ + MatchingRules: make([]RegexMatchesList, 0), + }, + } + 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 := GrafanaDataSource{ + User: promptAnswers.DSUser, + Password: promptAnswers.DSPassword, + } + answers.DataSourceSettings.MatchingRules = []RegexMatchesList{ + { + Rules: []MatchingRule{ + { + Field: "name", + Regex: ".*", + }, + }, + Auth: &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: "OutputPath", + Prompt: &survey.Input{Message: "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()) + } + + contextMap := s.GetAppConfig().GetContexts() + contextMap[name] = &answers + s.GetAppConfig().ContextName = name + + err = s.SaveToDisk(false) + if err != nil { + log.Fatal("could not save configuration.") + } + log.Infof("New configuration %s has been created", name) + +} diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 281a1f47..a41c98b5 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -2,9 +2,9 @@ package config_test import ( "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/grafana-swagger-api-golang/goclient/models" + log "github.com/sirupsen/logrus" "os" "strings" "testing" @@ -13,19 +13,7 @@ import ( "github.com/thoas/go-funk" ) -func TestSetup(t *testing.T) { - config.InitConfig("testing.yml", "") - conf := config.Config().ViperConfig() - assert.NotNil(t, conf) - context := conf.GetString("context_name") - assert.Equal(t, context, "qa") - grafanaConf := apphelpers.GetCtxDefaultGrafanaConfig() - assert.NotNil(t, grafanaConf) - validateGrafanaQA(t, grafanaConf) -} - -// Ensures that if the config is on a completely different path, the searchPath is updated accordingly -func TestSetupDifferentPath(t *testing.T) { +func DuplicateConfig(t *testing.T) string { dir, _ := os.Getwd() //Fix test path if strings.Contains(dir, "config") { @@ -39,12 +27,42 @@ func TestSetupDifferentPath(t *testing.T) { cfgFile := fmt.Sprintf("%s/config.yml", destination) err = os.WriteFile(cfgFile, data, 0644) assert.Nil(t, err, "Failed to save configuration file") + + return cfgFile +} + +func TestSetup(t *testing.T) { + //clear all ENV values + for _, key := range os.Environ() { + if strings.Contains(key, "GDG_") { + os.Unsetenv(key) + } + } + + config.InitConfig("testing.yml", "") + conf := config.Config().ViperConfig() + log.Info(conf.ConfigFileUsed()) + + confobj := config.Config().GetAppConfig() + _ = confobj + log.Infof(confobj.ContextName) + assert.NotNil(t, conf) + context := conf.GetString("context_name") + assert.Equal(t, context, "qa") + grafanaConf := config.Config().GetDefaultGrafanaConfig() + assert.NotNil(t, grafanaConf) + validateGrafanaQA(t, grafanaConf) +} + +// Ensures that if the config is on a completely different path, the searchPath is updated accordingly +func TestSetupDifferentPath(t *testing.T) { + cfgFile := DuplicateConfig(t) config.InitConfig(cfgFile, "") conf := config.Config().ViperConfig() assert.NotNil(t, conf) context := conf.GetString("context_name") assert.Equal(t, context, "production") - grafanaConf := apphelpers.GetCtxDefaultGrafanaConfig() + grafanaConf := config.Config().GetDefaultGrafanaConfig() assert.NotNil(t, grafanaConf) assert.Equal(t, grafanaConf.OutputPath, "prod") } @@ -58,7 +76,7 @@ func TestConfigEnv(t *testing.T) { assert.Equal(t, context, "testing") url := conf.GetString("contexts.testing.url") assert.Equal(t, url, "www.google.com") - grafanaConfig := apphelpers.GetCtxDefaultGrafanaConfig() + grafanaConfig := config.Config().GetDefaultGrafanaConfig() assert.Equal(t, grafanaConfig.URL, url) os.Setenv("GDG_CONTEXT_NAME", "production") os.Setenv("GDG_CONTEXTS__PRODUCTION__URL", "grafana.com") diff --git a/internal/service/alertnotifications.go b/internal/service/alertnotifications.go index 621222b4..77d32e31 100644 --- a/internal/service/alertnotifications.go +++ b/internal/service/alertnotifications.go @@ -2,7 +2,6 @@ package service import ( "encoding/json" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/grafana-swagger-api-golang/goclient/client/legacy_alerts_notification_channels" "github.com/esnet/grafana-swagger-api-golang/goclient/models" @@ -85,7 +84,7 @@ func (s *DashNGoImpl) ExportAlertNotifications() []string { err error ) - dirPath := apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.AlertNotificationResource) + dirPath := config.Config().GetDefaultGrafanaConfig().GetPath(config.AlertNotificationResource) filesInDir, err = s.storage.FindAllFiles(dirPath, true) if err != nil { log.WithError(err).Fatalf("Unable to find Alert data in Storage System %s", s.storage.Name()) diff --git a/internal/service/common.go b/internal/service/common.go index f9958286..fdb0751b 100644 --- a/internal/service/common.go +++ b/internal/service/common.go @@ -1,8 +1,8 @@ package service import ( + "errors" "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/gosimple/slug" log "github.com/sirupsen/logrus" @@ -40,18 +40,45 @@ func CreateDestinationPath(v string) { } } +// getFolderFromResourcePath if a use encodes a path seperator in path, we can't determine the folder name. This strips away +// all the known components of a resource type leaving only the folder name. +func getFolderFromResourcePath(storageEngine string, filePath string, resourceType config.ResourceType) (string, error) { + basePath := fmt.Sprintf("%s/", config.Config().GetDefaultGrafanaConfig().GetPath(config.DashboardResource)) + //Take into account cloud prefix is enabled + if storageEngine != "" { + cloudType, data := config.Config().GetCloudConfiguration(storageEngine) + if cloudType != "local" && data["prefix"] != "" { + basePath = fmt.Sprintf("%s/%s", data["prefix"], basePath) + } + } + + folderName := strings.Replace(filePath, basePath, "", 1) + ndx := strings.LastIndex(folderName, string(os.PathSeparator)) + if ndx != -1 { + folderName = folderName[0:ndx] + log.Debugf("Folder name is: %s", folderName) + return folderName, nil + } + return "", errors.New("unable to parse resource to retrieve folder name") +} + func buildResourceFolder(folderName string, resourceType config.ResourceType) string { if resourceType == config.DashboardResource && folderName == "" { folderName = DefaultFolderName } + strSeperator := string(os.PathSeparator) + + if strings.Contains(folderName, strSeperator) { + folderName = strings.ReplaceAll(folderName, strSeperator, fmt.Sprintf("//%s", strSeperator)) + } - v := fmt.Sprintf("%s/%s", apphelpers.GetCtxDefaultGrafanaConfig().GetPath(resourceType), folderName) + v := fmt.Sprintf("%s/%s", config.Config().GetDefaultGrafanaConfig().GetPath(resourceType), folderName) CreateDestinationPath(v) return v } func buildResourcePath(folderName string, resourceType config.ResourceType) string { - v := fmt.Sprintf("%s/%s.json", apphelpers.GetCtxDefaultGrafanaConfig().GetPath(resourceType), folderName) + v := fmt.Sprintf("%s/%s.json", config.Config().GetDefaultGrafanaConfig().GetPath(resourceType), folderName) CreateDestinationPath(filepath.Dir(v)) return v diff --git a/internal/service/contract.go b/internal/service/contract.go index 69f4d22e..d7eb0d9c 100644 --- a/internal/service/contract.go +++ b/internal/service/contract.go @@ -2,10 +2,7 @@ package service import ( "context" - "fmt" - "github.com/esnet/gdg/internal/api" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/grafana-swagger-api-golang/goclient/client" log "github.com/sirupsen/logrus" @@ -53,7 +50,7 @@ func NewDashNGoImpl() *DashNGoImpl { func newInstance() *DashNGoImpl { obj := &DashNGoImpl{} - obj.grafanaConf = apphelpers.GetCtxDefaultGrafanaConfig() + obj.grafanaConf = config.Config().GetDefaultGrafanaConfig() obj.configRef = config.Config().ViperConfig() obj.Login() @@ -70,12 +67,8 @@ func (s *DashNGoImpl) SetStorage(v Storage) { func configureStorage(obj *DashNGoImpl) { //config - appData := config.Config().ViperConfig().GetStringMap(fmt.Sprintf("storage_engine.%s", obj.grafanaConf.Storage)) + storageType, appData := config.Config().GetCloudConfiguration(config.Config().GetDefaultGrafanaConfig().Storage) - storageType := "local" - if len(appData) != 0 { - storageType = appData["kind"].(string) - } var err error ctx := context.Background() ctx = context.WithValue(ctx, StorageContext, appData) @@ -87,7 +80,6 @@ func configureStorage(obj *DashNGoImpl) { log.Warn("falling back on Local Storage, Cloud storage configuration error") obj.storage = NewLocalStorage(ctx) } - } default: obj.storage = NewLocalStorage(ctx) diff --git a/internal/service/dashboards.go b/internal/service/dashboards.go index 751df70b..82046344 100644 --- a/internal/service/dashboards.go +++ b/internal/service/dashboards.go @@ -3,7 +3,6 @@ package service import ( "encoding/json" "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" gapi "github.com/esnet/grafana-swagger-api-golang" @@ -161,7 +160,7 @@ func (s *DashNGoImpl) ListDashboards(filterReq filters.Filter) []*models.Hit { var limit uint = 5000 // Upper bound of Grafana API call var tagsParams = make([]string, 0) - if !apphelpers.GetCtxDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { + if !config.Config().GetDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { tagsParams = append(tagsParams, filterReq.GetEntity(filters.TagsFilter)...) } @@ -188,7 +187,7 @@ func (s *DashNGoImpl) ListDashboards(filterReq filters.Filter) []*models.Hit { var validUid bool for _, link := range boardLinks { validFolder = false - if apphelpers.GetCtxDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { + if config.Config().GetDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { validFolder = true } else if funk.ContainsString(folderFilters, link.FolderTitle) { validFolder = true @@ -275,7 +274,7 @@ func (s *DashNGoImpl) ExportDashboards(filterReq filters.Filter) { folderName string = "" folderId int64 ) - path := apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.DashboardResource) + path := config.Config().GetDefaultGrafanaConfig().GetPath(config.DashboardResource) filesInDir, err := s.storage.FindAllFiles(path, true) if err != nil { log.WithError(err).Fatal("unable to find any files to export from storage engine") @@ -317,7 +316,7 @@ func (s *DashNGoImpl) ExportDashboards(filterReq filters.Filter) { folderId = DefaultFolderId folderName = DefaultFolderName } - if !slices.Contains(validFolders, folderName) && !apphelpers.GetCtxDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { + if !slices.Contains(validFolders, folderName) && !config.Config().GetDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { log.Debugf("Skipping file %s, doesn't match any valid folders", file) continue } diff --git a/internal/service/datasources.go b/internal/service/datasources.go index 3a0155fb..1ae31c8f 100644 --- a/internal/service/datasources.go +++ b/internal/service/datasources.go @@ -3,7 +3,6 @@ package service import ( "encoding/json" "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" "github.com/esnet/grafana-swagger-api-golang/goclient/client/datasources" @@ -115,8 +114,8 @@ func (s *DashNGoImpl) ExportDataSources(filter filters.Filter) []string { var exported = make([]string, 0) - log.Infof("Reading files from folder: %s", apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.DataSourceResource)) - filesInDir, err := s.storage.FindAllFiles(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.DataSourceResource), false) + log.Infof("Reading files from folder: %s", config.Config().GetDefaultGrafanaConfig().GetPath(config.DataSourceResource)) + filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.DataSourceResource), false) if err != nil { log.WithError(err).Errorf("failed to list files in directory for datasources") @@ -127,7 +126,7 @@ func (s *DashNGoImpl) ExportDataSources(filter filters.Filter) []string { dsSettings := s.grafanaConf.GetDataSourceSettings() for _, file := range filesInDir { - fileLocation := filepath.Join(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.DataSourceResource), file) + fileLocation := filepath.Join(config.Config().GetDefaultGrafanaConfig().GetPath(config.DataSourceResource), file) if strings.HasSuffix(file, ".json") { if rawDS, err = s.storage.ReadFile(fileLocation); err != nil { log.WithError(err).Errorf("failed to read file: %s", fileLocation) diff --git a/internal/service/filters/filters.go b/internal/service/filters/filters.go index d4266292..4ab457c2 100644 --- a/internal/service/filters/filters.go +++ b/internal/service/filters/filters.go @@ -1,7 +1,7 @@ package filters import ( - "github.com/esnet/gdg/internal/apphelpers" + "github.com/esnet/gdg/internal/config" log "github.com/sirupsen/logrus" "github.com/thoas/go-funk" "regexp" @@ -92,7 +92,7 @@ func (s *BaseFilter) GetEntity(name FilterType) []string { case TagsFilter: return s.getEntities(TagsFilter, []string{}) case FolderFilter: - return s.getEntities(FolderFilter, apphelpers.GetCtxDefaultGrafanaConfig().GetMonitoredFolders()) + return s.getEntities(FolderFilter, config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders()) default: return defaultResponse } diff --git a/internal/service/folders.go b/internal/service/folders.go index b572b492..30cce85c 100644 --- a/internal/service/folders.go +++ b/internal/service/folders.go @@ -2,7 +2,6 @@ package service import ( "encoding/json" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" "github.com/esnet/grafana-swagger-api-golang/goclient/client/folders" @@ -26,9 +25,6 @@ type FoldersApi interface { func NewFolderFilter() filters.Filter { filterObj := filters.NewBaseFilter() - - //filterObj.AddFilter(filters.FolderFilter, folders) - //Add Folder Validation filterObj.AddValidation(filters.FolderFilter, func(i interface{}) bool { val, ok := i.(map[filters.FilterType]string) if !ok { @@ -36,7 +32,7 @@ func NewFolderFilter() filters.Filter { } //Check folder if folderFilter, ok := val[filters.FolderFilter]; ok { - return slices.Contains(apphelpers.GetCtxDefaultGrafanaConfig().GetMonitoredFolders(), folderFilter) + return slices.Contains(config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders(), folderFilter) } else { return true } @@ -47,7 +43,7 @@ func NewFolderFilter() filters.Filter { func (s *DashNGoImpl) ListFolder(filter filters.Filter) []*models.Hit { var result = make([]*models.Hit, 0) - if apphelpers.GetCtxDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { + if config.Config().GetDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters { filter = nil } p := search.NewSearchParams() @@ -68,14 +64,16 @@ func (s *DashNGoImpl) ListFolder(filter filters.Filter) []*models.Hit { return result } + +// ImportFolder func (s *DashNGoImpl) ImportFolder(filter filters.Filter) []string { var ( dsPacked []byte err error dataFiles []string ) - folders := s.ListFolder(filter) - for _, folder := range folders { + folderListing := s.ListFolder(filter) + for _, folder := range folderListing { if dsPacked, err = json.MarshalIndent(folder, "", " "); err != nil { log.Errorf("%s for %s\n", err, folder.Title) continue @@ -96,14 +94,14 @@ func (s *DashNGoImpl) ExportFolder(filter filters.Filter) []string { result []string rawFolder []byte ) - filesInDir, err := s.storage.FindAllFiles(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.FolderResource), false) + filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.FolderResource), false) if err != nil { log.WithError(err).Fatal("Failed to read folders imports") } folderItems := s.ListFolder(filter) for _, file := range filesInDir { - fileLocation := filepath.Join(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.FolderResource), file) + fileLocation := filepath.Join(config.Config().GetDefaultGrafanaConfig().GetPath(config.FolderResource), file) if strings.HasSuffix(file, ".json") { if rawFolder, err = s.storage.ReadFile(fileLocation); err != nil { log.WithError(err).Errorf("failed to read file %s", fileLocation) diff --git a/internal/service/libraryelements.go b/internal/service/libraryelements.go index edc45e71..bd5b21c5 100644 --- a/internal/service/libraryelements.go +++ b/internal/service/libraryelements.go @@ -3,7 +3,6 @@ package service import ( "encoding/json" "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" "github.com/esnet/grafana-swagger-api-golang/goclient/client/library_elements" @@ -51,7 +50,7 @@ func (s *DashNGoImpl) ListLibraryElementsConnections(filter filters.Filter, conn } func (s *DashNGoImpl) ListLibraryElements(filter filters.Filter) []*models.LibraryElementDTO { - ignoreFilters := apphelpers.GetCtxDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters + ignoreFilters := config.Config().GetDefaultGrafanaConfig().GetFilterOverrides().IgnoreDashboardFilters folderFilter := NewFolderFilter() if ignoreFilters { folderFilter = nil @@ -62,7 +61,7 @@ func (s *DashNGoImpl) ListLibraryElements(filter filters.Filter) []*models.Libra var buf = strings.Builder{} //Check to see if General should be included //If Ignore Filters OR General is in monitored list, add 0 folder - if (!ignoreFilters && slices.Contains(apphelpers.GetCtxDefaultGrafanaConfig().GetMonitoredFolders(), DefaultFolderName)) || ignoreFilters { + if (!ignoreFilters && slices.Contains(config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders(), DefaultFolderName)) || ignoreFilters { buf.WriteString("0,") } else { buf.WriteString("") @@ -123,8 +122,8 @@ func (s *DashNGoImpl) ExportLibraryElements(filter filters.Filter) []string { libraryUID string ) - log.Infof("Reading files from folder: %s", apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.LibraryElementResource)) - filesInDir, err := s.storage.FindAllFiles(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.LibraryElementResource), true) + log.Infof("Reading files from folder: %s", config.Config().GetDefaultGrafanaConfig().GetPath(config.LibraryElementResource)) + filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.LibraryElementResource), true) currentLibElements := s.ListLibraryElements(filter) libMapping := make(map[string]*models.LibraryElementDTO, 0) @@ -166,7 +165,7 @@ func (s *DashNGoImpl) ExportLibraryElements(filter filters.Filter) []string { continue } - if !slices.Contains(apphelpers.GetCtxDefaultGrafanaConfig().GetMonitoredFolders(), folderName) { + if !slices.Contains(config.Config().GetDefaultGrafanaConfig().GetMonitoredFolders(), folderName) { log.WithField("folder", folderName).WithField("file", file).Warn("Skipping since requested file is not in a folder gdg is configured to manage") continue } diff --git a/internal/service/login.go b/internal/service/login.go index 7f633f13..d06d2643 100644 --- a/internal/service/login.go +++ b/internal/service/login.go @@ -54,12 +54,12 @@ func (s *DashNGoImpl) getAdminAuth() runtime.ClientAuthInfoWriter { func (s *DashNGoImpl) getAuth() runtime.ClientAuthInfoWriter { if s.grafanaConf.APIToken != "" { - return gapi.APIKeyAuthenticator{ + return &gapi.APIKeyAuthenticator{ APIKey: s.grafanaConf.APIToken, } } else { - return gapi.BasicAuthenticator{ + return &gapi.BasicAuthenticator{ Username: s.grafanaConf.UserName, Password: s.grafanaConf.Password, } diff --git a/internal/service/storage_cloud.go b/internal/service/storage_cloud.go index fe8e3dd4..1aa6fc91 100644 --- a/internal/service/storage_cloud.go +++ b/internal/service/storage_cloud.go @@ -23,6 +23,7 @@ const ( CloudType = "cloud_type" BucketName = "bucket_name" Prefix = "prefix" + Kind = "kind" ) // getCloudLocation appends prefix to path @@ -99,7 +100,7 @@ func NewCloudStorage(c context.Context) (Storage, error) { if contextVal == nil { return nil, errors.New("cannot configure GCP storage, context missing") } - appData, ok := contextVal.(map[string]interface{}) + appData, ok := contextVal.(map[string]string) if !ok { return nil, errors.New("cannot convert appData to string map") } diff --git a/internal/service/teams.go b/internal/service/teams.go index 36a84878..3b4447ff 100644 --- a/internal/service/teams.go +++ b/internal/service/teams.go @@ -3,7 +3,6 @@ package service import ( "errors" "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" @@ -102,7 +101,7 @@ func (s *DashNGoImpl) ImportTeams(filter filters.Filter) map[*models.TeamDTO][]* // Export Teams func (s *DashNGoImpl) ExportTeams(filter filters.Filter) map[*models.TeamDTO][]*models.TeamMemberDTO { - filesInDir, err := s.storage.FindAllFiles(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.TeamResource), true) + filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.TeamResource), true) if err != nil { log.WithError(err).Errorf("failed to list files in directory for teams") } @@ -141,7 +140,7 @@ func (s *DashNGoImpl) ExportTeams(filter filters.Filter) map[*models.TeamDTO][]* var currentMembers []*models.TeamMemberDTO var rawMembers []byte - teamMemberLocation := filepath.Join(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.TeamResource), GetSlug(newTeam.Name), "members.json") + teamMemberLocation := filepath.Join(config.Config().GetDefaultGrafanaConfig().GetPath(config.TeamResource), GetSlug(newTeam.Name), "members.json") if rawMembers, err = s.storage.ReadFile(teamMemberLocation); err != nil { log.WithError(err).Errorf("failed to find team members: %s", fileLocation) continue diff --git a/internal/service/user.go b/internal/service/user.go index e46712a0..ac5d6d95 100644 --- a/internal/service/user.go +++ b/internal/service/user.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/esnet/gdg/internal/apphelpers" "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" gapi "github.com/esnet/grafana-swagger-api-golang" @@ -106,7 +105,7 @@ func (s *DashNGoImpl) isAdmin(id int64, name string) bool { } func (s *DashNGoImpl) ExportUsers(filter filters.Filter) []models.UserProfileDTO { - filesInDir, err := s.storage.FindAllFiles(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.UserResource), false) + filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.UserResource), false) if err != nil { log.WithError(err).Errorf("failed to list files in directory for userListings") } @@ -122,7 +121,7 @@ func (s *DashNGoImpl) ExportUsers(filter filters.Filter) []models.UserProfileDTO } for _, file := range filesInDir { - fileLocation := filepath.Join(apphelpers.GetCtxDefaultGrafanaConfig().GetPath(config.UserResource), file) + fileLocation := filepath.Join(config.Config().GetDefaultGrafanaConfig().GetPath(config.UserResource), file) if strings.HasSuffix(file, ".json") { if rawUser, err = s.storage.ReadFile(fileLocation); err != nil { log.WithError(err).Errorf("failed to read file: %s", fileLocation) diff --git a/internal/tools/generics_tooling.go b/internal/tools/generics_tooling.go index d92dd7e9..209e1e7d 100644 --- a/internal/tools/generics_tooling.go +++ b/internal/tools/generics_tooling.go @@ -1,5 +1,21 @@ package tools +import "encoding/json" + func PtrOf[T any](value T) *T { return &value } + +func DeepCopy[T any](value T) (*T, error) { + origJSON, err := json.Marshal(value) + if err != nil { + return nil, err + } + + clone := new(T) + if err = json.Unmarshal(origJSON, &clone); err != nil { + return nil, err + } + + return clone, nil +} diff --git a/test/cloud_integration_test.go b/test/cloud_integration_test.go index 5c8fb1fe..bbcfd760 100644 --- a/test/cloud_integration_test.go +++ b/test/cloud_integration_test.go @@ -5,6 +5,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" _ "gocloud.dev/blob/memblob" + "os" "testing" ) @@ -12,7 +13,9 @@ func TestCloudDataSourceCRUD(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - apiClient, _ := initTest(t, nil) + + os.Setenv("GDG_CONTEXT_NAME", "testing") + apiClient, cfg := initTest(t, nil) //Wipe all data from grafana dsFilter := service.NewDataSourceFilter("") @@ -21,7 +24,7 @@ func TestCloudDataSourceCRUD(t *testing.T) { apiClient.ExportDataSources(dsFilter) dsList := apiClient.ListDataSources(dsFilter) assert.True(t, len(dsList) > 0) - SetupCloudFunction(apiClient, []string{"minio", "testing"}) + SetupCloudFunction(t, cfg, apiClient, []string{"minio", "testing"}) //SetupCloudFunction(apiClient, []string{"mem", "testing"}) log.Info("Importing DataSources") @@ -45,7 +48,8 @@ func TestDashboardCloudCRUD(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - apiClient, _ := initTest(t, nil) + os.Setenv("GDG_CONTEXT_NAME", "testing") + apiClient, cfg := initTest(t, nil) //Wipe all data from grafana dashFilter := service.NewDashboardFilter("", "", "") @@ -56,7 +60,7 @@ func TestDashboardCloudCRUD(t *testing.T) { assert.True(t, len(boards) > 0) //SetupCloudFunction(apiClient, []string{"mem", "testing"}) - SetupCloudFunction(apiClient, []string{"minio", "testing"}) + _, apiClient = SetupCloudFunction(t, cfg, apiClient, []string{"minio", "testing"}) //At this point all operations are reading/writing from Minio log.Info("Importing Dashboards") @@ -72,6 +76,4 @@ func TestDashboardCloudCRUD(t *testing.T) { boards = apiClient.ListDashboards(dashFilter) //Read data assert.Equal(t, len(list), len(boards)) //verify apiClient.DeleteAllDashboards(dashFilter) - // - } diff --git a/test/dashboard_integration_test.go b/test/dashboard_integration_test.go index 89ff5297..6739f5d5 100644 --- a/test/dashboard_integration_test.go +++ b/test/dashboard_integration_test.go @@ -181,7 +181,7 @@ func TestWildcardFilter(t *testing.T) { filtersEntity.AddFilter(filters.TagsFilter, strings.Join([]string{"flow", "netsage"}, ",")) // Enable Wildcard - testingContext := config.Config().Contexts()["testing"] + testingContext := config.Config().GetAppConfig().GetContexts()["testing"] testingContext.GetFilterOverrides().IgnoreDashboardFilters = true assert.True(t, testingContext.GetFilterOverrides().IgnoreDashboardFilters) diff --git a/test/datasource_integration_test.go b/test/datasource_integration_test.go index c0ef7a53..9b87fb54 100644 --- a/test/datasource_integration_test.go +++ b/test/datasource_integration_test.go @@ -49,7 +49,7 @@ func TestDataSourceFilter(t *testing.T) { } initTest(t, nil) - testingContext := config.Config().Contexts()["testing"] + testingContext := config.Config().GetAppConfig().GetContexts()["testing"] testingContext.GetDataSourceSettings().FilterRules = []config.MatchingRule{ { Field: "name", @@ -61,7 +61,7 @@ func TestDataSourceFilter(t *testing.T) { Regex: "elasticsearch|globalnoc-tsds-datasource", }, } - testingContext = config.Config().Contexts()["testing"] + testingContext = config.Config().GetAppConfig().GetContexts()["testing"] apiClient := service.NewApiService("dummy") diff --git a/test/integration_common.go b/test/integration_common.go index 64aa68f0..e7d7f832 100644 --- a/test/integration_common.go +++ b/test/integration_common.go @@ -23,7 +23,6 @@ func initTest(t *testing.T, cfgName *string) (service.GrafanaService, *viper.Vip config.InitConfig(*cfgName, "'") conf := config.Config().ViperConfig() assert.NotNil(t, conf) - conf.Set("context_name", "testing") //Hack for Local testing conf.Set("context.testing.url", "http://localhost:3000") contextName := conf.GetString("context_name") @@ -39,20 +38,24 @@ func initTest(t *testing.T, cfgName *string) (service.GrafanaService, *viper.Vip return client, conf } -func SetupCloudFunction(apiClient service.GrafanaService, params []string) context.Context { +func SetupCloudFunction(t *testing.T, cfg *viper.Viper, apiClient service.GrafanaService, params []string) (context.Context, service.GrafanaService) { _ = os.Setenv("AWS_ACCESS_KEY", "test") _ = os.Setenv("AWS_SECRET_KEY", "secretsss") - bucketName := params[1] - var m = map[string]interface{}{ + var m = map[string]string{ service.CloudType: params[0], service.Prefix: "dummy", service.BucketName: bucketName, + service.Kind: "cloud", } + cfgObj := config.Config().GetAppConfig() + defaultCfg := config.Config().GetDefaultGrafanaConfig() + defaultCfg.Storage = "test" + cfgObj.StorageEngine["test"] = m + apiClient = service.NewApiService("dummy") + ctx := context.Background() - //ctx = context.WithValue(ctx, MINIO_HOST, "https://localhost:9000") - //ctx = context.WithValue(ctx, MINIO_SSL, false) ctx = context.WithValue(ctx, service.StorageContext, m) configMap := map[string]string{} for key, value := range m { @@ -66,5 +69,5 @@ func SetupCloudFunction(apiClient service.GrafanaService, params []string) conte dash := apiClient.(*service.DashNGoImpl) dash.SetStorage(s) - return ctx + return ctx, apiClient }