Merge branch 'master' into stackdriver-plugin

This commit is contained in:
Torkel Ödegaard
2018-09-21 10:17:13 +02:00
266 changed files with 5504 additions and 1770 deletions

View File

@@ -24,6 +24,7 @@ func GetAnnotations(c *m.ReqContext) Response {
Limit: c.QueryInt64("limit"),
Tags: c.QueryStrings("tags"),
Type: c.Query("type"),
MatchAny: c.QueryBool("matchAny"),
}
repo := annotations.GetRepository()

View File

@@ -4,6 +4,7 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
@@ -17,6 +18,11 @@ func GetTeamMembers(c *m.ReqContext) Response {
for _, member := range query.Result {
member.AvatarUrl = dtos.GetGravatarUrl(member.Email)
member.Labels = []string{}
if setting.IsEnterprise && setting.LdapEnabled && member.External {
member.Labels = append(member.Labels, "LDAP")
}
}
return JSON(200, query.Result)

View File

@@ -16,7 +16,7 @@ func upgradeCommand(c CommandLine) error {
return err
}
v, err2 := s.GetPlugin(localPlugin.Id, c.RepoDirectory())
v, err2 := s.GetPlugin(pluginName, c.RepoDirectory())
if err2 != nil {
return err2
@@ -24,9 +24,9 @@ func upgradeCommand(c CommandLine) error {
if ShouldUpgrade(localPlugin.Info.Version, v) {
s.RemoveInstalledPlugin(pluginsDir, pluginName)
return InstallPlugin(localPlugin.Id, "", c)
return InstallPlugin(pluginName, "", c)
}
logger.Infof("%s %s is up to date \n", color.GreenString("✔"), localPlugin.Id)
logger.Infof("%s %s is up to date \n", color.GreenString("✔"), pluginName)
return nil
}

View File

@@ -63,7 +63,7 @@ func ListAllPlugins(repoUrl string) (m.PluginRepo, error) {
var data m.PluginRepo
err = json.Unmarshal(body, &data)
if err != nil {
logger.Info("Failed to unmarshal graphite response error:", err)
logger.Info("Failed to unmarshal plugin repo response error:", err)
return m.PluginRepo{}, err
}
@@ -140,7 +140,7 @@ func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) {
var data m.Plugin
err = json.Unmarshal(body, &data)
if err != nil {
logger.Info("Failed to unmarshal graphite response error:", err)
logger.Info("Failed to unmarshal plugin repo response error:", err)
return m.Plugin{}, err
}

View File

@@ -326,15 +326,19 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
a.log.Info("Searching for user's groups", "filter", filter)
// support old way of reading settings
groupIdAttribute := a.server.Attr.MemberOf
// but prefer dn attribute if default settings are used
if groupIdAttribute == "" || groupIdAttribute == "memberOf" {
groupIdAttribute = "dn"
}
groupSearchReq := ldap.SearchRequest{
BaseDN: groupSearchBase,
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
Attributes: []string{
// Here MemberOf would be the thing that identifies the group, which is normally 'cn'
a.server.Attr.MemberOf,
},
Filter: filter,
Attributes: []string{groupIdAttribute},
Filter: filter,
}
groupSearchResult, err = a.conn.Search(&groupSearchReq)
@@ -344,7 +348,7 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
if len(groupSearchResult.Entries) > 0 {
for i := range groupSearchResult.Entries {
memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i))
memberOf = append(memberOf, getLdapAttrN(groupIdAttribute, groupSearchResult, i))
}
break
}

View File

@@ -61,6 +61,23 @@ var (
M_Grafana_Version *prometheus.GaugeVec
)
func newCounterVecStartingAtZero(opts prometheus.CounterOpts, labels []string, labelValues ...string) *prometheus.CounterVec {
counter := prometheus.NewCounterVec(opts, labels)
for _, label := range labelValues {
counter.WithLabelValues(label).Add(0)
}
return counter
}
func newCounterStartingAtZero(opts prometheus.CounterOpts, labelValues ...string) prometheus.Counter {
counter := prometheus.NewCounter(opts)
counter.Add(0)
return counter
}
func init() {
M_Instance_Start = prometheus.NewCounter(prometheus.CounterOpts{
Name: "instance_start_total",
@@ -68,32 +85,27 @@ func init() {
Namespace: exporterName,
})
M_Page_Status = prometheus.NewCounterVec(
httpStatusCodes := []string{"200", "404", "500", "unknown"}
M_Page_Status = newCounterVecStartingAtZero(
prometheus.CounterOpts{
Name: "page_response_status_total",
Help: "page http response status",
Namespace: exporterName,
},
[]string{"code"},
)
}, []string{"code"}, httpStatusCodes...)
M_Api_Status = prometheus.NewCounterVec(
M_Api_Status = newCounterVecStartingAtZero(
prometheus.CounterOpts{
Name: "api_response_status_total",
Help: "api http response status",
Namespace: exporterName,
},
[]string{"code"},
)
}, []string{"code"}, httpStatusCodes...)
M_Proxy_Status = prometheus.NewCounterVec(
M_Proxy_Status = newCounterVecStartingAtZero(
prometheus.CounterOpts{
Name: "proxy_response_status_total",
Help: "proxy http response status",
Namespace: exporterName,
},
[]string{"code"},
)
}, []string{"code"}, httpStatusCodes...)
M_Http_Request_Total = prometheus.NewCounterVec(
prometheus.CounterOpts{
@@ -111,19 +123,19 @@ func init() {
[]string{"handler", "statuscode", "method"},
)
M_Api_User_SignUpStarted = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_User_SignUpStarted = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_user_signup_started_total",
Help: "amount of users who started the signup flow",
Namespace: exporterName,
})
M_Api_User_SignUpCompleted = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_User_SignUpCompleted = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_user_signup_completed_total",
Help: "amount of users who completed the signup flow",
Namespace: exporterName,
})
M_Api_User_SignUpInvite = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_User_SignUpInvite = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_user_signup_invite_total",
Help: "amount of users who have been invited",
Namespace: exporterName,
@@ -147,49 +159,49 @@ func init() {
Namespace: exporterName,
})
M_Api_Admin_User_Create = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Admin_User_Create = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_admin_user_created_total",
Help: "api admin user created counter",
Namespace: exporterName,
})
M_Api_Login_Post = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Login_Post = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_login_post_total",
Help: "api login post counter",
Namespace: exporterName,
})
M_Api_Login_OAuth = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Login_OAuth = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_login_oauth_total",
Help: "api login oauth counter",
Namespace: exporterName,
})
M_Api_Org_Create = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Org_Create = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_org_create_total",
Help: "api org created counter",
Namespace: exporterName,
})
M_Api_Dashboard_Snapshot_Create = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Dashboard_Snapshot_Create = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_dashboard_snapshot_create_total",
Help: "dashboard snapshots created",
Namespace: exporterName,
})
M_Api_Dashboard_Snapshot_External = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Dashboard_Snapshot_External = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_dashboard_snapshot_external_total",
Help: "external dashboard snapshots created",
Namespace: exporterName,
})
M_Api_Dashboard_Snapshot_Get = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Dashboard_Snapshot_Get = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_dashboard_snapshot_get_total",
Help: "loaded dashboards",
Namespace: exporterName,
})
M_Api_Dashboard_Insert = prometheus.NewCounter(prometheus.CounterOpts{
M_Api_Dashboard_Insert = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "api_models_dashboard_insert_total",
Help: "dashboards inserted ",
Namespace: exporterName,
@@ -207,25 +219,25 @@ func init() {
Namespace: exporterName,
}, []string{"type"})
M_Aws_CloudWatch_GetMetricStatistics = prometheus.NewCounter(prometheus.CounterOpts{
M_Aws_CloudWatch_GetMetricStatistics = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "aws_cloudwatch_get_metric_statistics_total",
Help: "counter for getting metric statistics from aws",
Namespace: exporterName,
})
M_Aws_CloudWatch_ListMetrics = prometheus.NewCounter(prometheus.CounterOpts{
M_Aws_CloudWatch_ListMetrics = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "aws_cloudwatch_list_metrics_total",
Help: "counter for getting list of metrics from aws",
Namespace: exporterName,
})
M_Aws_CloudWatch_GetMetricData = prometheus.NewCounter(prometheus.CounterOpts{
M_Aws_CloudWatch_GetMetricData = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "aws_cloudwatch_get_metric_data_total",
Help: "counter for getting metric data time series from aws",
Namespace: exporterName,
})
M_DB_DataSource_QueryById = prometheus.NewCounter(prometheus.CounterOpts{
M_DB_DataSource_QueryById = newCounterStartingAtZero(prometheus.CounterOpts{
Name: "db_datasource_query_by_id_total",
Help: "counter for getting datasource by id",
Namespace: exporterName,

View File

@@ -12,10 +12,11 @@ var (
// TeamMember model
type TeamMember struct {
Id int64
OrgId int64
TeamId int64
UserId int64
Id int64
OrgId int64
TeamId int64
UserId int64
External bool
Created time.Time
Updated time.Time
@@ -25,9 +26,10 @@ type TeamMember struct {
// COMMANDS
type AddTeamMemberCommand struct {
UserId int64 `json:"userId" binding:"Required"`
OrgId int64 `json:"-"`
TeamId int64 `json:"-"`
UserId int64 `json:"userId" binding:"Required"`
OrgId int64 `json:"-"`
TeamId int64 `json:"-"`
External bool `json:"-"`
}
type RemoveTeamMemberCommand struct {
@@ -40,20 +42,23 @@ type RemoveTeamMemberCommand struct {
// QUERIES
type GetTeamMembersQuery struct {
OrgId int64
TeamId int64
UserId int64
Result []*TeamMemberDTO
OrgId int64
TeamId int64
UserId int64
External bool
Result []*TeamMemberDTO
}
// ----------------------
// Projections and DTOs
type TeamMemberDTO struct {
OrgId int64 `json:"orgId"`
TeamId int64 `json:"teamId"`
UserId int64 `json:"userId"`
Email string `json:"email"`
Login string `json:"login"`
AvatarUrl string `json:"avatarUrl"`
OrgId int64 `json:"orgId"`
TeamId int64 `json:"teamId"`
UserId int64 `json:"userId"`
External bool `json:"-"`
Email string `json:"email"`
Login string `json:"login"`
AvatarUrl string `json:"avatarUrl"`
Labels []string `json:"labels"`
}

View File

@@ -35,7 +35,7 @@ func TestDashboardImport(t *testing.T) {
So(cmd.Result, ShouldNotBeNil)
resultStr, _ := mock.SavedDashboards[0].Dashboard.Data.EncodePretty()
expectedBytes, _ := ioutil.ReadFile("../../tests/test-app/dashboards/connections_result.json")
expectedBytes, _ := ioutil.ReadFile("testdata/test-app/dashboards/connections_result.json")
expectedJson, _ := simplejson.NewJson(expectedBytes)
expectedStr, _ := expectedJson.EncodePretty()
@@ -89,7 +89,7 @@ func pluginScenario(desc string, t *testing.T, fn func()) {
Convey("Given a plugin", t, func() {
setting.Raw = ini.Empty()
sec, _ := setting.Raw.NewSection("plugin.test-app")
sec.NewKey("path", "../../tests/test-app")
sec.NewKey("path", "testdata/test-app")
pm := &PluginManager{}
err := pm.Init()

View File

@@ -16,7 +16,7 @@ func TestPluginDashboards(t *testing.T) {
Convey("When asking plugin dashboard info", t, func() {
setting.Raw = ini.Empty()
sec, _ := setting.Raw.NewSection("plugin.test-app")
sec.NewKey("path", "../../tests/test-app")
sec.NewKey("path", "testdata/test-app")
pm := &PluginManager{}
err := pm.Init()

View File

@@ -48,11 +48,7 @@ func autoUpdateAppDashboard(pluginDashInfo *PluginDashboardInfoDTO, orgId int64)
Path: pluginDashInfo.Path,
}
if err := bus.Dispatch(&updateCmd); err != nil {
return err
}
return nil
return bus.Dispatch(&updateCmd)
}
func syncPluginDashboards(pluginDef *PluginBase, orgId int64) {

View File

@@ -30,7 +30,7 @@ func TestPluginScans(t *testing.T) {
Convey("When reading app plugin definition", t, func() {
setting.Raw = ini.Empty()
sec, _ := setting.Raw.NewSection("plugin.nginx-app")
sec.NewKey("path", "../../tests/test-app")
sec.NewKey("path", "testdata/test-app")
pm := &PluginManager{}
err := pm.Init()

View File

@@ -0,0 +1,50 @@
System.register([], function (_export) {
"use strict";
return {
setters: [],
execute: function () {
function Datasource(instanceSettings, backendSrv) {
this.url = instanceSettings.url;
// this.testDatasource = function() {
// return backendSrv.datasourceRequest({
// method: 'GET',
// url: this.url + '/api/v4/search'
// });
// }
//
this.testDatasource = function() {
return backendSrv.datasourceRequest({
method: 'GET',
url: this.url + '/tokenTest'
});
}
}
function ConfigCtrl() {
}
ConfigCtrl.template = `
<div class="gf-form">
<label class="gf-form-label width-13">TenantId </label>
<input type="text" class="gf-form-input max-width-18" ng-model='ctrl.current.jsonData.tenantId'></input>
</div>
<div class="gf-form">
<label class="gf-form-label width-13">ClientId </label>
<input type="text" class="gf-form-input max-width-18" ng-model='ctrl.current.jsonData.clientId'></input>
</div>
<div class="gf-form">
<label class="gf-form-label width-13">Client secret</label>
<input type="text" class="gf-form-input max-width-18" ng-model='ctrl.current.secureJsonData.clientSecret'></input>
</div>
`;
_export('Datasource', Datasource);
_export('ConfigCtrl', ConfigCtrl);
}
};
});

View File

@@ -0,0 +1,31 @@
{
"type": "datasource",
"name": "Test Datasource",
"id": "test-ds",
"routes": [
{
"path": "tokenTest",
"method": "*",
"url": "https://management.azure.com",
"tokenAuth": {
"url": "https://login.microsoftonline.com/{{.JsonData.tenantId}}/oauth2/token",
"params": {
"grant_type": "client_credentials",
"client_id": "{{.JsonData.clientId}}",
"client_secret": "{{.SecureJsonData.clientSecret}}",
"resource": "https://management.azure.com/"
}
}
},
{
"path": "api/v4/",
"method": "*",
"url": "http://localhost:3333",
"headers": [
{"name": "X-CH-Auth-API-Token", "content": "test {{.SecureJsonData.token}}"},
{"name": "X-CH-Auth-Email", "content": "test {{.JsonData.email}}"}
]
}
]
}

View File

@@ -0,0 +1,29 @@
{
"__inputs": [
{
"name": "DS_NAME",
"type": "datasource",
"pluginId": "graphite"
}
],
"uid": "1MHHlVjzz",
"title": "Nginx Connections",
"revision": 25,
"schemaVersion": 11,
"tags": ["tag1", "tag2"],
"number_array": [1,2,3,10.33],
"boolean_true": true,
"boolean_false": false,
"rows": [
{
"panels": [
{
"type": "graph",
"datasource": "${DS_NAME}"
}
]
}
]
}

View File

@@ -0,0 +1,21 @@
{
"revision": 25,
"tags": ["tag1", "tag2"],
"boolean_false": false,
"boolean_true": true,
"number_array": [1,2,3,10.33],
"rows": [
{
"panels": [
{
"datasource": "graphite",
"type": "graph"
}
]
}
],
"schemaVersion": 11,
"title": "Nginx Connections",
"uid": "1MHHlVjzz",
"version": 0
}

View File

@@ -0,0 +1,5 @@
{
"title": "Nginx Memory",
"revision": 2,
"schemaVersion": 11
}

View File

@@ -0,0 +1,55 @@
{
"type": "app",
"name": "Test App",
"id": "test-app",
"staticRoot": ".",
"pages": [
{ "name": "Live stream", "component": "StreamPageCtrl", "role": "Editor"},
{ "name": "Log view", "component": "LogsPageCtrl", "role": "Viewer"}
],
"css": {
"dark": "css/dark.css",
"light": "css/light.css"
},
"info": {
"description": "Official Grafana Test App & Dashboard bundle",
"author": {
"name": "Test Inc.",
"url": "http://test.com"
},
"keywords": ["test"],
"logos": {
"small": "img/logo_small.png",
"large": "img/logo_large.png"
},
"screenshots": [
{"name": "img1", "path": "img/screenshot1.png"},
{"name": "img2", "path": "img/screenshot2.png"}
],
"links": [
{"name": "Project site", "url": "http://project.com"},
{"name": "License & Terms", "url": "http://license.com"}
],
"version": "1.0.0",
"updated": "2015-02-10"
},
"includes": [
{"type": "dashboard", "name": "Nginx Connections", "path": "dashboards/connections.json"},
{"type": "dashboard", "name": "Nginx Memory", "path": "dashboards/memory.json"},
{"type": "panel", "name": "Nginx Panel"},
{"type": "datasource", "name": "Nginx Datasource"}
],
"dependencies": {
"grafanaVersion": "3.x.x",
"plugins": [
{"type": "datasource", "id": "graphite", "name": "Graphite", "version": "1.0.0"},
{"type": "panel", "id": "graph", "name": "Graph", "version": "1.0.0"}
]
}
}

View File

@@ -125,7 +125,7 @@ func (this *HipChatNotifier) Notify(evalContext *alerting.EvalContext) error {
case models.AlertStateOK:
color = "green"
case models.AlertStateNoData:
color = "grey"
color = "gray"
case models.AlertStateAlerting:
color = "red"
}

View File

@@ -21,6 +21,7 @@ type ItemQuery struct {
RegionId int64 `json:"regionId"`
Tags []string `json:"tags"`
Type string `json:"type"`
MatchAny bool `json:"matchAny"`
Limit int64 `json:"limit"`
}

View File

@@ -40,7 +40,7 @@ func GetAlertById(query *m.GetAlertByIdQuery) error {
func GetAllAlertQueryHandler(query *m.GetAllAlertsQuery) error {
var alerts []*m.Alert
err := x.Sql("select * from alert").Find(&alerts)
err := x.SQL("select * from alert").Find(&alerts)
if err != nil {
return err
}
@@ -190,7 +190,7 @@ func updateAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBS
alert.Updated = timeNow()
alert.State = alertToUpdate.State
sess.MustCols("message")
_, err := sess.Id(alert.Id).Update(alert)
_, err := sess.ID(alert.Id).Update(alert)
if err != nil {
return err
}
@@ -249,7 +249,7 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
return inTransaction(func(sess *DBSession) error {
alert := m.Alert{}
if has, err := sess.Id(cmd.AlertId).Get(&alert); err != nil {
if has, err := sess.ID(cmd.AlertId).Get(&alert); err != nil {
return err
} else if !has {
return fmt.Errorf("Could not find alert")

View File

@@ -119,7 +119,7 @@ func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *DBS
}
results := make([]*m.AlertNotification, 0)
if err := sess.Sql(sql.String(), params...).Find(&results); err != nil {
if err := sess.SQL(sql.String(), params...).Find(&results); err != nil {
return err
}
@@ -239,11 +239,8 @@ func RecordNotificationJournal(ctx context.Context, cmd *m.RecordNotificationJou
Success: cmd.Success,
}
if _, err := sess.Insert(journalEntry); err != nil {
return err
}
return nil
_, err := sess.Insert(journalEntry)
return err
})
}

View File

@@ -110,7 +110,7 @@ func (r *SqlAnnotationRepo) Update(item *annotations.Item) error {
existing.Tags = item.Tags
_, err = sess.Table("annotation").Id(existing.Id).Cols("epoch", "text", "region_id", "updated", "tags").Update(existing)
_, err = sess.Table("annotation").ID(existing.Id).Cols("epoch", "text", "region_id", "updated", "tags").Update(existing)
return err
})
}
@@ -211,7 +211,12 @@ func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.I
)
`, strings.Join(keyValueFilters, " OR "))
sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
if query.MatchAny {
sql.WriteString(fmt.Sprintf(" AND (%s) > 0 ", tagsSubQuery))
} else {
sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
}
}
}
@@ -223,7 +228,7 @@ func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.I
items := make([]*annotations.ItemDTO, 0)
if err := x.Sql(sql.String(), params...).Find(&items); err != nil {
if err := x.SQL(sql.String(), params...).Find(&items); err != nil {
return nil, err
}

View File

@@ -78,7 +78,31 @@ func TestAnnotations(t *testing.T) {
So(err, ShouldBeNil)
So(annotation2.Id, ShouldBeGreaterThan, 0)
Convey("Can query for annotation", func() {
globalAnnotation1 := &annotations.Item{
OrgId: 1,
UserId: 1,
Text: "deploy",
Type: "",
Epoch: 15,
Tags: []string{"deploy"},
}
err = repo.Save(globalAnnotation1)
So(err, ShouldBeNil)
So(globalAnnotation1.Id, ShouldBeGreaterThan, 0)
globalAnnotation2 := &annotations.Item{
OrgId: 1,
UserId: 1,
Text: "rollback",
Type: "",
Epoch: 17,
Tags: []string{"rollback"},
}
err = repo.Save(globalAnnotation2)
So(err, ShouldBeNil)
So(globalAnnotation2.Id, ShouldBeGreaterThan, 0)
Convey("Can query for annotation by dashboard id", func() {
items, err := repo.Find(&annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
@@ -165,7 +189,7 @@ func TestAnnotations(t *testing.T) {
OrgId: 1,
DashboardId: 1,
From: 1,
To: 15,
To: 15, //this will exclude the second test annotation
Tags: []string{"outage", "error"},
})
@@ -173,6 +197,19 @@ func TestAnnotations(t *testing.T) {
So(items, ShouldHaveLength, 1)
})
Convey("Should find two annotations using partial match", func() {
items, err := repo.Find(&annotations.ItemQuery{
OrgId: 1,
From: 1,
To: 25,
MatchAny: true,
Tags: []string{"rollback", "deploy"},
})
So(err, ShouldBeNil)
So(items, ShouldHaveLength, 2)
})
Convey("Should find one when all key value tag filters does match", func() {
items, err := repo.Find(&annotations.ItemQuery{
OrgId: 1,

View File

@@ -225,7 +225,7 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear
var res []DashboardSearchProjection
sql, params := sb.ToSql()
err := x.Sql(sql, params...).Find(&res)
err := x.SQL(sql, params...).Find(&res)
if err != nil {
return nil, err
}
@@ -299,7 +299,7 @@ func GetDashboardTags(query *m.GetDashboardTagsQuery) error {
ORDER BY term`
query.Result = make([]*m.DashboardTagCloudItem, 0)
sess := x.Sql(sql, query.OrgId)
sess := x.SQL(sql, query.OrgId)
err := sess.Find(&query.Result)
return err
}
@@ -413,7 +413,7 @@ func GetDashboardPermissionsForUser(query *m.GetDashboardPermissionsForUserQuery
params = append(params, query.UserId)
params = append(params, dialect.BooleanStr(false))
err := x.Sql(sql, params...).Find(&query.Result)
err := x.SQL(sql, params...).Find(&query.Result)
for _, p := range query.Result {
p.PermissionName = p.Permission.String()
@@ -632,7 +632,7 @@ func HasEditPermissionInFolders(query *m.HasEditPermissionInFoldersQuery) error
}
resp := make([]*folderCount, 0)
if err := x.Sql(builder.GetSqlString(), builder.params...).Find(&resp); err != nil {
if err := x.SQL(builder.GetSqlString(), builder.params...).Find(&resp); err != nil {
return err
}

View File

@@ -51,4 +51,7 @@ func addTeamMigrations(mg *Migrator) {
Name: "email", Type: DB_NVarchar, Nullable: true, Length: 190,
}))
mg.AddMigration("Add column external to team_member table", NewAddColumnMigration(teamMemberV1, &Column{
Name: "external", Type: DB_Bool, Nullable: true,
}))
}

View File

@@ -134,7 +134,7 @@ type TempUserDTO struct {
func (m *AddMissingUserSaltAndRandsMigration) Exec(sess *xorm.Session, mg *Migrator) error {
users := make([]*TempUserDTO, 0)
err := sess.Sql(fmt.Sprintf("SELECT id, login from %s WHERE rands = ''", mg.Dialect.Quote("user"))).Find(&users)
err := sess.SQL(fmt.Sprintf("SELECT id, login from %s WHERE rands = ''", mg.Dialect.Quote("user"))).Find(&users)
if err != nil {
return err
}

View File

@@ -133,7 +133,7 @@ func UpdateOrg(cmd *m.UpdateOrgCommand) error {
Updated: time.Now(),
}
affectedRows, err := sess.Id(cmd.OrgId).Update(&org)
affectedRows, err := sess.ID(cmd.OrgId).Update(&org)
if err != nil {
return err
@@ -166,7 +166,7 @@ func UpdateOrgAddress(cmd *m.UpdateOrgAddressCommand) error {
Updated: time.Now(),
}
if _, err := sess.Id(cmd.OrgId).Update(&org); err != nil {
if _, err := sess.ID(cmd.OrgId).Update(&org); err != nil {
return err
}

View File

@@ -21,7 +21,7 @@ func AddOrgUser(cmd *m.AddOrgUserCommand) error {
return inTransaction(func(sess *DBSession) error {
// check if user exists
var user m.User
if exists, err := sess.Id(cmd.UserId).Get(&user); err != nil {
if exists, err := sess.ID(cmd.UserId).Get(&user); err != nil {
return err
} else if !exists {
return m.ErrUserNotFound
@@ -85,7 +85,7 @@ func UpdateOrgUser(cmd *m.UpdateOrgUserCommand) error {
orgUser.Role = cmd.Role
orgUser.Updated = time.Now()
_, err = sess.Id(orgUser.Id).Update(&orgUser)
_, err = sess.ID(orgUser.Id).Update(&orgUser)
if err != nil {
return err
}
@@ -138,7 +138,7 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error {
return inTransaction(func(sess *DBSession) error {
// check if user exists
var user m.User
if exists, err := sess.Id(cmd.UserId).Get(&user); err != nil {
if exists, err := sess.ID(cmd.UserId).Get(&user); err != nil {
return err
} else if !exists {
return m.ErrUserNotFound

View File

@@ -26,7 +26,7 @@ func GetPluginSettings(query *m.GetPluginSettingsQuery) error {
params = append(params, query.OrgId)
}
sess := x.Sql(sql, params...)
sess := x.SQL(sql, params...)
query.Result = make([]*m.PluginSettingInfoDTO, 0)
return sess.Find(&query.Result)
}
@@ -100,7 +100,7 @@ func UpdatePluginSetting(cmd *m.UpdatePluginSettingCmd) error {
pluginSetting.Pinned = cmd.Pinned
pluginSetting.PluginVersion = cmd.PluginVersion
_, err = sess.Id(pluginSetting.Id).Update(&pluginSetting)
_, err = sess.ID(pluginSetting.Id).Update(&pluginSetting)
return err
})
}

View File

@@ -94,7 +94,7 @@ func SavePreferences(cmd *m.SavePreferencesCommand) error {
prefs.Theme = cmd.Theme
prefs.Updated = time.Now()
prefs.Version += 1
_, err = sess.Id(prefs.Id).AllCols().Update(&prefs)
_, err = sess.ID(prefs.Id).AllCols().Update(&prefs)
return err
})
}

View File

@@ -38,7 +38,7 @@ func GetOrgQuotaByTarget(query *m.GetOrgQuotaByTargetQuery) error {
//get quota used.
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", dialect.Quote(query.Target))
resp := make([]*targetCount, 0)
if err := x.Sql(rawSql, query.OrgId).Find(&resp); err != nil {
if err := x.SQL(rawSql, query.OrgId).Find(&resp); err != nil {
return err
}
@@ -81,7 +81,7 @@ func GetOrgQuotas(query *m.GetOrgQuotasQuery) error {
//get quota used.
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", dialect.Quote(q.Target))
resp := make([]*targetCount, 0)
if err := x.Sql(rawSql, q.OrgId).Find(&resp); err != nil {
if err := x.SQL(rawSql, q.OrgId).Find(&resp); err != nil {
return err
}
result[i] = &m.OrgQuotaDTO{
@@ -116,7 +116,7 @@ func UpdateOrgQuota(cmd *m.UpdateOrgQuotaCmd) error {
}
} else {
//update existing quota entry in the DB.
if _, err := sess.Id(quota.Id).Update(&quota); err != nil {
if _, err := sess.ID(quota.Id).Update(&quota); err != nil {
return err
}
}
@@ -140,7 +140,7 @@ func GetUserQuotaByTarget(query *m.GetUserQuotaByTargetQuery) error {
//get quota used.
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(query.Target))
resp := make([]*targetCount, 0)
if err := x.Sql(rawSql, query.UserId).Find(&resp); err != nil {
if err := x.SQL(rawSql, query.UserId).Find(&resp); err != nil {
return err
}
@@ -183,7 +183,7 @@ func GetUserQuotas(query *m.GetUserQuotasQuery) error {
//get quota used.
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(q.Target))
resp := make([]*targetCount, 0)
if err := x.Sql(rawSql, q.UserId).Find(&resp); err != nil {
if err := x.SQL(rawSql, q.UserId).Find(&resp); err != nil {
return err
}
result[i] = &m.UserQuotaDTO{
@@ -218,7 +218,7 @@ func UpdateUserQuota(cmd *m.UpdateUserQuotaCmd) error {
}
} else {
//update existing quota entry in the DB.
if _, err := sess.Id(quota.Id).Update(&quota); err != nil {
if _, err := sess.ID(quota.Id).Update(&quota); err != nil {
return err
}
}
@@ -231,7 +231,7 @@ func GetGlobalQuotaByTarget(query *m.GetGlobalQuotaByTargetQuery) error {
//get quota used.
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s", dialect.Quote(query.Target))
resp := make([]*targetCount, 0)
if err := x.Sql(rawSql).Find(&resp); err != nil {
if err := x.SQL(rawSql).Find(&resp); err != nil {
return err
}

View File

@@ -74,7 +74,7 @@ func UpdateTeam(cmd *m.UpdateTeamCommand) error {
sess.MustCols("email")
affectedRows, err := sess.Id(cmd.Id).Update(&team)
affectedRows, err := sess.ID(cmd.Id).Update(&team)
if err != nil {
return err
@@ -169,7 +169,7 @@ func SearchTeams(query *m.SearchTeamsQuery) error {
sql.WriteString(dialect.LimitOffset(int64(query.Limit), int64(offset)))
}
if err := x.Sql(sql.String(), params...).Find(&query.Result.Teams); err != nil {
if err := x.SQL(sql.String(), params...).Find(&query.Result.Teams); err != nil {
return err
}
@@ -196,7 +196,7 @@ func GetTeamById(query *m.GetTeamByIdQuery) error {
sql.WriteString(` WHERE team.org_id = ? and team.id = ?`)
var team m.TeamDTO
exists, err := x.Sql(sql.String(), query.OrgId, query.Id).Get(&team)
exists, err := x.SQL(sql.String(), query.OrgId, query.Id).Get(&team)
if err != nil {
return err
@@ -220,7 +220,7 @@ func GetTeamsByUser(query *m.GetTeamsByUserQuery) error {
sql.WriteString(` INNER JOIN team_member on team.id = team_member.team_id`)
sql.WriteString(` WHERE team.org_id = ? and team_member.user_id = ?`)
err := x.Sql(sql.String(), query.OrgId, query.UserId).Find(&query.Result)
err := x.SQL(sql.String(), query.OrgId, query.UserId).Find(&query.Result)
return err
}
@@ -240,11 +240,12 @@ func AddTeamMember(cmd *m.AddTeamMemberCommand) error {
}
entity := m.TeamMember{
OrgId: cmd.OrgId,
TeamId: cmd.TeamId,
UserId: cmd.UserId,
Created: time.Now(),
Updated: time.Now(),
OrgId: cmd.OrgId,
TeamId: cmd.TeamId,
UserId: cmd.UserId,
External: cmd.External,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(&entity)
@@ -289,7 +290,10 @@ func GetTeamMembers(query *m.GetTeamMembersQuery) error {
if query.UserId != 0 {
sess.Where("team_member.user_id=?", query.UserId)
}
sess.Cols("user.org_id", "team_member.team_id", "team_member.user_id", "user.email", "user.login")
if query.External {
sess.Where("team_member.external=?", dialect.BooleanStr(true))
}
sess.Cols("team_member.org_id", "team_member.team_id", "team_member.user_id", "user.email", "user.login", "team_member.external")
sess.Asc("user.login", "user.email")
err := sess.Find(&query.Result)

View File

@@ -50,13 +50,29 @@ func TestTeamCommandsAndQueries(t *testing.T) {
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userIds[0]})
So(err, ShouldBeNil)
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userIds[1], External: true})
So(err, ShouldBeNil)
q1 := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id}
err = GetTeamMembers(q1)
So(err, ShouldBeNil)
So(q1.Result, ShouldHaveLength, 2)
So(q1.Result[0].TeamId, ShouldEqual, team1.Id)
So(q1.Result[0].Login, ShouldEqual, "loginuser0")
So(q1.Result[0].OrgId, ShouldEqual, testOrgId)
So(q1.Result[1].TeamId, ShouldEqual, team1.Id)
So(q1.Result[1].Login, ShouldEqual, "loginuser1")
So(q1.Result[1].OrgId, ShouldEqual, testOrgId)
So(q1.Result[1].External, ShouldEqual, true)
q2 := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id, External: true}
err = GetTeamMembers(q2)
So(err, ShouldBeNil)
So(q2.Result, ShouldHaveLength, 1)
So(q2.Result[0].TeamId, ShouldEqual, team1.Id)
So(q2.Result[0].Login, ShouldEqual, "loginuser1")
So(q2.Result[0].OrgId, ShouldEqual, testOrgId)
So(q2.Result[0].External, ShouldEqual, true)
})
Convey("Should be able to search for teams", func() {

View File

@@ -96,7 +96,7 @@ func GetTempUsersQuery(query *m.GetTempUsersQuery) error {
rawSql += " ORDER BY tu.created desc"
query.Result = make([]*m.TempUserDTO, 0)
sess := x.Sql(rawSql, params...)
sess := x.SQL(rawSql, params...)
err := sess.Find(&query.Result)
return err
}
@@ -121,7 +121,7 @@ func GetTempUserByCode(query *m.GetTempUserByCodeQuery) error {
WHERE tu.code=?`
var tempUser m.TempUserDTO
sess := x.Sql(rawSql, query.Code)
sess := x.SQL(rawSql, query.Code)
has, err := sess.Get(&tempUser)
if err != nil {

View File

@@ -240,7 +240,7 @@ func UpdateUser(cmd *m.UpdateUserCommand) error {
Updated: time.Now(),
}
if _, err := sess.Id(cmd.UserId).Update(&user); err != nil {
if _, err := sess.ID(cmd.UserId).Update(&user); err != nil {
return err
}
@@ -264,7 +264,7 @@ func ChangeUserPassword(cmd *m.ChangeUserPasswordCommand) error {
Updated: time.Now(),
}
_, err := sess.Id(cmd.UserId).Update(&user)
_, err := sess.ID(cmd.UserId).Update(&user)
return err
})
}
@@ -279,7 +279,7 @@ func UpdateUserLastSeenAt(cmd *m.UpdateUserLastSeenAtCommand) error {
LastSeenAt: time.Now(),
}
_, err := sess.Id(cmd.UserId).Update(&user)
_, err := sess.ID(cmd.UserId).Update(&user)
return err
})
}
@@ -310,7 +310,7 @@ func setUsingOrgInTransaction(sess *DBSession, userID int64, orgID int64) error
OrgId: orgID,
}
_, err := sess.Id(userID).Update(&user)
_, err := sess.ID(userID).Update(&user)
return err
}
@@ -372,11 +372,11 @@ func GetSignedInUser(query *m.GetSignedInUserQuery) error {
sess := x.Table("user")
if query.UserId > 0 {
sess.Sql(rawSql+"WHERE u.id=?", query.UserId)
sess.SQL(rawSql+"WHERE u.id=?", query.UserId)
} else if query.Login != "" {
sess.Sql(rawSql+"WHERE u.login=?", query.Login)
sess.SQL(rawSql+"WHERE u.login=?", query.Login)
} else if query.Email != "" {
sess.Sql(rawSql+"WHERE u.email=?", query.Email)
sess.SQL(rawSql+"WHERE u.email=?", query.Email)
}
var user m.SignedInUser
@@ -472,11 +472,11 @@ func DeleteUser(cmd *m.DeleteUserCommand) error {
func UpdateUserPermissions(cmd *m.UpdateUserPermissionsCommand) error {
return inTransaction(func(sess *DBSession) error {
user := m.User{}
sess.Id(cmd.UserId).Get(&user)
sess.ID(cmd.UserId).Get(&user)
user.IsAdmin = cmd.IsGrafanaAdmin
sess.UseBool("is_admin")
_, err := sess.Id(user.Id).Update(&user)
_, err := sess.ID(user.Id).Update(&user)
return err
})
}
@@ -490,7 +490,7 @@ func SetUserHelpFlag(cmd *m.SetUserHelpFlagCommand) error {
Updated: time.Now(),
}
_, err := sess.Id(cmd.UserId).Cols("help_flags1").Update(&user)
_, err := sess.ID(cmd.UserId).Cols("help_flags1").Update(&user)
return err
})
}

View File

@@ -97,7 +97,7 @@ func TestLoadingSettings(t *testing.T) {
Args: []string{
"cfg:default.server.domain=test2",
},
Config: filepath.Join(HomePath, "tests/config-files/override.ini"),
Config: filepath.Join(HomePath, "pkg/setting/testdata/override.ini"),
})
So(Domain, ShouldEqual, "test2")
@@ -108,7 +108,7 @@ func TestLoadingSettings(t *testing.T) {
cfg := NewCfg()
cfg.Load(&CommandLineArgs{
HomePath: "../../",
Config: filepath.Join(HomePath, "tests/config-files/override_windows.ini"),
Config: filepath.Join(HomePath, "pkg/setting/testdata/override_windows.ini"),
Args: []string{`cfg:default.paths.data=c:\tmp\data`},
})
@@ -117,7 +117,7 @@ func TestLoadingSettings(t *testing.T) {
cfg := NewCfg()
cfg.Load(&CommandLineArgs{
HomePath: "../../",
Config: filepath.Join(HomePath, "tests/config-files/override.ini"),
Config: filepath.Join(HomePath, "pkg/setting/testdata/override.ini"),
Args: []string{"cfg:default.paths.data=/tmp/data"},
})
@@ -130,7 +130,7 @@ func TestLoadingSettings(t *testing.T) {
cfg := NewCfg()
cfg.Load(&CommandLineArgs{
HomePath: "../../",
Config: filepath.Join(HomePath, "tests/config-files/override_windows.ini"),
Config: filepath.Join(HomePath, "pkg/setting/testdata/override_windows.ini"),
Args: []string{`cfg:paths.data=c:\tmp\data`},
})
@@ -139,7 +139,7 @@ func TestLoadingSettings(t *testing.T) {
cfg := NewCfg()
cfg.Load(&CommandLineArgs{
HomePath: "../../",
Config: filepath.Join(HomePath, "tests/config-files/override.ini"),
Config: filepath.Join(HomePath, "pkg/setting/testdata/override.ini"),
Args: []string{"cfg:paths.data=/tmp/data"},
})

3
pkg/setting/testdata/override.ini vendored Normal file
View File

@@ -0,0 +1,3 @@
[paths]
data = /tmp/override

View File

@@ -0,0 +1,3 @@
[paths]
data = c:\tmp\override

View File

@@ -144,7 +144,7 @@ func (c *baseClientImpl) encodeBatchRequests(requests []*multiRequest) ([]byte,
payload.WriteString(body + "\n")
}
elapsed := time.Now().Sub(start)
elapsed := time.Since(start)
clientLog.Debug("Encoded batch requests to json", "took", elapsed)
return payload.Bytes(), nil
@@ -187,7 +187,7 @@ func (c *baseClientImpl) executeRequest(method, uriPath string, body []byte) (*h
start := time.Now()
defer func() {
elapsed := time.Now().Sub(start)
elapsed := time.Since(start)
clientLog.Debug("Executed request", "took", elapsed)
}()
return ctxhttp.Do(c.ctx, httpClient, req)
@@ -215,7 +215,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
return nil, err
}
elapsed := time.Now().Sub(start)
elapsed := time.Since(start)
clientLog.Debug("Decoded multisearch json response", "took", elapsed)
msr.Status = res.StatusCode