Merge remote-tracking branch 'grafana/master' into alpha-react-table
* grafana/master: Fixed styling of gicon's in dropdown menus cleanup plugin versions use explore icon fix comments typescript functions on replace remove console.log add ScopedVars to replace function Expose onQueryChange to angular plugins fix allow anonymous initial bind for ldap search
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { ComponentClass } from 'react';
|
||||
import { TimeSeries, LoadingState, TableData } from './data';
|
||||
import { TimeRange } from './time';
|
||||
import { ScopedVars } from './datasource';
|
||||
|
||||
export type InterpolateFunction = (value: string, format?: string | Function) => string;
|
||||
export type InterpolateFunction = (value: string, scopedVars?: ScopedVars, format?: string | Function) => string;
|
||||
|
||||
export interface PanelProps<T = any> {
|
||||
panelData: PanelData;
|
||||
|
||||
+12
-1
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
type ILdapConn interface {
|
||||
Bind(username, password string) error
|
||||
UnauthenticatedBind(username string) error
|
||||
Search(*ldap.SearchRequest) (*ldap.SearchResult, error)
|
||||
StartTLS(*tls.Config) error
|
||||
Close()
|
||||
@@ -259,7 +260,17 @@ func (a *ldapAuther) initialBind(username, userPassword string) error {
|
||||
bindPath = fmt.Sprintf(a.server.BindDN, username)
|
||||
}
|
||||
|
||||
if err := a.conn.Bind(bindPath, userPassword); err != nil {
|
||||
bindFn := func() error {
|
||||
return a.conn.Bind(bindPath, userPassword)
|
||||
}
|
||||
|
||||
if userPassword == "" {
|
||||
bindFn = func() error {
|
||||
return a.conn.UnauthenticatedBind(bindPath)
|
||||
}
|
||||
}
|
||||
|
||||
if err := bindFn(); err != nil {
|
||||
a.log.Info("Initial bind failed", "error", err)
|
||||
|
||||
if ldapErr, ok := err.(*ldap.Error); ok {
|
||||
|
||||
+81
-3
@@ -13,6 +13,70 @@ import (
|
||||
)
|
||||
|
||||
func TestLdapAuther(t *testing.T) {
|
||||
Convey("initialBind", t, func() {
|
||||
Convey("Given bind dn and password configured", func() {
|
||||
conn := &mockLdapConn{}
|
||||
var actualUsername, actualPassword string
|
||||
conn.bindProvider = func(username, password string) error {
|
||||
actualUsername = username
|
||||
actualPassword = password
|
||||
return nil
|
||||
}
|
||||
ldapAuther := &ldapAuther{
|
||||
conn: conn,
|
||||
server: &LdapServerConf{
|
||||
BindDN: "cn=%s,o=users,dc=grafana,dc=org",
|
||||
BindPassword: "bindpwd",
|
||||
},
|
||||
}
|
||||
err := ldapAuther.initialBind("user", "pwd")
|
||||
So(err, ShouldBeNil)
|
||||
So(ldapAuther.requireSecondBind, ShouldBeTrue)
|
||||
So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org")
|
||||
So(actualPassword, ShouldEqual, "bindpwd")
|
||||
})
|
||||
|
||||
Convey("Given bind dn configured", func() {
|
||||
conn := &mockLdapConn{}
|
||||
var actualUsername, actualPassword string
|
||||
conn.bindProvider = func(username, password string) error {
|
||||
actualUsername = username
|
||||
actualPassword = password
|
||||
return nil
|
||||
}
|
||||
ldapAuther := &ldapAuther{
|
||||
conn: conn,
|
||||
server: &LdapServerConf{
|
||||
BindDN: "cn=%s,o=users,dc=grafana,dc=org",
|
||||
},
|
||||
}
|
||||
err := ldapAuther.initialBind("user", "pwd")
|
||||
So(err, ShouldBeNil)
|
||||
So(ldapAuther.requireSecondBind, ShouldBeFalse)
|
||||
So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org")
|
||||
So(actualPassword, ShouldEqual, "pwd")
|
||||
})
|
||||
|
||||
Convey("Given empty bind dn and password", func() {
|
||||
conn := &mockLdapConn{}
|
||||
unauthenticatedBindWasCalled := false
|
||||
var actualUsername string
|
||||
conn.unauthenticatedBindProvider = func(username string) error {
|
||||
unauthenticatedBindWasCalled = true
|
||||
actualUsername = username
|
||||
return nil
|
||||
}
|
||||
ldapAuther := &ldapAuther{
|
||||
conn: conn,
|
||||
server: &LdapServerConf{},
|
||||
}
|
||||
err := ldapAuther.initialBind("user", "pwd")
|
||||
So(err, ShouldBeNil)
|
||||
So(ldapAuther.requireSecondBind, ShouldBeTrue)
|
||||
So(unauthenticatedBindWasCalled, ShouldBeTrue)
|
||||
So(actualUsername, ShouldBeEmpty)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When translating ldap user to grafana user", t, func() {
|
||||
|
||||
@@ -365,12 +429,26 @@ func TestLdapAuther(t *testing.T) {
|
||||
}
|
||||
|
||||
type mockLdapConn struct {
|
||||
result *ldap.SearchResult
|
||||
searchCalled bool
|
||||
searchAttributes []string
|
||||
result *ldap.SearchResult
|
||||
searchCalled bool
|
||||
searchAttributes []string
|
||||
bindProvider func(username, password string) error
|
||||
unauthenticatedBindProvider func(username string) error
|
||||
}
|
||||
|
||||
func (c *mockLdapConn) Bind(username, password string) error {
|
||||
if c.bindProvider != nil {
|
||||
return c.bindProvider(username, password)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockLdapConn) UnauthenticatedBind(username string) error {
|
||||
if c.unauthenticatedBindProvider != nil {
|
||||
return c.unauthenticatedBindProvider(username)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { PanelChrome } from './PanelChrome';
|
||||
|
||||
jest.mock('sass/_variables.generated.scss', () => ({
|
||||
panelhorizontalpadding: 10,
|
||||
panelVerticalPadding: 10,
|
||||
}));
|
||||
|
||||
describe('PanelChrome', () => {
|
||||
let chrome: PanelChrome;
|
||||
|
||||
beforeEach(() => {
|
||||
chrome = new PanelChrome({
|
||||
panel: {
|
||||
scopedVars: {
|
||||
aaa: { value: 'AAA', text: 'upperA' },
|
||||
bbb: { value: 'BBB', text: 'upperB' },
|
||||
},
|
||||
},
|
||||
dashboard: {},
|
||||
plugin: {},
|
||||
isFullscreen: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('Should replace a panel variable', () => {
|
||||
const out = chrome.replaceVariables('hello $aaa');
|
||||
expect(out).toBe('hello AAA');
|
||||
});
|
||||
|
||||
it('But it should prefer the local variable value', () => {
|
||||
const extra = { aaa: { text: '???', value: 'XXX' } };
|
||||
const out = chrome.replaceVariables('hello $aaa and $bbb', extra);
|
||||
expect(out).toBe('hello XXX and BBB');
|
||||
});
|
||||
});
|
||||
@@ -19,6 +19,7 @@ import { profiler } from 'app/core/profiler';
|
||||
import { DashboardModel, PanelModel } from '../state';
|
||||
import { PanelPlugin } from 'app/types';
|
||||
import { DataQueryResponse, TimeRange, LoadingState, PanelData, DataQueryError } from '@grafana/ui';
|
||||
import { ScopedVars } from '@grafana/ui';
|
||||
|
||||
import variables from 'sass/_variables.generated.scss';
|
||||
import templateSrv from 'app/features/templating/template_srv';
|
||||
@@ -85,8 +86,12 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
});
|
||||
};
|
||||
|
||||
replaceVariables = (value: string, format?: string) => {
|
||||
return templateSrv.replace(value, this.props.panel.scopedVars, format);
|
||||
replaceVariables = (value: string, extraVars?: ScopedVars, format?: string) => {
|
||||
let vars = this.props.panel.scopedVars;
|
||||
if (extraVars) {
|
||||
vars = vars ? { ...vars, ...extraVars } : extraVars;
|
||||
}
|
||||
return templateSrv.replace(value, vars, format);
|
||||
};
|
||||
|
||||
onDataResponse = (dataQueryResponse: DataQueryResponse) => {
|
||||
|
||||
@@ -43,6 +43,9 @@ export default class QueryEditor extends PureComponent<QueryEditorProps, any> {
|
||||
this.props.onQueryChange(target);
|
||||
this.props.onExecuteQuery();
|
||||
},
|
||||
onQueryChange: () => {
|
||||
this.props.onQueryChange(target);
|
||||
},
|
||||
events: exploreEvents,
|
||||
panel: { datasource, targets: [target] },
|
||||
dashboard: {},
|
||||
|
||||
@@ -224,7 +224,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
items.push({
|
||||
text: 'Explore',
|
||||
click: 'ctrl.explore();',
|
||||
icon: 'fa fa-fw fa-rocket',
|
||||
icon: 'gicon gicon-explore',
|
||||
shortcut: 'x',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
|
||||
<aside class="page-sidebar">
|
||||
<section class="page-sidebar-section">
|
||||
<section class="page-sidebar-section" ng-if="ctrl.model.info.version">
|
||||
<h4>Version</h4>
|
||||
<span>{{ctrl.model.info.version}}</span>
|
||||
<div ng-show="ctrl.model.hasUpdate">
|
||||
@@ -54,7 +54,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="page-sidebar-section">
|
||||
<section class="page-sidebar-section" ng-if="ctrl.model.info.links">
|
||||
<h5>Links</h4>
|
||||
<ul class="ui-list">
|
||||
<li ng-repeat="link in ctrl.model.info.links">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import _ from 'lodash';
|
||||
import { variableRegex } from 'app/features/templating/variable';
|
||||
import { TimeRange } from '@grafana/ui/src';
|
||||
import { TimeRange, ScopedVars } from '@grafana/ui/src';
|
||||
|
||||
function luceneEscape(value) {
|
||||
return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, '\\$1');
|
||||
@@ -220,7 +220,7 @@ export class TemplateSrv {
|
||||
return values;
|
||||
}
|
||||
|
||||
replace(target, scopedVars?, format?) {
|
||||
replace(target: string, scopedVars?: ScopedVars, format?: string | Function) {
|
||||
if (!target) {
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
"logos": {
|
||||
"small": "img/amazon-web-services.png",
|
||||
"large": "img/amazon-web-services.png"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,7 @@
|
||||
"small": "img/elasticsearch.svg",
|
||||
"large": "img/elasticsearch.svg"
|
||||
},
|
||||
"links": [
|
||||
{"name": "elastic.co", "url": "https://www.elastic.co/products/elasticsearch"}
|
||||
],
|
||||
"version": "5.0.0"
|
||||
"links": [{ "name": "elastic.co", "url": "https://www.elastic.co/products/elasticsearch" }]
|
||||
},
|
||||
|
||||
"alerting": true,
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
"name": "Graphite 1.1 Release",
|
||||
"url": "https://grafana.com/blog/2018/01/11/graphite-1.1-teaching-an-old-dog-new-tricks/"
|
||||
}
|
||||
],
|
||||
"version": "5.0.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
"logos": {
|
||||
"small": "img/influxdb_logo.svg",
|
||||
"large": "img/influxdb_logo.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
"logos": {
|
||||
"small": "img/mysql_logo.svg",
|
||||
"large": "img/mysql_logo.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
},
|
||||
|
||||
"alerting": true,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"logos": {
|
||||
"small": "img/opentsdb_logo.png",
|
||||
"large": "img/opentsdb_logo.png"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
"logos": {
|
||||
"small": "img/postgresql_logo.svg",
|
||||
"large": "img/postgresql_logo.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
},
|
||||
|
||||
"alerting": true,
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
"name": "Prometheus",
|
||||
"url": "https://prometheus.io/"
|
||||
}
|
||||
],
|
||||
"version": "5.0.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-singlestat-panel.svg",
|
||||
"large": "img/icn-singlestat-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-dashlist-panel.svg",
|
||||
"large": "img/icn-dashlist-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-graph-panel.svg",
|
||||
"large": "img/icn-graph-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"links": [
|
||||
{ "name": "Brendan Gregg - Heatmaps", "url": "http://www.brendangregg.com/heatmaps.html" },
|
||||
{ "name": "Brendan Gregg - Latency Heatmaps", "url": " http://www.brendangregg.com/HeatMaps/latency.html" }
|
||||
],
|
||||
"version": "5.0.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-dashlist-panel.svg",
|
||||
"large": "img/icn-dashlist-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-singlestat-panel.svg",
|
||||
"large": "img/icn-singlestat-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-table-panel.svg",
|
||||
"large": "img/icn-table-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"logos": {
|
||||
"small": "img/icn-text-panel.svg",
|
||||
"large": "img/icn-text-panel.svg"
|
||||
},
|
||||
"version": "5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,9 @@
|
||||
}
|
||||
|
||||
.gicon {
|
||||
opacity: 0.9;
|
||||
opacity: 0.7;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user