mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
fix(templating): work on fixing exporting issues when using templating variables, like data source variables, and panel repeats, requires more work #6189
This commit is contained in:
parent
9d5928ddd6
commit
98d1748e43
@ -47,7 +47,7 @@ function (coreModule, kbn, rangeUtil) {
|
|||||||
if (ctrl.$isEmpty(modelValue)) {
|
if (ctrl.$isEmpty(modelValue)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (viewValue.indexOf('$') === 0) {
|
if (viewValue.indexOf('$') === 0 || viewValue.indexOf('+$') === 0) {
|
||||||
return true; // allow template variable
|
return true; // allow template variable
|
||||||
}
|
}
|
||||||
var info = rangeUtil.describeTextRange(viewValue);
|
var info = rangeUtil.describeTextRange(viewValue);
|
||||||
|
@ -52,7 +52,7 @@ export class DashboardCtrl {
|
|||||||
.catch($scope.onInitFailed.bind(this, 'Templating init failed', false))
|
.catch($scope.onInitFailed.bind(this, 'Templating init failed', false))
|
||||||
// continue
|
// continue
|
||||||
.finally(function() {
|
.finally(function() {
|
||||||
dynamicDashboardSrv.init(dashboard, variableSrv);
|
dynamicDashboardSrv.init(dashboard);
|
||||||
dynamicDashboardSrv.process();
|
dynamicDashboardSrv.process();
|
||||||
|
|
||||||
unsavedChangesSrv.init(dashboard, $scope);
|
unsavedChangesSrv.init(dashboard, $scope);
|
||||||
|
@ -12,12 +12,12 @@ export class DynamicDashboardSrv {
|
|||||||
dashboard: any;
|
dashboard: any;
|
||||||
variables: any;
|
variables: any;
|
||||||
|
|
||||||
init(dashboard, variableSrv) {
|
init(dashboard) {
|
||||||
this.dashboard = dashboard;
|
this.dashboard = dashboard;
|
||||||
this.variables = variableSrv.variables;
|
this.variables = dashboard.templating.list;
|
||||||
}
|
}
|
||||||
|
|
||||||
process(options) {
|
process(options?) {
|
||||||
if (this.dashboard.snapshot || this.variables.length === 0) {
|
if (this.dashboard.snapshot || this.variables.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -31,6 +31,8 @@ export class DynamicDashboardSrv {
|
|||||||
// cleanup scopedVars
|
// cleanup scopedVars
|
||||||
for (i = 0; i < this.dashboard.rows.length; i++) {
|
for (i = 0; i < this.dashboard.rows.length; i++) {
|
||||||
row = this.dashboard.rows[i];
|
row = this.dashboard.rows[i];
|
||||||
|
delete row.scopedVars;
|
||||||
|
|
||||||
for (j = 0; j < row.panels.length; j++) {
|
for (j = 0; j < row.panels.length; j++) {
|
||||||
delete row.panels[j].scopedVars;
|
delete row.panels[j].scopedVars;
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,7 @@ export class DashExportCtrl {
|
|||||||
constructor(private backendSrv, dashboardSrv, datasourceSrv, $scope) {
|
constructor(private backendSrv, dashboardSrv, datasourceSrv, $scope) {
|
||||||
this.exporter = new DashboardExporter(datasourceSrv);
|
this.exporter = new DashboardExporter(datasourceSrv);
|
||||||
|
|
||||||
var current = dashboardSrv.getCurrent().getSaveModelClone();
|
this.exporter.makeExportable(dashboardSrv.getCurrent()).then(dash => {
|
||||||
|
|
||||||
this.exporter.makeExportable(current).then(dash => {
|
|
||||||
$scope.$apply(() => {
|
$scope.$apply(() => {
|
||||||
this.dash = dash;
|
this.dash = dash;
|
||||||
});
|
});
|
||||||
|
@ -11,19 +11,40 @@ export class DashboardExporter {
|
|||||||
constructor(private datasourceSrv) {
|
constructor(private datasourceSrv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
makeExportable(dash) {
|
makeExportable(dashboard) {
|
||||||
var dynSrv = new DynamicDashboardSrv();
|
var dynSrv = new DynamicDashboardSrv();
|
||||||
dynSrv.init(dash, {variables: dash.templating.list});
|
|
||||||
|
// clean up repeated rows and panels,
|
||||||
|
// this is done on the live real dashboard instance, not on a clone
|
||||||
|
// so we need to undo this
|
||||||
|
// this is pretty hacky and needs to be changed
|
||||||
|
dynSrv.init(dashboard);
|
||||||
dynSrv.process({cleanUpOnly: true});
|
dynSrv.process({cleanUpOnly: true});
|
||||||
|
|
||||||
dash.id = null;
|
var saveModel = dashboard.getSaveModelClone();
|
||||||
|
saveModel.id = null;
|
||||||
|
|
||||||
|
// undo repeat cleanup
|
||||||
|
dynSrv.process();
|
||||||
|
|
||||||
var inputs = [];
|
var inputs = [];
|
||||||
var requires = {};
|
var requires = {};
|
||||||
var datasources = {};
|
var datasources = {};
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
var variableLookup: any = {};
|
||||||
|
|
||||||
|
for (let variable of saveModel.templating.list) {
|
||||||
|
variableLookup[variable.name] = variable;
|
||||||
|
}
|
||||||
|
|
||||||
var templateizeDatasourceUsage = obj => {
|
var templateizeDatasourceUsage = obj => {
|
||||||
|
// ignore data source properties that contain a variable
|
||||||
|
if (obj.datasource && obj.datasource.indexOf('$') === 0) {
|
||||||
|
if (variableLookup[obj.datasource.substring(1)]){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
promises.push(this.datasourceSrv.get(obj.datasource).then(ds => {
|
promises.push(this.datasourceSrv.get(obj.datasource).then(ds => {
|
||||||
if (ds.meta.builtIn) {
|
if (ds.meta.builtIn) {
|
||||||
return;
|
return;
|
||||||
@ -50,7 +71,7 @@ export class DashboardExporter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// check up panel data sources
|
// check up panel data sources
|
||||||
for (let row of dash.rows) {
|
for (let row of saveModel.rows) {
|
||||||
for (let panel of row.panels) {
|
for (let panel of row.panels) {
|
||||||
if (panel.datasource !== undefined) {
|
if (panel.datasource !== undefined) {
|
||||||
templateizeDatasourceUsage(panel);
|
templateizeDatasourceUsage(panel);
|
||||||
@ -77,7 +98,7 @@ export class DashboardExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// templatize template vars
|
// templatize template vars
|
||||||
for (let variable of dash.templating.list) {
|
for (let variable of saveModel.templating.list) {
|
||||||
if (variable.type === 'query') {
|
if (variable.type === 'query') {
|
||||||
templateizeDatasourceUsage(variable);
|
templateizeDatasourceUsage(variable);
|
||||||
variable.options = [];
|
variable.options = [];
|
||||||
@ -87,7 +108,7 @@ export class DashboardExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// templatize annotations vars
|
// templatize annotations vars
|
||||||
for (let annotationDef of dash.annotations.list) {
|
for (let annotationDef of saveModel.annotations.list) {
|
||||||
templateizeDatasourceUsage(annotationDef);
|
templateizeDatasourceUsage(annotationDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +126,7 @@ export class DashboardExporter {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// templatize constants
|
// templatize constants
|
||||||
for (let variable of dash.templating.list) {
|
for (let variable of saveModel.templating.list) {
|
||||||
if (variable.type === 'constant') {
|
if (variable.type === 'constant') {
|
||||||
var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
|
var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
|
||||||
inputs.push({
|
inputs.push({
|
||||||
@ -133,7 +154,7 @@ export class DashboardExporter {
|
|||||||
newObj["__inputs"] = inputs;
|
newObj["__inputs"] = inputs;
|
||||||
newObj["__requires"] = requires;
|
newObj["__requires"] = requires;
|
||||||
|
|
||||||
_.defaults(newObj, dash);
|
_.defaults(newObj, saveModel);
|
||||||
|
|
||||||
return newObj;
|
return newObj;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
@ -105,7 +105,7 @@ export class DashboardModel {
|
|||||||
|
|
||||||
// prepare save model
|
// prepare save model
|
||||||
this.rows = _.map(rows, row => row.getSaveModel());
|
this.rows = _.map(rows, row => row.getSaveModel());
|
||||||
this.templating.list = _.map(variables, variable => variable.getSaveModel());
|
this.templating.list = _.map(variables, variable => variable.getSaveModel ? variable.getSaveModel() : variable);
|
||||||
|
|
||||||
var copy = $.extend(true, {}, this);
|
var copy = $.extend(true, {}, this);
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ export class DashboardRow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSaveModel() {
|
getSaveModel() {
|
||||||
|
this.model = {};
|
||||||
assignModelProperties(this.model, this, this.defaults);
|
assignModelProperties(this.model, this, this.defaults);
|
||||||
|
|
||||||
// remove properties that dont server persisted purpose
|
// remove properties that dont server persisted purpose
|
||||||
delete this.model.isNew;
|
delete this.model.isNew;
|
||||||
|
|
||||||
return this.model;
|
return this.model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ function dynamicDashScenario(desc, func) {
|
|||||||
|
|
||||||
beforeEach(angularMocks.inject(function(dashboardSrv) {
|
beforeEach(angularMocks.inject(function(dashboardSrv) {
|
||||||
ctx.dashboardSrv = dashboardSrv;
|
ctx.dashboardSrv = dashboardSrv;
|
||||||
ctx.variableSrv = {};
|
|
||||||
|
|
||||||
var model = {
|
var model = {
|
||||||
rows: [],
|
rows: [],
|
||||||
@ -29,9 +28,8 @@ function dynamicDashScenario(desc, func) {
|
|||||||
|
|
||||||
setupFunc(model);
|
setupFunc(model);
|
||||||
ctx.dash = ctx.dashboardSrv.create(model);
|
ctx.dash = ctx.dashboardSrv.create(model);
|
||||||
ctx.variableSrv.variables = ctx.dash.templating.list;
|
|
||||||
ctx.dynamicDashboardSrv = new DynamicDashboardSrv();
|
ctx.dynamicDashboardSrv = new DynamicDashboardSrv();
|
||||||
ctx.dynamicDashboardSrv.init(ctx.dash, ctx.variableSrv);
|
ctx.dynamicDashboardSrv.init(ctx.dash);
|
||||||
ctx.dynamicDashboardSrv.process();
|
ctx.dynamicDashboardSrv.process();
|
||||||
ctx.rows = ctx.dash.rows;
|
ctx.rows = ctx.dash.rows;
|
||||||
}));
|
}));
|
||||||
|
@ -34,6 +34,14 @@ describe('given dashboard with repeated panels', function() {
|
|||||||
options: []
|
options: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dash.templating.list.push({
|
||||||
|
name: 'ds',
|
||||||
|
type: 'datasource',
|
||||||
|
query: 'testdb',
|
||||||
|
current: {value: 'prod', text: 'prod'},
|
||||||
|
options: []
|
||||||
|
});
|
||||||
|
|
||||||
dash.annotations.list.push({
|
dash.annotations.list.push({
|
||||||
name: 'logs',
|
name: 'logs',
|
||||||
datasource: 'gfdb',
|
datasource: 'gfdb',
|
||||||
@ -49,6 +57,7 @@ describe('given dashboard with repeated panels', function() {
|
|||||||
datasource: '-- Mixed --',
|
datasource: '-- Mixed --',
|
||||||
targets: [{datasource: 'other'}],
|
targets: [{datasource: 'other'}],
|
||||||
},
|
},
|
||||||
|
{id: 5, datasource: '$ds'},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -87,7 +96,7 @@ describe('given dashboard with repeated panels', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('exported dashboard should not contain repeated panels', function() {
|
it('exported dashboard should not contain repeated panels', function() {
|
||||||
expect(exported.rows[0].panels.length).to.be(2);
|
expect(exported.rows[0].panels.length).to.be(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('exported dashboard should not contain repeated rows', function() {
|
it('exported dashboard should not contain repeated rows', function() {
|
||||||
|
@ -34,10 +34,7 @@ export class DatasourceVariable implements Variable {
|
|||||||
assignModelProperties(this.model, this, this.defaults);
|
assignModelProperties(this.model, this, this.defaults);
|
||||||
|
|
||||||
// dont persist options
|
// dont persist options
|
||||||
if (this.refresh !== 0) {
|
|
||||||
this.model.options = [];
|
this.model.options = [];
|
||||||
}
|
|
||||||
|
|
||||||
return this.model;
|
return this.model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ describe('QueryVariable', function() {
|
|||||||
var model = variable.getSaveModel();
|
var model = variable.getSaveModel();
|
||||||
expect(model.options.length).to.be(0);
|
expect(model.options.length).to.be(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user