mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Refactor GoConvey in provisioning package (#40892)
* refactor goconvey in some provisioning subpackages * fix goconvey in provisioning/datasources * remove goconvey from notifiers subpackage * finally resolve goconvey in dashboards subpackage
This commit is contained in:
parent
b80fbe03f0
commit
7b15cd0ed2
@ -17,7 +17,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -32,403 +33,432 @@ const (
|
||||
var fakeService *fakeDashboardProvisioningService
|
||||
|
||||
func TestCreatingNewDashboardFileReader(t *testing.T) {
|
||||
Convey("creating new dashboard file reader", t, func() {
|
||||
cfg := &config{
|
||||
setup := func() *config {
|
||||
return &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "",
|
||||
Options: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
Convey("using path parameter", func() {
|
||||
cfg.Options["path"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(reader.Path, ShouldNotEqual, "")
|
||||
})
|
||||
t.Run("using path parameter", func(t *testing.T) {
|
||||
cfg := setup()
|
||||
cfg.Options["path"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, reader.Path, "")
|
||||
})
|
||||
|
||||
Convey("using folder as options", func() {
|
||||
cfg.Options["folder"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(reader.Path, ShouldNotEqual, "")
|
||||
})
|
||||
t.Run("using folder as options", func(t *testing.T) {
|
||||
cfg := setup()
|
||||
cfg.Options["folder"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, reader.Path, "")
|
||||
})
|
||||
|
||||
Convey("using foldersFromFilesStructure as options", func() {
|
||||
cfg.Options["path"] = foldersFromFilesStructure
|
||||
cfg.Options["foldersFromFilesStructure"] = true
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(reader.Path, ShouldNotEqual, "")
|
||||
})
|
||||
t.Run("using foldersFromFilesStructure as options", func(t *testing.T) {
|
||||
cfg := setup()
|
||||
cfg.Options["path"] = foldersFromFilesStructure
|
||||
cfg.Options["foldersFromFilesStructure"] = true
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, reader.Path, "")
|
||||
})
|
||||
|
||||
Convey("using full path", func() {
|
||||
fullPath := "/var/lib/grafana/dashboards"
|
||||
if runtime.GOOS == "windows" {
|
||||
fullPath = `c:\var\lib\grafana`
|
||||
}
|
||||
t.Run("using full path", func(t *testing.T) {
|
||||
cfg := setup()
|
||||
fullPath := "/var/lib/grafana/dashboards"
|
||||
if runtime.GOOS == "windows" {
|
||||
fullPath = `c:\var\lib\grafana`
|
||||
}
|
||||
|
||||
cfg.Options["folder"] = fullPath
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
cfg.Options["folder"] = fullPath
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
So(reader.Path, ShouldEqual, fullPath)
|
||||
So(filepath.IsAbs(reader.Path), ShouldBeTrue)
|
||||
})
|
||||
require.Equal(t, reader.Path, fullPath)
|
||||
require.True(t, filepath.IsAbs(reader.Path))
|
||||
})
|
||||
|
||||
Convey("using relative path", func() {
|
||||
cfg.Options["folder"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
t.Run("using relative path", func(t *testing.T) {
|
||||
cfg := setup()
|
||||
cfg.Options["folder"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
resolvedPath := reader.resolvedPath()
|
||||
So(filepath.IsAbs(resolvedPath), ShouldBeTrue)
|
||||
})
|
||||
resolvedPath := reader.resolvedPath()
|
||||
require.True(t, filepath.IsAbs(resolvedPath))
|
||||
})
|
||||
}
|
||||
|
||||
func TestDashboardFileReader(t *testing.T) {
|
||||
Convey("Dashboard file reader", t, func() {
|
||||
logger := log.New("test.logger")
|
||||
cfg := &config{}
|
||||
|
||||
origNewDashboardProvisioningService := dashboards.NewProvisioningService
|
||||
defer func() {
|
||||
dashboards.NewProvisioningService = origNewDashboardProvisioningService
|
||||
}()
|
||||
|
||||
setup := func() {
|
||||
bus.ClearBusHandlers()
|
||||
origNewDashboardProvisioningService := dashboards.NewProvisioningService
|
||||
Reset(func() {
|
||||
dashboards.NewProvisioningService = origNewDashboardProvisioningService
|
||||
})
|
||||
fakeService = mockDashboardProvisioningService()
|
||||
|
||||
bus.AddHandler("test", mockGetDashboardQuery)
|
||||
logger := log.New("test.logger")
|
||||
cfg = &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "",
|
||||
Options: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
Convey("Reading dashboards from disk", func() {
|
||||
cfg := &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "",
|
||||
Options: map[string]interface{}{},
|
||||
t.Run("Reading dashboards from disk", func(t *testing.T) {
|
||||
t.Run("Can read default dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = defaultDashboards
|
||||
cfg.Folder = "Team A"
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
folders := 0
|
||||
dashboards := 0
|
||||
|
||||
for _, i := range fakeService.inserted {
|
||||
if i.Dashboard.IsFolder {
|
||||
folders++
|
||||
} else {
|
||||
dashboards++
|
||||
}
|
||||
}
|
||||
|
||||
Convey("Can read default dashboard", func() {
|
||||
cfg.Options["path"] = defaultDashboards
|
||||
cfg.Folder = "Team A"
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
folders := 0
|
||||
dashboards := 0
|
||||
|
||||
for _, i := range fakeService.inserted {
|
||||
if i.Dashboard.IsFolder {
|
||||
folders++
|
||||
} else {
|
||||
dashboards++
|
||||
}
|
||||
}
|
||||
|
||||
So(folders, ShouldEqual, 1)
|
||||
So(dashboards, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("Can read default dashboard and replace old version in database", func() {
|
||||
cfg.Options["path"] = oneDashboard
|
||||
|
||||
stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
|
||||
fakeService.getDashboard = append(fakeService.getDashboard, &models.Dashboard{
|
||||
Updated: stat.ModTime().AddDate(0, 0, -1),
|
||||
Slug: "grafana",
|
||||
})
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(fakeService.inserted), ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("Dashboard with older timestamp and the same checksum will not replace imported dashboard", func() {
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
file, err := os.Open(filepath.Clean(absPath))
|
||||
So(err, ShouldBeNil)
|
||||
t.Cleanup(func() {
|
||||
_ = file.Close()
|
||||
})
|
||||
|
||||
checksum, err := util.Md5Sum(file)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
|
||||
CheckSum: checksum,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
So(len(fakeService.inserted), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Dashboard with older timestamp and different checksum will replace imported dashboard", func() {
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
|
||||
CheckSum: "fakechecksum",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
So(len(fakeService.inserted), ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("Dashboard with newer timestamp and the same checksum will not replace imported dashboard", func() {
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
file, err := os.Open(filepath.Clean(absPath))
|
||||
So(err, ShouldBeNil)
|
||||
t.Cleanup(func() {
|
||||
_ = file.Close()
|
||||
})
|
||||
|
||||
checksum, err := util.Md5Sum(file)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
|
||||
CheckSum: checksum,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
So(len(fakeService.inserted), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Dashboard with newer timestamp and different checksum should replace imported dashboard", func() {
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
|
||||
CheckSum: "fakechecksum",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
So(len(fakeService.inserted), ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("Overrides id from dashboard.json files", func() {
|
||||
cfg.Options["path"] = containingID
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(fakeService.inserted), ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("Get folder from files structure", func() {
|
||||
cfg.Options["path"] = foldersFromFilesStructure
|
||||
cfg.Options["foldersFromFilesStructure"] = true
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(fakeService.inserted), ShouldEqual, 5)
|
||||
|
||||
foldersCount := 0
|
||||
for _, d := range fakeService.inserted {
|
||||
if d.Dashboard.IsFolder {
|
||||
foldersCount++
|
||||
}
|
||||
}
|
||||
So(foldersCount, ShouldEqual, 2)
|
||||
|
||||
foldersAndDashboards := make(map[string]struct{}, 5)
|
||||
for _, d := range fakeService.inserted {
|
||||
title := d.Dashboard.Title
|
||||
if _, ok := foldersAndDashboards[title]; ok {
|
||||
So(fmt.Errorf("dashboard title %q already exists", title), ShouldBeNil)
|
||||
}
|
||||
|
||||
switch title {
|
||||
case "folderOne", "folderTwo":
|
||||
So(d.Dashboard.IsFolder, ShouldBeTrue)
|
||||
case "Grafana1", "Grafana2", "RootDashboard":
|
||||
So(d.Dashboard.IsFolder, ShouldBeFalse)
|
||||
default:
|
||||
So(fmt.Errorf("unknown dashboard title %q", title), ShouldBeNil)
|
||||
}
|
||||
|
||||
foldersAndDashboards[title] = struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
Convey("Invalid configuration should return error", func() {
|
||||
cfg := &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "",
|
||||
}
|
||||
|
||||
_, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Broken dashboards should not cause error", func() {
|
||||
cfg.Options["path"] = brokenDashboards
|
||||
|
||||
_, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Two dashboard providers should be able to provisioned the same dashboard without uid", func() {
|
||||
cfg1 := &config{Name: "1", Type: "file", OrgID: 1, Folder: "f1", Options: map[string]interface{}{"path": containingID}}
|
||||
cfg2 := &config{Name: "2", Type: "file", OrgID: 1, Folder: "f2", Options: map[string]interface{}{"path": containingID}}
|
||||
|
||||
reader1, err := NewDashboardFileReader(cfg1, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader1.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
reader2, err := NewDashboardFileReader(cfg2, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader2.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
var folderCount int
|
||||
var dashCount int
|
||||
for _, o := range fakeService.inserted {
|
||||
if o.Dashboard.IsFolder {
|
||||
folderCount++
|
||||
} else {
|
||||
dashCount++
|
||||
}
|
||||
}
|
||||
|
||||
So(folderCount, ShouldEqual, 2)
|
||||
So(dashCount, ShouldEqual, 2)
|
||||
})
|
||||
require.Equal(t, folders, 1)
|
||||
require.Equal(t, dashboards, 2)
|
||||
})
|
||||
|
||||
Convey("Should not create new folder if folder name is missing", func() {
|
||||
t.Run("Can read default dashboard and replace old version in database", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = oneDashboard
|
||||
|
||||
stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
|
||||
fakeService.getDashboard = append(fakeService.getDashboard, &models.Dashboard{
|
||||
Updated: stat.ModTime().AddDate(0, 0, -1),
|
||||
Slug: "grafana",
|
||||
})
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(fakeService.inserted), 1)
|
||||
})
|
||||
|
||||
t.Run("Dashboard with older timestamp and the same checksum will not replace imported dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
file, err := os.Open(filepath.Clean(absPath))
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = file.Close()
|
||||
})
|
||||
|
||||
checksum, err := util.Md5Sum(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
|
||||
CheckSum: checksum,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(fakeService.inserted), 0)
|
||||
})
|
||||
|
||||
t.Run("Dashboard with older timestamp and different checksum will replace imported dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
|
||||
CheckSum: "fakechecksum",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(fakeService.inserted), 1)
|
||||
})
|
||||
|
||||
t.Run("Dashboard with newer timestamp and the same checksum will not replace imported dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
file, err := os.Open(filepath.Clean(absPath))
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = file.Close()
|
||||
})
|
||||
|
||||
checksum, err := util.Md5Sum(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
|
||||
CheckSum: checksum,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(fakeService.inserted), 0)
|
||||
})
|
||||
|
||||
t.Run("Dashboard with newer timestamp and different checksum should replace imported dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = oneDashboard
|
||||
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{
|
||||
Name: "Default",
|
||||
ExternalId: absPath,
|
||||
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
|
||||
CheckSum: "fakechecksum",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(fakeService.inserted), 1)
|
||||
})
|
||||
|
||||
t.Run("Overrides id from dashboard.json files", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = containingID
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(fakeService.inserted), 1)
|
||||
})
|
||||
|
||||
t.Run("Get folder from files structure", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = foldersFromFilesStructure
|
||||
cfg.Options["foldersFromFilesStructure"] = true
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(fakeService.inserted), 5)
|
||||
|
||||
foldersCount := 0
|
||||
for _, d := range fakeService.inserted {
|
||||
if d.Dashboard.IsFolder {
|
||||
foldersCount++
|
||||
}
|
||||
}
|
||||
require.Equal(t, foldersCount, 2)
|
||||
|
||||
foldersAndDashboards := make(map[string]struct{}, 5)
|
||||
for _, d := range fakeService.inserted {
|
||||
title := d.Dashboard.Title
|
||||
if _, ok := foldersAndDashboards[title]; ok {
|
||||
require.Nil(t, fmt.Errorf("dashboard title %q already exists", title))
|
||||
}
|
||||
|
||||
switch title {
|
||||
case "folderOne", "folderTwo":
|
||||
require.True(t, d.Dashboard.IsFolder)
|
||||
case "Grafana1", "Grafana2", "RootDashboard":
|
||||
require.False(t, d.Dashboard.IsFolder)
|
||||
default:
|
||||
require.Nil(t, fmt.Errorf("unknown dashboard title %q", title))
|
||||
}
|
||||
|
||||
foldersAndDashboards[title] = struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid configuration should return error", func(t *testing.T) {
|
||||
setup()
|
||||
cfg := &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "",
|
||||
Options: map[string]interface{}{
|
||||
"folder": defaultDashboards,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
|
||||
So(err, ShouldEqual, ErrFolderNameMissing)
|
||||
_, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
Convey("can get or Create dashboard folder", func() {
|
||||
cfg := &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "TEAM A",
|
||||
Options: map[string]interface{}{
|
||||
"folder": defaultDashboards,
|
||||
},
|
||||
}
|
||||
t.Run("Broken dashboards should not cause error", func(t *testing.T) {
|
||||
setup()
|
||||
cfg.Options["path"] = brokenDashboards
|
||||
|
||||
folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
|
||||
So(err, ShouldBeNil)
|
||||
inserted := false
|
||||
for _, d := range fakeService.inserted {
|
||||
if d.Dashboard.IsFolder && d.Dashboard.Id == folderID {
|
||||
inserted = true
|
||||
_, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Two dashboard providers should be able to provisioned the same dashboard without uid", func(t *testing.T) {
|
||||
setup()
|
||||
cfg1 := &config{Name: "1", Type: "file", OrgID: 1, Folder: "f1", Options: map[string]interface{}{"path": containingID}}
|
||||
cfg2 := &config{Name: "2", Type: "file", OrgID: 1, Folder: "f2", Options: map[string]interface{}{"path": containingID}}
|
||||
|
||||
reader1, err := NewDashboardFileReader(cfg1, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader1.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
reader2, err := NewDashboardFileReader(cfg2, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader2.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
var folderCount int
|
||||
var dashCount int
|
||||
for _, o := range fakeService.inserted {
|
||||
if o.Dashboard.IsFolder {
|
||||
folderCount++
|
||||
} else {
|
||||
dashCount++
|
||||
}
|
||||
}
|
||||
So(len(fakeService.inserted), ShouldEqual, 1)
|
||||
So(inserted, ShouldBeTrue)
|
||||
|
||||
require.Equal(t, folderCount, 2)
|
||||
require.Equal(t, dashCount, 2)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Should not create new folder if folder name is missing", func(t *testing.T) {
|
||||
setup()
|
||||
cfg := &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "",
|
||||
Options: map[string]interface{}{
|
||||
"folder": defaultDashboards,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
|
||||
require.Equal(t, err, ErrFolderNameMissing)
|
||||
})
|
||||
|
||||
t.Run("can get or Create dashboard folder", func(t *testing.T) {
|
||||
setup()
|
||||
cfg := &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
Folder: "TEAM A",
|
||||
Options: map[string]interface{}{
|
||||
"folder": defaultDashboards,
|
||||
},
|
||||
}
|
||||
|
||||
folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
|
||||
require.NoError(t, err)
|
||||
inserted := false
|
||||
for _, d := range fakeService.inserted {
|
||||
if d.Dashboard.IsFolder && d.Dashboard.Id == folderID {
|
||||
inserted = true
|
||||
}
|
||||
}
|
||||
require.Equal(t, len(fakeService.inserted), 1)
|
||||
require.True(t, inserted)
|
||||
})
|
||||
|
||||
t.Run("Walking the folder with dashboards", func(t *testing.T) {
|
||||
setup()
|
||||
noFiles := map[string]os.FileInfo{}
|
||||
|
||||
t.Run("should skip dirs that starts with .", func(t *testing.T) {
|
||||
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil)
|
||||
require.Equal(t, shouldSkip, filepath.SkipDir)
|
||||
})
|
||||
|
||||
Convey("Walking the folder with dashboards", func() {
|
||||
noFiles := map[string]os.FileInfo{}
|
||||
|
||||
Convey("should skip dirs that starts with .", func() {
|
||||
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil)
|
||||
So(shouldSkip, ShouldEqual, filepath.SkipDir)
|
||||
})
|
||||
|
||||
Convey("should keep walking if file is not .json", func() {
|
||||
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil)
|
||||
So(shouldSkip, ShouldBeNil)
|
||||
})
|
||||
t.Run("should keep walking if file is not .json", func(t *testing.T) {
|
||||
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil)
|
||||
require.Nil(t, shouldSkip)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Given missing dashboard file", func() {
|
||||
cfg := &config{
|
||||
t.Run("Given missing dashboard file", func(t *testing.T) {
|
||||
absPath1, err := filepath.Abs(unprovision + "/dashboard1.json")
|
||||
require.NoError(t, err)
|
||||
// This one does not exist on disk, simulating a deleted file
|
||||
absPath2, err := filepath.Abs(unprovision + "/dashboard2.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
setupFakeService := func() {
|
||||
setup()
|
||||
cfg = &config{
|
||||
Name: "Default",
|
||||
Type: "file",
|
||||
OrgID: 1,
|
||||
@ -442,44 +472,40 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
{Dashboard: &models.Dashboard{Id: 2}},
|
||||
}
|
||||
|
||||
absPath1, err := filepath.Abs(unprovision + "/dashboard1.json")
|
||||
So(err, ShouldBeNil)
|
||||
// This one does not exist on disk, simulating a deleted file
|
||||
absPath2, err := filepath.Abs(unprovision + "/dashboard2.json")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
|
||||
"Default": {
|
||||
{DashboardId: 1, Name: "Default", ExternalId: absPath1},
|
||||
{DashboardId: 2, Name: "Default", ExternalId: absPath2},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Convey("Missing dashboard should be unprovisioned if DisableDeletion = true", func() {
|
||||
cfg.DisableDeletion = true
|
||||
t.Run("Missing dashboard should be unprovisioned if DisableDeletion = true", func(t *testing.T) {
|
||||
setupFakeService()
|
||||
cfg.DisableDeletion = true
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
So(len(fakeService.provisioned["Default"]), ShouldEqual, 1)
|
||||
So(fakeService.provisioned["Default"][0].ExternalId, ShouldEqual, absPath1)
|
||||
})
|
||||
require.Equal(t, len(fakeService.provisioned["Default"]), 1)
|
||||
require.Equal(t, fakeService.provisioned["Default"][0].ExternalId, absPath1)
|
||||
})
|
||||
|
||||
Convey("Missing dashboard should be deleted if DisableDeletion = false", func() {
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
t.Run("Missing dashboard should be deleted if DisableDeletion = false", func(t *testing.T) {
|
||||
setupFakeService()
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = reader.walkDisk(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
err = reader.walkDisk(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
So(len(fakeService.provisioned["Default"]), ShouldEqual, 1)
|
||||
So(fakeService.provisioned["Default"][0].ExternalId, ShouldEqual, absPath1)
|
||||
So(len(fakeService.inserted), ShouldEqual, 1)
|
||||
So(fakeService.inserted[0].Dashboard.Id, ShouldEqual, 1)
|
||||
})
|
||||
require.Equal(t, len(fakeService.provisioned["Default"]), 1)
|
||||
require.Equal(t, fakeService.provisioned["Default"][0].ExternalId, absPath1)
|
||||
require.Equal(t, len(fakeService.inserted), 1)
|
||||
require.Equal(t, fakeService.inserted[0].Dashboard.Id, int64(1))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -29,7 +29,7 @@ var (
|
||||
)
|
||||
|
||||
func TestDatasourceAsConfig(t *testing.T) {
|
||||
Convey("Testing datasource as configuration", t, func() {
|
||||
setup := func() {
|
||||
fakeRepo = &fakeRepository{}
|
||||
bus.ClearBusHandlers()
|
||||
bus.AddHandler("test", mockDelete)
|
||||
@ -37,226 +37,229 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
bus.AddHandler("test", mockUpdate)
|
||||
bus.AddHandler("test", mockGet)
|
||||
bus.AddHandler("test", mockGetOrg)
|
||||
}
|
||||
|
||||
Convey("apply default values when missing", func() {
|
||||
t.Run("apply default values when missing", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), withoutDefaults)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
|
||||
require.Equal(t, len(fakeRepo.inserted), 1)
|
||||
require.Equal(t, fakeRepo.inserted[0].OrgId, int64(1))
|
||||
require.Equal(t, fakeRepo.inserted[0].Access, models.DsAccess("proxy"))
|
||||
})
|
||||
|
||||
t.Run("no datasource in database", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
|
||||
require.Equal(t, len(fakeRepo.deleted), 0)
|
||||
require.Equal(t, len(fakeRepo.inserted), 2)
|
||||
require.Equal(t, len(fakeRepo.updated), 0)
|
||||
})
|
||||
|
||||
t.Run("One datasource in database with same name", func(t *testing.T) {
|
||||
setup()
|
||||
fakeRepo.loadAll = []*models.DataSource{
|
||||
{Name: "Graphite", OrgId: 1, Id: 1},
|
||||
}
|
||||
|
||||
t.Run("should update one datasource", func(t *testing.T) {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), withoutDefaults)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
|
||||
So(len(fakeRepo.inserted), ShouldEqual, 1)
|
||||
So(fakeRepo.inserted[0].OrgId, ShouldEqual, 1)
|
||||
So(fakeRepo.inserted[0].Access, ShouldEqual, "proxy")
|
||||
require.Equal(t, len(fakeRepo.deleted), 0)
|
||||
require.Equal(t, len(fakeRepo.inserted), 1)
|
||||
require.Equal(t, len(fakeRepo.updated), 1)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("One configured datasource", func() {
|
||||
Convey("no datasource in database", func() {
|
||||
t.Run("Two datasources with is_default", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), doubleDatasourcesConfig)
|
||||
t.Run("should raise error", func(t *testing.T) { require.Equal(t, err, ErrInvalidConfigToManyDefault) })
|
||||
})
|
||||
|
||||
t.Run("Multiple datasources in different organizations with isDefault in each organization", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), multipleOrgsWithDefault)
|
||||
t.Run("should not raise error", func(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(fakeRepo.inserted), 4)
|
||||
require.True(t, fakeRepo.inserted[0].IsDefault)
|
||||
require.Equal(t, fakeRepo.inserted[0].OrgId, int64(1))
|
||||
require.True(t, fakeRepo.inserted[2].IsDefault)
|
||||
require.Equal(t, fakeRepo.inserted[2].OrgId, int64(2))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Two configured datasource and purge others ", func(t *testing.T) {
|
||||
setup()
|
||||
t.Run("two other datasources in database", func(t *testing.T) {
|
||||
fakeRepo.loadAll = []*models.DataSource{
|
||||
{Name: "old-graphite", OrgId: 1, Id: 1},
|
||||
{Name: "old-graphite2", OrgId: 1, Id: 2},
|
||||
}
|
||||
|
||||
t.Run("should have two new datasources", func(t *testing.T) {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfigPurgeOthers)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
|
||||
require.Equal(t, len(fakeRepo.deleted), 2)
|
||||
require.Equal(t, len(fakeRepo.inserted), 2)
|
||||
require.Equal(t, len(fakeRepo.updated), 0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Two configured datasource and purge others = false", func(t *testing.T) {
|
||||
setup()
|
||||
t.Run("two other datasources in database", func(t *testing.T) {
|
||||
fakeRepo.loadAll = []*models.DataSource{
|
||||
{Name: "Graphite", OrgId: 1, Id: 1},
|
||||
{Name: "old-graphite2", OrgId: 1, Id: 2},
|
||||
}
|
||||
|
||||
t.Run("should have two new datasources", func(t *testing.T) {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
|
||||
So(len(fakeRepo.deleted), ShouldEqual, 0)
|
||||
So(len(fakeRepo.inserted), ShouldEqual, 2)
|
||||
So(len(fakeRepo.updated), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("One datasource in database with same name", func() {
|
||||
fakeRepo.loadAll = []*models.DataSource{
|
||||
{Name: "Graphite", OrgId: 1, Id: 1},
|
||||
}
|
||||
|
||||
Convey("should update one datasource", func() {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
|
||||
So(len(fakeRepo.deleted), ShouldEqual, 0)
|
||||
So(len(fakeRepo.inserted), ShouldEqual, 1)
|
||||
So(len(fakeRepo.updated), ShouldEqual, 1)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Two datasources with is_default", func() {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), doubleDatasourcesConfig)
|
||||
Convey("should raise error", func() {
|
||||
So(err, ShouldEqual, ErrInvalidConfigToManyDefault)
|
||||
})
|
||||
require.Equal(t, len(fakeRepo.deleted), 0)
|
||||
require.Equal(t, len(fakeRepo.inserted), 1)
|
||||
require.Equal(t, len(fakeRepo.updated), 1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Multiple datasources in different organizations with isDefault in each organization", func() {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), multipleOrgsWithDefault)
|
||||
Convey("should not raise error", func() {
|
||||
So(err, ShouldBeNil)
|
||||
So(len(fakeRepo.inserted), ShouldEqual, 4)
|
||||
So(fakeRepo.inserted[0].IsDefault, ShouldBeTrue)
|
||||
So(fakeRepo.inserted[0].OrgId, ShouldEqual, 1)
|
||||
So(fakeRepo.inserted[2].IsDefault, ShouldBeTrue)
|
||||
So(fakeRepo.inserted[2].OrgId, ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
t.Run("broken yaml should return error", func(t *testing.T) {
|
||||
reader := &configReader{}
|
||||
_, err := reader.readConfig(brokenYaml)
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
Convey("Two configured datasource and purge others ", func() {
|
||||
Convey("two other datasources in database", func() {
|
||||
fakeRepo.loadAll = []*models.DataSource{
|
||||
{Name: "old-graphite", OrgId: 1, Id: 1},
|
||||
{Name: "old-graphite2", OrgId: 1, Id: 2},
|
||||
}
|
||||
t.Run("invalid access should warn about invalid value and return 'proxy'", func(t *testing.T) {
|
||||
reader := &configReader{log: logger}
|
||||
configs, err := reader.readConfig(invalidAccess)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, configs[0].Datasources[0].Access, models.DS_ACCESS_PROXY)
|
||||
})
|
||||
|
||||
Convey("should have two new datasources", func() {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfigPurgeOthers)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
t.Run("skip invalid directory", func(t *testing.T) {
|
||||
cfgProvider := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvider.readConfig("./invalid-directory")
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
|
||||
So(len(fakeRepo.deleted), ShouldEqual, 2)
|
||||
So(len(fakeRepo.inserted), ShouldEqual, 2)
|
||||
So(len(fakeRepo.updated), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
})
|
||||
require.Equal(t, len(cfg), 0)
|
||||
})
|
||||
|
||||
Convey("Two configured datasource and purge others = false", func() {
|
||||
Convey("two other datasources in database", func() {
|
||||
fakeRepo.loadAll = []*models.DataSource{
|
||||
{Name: "Graphite", OrgId: 1, Id: 1},
|
||||
{Name: "old-graphite2", OrgId: 1, Id: 2},
|
||||
}
|
||||
t.Run("can read all properties from version 1", func(t *testing.T) {
|
||||
_ = os.Setenv("TEST_VAR", "name")
|
||||
cfgProvider := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvider.readConfig(allProperties)
|
||||
_ = os.Unsetenv("TEST_VAR")
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
|
||||
Convey("should have two new datasources", func() {
|
||||
dc := newDatasourceProvisioner(logger)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
require.Equal(t, len(cfg), 3)
|
||||
|
||||
So(len(fakeRepo.deleted), ShouldEqual, 0)
|
||||
So(len(fakeRepo.inserted), ShouldEqual, 1)
|
||||
So(len(fakeRepo.updated), ShouldEqual, 1)
|
||||
})
|
||||
})
|
||||
})
|
||||
dsCfg := cfg[0]
|
||||
|
||||
Convey("broken yaml should return error", func() {
|
||||
reader := &configReader{}
|
||||
_, err := reader.readConfig(brokenYaml)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
require.Equal(t, dsCfg.APIVersion, int64(1))
|
||||
|
||||
Convey("invalid access should warn about invalid value and return 'proxy'", func() {
|
||||
reader := &configReader{log: logger}
|
||||
configs, err := reader.readConfig(invalidAccess)
|
||||
So(err, ShouldBeNil)
|
||||
So(configs[0].Datasources[0].Access, ShouldEqual, models.DS_ACCESS_PROXY)
|
||||
})
|
||||
validateDatasourceV1(t, dsCfg)
|
||||
validateDeleteDatasources(t, dsCfg)
|
||||
|
||||
Convey("skip invalid directory", func() {
|
||||
cfgProvider := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvider.readConfig("./invalid-directory")
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
dsCount := 0
|
||||
delDsCount := 0
|
||||
|
||||
So(len(cfg), ShouldEqual, 0)
|
||||
})
|
||||
for _, c := range cfg {
|
||||
dsCount += len(c.Datasources)
|
||||
delDsCount += len(c.DeleteDatasources)
|
||||
}
|
||||
|
||||
Convey("can read all properties from version 1", func() {
|
||||
_ = os.Setenv("TEST_VAR", "name")
|
||||
cfgProvider := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvider.readConfig(allProperties)
|
||||
_ = os.Unsetenv("TEST_VAR")
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
require.Equal(t, dsCount, 2)
|
||||
require.Equal(t, delDsCount, 1)
|
||||
})
|
||||
|
||||
So(len(cfg), ShouldEqual, 3)
|
||||
t.Run("can read all properties from version 0", func(t *testing.T) {
|
||||
cfgProvider := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvider.readConfig(versionZero)
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
|
||||
dsCfg := cfg[0]
|
||||
require.Equal(t, len(cfg), 1)
|
||||
|
||||
So(dsCfg.APIVersion, ShouldEqual, 1)
|
||||
dsCfg := cfg[0]
|
||||
|
||||
validateDatasourceV1(dsCfg)
|
||||
validateDeleteDatasources(dsCfg)
|
||||
require.Equal(t, dsCfg.APIVersion, int64(0))
|
||||
|
||||
dsCount := 0
|
||||
delDsCount := 0
|
||||
|
||||
for _, c := range cfg {
|
||||
dsCount += len(c.Datasources)
|
||||
delDsCount += len(c.DeleteDatasources)
|
||||
}
|
||||
|
||||
So(dsCount, ShouldEqual, 2)
|
||||
So(delDsCount, ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("can read all properties from version 0", func() {
|
||||
cfgProvider := &configReader{log: log.New("test logger")}
|
||||
cfg, err := cfgProvider.readConfig(versionZero)
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
|
||||
So(len(cfg), ShouldEqual, 1)
|
||||
|
||||
dsCfg := cfg[0]
|
||||
|
||||
So(dsCfg.APIVersion, ShouldEqual, 0)
|
||||
|
||||
validateDatasource(dsCfg)
|
||||
validateDeleteDatasources(dsCfg)
|
||||
})
|
||||
validateDatasource(t, dsCfg)
|
||||
validateDeleteDatasources(t, dsCfg)
|
||||
})
|
||||
}
|
||||
|
||||
func validateDeleteDatasources(dsCfg *configs) {
|
||||
So(len(dsCfg.DeleteDatasources), ShouldEqual, 1)
|
||||
func validateDeleteDatasources(t *testing.T, dsCfg *configs) {
|
||||
require.Equal(t, len(dsCfg.DeleteDatasources), 1)
|
||||
deleteDs := dsCfg.DeleteDatasources[0]
|
||||
So(deleteDs.Name, ShouldEqual, "old-graphite3")
|
||||
So(deleteDs.OrgID, ShouldEqual, 2)
|
||||
require.Equal(t, deleteDs.Name, "old-graphite3")
|
||||
require.Equal(t, deleteDs.OrgID, int64(2))
|
||||
}
|
||||
|
||||
func validateDatasource(dsCfg *configs) {
|
||||
func validateDatasource(t *testing.T, dsCfg *configs) {
|
||||
ds := dsCfg.Datasources[0]
|
||||
So(ds.Name, ShouldEqual, "name")
|
||||
So(ds.Type, ShouldEqual, "type")
|
||||
So(ds.Access, ShouldEqual, models.DS_ACCESS_PROXY)
|
||||
So(ds.OrgID, ShouldEqual, 2)
|
||||
So(ds.URL, ShouldEqual, "url")
|
||||
So(ds.User, ShouldEqual, "user")
|
||||
So(ds.Password, ShouldEqual, "password")
|
||||
So(ds.Database, ShouldEqual, "database")
|
||||
So(ds.BasicAuth, ShouldBeTrue)
|
||||
So(ds.BasicAuthUser, ShouldEqual, "basic_auth_user")
|
||||
So(ds.BasicAuthPassword, ShouldEqual, "basic_auth_password")
|
||||
So(ds.WithCredentials, ShouldBeTrue)
|
||||
So(ds.IsDefault, ShouldBeTrue)
|
||||
So(ds.Editable, ShouldBeTrue)
|
||||
So(ds.Version, ShouldEqual, 10)
|
||||
require.Equal(t, ds.Name, "name")
|
||||
require.Equal(t, ds.Type, "type")
|
||||
require.Equal(t, ds.Access, models.DS_ACCESS_PROXY)
|
||||
require.Equal(t, ds.OrgID, int64(2))
|
||||
require.Equal(t, ds.URL, "url")
|
||||
require.Equal(t, ds.User, "user")
|
||||
require.Equal(t, ds.Password, "password")
|
||||
require.Equal(t, ds.Database, "database")
|
||||
require.True(t, ds.BasicAuth)
|
||||
require.Equal(t, ds.BasicAuthUser, "basic_auth_user")
|
||||
require.Equal(t, ds.BasicAuthPassword, "basic_auth_password")
|
||||
require.True(t, ds.WithCredentials)
|
||||
require.True(t, ds.IsDefault)
|
||||
require.True(t, ds.Editable)
|
||||
require.Equal(t, ds.Version, 10)
|
||||
|
||||
So(len(ds.JSONData), ShouldBeGreaterThan, 2)
|
||||
So(ds.JSONData["graphiteVersion"], ShouldEqual, "1.1")
|
||||
So(ds.JSONData["tlsAuth"], ShouldEqual, true)
|
||||
So(ds.JSONData["tlsAuthWithCACert"], ShouldEqual, true)
|
||||
require.Greater(t, len(ds.JSONData), 2)
|
||||
require.Equal(t, ds.JSONData["graphiteVersion"], "1.1")
|
||||
require.Equal(t, ds.JSONData["tlsAuth"], true)
|
||||
require.Equal(t, ds.JSONData["tlsAuthWithCACert"], true)
|
||||
|
||||
So(len(ds.SecureJSONData), ShouldBeGreaterThan, 2)
|
||||
So(ds.SecureJSONData["tlsCACert"], ShouldEqual, "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
|
||||
So(ds.SecureJSONData["tlsClientCert"], ShouldEqual, "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
|
||||
So(ds.SecureJSONData["tlsClientKey"], ShouldEqual, "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
|
||||
require.Greater(t, len(ds.SecureJSONData), 2)
|
||||
require.Equal(t, ds.SecureJSONData["tlsCACert"], "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
|
||||
require.Equal(t, ds.SecureJSONData["tlsClientCert"], "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
|
||||
require.Equal(t, ds.SecureJSONData["tlsClientKey"], "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
|
||||
}
|
||||
|
||||
func validateDatasourceV1(dsCfg *configs) {
|
||||
validateDatasource(dsCfg)
|
||||
func validateDatasourceV1(t *testing.T, dsCfg *configs) {
|
||||
validateDatasource(t, dsCfg)
|
||||
ds := dsCfg.Datasources[0]
|
||||
So(ds.UID, ShouldEqual, "test_uid")
|
||||
require.Equal(t, ds.UID, "test_uid")
|
||||
}
|
||||
|
||||
type fakeRepository struct {
|
||||
|
@ -12,7 +12,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -29,31 +30,35 @@ var (
|
||||
)
|
||||
|
||||
func TestNotificationAsConfig(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
logger := log.New("fake.log")
|
||||
|
||||
Convey("Testing notification as configuration", t, func() {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
setupBusHandlers(sqlStore)
|
||||
t.Run("Testing notification as configuration", func(t *testing.T) {
|
||||
setup := func() {
|
||||
sqlStore = sqlstore.InitTestDB(t)
|
||||
setupBusHandlers(sqlStore)
|
||||
|
||||
for i := 1; i < 5; i++ {
|
||||
orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)}
|
||||
err := sqlstore.CreateOrg(&orgCommand)
|
||||
So(err, ShouldBeNil)
|
||||
for i := 1; i < 5; i++ {
|
||||
orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)}
|
||||
err := sqlstore.CreateOrg(&orgCommand)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: "slack",
|
||||
Name: "slack",
|
||||
Factory: notifiers.NewSlackNotifier,
|
||||
})
|
||||
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: "email",
|
||||
Name: "email",
|
||||
Factory: notifiers.NewEmailNotifier,
|
||||
})
|
||||
}
|
||||
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: "slack",
|
||||
Name: "slack",
|
||||
Factory: notifiers.NewSlackNotifier,
|
||||
})
|
||||
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: "email",
|
||||
Name: "email",
|
||||
Factory: notifiers.NewEmailNotifier,
|
||||
})
|
||||
|
||||
Convey("Can read correct properties", func() {
|
||||
t.Run("Can read correct properties", func(t *testing.T) {
|
||||
setup()
|
||||
_ = os.Setenv("TEST_VAR", "default")
|
||||
cfgProvider := &configReader{
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
@ -65,73 +70,74 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
So(len(cfg), ShouldEqual, 1)
|
||||
require.Equal(t, len(cfg), 1)
|
||||
|
||||
ntCfg := cfg[0]
|
||||
nts := ntCfg.Notifications
|
||||
So(len(nts), ShouldEqual, 4)
|
||||
require.Equal(t, len(nts), 4)
|
||||
|
||||
nt := nts[0]
|
||||
So(nt.Name, ShouldEqual, "default-slack-notification")
|
||||
So(nt.Type, ShouldEqual, "slack")
|
||||
So(nt.OrgID, ShouldEqual, 2)
|
||||
So(nt.UID, ShouldEqual, "notifier1")
|
||||
So(nt.IsDefault, ShouldBeTrue)
|
||||
So(nt.Settings, ShouldResemble, map[string]interface{}{
|
||||
require.Equal(t, nt.Name, "default-slack-notification")
|
||||
require.Equal(t, nt.Type, "slack")
|
||||
require.Equal(t, nt.OrgID, int64(2))
|
||||
require.Equal(t, nt.UID, "notifier1")
|
||||
require.True(t, nt.IsDefault)
|
||||
require.Equal(t, nt.Settings, map[string]interface{}{
|
||||
"recipient": "XXX", "token": "xoxb", "uploadImage": true, "url": "https://slack.com",
|
||||
})
|
||||
So(nt.SecureSettings, ShouldResemble, map[string]string{
|
||||
require.Equal(t, nt.SecureSettings, map[string]string{
|
||||
"token": "xoxbsecure", "url": "https://slack.com/secure",
|
||||
})
|
||||
So(nt.SendReminder, ShouldBeTrue)
|
||||
So(nt.Frequency, ShouldEqual, "1h")
|
||||
require.True(t, nt.SendReminder)
|
||||
require.Equal(t, nt.Frequency, "1h")
|
||||
|
||||
nt = nts[1]
|
||||
So(nt.Name, ShouldEqual, "another-not-default-notification")
|
||||
So(nt.Type, ShouldEqual, "email")
|
||||
So(nt.OrgID, ShouldEqual, 3)
|
||||
So(nt.UID, ShouldEqual, "notifier2")
|
||||
So(nt.IsDefault, ShouldBeFalse)
|
||||
require.Equal(t, nt.Name, "another-not-default-notification")
|
||||
require.Equal(t, nt.Type, "email")
|
||||
require.Equal(t, nt.OrgID, int64(3))
|
||||
require.Equal(t, nt.UID, "notifier2")
|
||||
require.False(t, nt.IsDefault)
|
||||
|
||||
nt = nts[2]
|
||||
So(nt.Name, ShouldEqual, "check-unset-is_default-is-false")
|
||||
So(nt.Type, ShouldEqual, "slack")
|
||||
So(nt.OrgID, ShouldEqual, 3)
|
||||
So(nt.UID, ShouldEqual, "notifier3")
|
||||
So(nt.IsDefault, ShouldBeFalse)
|
||||
require.Equal(t, nt.Name, "check-unset-is_default-is-false")
|
||||
require.Equal(t, nt.Type, "slack")
|
||||
require.Equal(t, nt.OrgID, int64(3))
|
||||
require.Equal(t, nt.UID, "notifier3")
|
||||
require.False(t, nt.IsDefault)
|
||||
|
||||
nt = nts[3]
|
||||
So(nt.Name, ShouldEqual, "Added notification with whitespaces in name")
|
||||
So(nt.Type, ShouldEqual, "email")
|
||||
So(nt.UID, ShouldEqual, "notifier4")
|
||||
So(nt.OrgID, ShouldEqual, 3)
|
||||
require.Equal(t, nt.Name, "Added notification with whitespaces in name")
|
||||
require.Equal(t, nt.Type, "email")
|
||||
require.Equal(t, nt.UID, "notifier4")
|
||||
require.Equal(t, nt.OrgID, int64(3))
|
||||
|
||||
deleteNts := ntCfg.DeleteNotifications
|
||||
So(len(deleteNts), ShouldEqual, 4)
|
||||
require.Equal(t, len(deleteNts), 4)
|
||||
|
||||
deleteNt := deleteNts[0]
|
||||
So(deleteNt.Name, ShouldEqual, "default-slack-notification")
|
||||
So(deleteNt.UID, ShouldEqual, "notifier1")
|
||||
So(deleteNt.OrgID, ShouldEqual, 2)
|
||||
require.Equal(t, deleteNt.Name, "default-slack-notification")
|
||||
require.Equal(t, deleteNt.UID, "notifier1")
|
||||
require.Equal(t, deleteNt.OrgID, int64(2))
|
||||
|
||||
deleteNt = deleteNts[1]
|
||||
So(deleteNt.Name, ShouldEqual, "deleted-notification-without-orgId")
|
||||
So(deleteNt.OrgID, ShouldEqual, 1)
|
||||
So(deleteNt.UID, ShouldEqual, "notifier2")
|
||||
require.Equal(t, deleteNt.Name, "deleted-notification-without-orgId")
|
||||
require.Equal(t, deleteNt.OrgID, int64(1))
|
||||
require.Equal(t, deleteNt.UID, "notifier2")
|
||||
|
||||
deleteNt = deleteNts[2]
|
||||
So(deleteNt.Name, ShouldEqual, "deleted-notification-with-0-orgId")
|
||||
So(deleteNt.OrgID, ShouldEqual, 1)
|
||||
So(deleteNt.UID, ShouldEqual, "notifier3")
|
||||
require.Equal(t, deleteNt.Name, "deleted-notification-with-0-orgId")
|
||||
require.Equal(t, deleteNt.OrgID, int64(1))
|
||||
require.Equal(t, deleteNt.UID, "notifier3")
|
||||
|
||||
deleteNt = deleteNts[3]
|
||||
So(deleteNt.Name, ShouldEqual, "Deleted notification with whitespaces in name")
|
||||
So(deleteNt.OrgID, ShouldEqual, 1)
|
||||
So(deleteNt.UID, ShouldEqual, "notifier4")
|
||||
require.Equal(t, deleteNt.Name, "Deleted notification with whitespaces in name")
|
||||
require.Equal(t, deleteNt.OrgID, int64(1))
|
||||
require.Equal(t, deleteNt.UID, "notifier4")
|
||||
})
|
||||
|
||||
Convey("One configured notification", func() {
|
||||
Convey("no notification in database", func() {
|
||||
t.Run("One configured notification", func(t *testing.T) {
|
||||
t.Run("no notification in database", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
|
||||
err := dc.applyChanges(twoNotificationsConfig)
|
||||
@ -140,12 +146,13 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
}
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 2)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 2)
|
||||
})
|
||||
|
||||
Convey("One notification in database with same name and uid", func() {
|
||||
t.Run("One notification in database with same name and uid", func(t *testing.T) {
|
||||
setup()
|
||||
existingNotificationCmd := models.CreateAlertNotificationCommand{
|
||||
Name: "channel1",
|
||||
OrgId: 1,
|
||||
@ -153,56 +160,58 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Type: "slack",
|
||||
}
|
||||
err := sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
|
||||
So(err, ShouldBeNil)
|
||||
So(existingNotificationCmd.Result, ShouldNotBeNil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, existingNotificationCmd.Result)
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 1)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 1)
|
||||
|
||||
Convey("should update one notification", func() {
|
||||
t.Run("should update one notification", func(t *testing.T) {
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
err = dc.applyChanges(twoNotificationsConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 2)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 2)
|
||||
|
||||
nts := notificationsQuery.Result
|
||||
nt1 := nts[0]
|
||||
So(nt1.Type, ShouldEqual, "email")
|
||||
So(nt1.Name, ShouldEqual, "channel1")
|
||||
So(nt1.Uid, ShouldEqual, "notifier1")
|
||||
require.Equal(t, nt1.Type, "email")
|
||||
require.Equal(t, nt1.Name, "channel1")
|
||||
require.Equal(t, nt1.Uid, "notifier1")
|
||||
|
||||
nt2 := nts[1]
|
||||
So(nt2.Type, ShouldEqual, "slack")
|
||||
So(nt2.Name, ShouldEqual, "channel2")
|
||||
So(nt2.Uid, ShouldEqual, "notifier2")
|
||||
require.Equal(t, nt2.Type, "slack")
|
||||
require.Equal(t, nt2.Name, "channel2")
|
||||
require.Equal(t, nt2.Uid, "notifier2")
|
||||
})
|
||||
})
|
||||
Convey("Two notifications with is_default", func() {
|
||||
t.Run("Two notifications with is_default", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
err := dc.applyChanges(doubleNotificationsConfig)
|
||||
Convey("should both be inserted", func() {
|
||||
So(err, ShouldBeNil)
|
||||
t.Run("should both be inserted", func(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 2)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 2)
|
||||
|
||||
So(notificationsQuery.Result[0].IsDefault, ShouldBeTrue)
|
||||
So(notificationsQuery.Result[1].IsDefault, ShouldBeTrue)
|
||||
require.True(t, notificationsQuery.Result[0].IsDefault)
|
||||
require.True(t, notificationsQuery.Result[1].IsDefault)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Two configured notification", func() {
|
||||
Convey("two other notifications in database", func() {
|
||||
t.Run("Two configured notification", func(t *testing.T) {
|
||||
t.Run("two other notifications in database", func(t *testing.T) {
|
||||
setup()
|
||||
existingNotificationCmd := models.CreateAlertNotificationCommand{
|
||||
Name: "channel0",
|
||||
OrgId: 1,
|
||||
@ -210,7 +219,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Type: "slack",
|
||||
}
|
||||
err := sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
existingNotificationCmd = models.CreateAlertNotificationCommand{
|
||||
Name: "channel3",
|
||||
OrgId: 1,
|
||||
@ -218,15 +227,15 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Type: "slack",
|
||||
}
|
||||
err = sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 2)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 2)
|
||||
|
||||
Convey("should have two new notifications", func() {
|
||||
t.Run("should have two new notifications", func(t *testing.T) {
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
err := dc.applyChanges(twoNotificationsConfig)
|
||||
if err != nil {
|
||||
@ -234,22 +243,23 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
}
|
||||
notificationsQuery = models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 4)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 4)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Can read correct properties with orgName instead of orgId", func() {
|
||||
t.Run("Can read correct properties with orgName instead of orgId", func(t *testing.T) {
|
||||
setup()
|
||||
existingOrg1 := models.GetOrgByNameQuery{Name: "Main Org. 1"}
|
||||
err := sqlstore.GetOrgByName(&existingOrg1)
|
||||
So(err, ShouldBeNil)
|
||||
So(existingOrg1.Result, ShouldNotBeNil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, existingOrg1.Result)
|
||||
existingOrg2 := models.GetOrgByNameQuery{Name: "Main Org. 2"}
|
||||
err = sqlstore.GetOrgByName(&existingOrg2)
|
||||
So(err, ShouldBeNil)
|
||||
So(existingOrg2.Result, ShouldNotBeNil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, existingOrg2.Result)
|
||||
|
||||
existingNotificationCmd := models.CreateAlertNotificationCommand{
|
||||
Name: "default-notification-delete",
|
||||
@ -258,7 +268,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Type: "slack",
|
||||
}
|
||||
err = sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
err = dc.applyChanges(correctPropertiesWithOrgName)
|
||||
@ -268,29 +278,31 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: existingOrg2.Result.Id}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldNotBeNil)
|
||||
So(len(notificationsQuery.Result), ShouldEqual, 1)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 1)
|
||||
|
||||
nt := notificationsQuery.Result[0]
|
||||
So(nt.Name, ShouldEqual, "default-notification-create")
|
||||
So(nt.OrgId, ShouldEqual, existingOrg2.Result.Id)
|
||||
require.Equal(t, nt.Name, "default-notification-create")
|
||||
require.Equal(t, nt.OrgId, existingOrg2.Result.Id)
|
||||
})
|
||||
|
||||
Convey("Config doesn't contain required field", func() {
|
||||
t.Run("Config doesn't contain required field", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
err := dc.applyChanges(noRequiredFields)
|
||||
So(err, ShouldNotBeNil)
|
||||
require.NotNil(t, err)
|
||||
|
||||
errString := err.Error()
|
||||
So(errString, ShouldContainSubstring, "Deleted alert notification item 1 in configuration doesn't contain required field uid")
|
||||
So(errString, ShouldContainSubstring, "Deleted alert notification item 2 in configuration doesn't contain required field name")
|
||||
So(errString, ShouldContainSubstring, "Added alert notification item 1 in configuration doesn't contain required field name")
|
||||
So(errString, ShouldContainSubstring, "Added alert notification item 2 in configuration doesn't contain required field uid")
|
||||
require.Contains(t, errString, "Deleted alert notification item 1 in configuration doesn't contain required field uid")
|
||||
require.Contains(t, errString, "Deleted alert notification item 2 in configuration doesn't contain required field name")
|
||||
require.Contains(t, errString, "Added alert notification item 1 in configuration doesn't contain required field name")
|
||||
require.Contains(t, errString, "Added alert notification item 2 in configuration doesn't contain required field uid")
|
||||
})
|
||||
|
||||
Convey("Empty yaml file", func() {
|
||||
Convey("should have not changed repo", func() {
|
||||
t.Run("Empty yaml file", func(t *testing.T) {
|
||||
t.Run("should have not changed repo", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
|
||||
err := dc.applyChanges(emptyFile)
|
||||
if err != nil {
|
||||
@ -298,22 +310,22 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
}
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(¬ificationsQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(notificationsQuery.Result, ShouldBeEmpty)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, notificationsQuery.Result)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Broken yaml should return error", func() {
|
||||
t.Run("Broken yaml should return error", func(t *testing.T) {
|
||||
reader := &configReader{
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
|
||||
_, err := reader.readConfig(brokenYaml)
|
||||
So(err, ShouldNotBeNil)
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
Convey("Skip invalid directory", func() {
|
||||
t.Run("Skip invalid directory", func(t *testing.T) {
|
||||
cfgProvider := &configReader{
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
log: log.New("test logger"),
|
||||
@ -323,27 +335,27 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("readConfig return an error %v", err)
|
||||
}
|
||||
So(len(cfg), ShouldEqual, 0)
|
||||
require.Equal(t, len(cfg), 0)
|
||||
})
|
||||
|
||||
Convey("Unknown notifier should return error", func() {
|
||||
t.Run("Unknown notifier should return error", func(t *testing.T) {
|
||||
cfgProvider := &configReader{
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
_, err := cfgProvider.readConfig(unknownNotifier)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err.Error(), ShouldEqual, `unsupported notification type "nonexisting"`)
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, err.Error(), `unsupported notification type "nonexisting"`)
|
||||
})
|
||||
|
||||
Convey("Read incorrect properties", func() {
|
||||
t.Run("Read incorrect properties", func(t *testing.T) {
|
||||
cfgProvider := &configReader{
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
_, err := cfgProvider.readConfig(incorrectSettings)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err.Error(), ShouldEqual, "alert validation error: token must be specified when using the Slack chat API")
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, err.Error(), "alert validation error: token must be specified when using the Slack chat API")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -5,25 +5,26 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCheckOrgExists(t *testing.T) {
|
||||
Convey("with default org in database", t, func() {
|
||||
t.Run("with default org in database", func(t *testing.T) {
|
||||
sqlstore.InitTestDB(t)
|
||||
|
||||
defaultOrg := models.CreateOrgCommand{Name: "Main Org."}
|
||||
err := sqlstore.CreateOrg(&defaultOrg)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
Convey("default org exists", func() {
|
||||
t.Run("default org exists", func(t *testing.T) {
|
||||
err := CheckOrgExists(defaultOrg.Result.Id)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
Convey("other org doesn't exist", func() {
|
||||
t.Run("other org doesn't exist", func(t *testing.T) {
|
||||
err := CheckOrgExists(defaultOrg.Result.Id + 1)
|
||||
So(err, ShouldEqual, models.ErrOrgNotFound)
|
||||
require.Equal(t, err, models.ErrOrgNotFound)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -8,132 +8,140 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"gopkg.in/ini.v1"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestValues(t *testing.T) {
|
||||
Convey("Values", t, func() {
|
||||
t.Run("Values", func(t *testing.T) {
|
||||
err := os.Setenv("INT", "1")
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
err = os.Setenv("STRING", "test")
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
err = os.Setenv("EMPTYSTRING", "")
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
err = os.Setenv("BOOL", "true")
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
|
||||
Convey("IntValue", func() {
|
||||
defer func() {
|
||||
err := os.Unsetenv("INT")
|
||||
require.NoError(t, err)
|
||||
err = os.Unsetenv("STRING")
|
||||
require.NoError(t, err)
|
||||
err = os.Unsetenv("EMPTYSTRING")
|
||||
require.NoError(t, err)
|
||||
err = os.Unsetenv("BOOL")
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
t.Run("IntValue", func(t *testing.T) {
|
||||
type Data struct {
|
||||
Val IntValue `yaml:"val"`
|
||||
}
|
||||
d := &Data{}
|
||||
|
||||
Convey("Should unmarshal simple number", func() {
|
||||
unmarshalingTest(`val: 1`, d)
|
||||
So(d.Val.Value(), ShouldEqual, 1)
|
||||
So(d.Val.Raw, ShouldEqual, "1")
|
||||
t.Run("Should unmarshal simple number", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: 1`, d)
|
||||
require.Equal(t, d.Val.Value(), 1)
|
||||
require.Equal(t, d.Val.Raw, "1")
|
||||
})
|
||||
|
||||
Convey("Should unmarshal env var", func() {
|
||||
unmarshalingTest(`val: $INT`, d)
|
||||
So(d.Val.Value(), ShouldEqual, 1)
|
||||
So(d.Val.Raw, ShouldEqual, "$INT")
|
||||
t.Run("Should unmarshal env var", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: $INT`, d)
|
||||
require.Equal(t, d.Val.Value(), 1)
|
||||
require.Equal(t, d.Val.Raw, "$INT")
|
||||
})
|
||||
|
||||
Convey("Should ignore empty value", func() {
|
||||
unmarshalingTest(`val: `, d)
|
||||
So(d.Val.Value(), ShouldEqual, 0)
|
||||
So(d.Val.Raw, ShouldEqual, "")
|
||||
t.Run("Should ignore empty value", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: `, d)
|
||||
require.Equal(t, d.Val.Value(), 0)
|
||||
require.Equal(t, d.Val.Raw, "")
|
||||
})
|
||||
})
|
||||
|
||||
Convey("StringValue", func() {
|
||||
t.Run("StringValue", func(t *testing.T) {
|
||||
type Data struct {
|
||||
Val StringValue `yaml:"val"`
|
||||
}
|
||||
d := &Data{}
|
||||
|
||||
Convey("Should unmarshal simple string", func() {
|
||||
unmarshalingTest(`val: test`, d)
|
||||
So(d.Val.Value(), ShouldEqual, "test")
|
||||
So(d.Val.Raw, ShouldEqual, "test")
|
||||
t.Run("Should unmarshal simple string", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: test`, d)
|
||||
require.Equal(t, d.Val.Value(), "test")
|
||||
require.Equal(t, d.Val.Raw, "test")
|
||||
})
|
||||
|
||||
Convey("Should unmarshal env var", func() {
|
||||
unmarshalingTest(`val: $STRING`, d)
|
||||
So(d.Val.Value(), ShouldEqual, "test")
|
||||
So(d.Val.Raw, ShouldEqual, "$STRING")
|
||||
t.Run("Should unmarshal env var", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: $STRING`, d)
|
||||
require.Equal(t, d.Val.Value(), "test")
|
||||
require.Equal(t, d.Val.Raw, "$STRING")
|
||||
})
|
||||
|
||||
Convey("Should ignore empty value", func() {
|
||||
unmarshalingTest(`val: `, d)
|
||||
So(d.Val.Value(), ShouldEqual, "")
|
||||
So(d.Val.Raw, ShouldEqual, "")
|
||||
t.Run("Should ignore empty value", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: `, d)
|
||||
require.Equal(t, d.Val.Value(), "")
|
||||
require.Equal(t, d.Val.Raw, "")
|
||||
})
|
||||
|
||||
Convey("empty var should have empty value", func() {
|
||||
unmarshalingTest(`val: $EMPTYSTRING`, d)
|
||||
So(d.Val.Value(), ShouldEqual, "")
|
||||
So(d.Val.Raw, ShouldEqual, "$EMPTYSTRING")
|
||||
t.Run("empty var should have empty value", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: $EMPTYSTRING`, d)
|
||||
require.Equal(t, d.Val.Value(), "")
|
||||
require.Equal(t, d.Val.Raw, "$EMPTYSTRING")
|
||||
})
|
||||
|
||||
Convey("$$ should be a literal $", func() {
|
||||
unmarshalingTest(`val: $$`, d)
|
||||
So(d.Val.Value(), ShouldEqual, "$")
|
||||
So(d.Val.Raw, ShouldEqual, "$$")
|
||||
t.Run("$$ should be a literal $", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: $$`, d)
|
||||
require.Equal(t, d.Val.Value(), "$")
|
||||
require.Equal(t, d.Val.Raw, "$$")
|
||||
})
|
||||
|
||||
Convey("$$ should be a literal $ and not expanded within a string", func() {
|
||||
unmarshalingTest(`val: mY,Passwo$$rd`, d)
|
||||
So(d.Val.Value(), ShouldEqual, "mY,Passwo$rd")
|
||||
So(d.Val.Raw, ShouldEqual, "mY,Passwo$$rd")
|
||||
t.Run("$$ should be a literal $ and not expanded within a string", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: mY,Passwo$$rd`, d)
|
||||
require.Equal(t, d.Val.Value(), "mY,Passwo$rd")
|
||||
require.Equal(t, d.Val.Raw, "mY,Passwo$$rd")
|
||||
})
|
||||
})
|
||||
|
||||
Convey("BoolValue", func() {
|
||||
t.Run("BoolValue", func(t *testing.T) {
|
||||
type Data struct {
|
||||
Val BoolValue `yaml:"val"`
|
||||
}
|
||||
d := &Data{}
|
||||
|
||||
Convey("Should unmarshal bool value", func() {
|
||||
unmarshalingTest(`val: true`, d)
|
||||
So(d.Val.Value(), ShouldBeTrue)
|
||||
So(d.Val.Raw, ShouldEqual, "true")
|
||||
t.Run("Should unmarshal bool value", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: true`, d)
|
||||
require.True(t, d.Val.Value())
|
||||
require.Equal(t, d.Val.Raw, "true")
|
||||
})
|
||||
|
||||
Convey("Should unmarshal explicit string", func() {
|
||||
unmarshalingTest(`val: "true"`, d)
|
||||
So(d.Val.Value(), ShouldBeTrue)
|
||||
So(d.Val.Raw, ShouldEqual, "true")
|
||||
t.Run("Should unmarshal explicit string", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: "true"`, d)
|
||||
require.True(t, d.Val.Value())
|
||||
require.Equal(t, d.Val.Raw, "true")
|
||||
})
|
||||
|
||||
Convey("Should unmarshal env var", func() {
|
||||
unmarshalingTest(`val: $BOOL`, d)
|
||||
So(d.Val.Value(), ShouldBeTrue)
|
||||
So(d.Val.Raw, ShouldEqual, "$BOOL")
|
||||
t.Run("Should unmarshal env var", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: $BOOL`, d)
|
||||
require.True(t, d.Val.Value())
|
||||
require.Equal(t, d.Val.Raw, "$BOOL")
|
||||
})
|
||||
|
||||
Convey("Should ignore empty value", func() {
|
||||
unmarshalingTest(`val: `, d)
|
||||
So(d.Val.Value(), ShouldBeFalse)
|
||||
So(d.Val.Raw, ShouldEqual, "")
|
||||
t.Run("Should ignore empty value", func(t *testing.T) {
|
||||
unmarshalingTest(t, `val: `, d)
|
||||
require.False(t, d.Val.Value())
|
||||
require.Equal(t, d.Val.Raw, "")
|
||||
})
|
||||
})
|
||||
|
||||
Convey("JSONValue", func() {
|
||||
t.Run("JSONValue", func(t *testing.T) {
|
||||
type Data struct {
|
||||
Val JSONValue `yaml:"val"`
|
||||
}
|
||||
d := &Data{}
|
||||
|
||||
Convey("Should unmarshal variable nesting", func() {
|
||||
t.Run("Should unmarshal variable nesting", func(t *testing.T) {
|
||||
doc := `
|
||||
val:
|
||||
one: 1
|
||||
@ -153,10 +161,10 @@ func TestValues(t *testing.T) {
|
||||
anchor: &label $INT
|
||||
anchored: *label
|
||||
`
|
||||
unmarshalingTest(doc, d)
|
||||
unmarshalingTest(t, doc, d)
|
||||
|
||||
type stringMap = map[string]interface{}
|
||||
So(d.Val.Value(), ShouldResemble, stringMap{
|
||||
require.Equal(t, d.Val.Value(), stringMap{
|
||||
"one": 1,
|
||||
"two": "test",
|
||||
"three": []interface{}{
|
||||
@ -183,7 +191,7 @@ func TestValues(t *testing.T) {
|
||||
"anchored": "1",
|
||||
})
|
||||
|
||||
So(d.Val.Raw, ShouldResemble, stringMap{
|
||||
require.Equal(t, d.Val.Raw, stringMap{
|
||||
"one": 1,
|
||||
"two": "$STRING",
|
||||
"three": []interface{}{
|
||||
@ -212,13 +220,13 @@ func TestValues(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
Convey("StringMapValue", func() {
|
||||
t.Run("StringMapValue", func(t *testing.T) {
|
||||
type Data struct {
|
||||
Val StringMapValue `yaml:"val"`
|
||||
}
|
||||
d := &Data{}
|
||||
|
||||
Convey("Should unmarshal mapping", func() {
|
||||
t.Run("Should unmarshal mapping", func(t *testing.T) {
|
||||
doc := `
|
||||
val:
|
||||
one: 1
|
||||
@ -226,15 +234,15 @@ func TestValues(t *testing.T) {
|
||||
three: $STRING
|
||||
four: true
|
||||
`
|
||||
unmarshalingTest(doc, d)
|
||||
So(d.Val.Value(), ShouldResemble, map[string]string{
|
||||
unmarshalingTest(t, doc, d)
|
||||
require.Equal(t, d.Val.Value(), map[string]string{
|
||||
"one": "1",
|
||||
"two": "test string",
|
||||
"three": "test",
|
||||
"four": "true",
|
||||
})
|
||||
|
||||
So(d.Val.Raw, ShouldResemble, map[string]string{
|
||||
require.Equal(t, d.Val.Raw, map[string]string{
|
||||
"one": "1",
|
||||
"two": "test string",
|
||||
"three": "$STRING",
|
||||
@ -242,23 +250,12 @@ func TestValues(t *testing.T) {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reset(func() {
|
||||
err := os.Unsetenv("INT")
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Unsetenv("STRING")
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Unsetenv("EMPTYSTRING")
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Unsetenv("BOOL")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func unmarshalingTest(document string, out interface{}) {
|
||||
func unmarshalingTest(t *testing.T, document string, out interface{}) {
|
||||
err := yaml.Unmarshal([]byte(document), out)
|
||||
So(err, ShouldBeNil)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValues_readFile(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user