Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing Nested requirements #319

Merged
merged 1 commit into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ Current Entities supported (See official docs for more details)
- Teams
- Users
- Library Elements
- Alert rules
- Contact points
- Alerting:
- Contact points (master branch only)

Grafana Enterprise Only feature
- Connection Permissions
Expand Down
5 changes: 2 additions & 3 deletions cli/backup/alerting_contacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/bep/simplecobra"
"github.com/esnet/gdg/cli/support"
"github.com/esnet/gdg/internal/service"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -49,7 +48,7 @@ func newListContactPointsCmd() simplecobra.Commander {
cmd.Aliases = []string{"l"}
},
RunFunc: func(ctx context.Context, cd *simplecobra.Commandeer, rootCmd *support.RootCommand, args []string) error {
rootCmd.TableObj.AppendHeader(table.Row{"uid", "name", "slug", "type", "provenance", "settings"})
rootCmd.TableObj.AppendHeader(table.Row{"uid", "name", "type", "settings"})
contactPoints, err := rootCmd.GrafanaSvc().ListContactPoints()
slog.Info("Listing contact points for context",
slog.String("Organization", GetOrganizationName()),
Expand All @@ -71,7 +70,7 @@ func newListContactPointsCmd() simplecobra.Commander {
if link.Type != nil {
typeVal = *link.Type
}
rootCmd.TableObj.AppendRow(table.Row{link.UID, link.Name, service.GetSlug(link.Name), typeVal, link.Provenance, string(rawBytes)})
rootCmd.TableObj.AppendRow(table.Row{link.UID, link.Name, typeVal, string(rawBytes)})
}
rootCmd.Render(cd.CobraCommand, contactPoints)
}
Expand Down
6 changes: 1 addition & 5 deletions cli/backup/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,7 @@ func newListDashboardsCmd() simplecobra.Commander {
},
RunFunc: func(ctx context.Context, cd *simplecobra.Commandeer, rootCmd *support.RootCommand, args []string) error {
cfg := config.Config().GetDefaultGrafanaConfig()
if cfg.GetDashboardSettings().NestedFolders {
rootCmd.TableObj.AppendHeader(table.Row{"id", "Title", "Slug", "Folder", "NestedPath", "UID", "Tags", "URL"})
} else {
rootCmd.TableObj.AppendHeader(table.Row{"id", "Title", "Slug", "Folder", "UID", "Tags", "URL"})
}
rootCmd.TableObj.AppendHeader(table.Row{"id", "Title", "Slug", "Folder", "NestedPath", "UID", "Tags", "URL"})

filters := service.NewDashboardFilter(parseDashboardGlobalFlags(cd.CobraCommand)...)
boards := rootCmd.GrafanaSvc().ListDashboards(filters)
Expand Down
6 changes: 1 addition & 5 deletions cli/backup/folders.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,7 @@ func newFolderListCmd() simplecobra.Commander {
RunFunc: func(ctx context.Context, cd *simplecobra.Commandeer, rootCmd *support.RootCommand, args []string) error {
slog.Info("Listing Folders for context", "context", config.Config().GetGDGConfig().GetContext())
cfg := config.Config().GetDefaultGrafanaConfig()
if cfg.GetDashboardSettings().NestedFolders {
rootCmd.TableObj.AppendHeader(table.Row{"uid", "title", "nestedPath"})
} else {
rootCmd.TableObj.AppendHeader(table.Row{"uid", "title"})
}
rootCmd.TableObj.AppendHeader(table.Row{"uid", "title", "nestedPath"})
folders := rootCmd.GrafanaSvc().ListFolders(getFolderFilter())

if len(folders) == 0 {
Expand Down
5 changes: 4 additions & 1 deletion cli/test/backup/alerting_contactpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ func TestListContactPoints(t *testing.T) {
name: "ListingTest",
validateFn: func(t *testing.T, output string) {
assert.True(t, strings.Contains(output, "WRN GDG does not manage the 'email receiver' entity."))
assert.True(t, strings.Contains(output, "PROVENANCE"))
assert.True(t, strings.Contains(output, "discordUid"))
assert.True(t, strings.Contains(output, "slackUid"))
assert.True(t, strings.Contains(output, "Discord"))
assert.True(t, strings.Contains(output, "Slack"))
// validate Type
Expand All @@ -180,11 +181,13 @@ func TestListContactPoints(t *testing.T) {
testSvc.EXPECT().InitOrganizations().Return()
resp := []*models.EmbeddedContactPoint{
{
UID: "discordUid",
Name: "Discord",
Type: ptr.Of("discordType"),
Settings: map[string]any{"token": "secret", "someValue": "result"},
},
{
UID: "slackUid",
Name: "Slack",
Type: ptr.Of("slackType"),
Settings: map[string]any{"token": "secret", "slack": "rocks"},
Expand Down
2 changes: 1 addition & 1 deletion config/importer-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ contexts:
password: admin
dashboard_settings:
ignore_filters: false # When set to true all Watched filtered folders will be ignored and ALL folders will be acted on
nested_folders: true # If true, the dashboard-download will create the proper nesting of (sub)folders - WARN: not (yet) compatible with the upload-feature!!!
nested_folders: true
watched:
- General
- Other
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: '3.8'
services:
minio:
image: bitnami/minio:latest
Expand Down
4 changes: 2 additions & 2 deletions internal/service/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ func TestSlug(t *testing.T) {

func TestUserPath(t *testing.T) {
fixEnvironment(t)
path := BuildResourceFolder("", config.UserResource)
assert.Equal(t, "test/data/users/", path)
userPath := BuildResourceFolder("", config.UserResource)
assert.Equal(t, "test/data/users/", userPath)
}

func TestBuildDashboardPath(t *testing.T) {
Expand Down
33 changes: 2 additions & 31 deletions internal/service/dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,41 +91,12 @@ func NewDashboardFilter(entries ...string) filters.Filter {
}

// nestedFoldersSanityCheck returns an error if minimum Version does not match, if grafana settings has nested folders enabled
// but configuration does not match
// but minimum version is not met.
func (s *DashNGoImpl) nestedFoldersSanityCheck() error {
if s.grafanaConf.GetDashboardSettings().NestedFolders && !tools.ValidateMinimumVersion(minimumNestedDashboardVersion, s) {
log.Fatalf("Minimum version required for nested folders is %s", minimumNestedDashboardVersion)
}
handleError := func() error {
slog.Warn("Either you don't have admin access or we're unable to retrieve grafana settings. " +
"Unable to perform a sanity check on the grafana settings. Continuing with best effort")
return nil
}
displayGdgMisconfigured := func() error {
slog.Warn("You have nested folders configured for grafana, but your gdg settings do not match. Some Dashboards backup and restore may not work as intended.")
return nil
}
if s.grafanaConf.IsGrafanaAdmin() {
payload, err := s.GetAdminClient().Admin.AdminGetSettings()
if err != nil {
return handleError()
}
preferences := payload.GetPayload()
if val, ok := preferences["feature_toggles"]["enable"]; ok {
if strings.Contains(val, "nestedFolders") && !s.grafanaConf.GetDashboardSettings().NestedFolders /* grafana has nested folders but GDG is configured to ignore those */ {
slog.Warn("You have nested folders enabled on your grafana instance and the setting disabled in your settings. Some Dashboards backup and restore may not work as intended.")
return nil
} else if !strings.Contains(val, "nestedFolders") && s.grafanaConf.GetDashboardSettings().NestedFolders /* and grafana has nested folder disabled */ {
return displayGdgMisconfigured()
} else {
return nil
}
} else if s.grafanaConf.GetDashboardSettings().NestedFolders { //"feature_toggles" no set, which currently means nested_folders is disabled.
return displayGdgMisconfigured()
}
}

return handleError()
return nil
}

func (s *DashNGoImpl) LintDashboards(req types.LintRequest) []string {
Expand Down
2 changes: 1 addition & 1 deletion test/dashboard_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestDashboardNestedFolderCRUD(t *testing.T) {
var generalBoard *models.Hit
var nestedFolder *models.Hit
for ndx, board := range boards {
slog.Info(board.Slug)

if board.Slug == "rabbitmq-overview" {
generalBoard = boards[ndx]
}
Expand Down
12 changes: 12 additions & 0 deletions test/data/org_main-org/alerting/contacts.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,17 @@
"uid": "fdxmqkyb5gl4xb"
}
]
},
{
"name": "email receiver",
"orgId": 1,
"receivers": [
{
"settings": {
"addresses": "\[email protected]\u003e"
},
"type": "email"
}
]
}
]
26 changes: 25 additions & 1 deletion website/content/docs/gdg/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,33 @@ Watched folders under grafana is a white list of folders that are being managed

## Dashboards

By default ONLY the General folder is inspected. You may override this behavior by
By default, ONLY the General folder is inspected. You may override this behavior by setting a list of watched folder

example:

```yaml
watched:
- Folder1
- Folder2
- Prod*[a-zA-Z0-9]+$
```
You can use a combination of folder names and regex patterns. If you need to monitor a different set for various
organization you can additionally set the watched_folders_override as detailed below.

If you do not watch to set an approved watch list, then you can configure gdg to ignore all filters.
```yaml
dashboard_settings:
ignore_filters: true
```

Starting with V11 of grafana, nested_folders are supported. To enable that feature use:

```yaml
dashboard_settings:
nested_folders: true
```

This will likely be become a default behavior once grafana 12 is released.
## Organization

The organization is set for a given context via the `orgnization_name`. If the org is not set, gdg will fallback on the default value that grafana starts out with `Main Org.`
Expand Down
9 changes: 8 additions & 1 deletion website/content/docs/releases/gdg_0.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ toc: true
**Release Date: TBD**

### Breaking Changes
- [#318](https://github.com/esnet/gdg/pull/318) Removed the default config fall back. For backup and tools functionality
a valid configuration file is now required. A new cli parameter is introduced: `default-config` which will print an example configuration
to stdout.
### Changes
- [#319](https://github.com/esnet/gdg/pull/319) Remove the requirement for GF_FEATURE_TOGGLES_ENABLE for nested folder as it was incorrectly required in 0.7.1
- [#302](https://github.com/esnet/gdg/pull/302) Adding Contact Points support.
- [#303](https://github.com/esnet/gdg/pull/303) Cleaning up Permission based listings.
- [#274](https://github.com/esnet/gdg/pull/274) Adding Dashboard Permissions, enterprise feature.


### Changes
- [#274](https://github.com/esnet/gdg/pull/274) Adding Dashboard Permissions, enterprise feature.
-

## Release Notes for v0.7.1
**Release Date: 09/11/2024**
Expand Down
16 changes: 16 additions & 0 deletions website/content/docs/usage_guide/backup_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ weight: 16

Every namespace supporting CRUD operations has the functions: list, download, upload, clear operating on only the monitored folders.

### Alerting

Alerting is made up of several type of entities: ContactPoints, Alert Rules, Notification Policy and finally Templates.
Currently only Contact Points is supported.

#### Contact Points

{{< callout note >}} Grafana has a contact point type named 'grafana-default-email' that has an inconsistent behavior.
Unless it has been modified, GDG will ignore it on listing, download and upload. If it has been modified, it will not be able to clear it due to grafana restriction {{< /callout >}}

```sh
./bin/gdg backup alerting contactpoints list -- Lists all current contact points
./bin/gdg backup alerting contactpoints download -- Download all known contact points
./bin/gdg backup alerting contactpoints upload -- Upload all contact points
./bin/gdg backup alerting contactpoints clear -- Clear all contact points
```

### Connections

Expand Down
Loading