Skip to content

Commit

Permalink
feat: Harvest grafana import should support nested Grafana folders (#…
Browse files Browse the repository at this point in the history
…3417)

* feat: Harvest grafana import should support nested Grafana folders
  • Loading branch information
cgrinds authored Jan 10, 2025
1 parent 09ebfa7 commit f5efb21
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 22 deletions.
70 changes: 59 additions & 11 deletions cmd/tools/grafana/grafana.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (
var (
grafanaMinVers = "7.1.0" // lowest grafana version we require
homePath string
grafanaVersion *goversion.Version
)

type options struct {
Expand Down Expand Up @@ -68,9 +69,10 @@ type options struct {
}

type Folder struct {
name string // Grafana folder where to upload from where to download dashboards
id int64
uid string
name string // Grafana folder where to upload from where to download dashboards
id int64
uid string
parentUID string // If nested folders are enabled, and the folder is nested, this is the parent folder's uid
}

func adjustOptions() {
Expand Down Expand Up @@ -472,12 +474,13 @@ func checkAndCreateServerFolder(folder *Folder) error {
os.Exit(1)
}

folderName := folder.name
if folder.uid != "" && folder.id != 0 {
fmt.Printf("folder [%s] exists in Grafana - OK\n", folder.name)
} else if err := createServerFolder(folder); err != nil {
} else if err := createServerFolders(folder); err != nil {
return err
} else {
fmt.Printf("created Grafana folder [%s] - OK\n", folder.name)
fmt.Printf("created Grafana folder [%s] - OK\n", folderName)
}
return nil
}
Expand Down Expand Up @@ -1123,27 +1126,34 @@ func isValidDatasource(result map[string]any) bool {
}

func checkVersion(inputVersion string) bool {
v1, err := goversion.NewVersion(inputVersion)
var err error

grafanaVersion, err = goversion.NewVersion(inputVersion)
if err != nil {
fmt.Println(err)
return false
}

minV, _ := goversion.NewVersion(grafanaMinVers)

// Not using a constraint check since a pre-release version (e.g. 8.4.0-beta1) never matches
// a constraint specified without a pre-release https://github.com/hashicorp/go-version/pull/35

satisfies := v1.GreaterThanOrEqual(minV)
satisfies := grafanaVersion.GreaterThanOrEqual(minV)
if !satisfies {
fmt.Printf("%s is not >= %s", v1, minV)
fmt.Printf("%s is not >= %s", grafanaVersion, minV)
}
return satisfies
}

func checkFolder(folder *Folder) error {

result, status, code, err := sendRequestArray(opts, "GET", "/api/folders?limit=1000", nil)
q := "/api/folders?limit=1000"

if folder.parentUID != "" {
q += "&parentUid=" + folder.parentUID
}

result, status, code, err := sendRequestArray(opts, "GET", q, nil)

if err != nil {
return err
Expand Down Expand Up @@ -1174,11 +1184,14 @@ func checkFolder(folder *Folder) error {
}

func createServerFolder(folder *Folder) error {

request := make(map[string]any)

request["title"] = folder.name

if folder.parentUID != "" {
request["parentUid"] = folder.parentUID
}

result, status, code, err := sendRequest(opts, "POST", "/api/folders", request)

if err != nil {
Expand All @@ -1195,6 +1208,41 @@ func createServerFolder(folder *Folder) error {
return nil
}

func createServerFolders(folder *Folder) error {

if grafanaVersion == nil || grafanaVersion.LessThan(goversion.Must(goversion.NewVersion("11.0.0"))) {
return createServerFolder(folder)
}

// handle nested folders
folders := strings.Split(folder.name, "/")
var parentUID string

for _, f := range folders {
curFolder := &Folder{name: f}
if parentUID != "" {
curFolder.parentUID = parentUID
}

if err := checkFolder(curFolder); err != nil {
return err
}

if curFolder.id == 0 {
curFolder.name = f
if err := createServerFolder(curFolder); err != nil {
return err
}
}

parentUID = curFolder.uid
folder.name = f
folder.id = curFolder.id
}

return nil
}

func sendRequest(opts *options, method, url string, query map[string]any) (map[string]any, string, int, error) {

var result map[string]any
Expand Down
6 changes: 3 additions & 3 deletions integration/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/shirou/gopsutil/v4 v4.24.11 // indirect
github.com/shirou/gopsutil/v4 v4.24.12 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tidwall/match v1.1.1 // indirect
Expand All @@ -34,8 +34,8 @@ require (
github.com/tklauser/numcpus v0.9.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
16 changes: 8 additions & 8 deletions integration/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4=
github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
Expand All @@ -62,10 +62,10 @@ golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down

0 comments on commit f5efb21

Please sign in to comment.