@ -5,7 +5,6 @@ import (
"os"
"testing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/util"
@ -26,173 +25,133 @@ var (
multipleOrgsWithDefault = "testdata/multiple-org-default"
withoutDefaults = "testdata/appliedDefaults"
invalidAccess = "testdata/invalid-access"
fakeRepo * fakeRepository
)
func TestDatasourceAsConfig ( t * testing . T ) {
setup := func ( ) {
fakeRepo = & fakeRepository { }
bus . ClearBusHandlers ( )
bus . AddHandler ( "test" , mockDelete )
bus . AddHandler ( "test" , mockInsert )
bus . AddHandler ( "test" , mockUpdate )
bus . AddHandler ( "test" , mockGet )
bus . AddHandler ( "test" , mockGetOrg )
}
t . Run ( "when some values missing should apply default on insert" , func ( t * testing . T ) {
store := & spyStore { }
orgStore := & mockOrgStore { ExpectedOrg : & models . Org { Id : 1 } }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , withoutDefaults )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
require . Equal ( t , len ( store . inserted ) , 1 )
require . Equal ( t , store . inserted [ 0 ] . OrgId , int64 ( 1 ) )
require . Equal ( t , store . inserted [ 0 ] . Access , models . DsAccess ( "proxy" ) )
require . Equal ( t , store . inserted [ 0 ] . Name , "My datasource name" )
require . Equal ( t , store . inserted [ 0 ] . Uid , "P2AD1F727255C56BA" )
} )
t . Run ( "when some values missing should not change UID when updates" , func ( t * testing . T ) {
store := & spyStore {
items : [ ] * models . DataSource { { Name : "My datasource name" , OrgId : 1 , Id : 1 , Uid : util . GenerateShortUID ( ) } } ,
}
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , withoutDefaults )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
t . Run ( "when some values missing" , func ( t * testing . T ) {
t . Run ( "should apply default on insert" , 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" ) )
require . Equal ( t , fakeRepo . inserted [ 0 ] . Name , "My datasource name" )
require . Equal ( t , fakeRepo . inserted [ 0 ] . Uid , "P2AD1F727255C56BA" )
} )
t . Run ( "should not change UID when updates" , func ( t * testing . T ) {
setup ( )
fakeRepo . loadAll = [ ] * models . DataSource {
{ Name : "My datasource name" , OrgId : 1 , Id : 1 , Uid : util . GenerateShortUID ( ) } ,
}
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 . deleted ) , 0 )
require . Equal ( t , len ( fakeRepo . inserted ) , 0 )
require . Equal ( t , len ( fakeRepo . updated ) , 1 )
require . Equal ( t , "" , fakeRepo . updated [ 0 ] . Uid ) // XORM will not update the field if its value is default
} )
require . Equal ( t , len ( store . deleted ) , 0 )
require . Equal ( t , len ( store . inserted ) , 0 )
require . Equal ( t , len ( store . updated ) , 1 )
require . Equal ( t , "" , store . updated [ 0 ] . Uid ) // XORM will not update the field if its value is default
} )
t . Run ( "no datasource in database" , func ( t * testing . T ) {
setup ( )
dc := newDatasourceProvisioner ( logger )
store := & spyStore { }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
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 )
require . Equal ( t , len ( store . deleted ) , 0 )
require . Equal ( t , len ( store . inserted ) , 2 )
require . Equal ( t , len ( store . 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 ( "One datasource in database with same name should update one datasource" , func ( t * testing . T ) {
store := & spyStore { items : [ ] * models . DataSource { { Name : "Graphite" , OrgId : 1 , Id : 1 } } }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , twoDatasourcesConfig )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
t . Run ( "should update one datasource" , func ( t * testing . T ) {
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 ) , 1 )
require . Equal ( t , len ( fakeRepo . updated ) , 1 )
} )
require . Equal ( t , len ( store . deleted ) , 0 )
require . Equal ( t , len ( store . inserted ) , 1 )
require . Equal ( t , len ( store . updated ) , 1 )
} )
t . Run ( "Two datasources with is_default" , func ( t * testing . T ) {
setup ( )
dc := newDatasourceProvisioner ( logger )
t . Run ( "Two datasources with is_default should raise error" , func ( t * testing . T ) {
store := & spyStore { }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , doubleDatasourcesConfig )
t . Run ( "should raise error" , func ( t * testing . T ) { require . Equal ( t , err , ErrInvalidConfigToManyDefault ) } )
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 )
t . Run ( "Multiple datasources in different organizations with isDefault in each organization should not raise error" , func ( t * testing . T ) {
store := & spyStore { }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
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 ) )
} )
require . NoError ( t , err )
require . Equal ( t , len ( store . inserted ) , 4 )
require . True ( t , store . inserted [ 0 ] . IsDefault )
require . Equal ( t , store . inserted [ 0 ] . OrgId , int64 ( 1 ) )
require . True ( t , store . inserted [ 2 ] . IsDefault )
require . Equal ( t , store . inserted [ 2 ] . OrgId , int64 ( 2 ) )
} )
t . Run ( "Remove one datasource" , func ( t * testing . T ) {
setup ( )
t . Run ( "Remove one datasource" , func ( t * testing . T ) {
fakeRepo . loadAll = [ ] * models . DataSource { }
t . Run ( "should have removed old datasource" , func ( t * testing . T ) {
dc := newDatasourceProvisioner ( logger )
err := dc . applyChanges ( context . Background ( ) , deleteOneDatasource )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
require . Equal ( t , 1 , len ( fakeRepo . deleted ) )
// should have set OrgID to 1
require . Equal ( t , fakeRepo . deleted [ 0 ] . OrgID , int64 ( 1 ) )
require . Equal ( t , 0 , len ( fakeRepo . inserted ) )
require . Equal ( t , len ( fakeRepo . updated ) , 0 )
} )
} )
t . Run ( "Remove one datasource should have removed old datasource" , func ( t * testing . T ) {
store := & spyStore { }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , deleteOneDatasource )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
require . Equal ( t , 1 , len ( store . deleted ) )
// should have set OrgID to 1
require . Equal ( t , store . deleted [ 0 ] . OrgID , int64 ( 1 ) )
require . Equal ( t , 0 , len ( store . inserted ) )
require . Equal ( t , len ( store . updated ) , 0 )
} )
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" , func ( t * testing . T ) {
store := & spyStore { items : [ ] * models . DataSource { { Name : "old-graphite" , OrgId : 1 , Id : 1 } , { Name : "old-graphite2" , OrgId : 1 , Id : 2 } } }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , twoDatasourcesConfigPurgeOthers )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
require . Equal ( t , len ( store . deleted ) , 2 )
require . Equal ( t , len ( store . inserted ) , 2 )
require . Equal ( t , len ( store . 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 )
}
require . Equal ( t , len ( fakeRepo . deleted ) , 0 )
require . Equal ( t , len ( fakeRepo . inserted ) , 1 )
require . Equal ( t , len ( fakeRepo . updated ) , 1 )
} )
} )
store := & spyStore { items : [ ] * models . DataSource { { Name : "Graphite" , OrgId : 1 , Id : 1 } , { Name : "old-graphite2" , OrgId : 1 , Id : 2 } } }
orgStore := & mockOrgStore { }
dc := newDatasourceProvisioner ( logger , store , orgStore )
err := dc . applyChanges ( context . Background ( ) , twoDatasourcesConfig )
if err != nil {
t . Fatalf ( "applyChanges return an error %v" , err )
}
require . Equal ( t , len ( store . deleted ) , 0 )
require . Equal ( t , len ( store . inserted ) , 1 )
require . Equal ( t , len ( store . updated ) , 1 )
} )
t . Run ( "broken yaml should return error" , func ( t * testing . T ) {
@ -202,14 +161,14 @@ func TestDatasourceAsConfig(t *testing.T) {
} )
t . Run ( "invalid access should warn about invalid value and return 'proxy'" , func ( t * testing . T ) {
reader := & configReader { log : logger }
reader := & configReader { log : logger , orgStore : & mockOrgStore { } }
configs , err := reader . readConfig ( context . Background ( ) , invalidAccess )
require . NoError ( t , err )
require . Equal ( t , configs [ 0 ] . Datasources [ 0 ] . Access , models . DS_ACCESS_PROXY )
} )
t . Run ( "skip invalid directory" , func ( t * testing . T ) {
cfgProvider := & configReader { log : log . New ( "test logger" ) }
cfgProvider := & configReader { log : log . New ( "test logger" ) , orgStore : & mockOrgStore { } }
cfg , err := cfgProvider . readConfig ( context . Background ( ) , "./invalid-directory" )
if err != nil {
t . Fatalf ( "readConfig return an error %v" , err )
@ -220,7 +179,7 @@ func TestDatasourceAsConfig(t *testing.T) {
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" ) }
cfgProvider := & configReader { log : log . New ( "test logger" ) , orgStore : & mockOrgStore { } }
cfg , err := cfgProvider . readConfig ( context . Background ( ) , allProperties )
_ = os . Unsetenv ( "TEST_VAR" )
if err != nil {
@ -249,7 +208,7 @@ func TestDatasourceAsConfig(t *testing.T) {
} )
t . Run ( "can read all properties from version 0" , func ( t * testing . T ) {
cfgProvider := & configReader { log : log . New ( "test logger" ) }
cfgProvider := & configReader { log : log . New ( "test logger" ) , orgStore : & mockOrgStore { } }
cfg , err := cfgProvider . readConfig ( context . Background ( ) , versionZero )
if err != nil {
t . Fatalf ( "readConfig return an error %v" , err )
@ -308,40 +267,41 @@ func validateDatasourceV1(t *testing.T, dsCfg *configs) {
require . Equal ( t , ds . UID , "test_uid" )
}
type fakeRepository struct {
type mockOrgStore struct { ExpectedOrg * models . Org }
func ( m * mockOrgStore ) GetOrgById ( c context . Context , cmd * models . GetOrgByIdQuery ) error {
cmd . Result = m . ExpectedOrg
return nil
}
type spyStore struct {
inserted [ ] * models . AddDataSourceCommand
deleted [ ] * models . DeleteDataSourceCommand
updated [ ] * models . UpdateDataSourceCommand
loadAll [ ] * models . DataSource
items [ ] * models . DataSource
}
func mockDelete ( ctx context . Context , cmd * models . DeleteDataSourceCommand ) error {
fakeRepo . deleted = append ( fakeRepo . deleted , cmd )
return nil
func ( s * spyStore ) GetDataSource ( ctx context . Context , query * models . GetDataSourceQuery ) error {
for _ , v := range s . items {
if query . Name == v . Name && query . OrgId == v . OrgId {
query . Result = v
return nil
}
}
return models . ErrDataSourceNotFound
}
func mockUpdate ( ctx context . Context , cmd * models . UpdateDataSourceCommand ) error {
fakeRepo . updated = append ( fakeRepo . updated , cmd )
func ( s * spyStore ) DeleteDataSourc e( ctx context . Context , cmd * models . Dele teDataSourceCommand) error {
s . dele ted = append ( s . dele ted, cmd )
return nil
}
func mockInsert ( ctx context . Context , cmd * models . AddDataSourceCommand ) error {
fakeRepo . inserted = append ( fakeRepo . inserted , cmd )
func ( s * spyStore ) AddDataSource ( ctx context . Context , cmd * models . AddDataSourceCommand ) error {
s . inserted = append ( s . inserted , cmd )
return nil
}
func mockGet ( ctx context . Context , cmd * models . GetDataSourceQuery ) error {
for _ , v := range fakeRepo . loadAll {
if cmd . Name == v . Name && cmd . OrgId == v . OrgId {
cmd . Result = v
return nil
}
}
return models . ErrDataSourceNotFound
}
func mockGetOrg ( ctx context . Context , _ * models . GetOrgByIdQuery ) error {
func ( s * spyStore ) UpdateDataSource ( ctx context . Context , cmd * models . UpdateDataSourceCommand ) error {
s . updated = append ( s . updated , cmd )
return nil
}