CloudWatch: Handle nested panels when migrating CloudWatch queries (#40993)

* support nested targets when migrating cloudwatch queries

* cleanup

* use panelUpgrades array

* bump schema version number
This commit is contained in:
Erik Sundell 2021-10-28 09:47:35 +02:00 committed by GitHub
parent 6a2dc11545
commit 7521d56cec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 207 additions and 11 deletions

View File

@ -162,7 +162,7 @@ describe('DashboardModel', () => {
});
it('dashboard schema version should be set to latest', () => {
expect(model.schemaVersion).toBe(31);
expect(model.schemaVersion).toBe(32);
});
it('graph thresholds should be migrated', () => {
@ -1560,6 +1560,194 @@ describe('DashboardModel', () => {
expect(panelTargets[2].refId).toBe('C');
expect(panelTargets[3].refId).toBe('D');
});
describe('with nested panels', () => {
let panel1Targets: any;
let panel2Targets: any;
let nestedModel: DashboardModel;
beforeEach(() => {
nestedModel = new DashboardModel({
annotations: {
list: [
{
actionPrefix: '',
alarmNamePrefix: '',
alias: '',
dimensions: {
InstanceId: 'i-123',
},
enable: true,
expression: '',
iconColor: 'red',
id: '',
matchExact: true,
metricName: 'CPUUtilization',
name: 'test',
namespace: 'AWS/EC2',
period: '',
prefixMatching: false,
region: 'us-east-2',
statistics: ['Minimum', 'Sum'],
},
],
},
panels: [
{
collapsed: false,
gridPos: {
h: 1,
w: 24,
x: 0,
y: 89,
},
id: 96,
title: 'DynamoDB',
type: 'row',
panels: [
{
gridPos: {
h: 8,
w: 12,
x: 0,
y: 0,
},
id: 4,
options: {
legend: {
calcs: [],
displayMode: 'list',
placement: 'bottom',
},
tooltipOptions: {
mode: 'single',
},
},
targets: [
{
alias: '',
dimensions: {
InstanceId: 'i-123',
},
expression: '',
id: '',
matchExact: true,
metricName: 'CPUUtilization',
namespace: 'AWS/EC2',
period: '',
refId: 'C',
region: 'default',
statistics: ['Average', 'Minimum', 'p12.21'],
},
{
alias: '',
dimensions: {
InstanceId: 'i-123',
},
expression: '',
hide: false,
id: '',
matchExact: true,
metricName: 'CPUUtilization',
namespace: 'AWS/EC2',
period: '',
refId: 'B',
region: 'us-east-2',
statistics: ['Sum'],
},
],
title: 'Panel Title',
type: 'timeseries',
},
{
gridPos: {
h: 8,
w: 12,
x: 0,
y: 0,
},
id: 4,
options: {
legend: {
calcs: [],
displayMode: 'list',
placement: 'bottom',
},
tooltipOptions: {
mode: 'single',
},
},
targets: [
{
alias: '',
dimensions: {
InstanceId: 'i-123',
},
expression: '',
id: '',
matchExact: true,
metricName: 'CPUUtilization',
namespace: 'AWS/EC2',
period: '',
refId: 'A',
region: 'default',
statistics: ['Average'],
},
{
alias: '',
dimensions: {
InstanceId: 'i-123',
},
expression: '',
hide: false,
id: '',
matchExact: true,
metricName: 'CPUUtilization',
namespace: 'AWS/EC2',
period: '',
refId: 'B',
region: 'us-east-2',
statistics: ['Sum', 'Min'],
},
],
title: 'Panel Title',
type: 'timeseries',
},
],
},
],
});
panel1Targets = nestedModel.panels[0].panels[0].targets;
panel2Targets = nestedModel.panels[0].panels[1].targets;
});
it('multiple stats query should have been split into one query per stat', () => {
expect(panel1Targets.length).toBe(4);
expect(panel2Targets.length).toBe(3);
});
it('new stats query should get the right statistic', () => {
expect(panel1Targets[0].statistic).toBe('Average');
expect(panel1Targets[1].statistic).toBe('Sum');
expect(panel1Targets[2].statistic).toBe('Minimum');
expect(panel1Targets[3].statistic).toBe('p12.21');
expect(panel2Targets[0].statistic).toBe('Average');
expect(panel2Targets[1].statistic).toBe('Sum');
expect(panel2Targets[2].statistic).toBe('Min');
});
it('new stats queries should be put in the end of the array', () => {
expect(panel1Targets[0].refId).toBe('C');
expect(panel1Targets[1].refId).toBe('B');
expect(panel1Targets[2].refId).toBe('A');
expect(panel1Targets[3].refId).toBe('D');
expect(panel2Targets[0].refId).toBe('A');
expect(panel2Targets[1].refId).toBe('B');
expect(panel2Targets[2].refId).toBe('C');
});
});
});
});

View File

@ -62,7 +62,7 @@ export class DashboardMigrator {
let i, j, k, n;
const oldVersion = this.dashboard.schemaVersion;
const panelUpgrades: PanelSchemeUpgradeHandler[] = [];
this.dashboard.schemaVersion = 31;
this.dashboard.schemaVersion = 32;
if (oldVersion === this.dashboard.schemaVersion) {
return;
@ -686,6 +686,15 @@ export class DashboardMigrator {
});
}
if (oldVersion < 32) {
panelUpgrades.push((panel: PanelModel) => {
this.migrateCloudWatchQueries(panel);
return panel;
});
this.migrateCloudWatchAnnotationQuery();
}
if (panelUpgrades.length === 0) {
return;
}
@ -705,18 +714,18 @@ export class DashboardMigrator {
// Migrates metric queries and/or annotation queries that use more than one statistic.
// E.g query.statistics = ['Max', 'Min'] will be migrated to two queries - query1.statistic = 'Max' and query2.statistic = 'Min'
// New queries, that were created during migration, are put at the end of the array.
migrateCloudWatchQueries() {
for (const panel of this.dashboard.panels) {
for (const target of panel.targets) {
if (isLegacyCloudWatchQuery(target)) {
const newQueries = migrateMultipleStatsMetricsQuery(target, [...panel.targets]);
for (const newQuery of newQueries) {
panel.targets.push(newQuery);
}
migrateCloudWatchQueries(panel: PanelModel) {
for (const target of panel.targets || []) {
if (isLegacyCloudWatchQuery(target)) {
const newQueries = migrateMultipleStatsMetricsQuery(target, [...panel.targets]);
for (const newQuery of newQueries) {
panel.targets.push(newQuery);
}
}
}
}
migrateCloudWatchAnnotationQuery() {
for (const annotation of this.dashboard.annotations.list) {
if (isLegacyCloudWatchAnnotationQuery(annotation)) {
const newAnnotationQueries = migrateMultipleStatsAnnotationQuery(annotation);

View File

@ -1041,7 +1041,6 @@ export class DashboardModel {
private updateSchema(old: any) {
const migrator = new DashboardMigrator(this);
migrator.updateSchema(old);
migrator.migrateCloudWatchQueries();
}
resetOriginalTime() {