diff --git a/ui/packages/consul-ui/app/services/repository/metrics.js b/ui/packages/consul-ui/app/services/repository/metrics.js
index 9f29137d3..e0138241d 100644
--- a/ui/packages/consul-ui/app/services/repository/metrics.js
+++ b/ui/packages/consul-ui/app/services/repository/metrics.js
@@ -1,20 +1,13 @@
import { inject as service } from '@ember/service';
import RepositoryService from 'consul-ui/services/repository';
-import { env } from 'consul-ui/env';
-// meta is used by DataSource to configure polling. The interval controls how
-// long between each poll to the metrics provider. TODO - make this configurable
-// in the UI settings.
-const meta = {
- interval: env('CONSUL_METRICS_POLL_INTERVAL') || 10000,
-};
+// CONSUL_METRICS_POLL_INTERVAL controls how long between each poll to the
+// metrics provider
export default class MetricsService extends RepositoryService {
- @service('ui-config')
- cfg;
-
- @service('client/http')
- client;
+ @service('ui-config') cfg;
+ @service('env') env;
+ @service('client/http') client;
error = null;
@@ -49,9 +42,11 @@ export default class MetricsService extends RepositoryService {
this.provider.serviceRecentSummarySeries(slug, dc, nspace, protocol, {}),
this.provider.serviceRecentSummaryStats(slug, dc, nspace, protocol, {}),
];
- return Promise.all(promises).then(function (results) {
+ return Promise.all(promises).then(results => {
return {
- meta: meta,
+ meta: {
+ interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
+ },
series: results[0],
stats: results[1].stats,
};
@@ -62,8 +57,10 @@ export default class MetricsService extends RepositoryService {
if (this.error) {
return Promise.reject(this.error);
}
- return this.provider.upstreamRecentSummaryStats(slug, dc, nspace, {}).then(function (result) {
- result.meta = meta;
+ return this.provider.upstreamRecentSummaryStats(slug, dc, nspace, {}).then(result => {
+ result.meta = {
+ interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
+ };
return result;
});
}
@@ -72,8 +69,10 @@ export default class MetricsService extends RepositoryService {
if (this.error) {
return Promise.reject(this.error);
}
- return this.provider.downstreamRecentSummaryStats(slug, dc, nspace, {}).then(function (result) {
- result.meta = meta;
+ return this.provider.downstreamRecentSummaryStats(slug, dc, nspace, {}).then(result => {
+ result.meta = {
+ interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
+ };
return result;
});
}
diff --git a/ui/packages/consul-ui/app/services/ui-config.js b/ui/packages/consul-ui/app/services/ui-config.js
index cdd6b8593..afef0cfd9 100644
--- a/ui/packages/consul-ui/app/services/ui-config.js
+++ b/ui/packages/consul-ui/app/services/ui-config.js
@@ -1,15 +1,14 @@
-import Service from '@ember/service';
+import Service, { inject as service } from '@ember/service';
+import { get } from '@ember/object';
export default class UiConfigService extends Service {
- config = undefined;
+ @service('env') env;
+
+ async findByPath(path, configuration = {}) {
+ return get(this.get(), path);
+ }
get() {
- if (this.config === undefined) {
- // Load config from our special meta tag for now. Later it might come from
- // an API instead/as well.
- var meta = unescape(document.getElementsByName('consul-ui/ui_config')[0].content);
- this.config = JSON.parse(meta);
- }
- return this.config;
+ return this.env.var('CONSUL_UI_CONFIG');
}
}
diff --git a/ui/packages/consul-ui/app/utils/get-environment.js b/ui/packages/consul-ui/app/utils/get-environment.js
index bfe93a2ea..0405ecf48 100644
--- a/ui/packages/consul-ui/app/utils/get-environment.js
+++ b/ui/packages/consul-ui/app/utils/get-environment.js
@@ -1,6 +1,26 @@
+import { runInDebug } from '@ember/debug';
+// 'environment' getter
+// there are currently 3 levels of environment variables:
+// 1. Those that can be set by the user by setting localStorage values
+// 2. Those that can be set by the operator either via ui_config, or inferring
+// from other server type properties (protocol)
+// 3. Those that can be set only during development by adding cookie values
+// via the browsers Web Inspector, or via the browsers hash (#COOKIE_NAME=1),
+// which is useful for showing the UI with various settings enabled/disabled
export default function(config = {}, win = window, doc = document) {
- const dev = function() {
- return doc.cookie
+ // look at the hash in the URL and transfer anything after the hash into
+ // cookies to enable linking of the UI with various settings enabled
+ runInDebug(() => {
+ if (
+ typeof win.location !== 'undefined' &&
+ typeof win.location.hash === 'string' &&
+ win.location.hash.length > 0
+ ) {
+ doc.cookie = win.location.hash.substr(1);
+ }
+ });
+ const dev = function(str = doc.cookie) {
+ return str
.split(';')
.filter(item => item !== '')
.map(item => item.trim().split('='));
@@ -20,6 +40,7 @@ export default function(config = {}, win = window, doc = document) {
return {};
}
};
+ const ui_config = JSON.parse(unescape(doc.getElementsByName('consul-ui/ui_config')[0].content));
const scripts = doc.getElementsByTagName('script');
// we use the currently executing script as a reference
// to figure out where we are for other things such as
@@ -33,6 +54,21 @@ export default function(config = {}, win = window, doc = document) {
const operator = function(str, env) {
let protocol;
switch (str) {
+ case 'CONSUL_UI_CONFIG':
+ const dashboards = {};
+ const provider = env('CONSUL_METRICS_PROVIDER');
+ const proxy = env('CONSUL_METRICS_PROXY_ENABLED');
+ dashboards.service = env('CONSUL_SERVICE_DASHBOARD_URL');
+ if (provider) {
+ ui_config.metrics_provider = provider;
+ }
+ if (proxy) {
+ ui_config.metrics_proxy_enabled = proxy;
+ }
+ if (dashboards.service) {
+ ui_config.dashboard_url_templates = dashboards;
+ }
+ return ui_config;
case 'CONSUL_BASE_UI_URL':
return currentSrc
.split('/')
@@ -85,6 +121,12 @@ export default function(config = {}, win = window, doc = document) {
case 'CONSUL_SSO_ENABLE':
prev['CONSUL_SSO_ENABLED'] = !!JSON.parse(String(value).toLowerCase());
break;
+ case 'CONSUL_METRICS_PROXY_ENABLE':
+ prev['CONSUL_METRICS_PROXY_ENABLED'] = !!JSON.parse(String(value).toLowerCase());
+ break;
+ case 'CONSUL_UI_CONFIG':
+ prev['CONSUL_UI_CONFIG'] = JSON.parse(value);
+ break;
default:
prev[key] = value;
}
@@ -109,7 +151,10 @@ export default function(config = {}, win = window, doc = document) {
case 'CONSUL_UI_REALTIME_RUNNER':
// these are strings
return user(str) || ui(str);
-
+ case 'CONSUL_UI_CONFIG':
+ case 'CONSUL_METRICS_PROVIDER':
+ case 'CONSUL_METRICS_PROXY_ENABLE':
+ case 'CONSUL_SERVICE_DASHBOARD_URL':
case 'CONSUL_BASE_UI_URL':
case 'CONSUL_HTTP_PROTOCOL':
case 'CONSUL_HTTP_MAX_CONNECTIONS':
diff --git a/ui/packages/consul-ui/lib/startup/templates/head.html.js b/ui/packages/consul-ui/lib/startup/templates/head.html.js
index 35c217e1f..702b6871b 100644
--- a/ui/packages/consul-ui/lib/startup/templates/head.html.js
+++ b/ui/packages/consul-ui/lib/startup/templates/head.html.js
@@ -3,15 +3,7 @@ module.exports = ({ appName, environment, rootURL, config }) => `
diff --git a/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature b/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature
index 2b5b0399e..599475ed7 100644
--- a/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature
+++ b/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature
@@ -107,10 +107,15 @@ Feature: dc / services / show: Show Service
---
Scenario: Given a dashboard template has been set
Given 1 datacenter model with the value "dc1"
+ And ui_config from yaml
+ ---
+ dashboard_url_templates:
+ service: https://something.com?{{Service.Name}}&{{Datacenter}}
+ ---
When I visit the service page for yaml
---
dc: dc1
service: service-0
---
# The Metrics dashboard should use the Service.Name not the ID
- And I see href on the metricsAnchor like "https://example.com?service-0&dc1"
+ And I see href on the metricsAnchor like "https://something.com?service-0&dc1"
diff --git a/ui/packages/consul-ui/tests/helpers/yadda-annotations.js b/ui/packages/consul-ui/tests/helpers/yadda-annotations.js
index 40056ca05..e629f8653 100644
--- a/ui/packages/consul-ui/tests/helpers/yadda-annotations.js
+++ b/ui/packages/consul-ui/tests/helpers/yadda-annotations.js
@@ -9,7 +9,23 @@ import dictionary from '../dictionary';
const getDictionary = dictionary(utils);
const staticClassList = [...document.documentElement.classList];
+const getCookies = () => {
+ return Object.fromEntries(document.cookie.split(';').map(item => item.split('=')));
+};
+const getResetCookies = function() {
+ const start = getCookies();
+ return () => {
+ const startKeys = Object.keys(start);
+ const endKeys = Object.keys(getCookies());
+ const diff = endKeys.filter(key => !startKeys.includes(key));
+ diff.forEach(item => {
+ document.cookie = `${item}= ; expires=${new Date(0)}`;
+ });
+ };
+};
+let resetCookies;
const reset = function() {
+ resetCookies();
window.localStorage.clear();
api.server.reset();
const list = document.documentElement.classList;
@@ -21,6 +37,7 @@ const reset = function() {
});
};
const startup = function() {
+ resetCookies = getResetCookies();
api.server.setCookie('CONSUL_LATENCY', 0);
};
diff --git a/ui/packages/consul-ui/tests/steps/doubles/model.js b/ui/packages/consul-ui/tests/steps/doubles/model.js
index 75a0cb981..ca9e035c8 100644
--- a/ui/packages/consul-ui/tests/steps/doubles/model.js
+++ b/ui/packages/consul-ui/tests/steps/doubles/model.js
@@ -1,4 +1,4 @@
-export default function(scenario, create) {
+export default function(scenario, create, win = window, doc = document) {
scenario
.given(['an external edit results in $number $model model[s]?'], function(number, model) {
return create(number, model);
@@ -17,7 +17,10 @@ export default function(scenario, create) {
)
.given(['settings from yaml\n$yaml'], function(data) {
return Object.keys(data).forEach(function(key) {
- window.localStorage[key] = JSON.stringify(data[key]);
+ win.localStorage[key] = JSON.stringify(data[key]);
});
+ })
+ .given(['ui_config from yaml\n$yaml'], function(data) {
+ doc.cookie = `CONSUL_UI_CONFIG=${JSON.stringify(data)}`;
});
}
diff --git a/ui/packages/consul-ui/tests/unit/utils/get-environment-test.js b/ui/packages/consul-ui/tests/unit/utils/get-environment-test.js
index 94667ded0..bb91aa38e 100644
--- a/ui/packages/consul-ui/tests/unit/utils/get-environment-test.js
+++ b/ui/packages/consul-ui/tests/unit/utils/get-environment-test.js
@@ -9,11 +9,12 @@ const getEntriesByType = function(type) {
},
];
};
-const makeGetElementsByTagName = function(src) {
+const makeGetElementsBy = function(str) {
return function(name) {
return [
{
- src: src,
+ src: str,
+ content: str,
},
];
};
@@ -22,13 +23,17 @@ const win = {
performance: {
getEntriesByType: getEntriesByType,
},
+ location: {
+ hash: '',
+ },
localStorage: {
getItem: function(key) {},
},
};
const doc = {
cookie: '',
- getElementsByTagName: makeGetElementsByTagName(''),
+ getElementsByTagName: makeGetElementsBy(''),
+ getElementsByName: makeGetElementsBy('{}'),
};
module('Unit | Utility | getEnvironment', function() {
test('it returns a function', function(assert) {
@@ -55,14 +60,16 @@ module('Unit | Utility | getEnvironment', function() {
let expected = 'http://localhost/ui';
let doc = {
cookie: '',
- getElementsByTagName: makeGetElementsByTagName(`${expected}/assets/consul-ui.js`),
+ getElementsByTagName: makeGetElementsBy(`${expected}/assets/consul-ui.js`),
+ getElementsByName: makeGetElementsBy('{}'),
};
let env = getEnvironment(config, win, doc);
assert.equal(env('CONSUL_BASE_UI_URL'), expected);
expected = 'http://localhost/somewhere/else';
doc = {
cookie: '',
- getElementsByTagName: makeGetElementsByTagName(`${expected}/assets/consul-ui.js`),
+ getElementsByTagName: makeGetElementsBy(`${expected}/assets/consul-ui.js`),
+ getElementsByName: makeGetElementsBy('{}'),
};
env = getEnvironment(config, win, doc);
assert.equal(env('CONSUL_BASE_UI_URL'), expected);
@@ -135,7 +142,8 @@ module('Unit | Utility | getEnvironment', function() {
};
let doc = {
cookie: 'CONSUL_NSPACES_ENABLE=1',
- getElementsByTagName: makeGetElementsByTagName(''),
+ getElementsByTagName: makeGetElementsBy(''),
+ getElementsByName: makeGetElementsBy('{}'),
};
let env = getEnvironment(config, win, doc);
assert.ok(env('CONSUL_NSPACES_ENABLED'));
@@ -145,7 +153,8 @@ module('Unit | Utility | getEnvironment', function() {
};
doc = {
cookie: 'CONSUL_NSPACES_ENABLE=0',
- getElementsByTagName: makeGetElementsByTagName(''),
+ getElementsByTagName: makeGetElementsBy(''),
+ getElementsByName: makeGetElementsBy('{}'),
};
env = getEnvironment(config, win, doc);
assert.notOk(env('CONSUL_NSPACES_ENABLED'));
@@ -169,7 +178,8 @@ module('Unit | Utility | getEnvironment', function() {
};
let doc = {
cookie: 'CONSUL_NSPACES_ENABLE=1',
- getElementsByTagName: makeGetElementsByTagName(''),
+ getElementsByTagName: makeGetElementsBy(''),
+ getElementsByName: makeGetElementsBy('{}'),
};
let env = getEnvironment(config, win, doc);
assert.notOk(env('CONSUL_NSPACES_ENABLED'));
@@ -179,7 +189,8 @@ module('Unit | Utility | getEnvironment', function() {
};
doc = {
cookie: 'CONSUL_NSPACES_ENABLE=0',
- getElementsByTagName: makeGetElementsByTagName(''),
+ getElementsByTagName: makeGetElementsBy(''),
+ getElementsByName: makeGetElementsBy('{}'),
};
env = getEnvironment(config, win, doc);
assert.ok(env('CONSUL_NSPACES_ENABLED'));