mirror of https://github.com/hashicorp/consul
ui: Improve configuration/env/feature flag usage (also add build time year detection) (#7072)
* Add new getEnvironment util/function * Use new-ish `env` function in all the places * Clean up ember env file, add year detection from commit datepull/7099/head
parent
ac613993bb
commit
a65d941e76
@ -1,61 +1,3 @@
|
||||
import _config from './config/environment';
|
||||
const doc = document;
|
||||
const getDevEnvVars = function() {
|
||||
return doc.cookie
|
||||
.split(';')
|
||||
.filter(item => item !== '')
|
||||
.map(item => item.trim().split('='));
|
||||
};
|
||||
const getUserEnvVar = function(str) {
|
||||
return window.localStorage.getItem(str);
|
||||
};
|
||||
// TODO: Look at `services/client` for pulling
|
||||
// HTTP headers in here so we can let things be controlled
|
||||
// via HTTP proxies, for example turning off blocking
|
||||
// queries if its a busy cluster
|
||||
// const getOperatorEnvVars = function() {}
|
||||
|
||||
// TODO: Not necessarily here but the entire app should
|
||||
// use the `env` export not the `default` one
|
||||
// but we might also change the name of this file, so wait for that first
|
||||
export const env = function(str) {
|
||||
let user = null;
|
||||
switch (str) {
|
||||
case 'CONSUL_UI_DISABLE_REALTIME':
|
||||
case 'CONSUL_UI_DISABLE_ANCHOR_SELECTION':
|
||||
case 'CONSUL_UI_REALTIME_RUNNER':
|
||||
user = getUserEnvVar(str);
|
||||
break;
|
||||
}
|
||||
// We use null here instead of an undefined check
|
||||
// as localStorage will return null if not set
|
||||
return user !== null ? user : _config[str];
|
||||
};
|
||||
export const config = function(key) {
|
||||
let $;
|
||||
switch (_config.environment) {
|
||||
case 'development':
|
||||
case 'staging':
|
||||
case 'test':
|
||||
$ = getDevEnvVars().reduce(function(prev, [key, value]) {
|
||||
const val = !!JSON.parse(String(value).toLowerCase());
|
||||
switch (key) {
|
||||
case 'CONSUL_ACLS_ENABLE':
|
||||
prev['CONSUL_ACLS_ENABLED'] = val;
|
||||
break;
|
||||
case 'CONSUL_NSPACES_ENABLE':
|
||||
prev['CONSUL_NSPACES_ENABLED'] = val;
|
||||
break;
|
||||
default:
|
||||
prev[key] = value;
|
||||
}
|
||||
return prev;
|
||||
}, {});
|
||||
if (typeof $[key] !== 'undefined') {
|
||||
return $[key];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return _config[key];
|
||||
};
|
||||
export default env;
|
||||
import config from './config/environment';
|
||||
import getEnvironment from './utils/get-environment';
|
||||
export const env = getEnvironment(config, window, document);
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { helper } from '@ember/component/helper';
|
||||
import { config } from 'consul-ui/env';
|
||||
// TODO: env actually uses config values not env values
|
||||
// see `app/env` for the renaming TODO's also
|
||||
export function env([name, def = ''], hash) {
|
||||
return config(name) != null ? config(name) : def;
|
||||
}
|
||||
|
||||
export default helper(env);
|
||||
import { env } from 'consul-ui/env';
|
||||
export default helper(function([name, def = ''], hash) {
|
||||
const val = env(name);
|
||||
return val != null ? val : def;
|
||||
});
|
||||
|
@ -1,15 +0,0 @@
|
||||
const scripts = document.getElementsByTagName('script');
|
||||
const current = scripts[scripts.length - 1];
|
||||
|
||||
export function initialize(application) {
|
||||
const Client = application.resolveRegistration('service:client/http');
|
||||
Client.reopen({
|
||||
isCurrent: function(src) {
|
||||
return current.src === src;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
initialize,
|
||||
};
|
@ -0,0 +1,100 @@
|
||||
export default function(config = {}, win = window, doc = document) {
|
||||
const dev = function() {
|
||||
return doc.cookie
|
||||
.split(';')
|
||||
.filter(item => item !== '')
|
||||
.map(item => item.trim().split('='));
|
||||
};
|
||||
const user = function(str) {
|
||||
const item = win.localStorage.getItem(str);
|
||||
return item === null ? undefined : item;
|
||||
};
|
||||
const getCurrentResource = function(scripts) {
|
||||
const current = scripts[scripts.length - 1];
|
||||
try {
|
||||
return win.performance.getEntriesByType('resource').find(item => {
|
||||
// current is based on the assumption that whereever this script is it's
|
||||
// likely to be the same as the xmlhttprequests
|
||||
return item.initiatorType === 'script' && current.src === item.name;
|
||||
});
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
const resource = getCurrentResource(doc.getElementsByTagName('script'));
|
||||
|
||||
// TODO: Look to see if we can pull in HTTP headers here
|
||||
// so we can let things be controlled via HTTP proxies, for example
|
||||
// turning off blocking queries if its a busy cluster etc
|
||||
const operator = function(str, env) {
|
||||
let protocol;
|
||||
switch (str) {
|
||||
case 'CONSUL_HTTP_PROTOCOL':
|
||||
return resource.nextHopProtocol || 'http/1.1';
|
||||
case 'CONSUL_HTTP_MAX_CONNECTIONS':
|
||||
protocol = env('CONSUL_HTTP_PROTOCOL');
|
||||
// http/2, http2+QUIC/39 and SPDY don't have connection limits
|
||||
switch (true) {
|
||||
case protocol.indexOf('h2') === 0:
|
||||
case protocol.indexOf('hq') === 0:
|
||||
case protocol.indexOf('spdy') === 0:
|
||||
// TODO: Change this to return -1 so we try to consistently
|
||||
// return a value from env vars
|
||||
return;
|
||||
default:
|
||||
// generally 6 are available
|
||||
// reserve 1 for traffic that we can't manage
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
};
|
||||
const ui = function(key) {
|
||||
let $;
|
||||
switch (config.environment) {
|
||||
case 'development':
|
||||
case 'staging':
|
||||
case 'coverage':
|
||||
case 'test':
|
||||
$ = dev().reduce(function(prev, [key, value]) {
|
||||
switch (key) {
|
||||
case 'CONSUL_ACLS_ENABLE':
|
||||
prev['CONSUL_ACLS_ENABLED'] = !!JSON.parse(String(value).toLowerCase());
|
||||
break;
|
||||
case 'CONSUL_NSPACES_ENABLE':
|
||||
prev['CONSUL_NSPACES_ENABLED'] = !!JSON.parse(String(value).toLowerCase());
|
||||
break;
|
||||
default:
|
||||
prev[key] = value;
|
||||
}
|
||||
return prev;
|
||||
}, {});
|
||||
if (typeof $[key] !== 'undefined') {
|
||||
return $[key];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return config[key];
|
||||
};
|
||||
return function env(str) {
|
||||
switch (str) {
|
||||
// All user providable values should start with CONSUL_UI
|
||||
// We allow the user to set these ones via localStorage
|
||||
// user value is preferred.
|
||||
case 'CONSUL_UI_DISABLE_REALTIME':
|
||||
case 'CONSUL_UI_DISABLE_ANCHOR_SELECTION':
|
||||
// these are booleans cast things out
|
||||
return !!JSON.parse(String(user(str) || 0).toLowerCase()) || ui(str);
|
||||
case 'CONSUL_UI_REALTIME_RUNNER':
|
||||
// these are strings
|
||||
return user(str) || ui(str);
|
||||
|
||||
case 'CONSUL_HTTP_PROTOCOL':
|
||||
case 'CONSUL_HTTP_MAX_CONNECTIONS':
|
||||
// We allow the operator to set these ones via various methods
|
||||
// although UI developer config is preferred
|
||||
return ui(str) || operator(str, env);
|
||||
default:
|
||||
return ui(str);
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
import getEnvironment from 'consul-ui/utils/get-environment';
|
||||
import { module, test } from 'qunit';
|
||||
const getEntriesByType = function(type) {
|
||||
return [
|
||||
{
|
||||
initiatorType: 'script',
|
||||
name: '',
|
||||
nextHopProtocol: 'spdy',
|
||||
},
|
||||
];
|
||||
};
|
||||
const getElementsByTagName = function(name) {
|
||||
return [
|
||||
{
|
||||
src: '',
|
||||
},
|
||||
];
|
||||
};
|
||||
const win = {
|
||||
performance: {
|
||||
getEntriesByType: getEntriesByType,
|
||||
},
|
||||
localStorage: {
|
||||
getItem: function(key) {},
|
||||
},
|
||||
};
|
||||
const doc = {
|
||||
cookie: '',
|
||||
getElementsByTagName: getElementsByTagName,
|
||||
};
|
||||
module('Unit | Utility | getEnvironment', function() {
|
||||
test('it returns a function', function(assert) {
|
||||
const config = {};
|
||||
const env = getEnvironment(config, win, doc);
|
||||
assert.ok(typeof env === 'function');
|
||||
});
|
||||
test('it returns the correct operator value', function(assert) {
|
||||
const config = {};
|
||||
const env = getEnvironment(config, win, doc);
|
||||
assert.equal(env('CONSUL_HTTP_PROTOCOL'), 'spdy');
|
||||
});
|
||||
test('it returns the correct operator value when set via config', function(assert) {
|
||||
const config = {
|
||||
CONSUL_HTTP_PROTOCOL: 'hq',
|
||||
};
|
||||
const env = getEnvironment(config, win, doc);
|
||||
assert.equal(env('CONSUL_HTTP_PROTOCOL'), 'hq');
|
||||
});
|
||||
test('it returns the correct max connections depending on protocol', function(assert) {
|
||||
let config = {
|
||||
CONSUL_HTTP_PROTOCOL: 'hq',
|
||||
};
|
||||
let env = getEnvironment(config, win, doc);
|
||||
assert.equal(env('CONSUL_HTTP_MAX_CONNECTIONS'), undefined);
|
||||
config = {
|
||||
CONSUL_HTTP_PROTOCOL: 'http/1.1',
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.equal(env('CONSUL_HTTP_MAX_CONNECTIONS'), 5);
|
||||
});
|
||||
test('it returns the correct max connections if performance.getEntriesByType is not available', function(assert) {
|
||||
const config = {};
|
||||
let win = {};
|
||||
let env = getEnvironment(config, win, doc);
|
||||
assert.equal(env('CONSUL_HTTP_MAX_CONNECTIONS'), 5);
|
||||
win = {
|
||||
performance: {},
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.equal(env('CONSUL_HTTP_MAX_CONNECTIONS'), 5);
|
||||
});
|
||||
test('it returns the correct user value', function(assert) {
|
||||
const config = {};
|
||||
let win = {
|
||||
localStorage: {
|
||||
getItem: function(key) {
|
||||
return '1';
|
||||
},
|
||||
},
|
||||
};
|
||||
let env = getEnvironment(config, win, doc);
|
||||
assert.ok(env('CONSUL_UI_DISABLE_REALTIME'));
|
||||
win = {
|
||||
localStorage: {
|
||||
getItem: function(key) {
|
||||
return '0';
|
||||
},
|
||||
},
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.notOk(env('CONSUL_UI_DISABLE_REALTIME'));
|
||||
win = {
|
||||
localStorage: {
|
||||
getItem: function(key) {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.notOk(env('CONSUL_UI_DISABLE_REALTIME'));
|
||||
});
|
||||
test('it returns the correct user value when set via config', function(assert) {
|
||||
const config = {
|
||||
CONSUL_UI_DISABLE_REALTIME: true,
|
||||
};
|
||||
const env = getEnvironment(config, win, doc);
|
||||
assert.ok(env('CONSUL_UI_DISABLE_REALTIME'));
|
||||
});
|
||||
test('it returns the correct dev value (via cookies)', function(assert) {
|
||||
let config = {
|
||||
environment: 'test',
|
||||
CONSUL_NSPACES_ENABLED: false,
|
||||
};
|
||||
let doc = {
|
||||
cookie: 'CONSUL_NSPACES_ENABLE=1',
|
||||
getElementsByTagName: getElementsByTagName,
|
||||
};
|
||||
let env = getEnvironment(config, win, doc);
|
||||
assert.ok(env('CONSUL_NSPACES_ENABLED'));
|
||||
config = {
|
||||
environment: 'test',
|
||||
CONSUL_NSPACES_ENABLED: true,
|
||||
};
|
||||
doc = {
|
||||
cookie: 'CONSUL_NSPACES_ENABLE=0',
|
||||
getElementsByTagName: getElementsByTagName,
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.notOk(env('CONSUL_NSPACES_ENABLED'));
|
||||
});
|
||||
test('it returns the correct dev value when set via config', function(assert) {
|
||||
let config = {
|
||||
CONSUL_NSPACES_ENABLED: true,
|
||||
};
|
||||
let env = getEnvironment(config, win, doc);
|
||||
assert.ok(env('CONSUL_NSPACES_ENABLED'));
|
||||
config = {
|
||||
CONSUL_NSPACES_ENABLED: false,
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.notOk(env('CONSUL_NSPACES_ENABLED'));
|
||||
});
|
||||
test("it returns the correct dev value (ignoring cookies when the environment doesn't allow it)", function(assert) {
|
||||
let config = {
|
||||
environment: 'production',
|
||||
CONSUL_NSPACES_ENABLED: false,
|
||||
};
|
||||
let doc = {
|
||||
cookie: 'CONSUL_NSPACES_ENABLE=1',
|
||||
getElementsByTagName: getElementsByTagName,
|
||||
};
|
||||
let env = getEnvironment(config, win, doc);
|
||||
assert.notOk(env('CONSUL_NSPACES_ENABLED'));
|
||||
config = {
|
||||
environment: 'production',
|
||||
CONSUL_NSPACES_ENABLED: true,
|
||||
};
|
||||
doc = {
|
||||
cookie: 'CONSUL_NSPACES_ENABLE=0',
|
||||
getElementsByTagName: getElementsByTagName,
|
||||
};
|
||||
env = getEnvironment(config, win, doc);
|
||||
assert.ok(env('CONSUL_NSPACES_ENABLED'));
|
||||
});
|
||||
});
|
Loading…
Reference in new issue