Skip to content
Extraits de code Groupes Projets
Valider 45d2bf8f rédigé par pacien's avatar pacien
Parcourir les fichiers

add config override using env variables

parent 8c09564e
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -14,6 +14,10 @@ See the License for the specific language governing permissions and ...@@ -14,6 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
const ENV_PREFIX = "APPSERVICE_DISCORD";
const ENV_KEY_SEPARATOR = "_";
const ENV_VAL_SEPARATOR = ",";
/** Type annotations for config/config.schema.yaml */ /** Type annotations for config/config.schema.yaml */
export class DiscordBridgeConfig { export class DiscordBridgeConfig {
public bridge: DiscordBridgeConfigBridge = new DiscordBridgeConfigBridge(); public bridge: DiscordBridgeConfigBridge = new DiscordBridgeConfigBridge();
...@@ -27,18 +31,48 @@ export class DiscordBridgeConfig { ...@@ -27,18 +31,48 @@ export class DiscordBridgeConfig {
/** /**
* Apply a set of keys and values over the default config. * Apply a set of keys and values over the default config.
* @param _config Config keys * @param newConfig Config keys
* @param configLayer Private parameter * @param configLayer Private parameter
*/ */
// tslint:disable-next-line no-any // tslint:disable-next-line no-any
public ApplyConfig(newConfig: {[key: string]: any}, configLayer: any = this) { public applyConfig(newConfig: {[key: string]: any}, configLayer: {[key: string]: any} = this) {
Object.keys(newConfig).forEach((key) => { Object.keys(newConfig).forEach((key) => {
if ( typeof(configLayer[key]) === "object" && if (configLayer[key] instanceof Object && !(configLayer[key] instanceof Array)) {
!Array.isArray(configLayer[key])) { this.applyConfig(newConfig[key], configLayer[key]);
this.ApplyConfig(newConfig[key], this[key]); } else {
return; configLayer[key] = newConfig[key];
}
});
}
/**
* Override configuration keys defined in the supplied environment dictionary.
* @param environment environment variable dictionary
* @param path private parameter: config layer path determining the environment key prefix
* @param configLayer private parameter: current layer of configuration to alter recursively
*/
public applyEnvironmentOverrides(
// tslint:disable-next-line no-any
environment: {[key: string]: any},
path: string[] = [ENV_PREFIX],
// tslint:disable-next-line no-any
configLayer: {[key: string]: any} = this,
) {
Object.keys(configLayer).forEach((key) => {
// camelCase to THICK_SNAKE
const attributeKey = key.replace(/[A-Z]/g, (prefix) => `${ENV_KEY_SEPARATOR}${prefix}`).toUpperCase();
const attributePath = path.concat([attributeKey]);
if (configLayer[key] instanceof Object && !(configLayer[key] instanceof Array)) {
this.applyEnvironmentOverrides(environment, attributePath, configLayer[key]);
} else {
const lookupKey = attributePath.join(ENV_KEY_SEPARATOR);
if (lookupKey in environment) {
configLayer[key] = (configLayer[key] instanceof Array)
? environment[lookupKey].split(ENV_VAL_SEPARATOR)
: environment[lookupKey];
}
} }
configLayer[key] = newConfig[key];
}); });
} }
} }
......
...@@ -59,7 +59,8 @@ type callbackFn = (...args: any[]) => Promise<any>; ...@@ -59,7 +59,8 @@ type callbackFn = (...args: any[]) => Promise<any>;
async function run(port: number, fileConfig: DiscordBridgeConfig) { async function run(port: number, fileConfig: DiscordBridgeConfig) {
const config = new DiscordBridgeConfig(); const config = new DiscordBridgeConfig();
config.ApplyConfig(fileConfig); config.applyConfig(fileConfig);
config.applyEnvironmentOverrides(process.env);
Log.Configure(config.logging); Log.Configure(config.logging);
log.info("Starting Discord AS"); log.info("Starting Discord AS");
const yamlConfig = yaml.safeLoad(fs.readFileSync(cli.opts.registrationPath, "utf8")); const yamlConfig = yaml.safeLoad(fs.readFileSync(cli.opts.registrationPath, "utf8"));
......
...@@ -22,10 +22,10 @@ import { DiscordBridgeConfig } from "../src/config"; ...@@ -22,10 +22,10 @@ import { DiscordBridgeConfig } from "../src/config";
const expect = Chai.expect; const expect = Chai.expect;
describe("DiscordBridgeConfig.ApplyConfig", () => { describe("DiscordBridgeConfig.applyConfig", () => {
it("should merge configs correctly", () => { it("should merge configs correctly", () => {
const config = new DiscordBridgeConfig(); const config = new DiscordBridgeConfig();
config.ApplyConfig({ config.applyConfig({
bridge: { bridge: {
disableDeletionForwarding: true, disableDeletionForwarding: true,
disableDiscordMentions: false, disableDiscordMentions: false,
...@@ -46,9 +46,32 @@ describe("DiscordBridgeConfig.ApplyConfig", () => { ...@@ -46,9 +46,32 @@ describe("DiscordBridgeConfig.ApplyConfig", () => {
expect(config.bridge.disableJoinLeaveNotifications).to.be.true; expect(config.bridge.disableJoinLeaveNotifications).to.be.true;
expect(config.logging.console).to.equal("warn"); expect(config.logging.console).to.equal("warn");
}); });
it("should merge environment overrides correctly", () => {
const config = new DiscordBridgeConfig();
config.applyConfig({
bridge: {
disableDeletionForwarding: true,
disableDiscordMentions: false,
homeserverUrl: "blah",
},
logging: {
console: "warn",
},
});
config.applyEnvironmentOverrides({
APPSERVICE_DISCORD_BRIDGE_DISABLE_DELETION_FORWARDING: false,
APPSERVICE_DISCORD_BRIDGE_DISABLE_JOIN_LEAVE_NOTIFICATIONS: true,
APPSERVICE_DISCORD_LOGGING_CONSOLE: "debug",
});
expect(config.bridge.disableJoinLeaveNotifications).to.be.true;
expect(config.bridge.disableDeletionForwarding).to.be.false;
expect(config.bridge.disableDiscordMentions).to.be.false;
expect(config.bridge.homeserverUrl).to.equal("blah");
expect(config.logging.console).to.equal("debug");
});
it("should merge logging.files correctly", () => { it("should merge logging.files correctly", () => {
const config = new DiscordBridgeConfig(); const config = new DiscordBridgeConfig();
config.ApplyConfig({ config.applyConfig({
logging: { logging: {
console: "silent", console: "silent",
files: [ files: [
......
...@@ -67,7 +67,8 @@ if (options.help) { ...@@ -67,7 +67,8 @@ if (options.help) {
const yamlConfig = yaml.safeLoad(fs.readFileSync("./discord-registration.yaml", "utf8")); const yamlConfig = yaml.safeLoad(fs.readFileSync("./discord-registration.yaml", "utf8"));
const registration = AppServiceRegistration.fromObject(yamlConfig); const registration = AppServiceRegistration.fromObject(yamlConfig);
const config = new DiscordBridgeConfig(); const config = new DiscordBridgeConfig();
config.ApplyConfig(yaml.safeLoad(fs.readFileSync(options.config, "utf8")) as DiscordBridgeConfig); config.applyConfig(yaml.safeLoad(fs.readFileSync(options.config, "utf8")) as DiscordBridgeConfig);
config.applyEnvironmentOverrides(process.env);
if (registration === null) { if (registration === null) {
throw new Error("Failed to parse registration file"); throw new Error("Failed to parse registration file");
......
...@@ -76,7 +76,8 @@ if (options.help) { ...@@ -76,7 +76,8 @@ if (options.help) {
const yamlConfig = yaml.safeLoad(fs.readFileSync("./discord-registration.yaml", "utf8")); const yamlConfig = yaml.safeLoad(fs.readFileSync("./discord-registration.yaml", "utf8"));
const registration = AppServiceRegistration.fromObject(yamlConfig); const registration = AppServiceRegistration.fromObject(yamlConfig);
const config = new DiscordBridgeConfig(); const config = new DiscordBridgeConfig();
config.ApplyConfig(yaml.safeLoad(fs.readFileSync(options.config, "utf8")) as DiscordBridgeConfig); config.applyConfig(yaml.safeLoad(fs.readFileSync(options.config, "utf8")) as DiscordBridgeConfig);
config.applyEnvironmentOverrides(process.env);
if (registration === null) { if (registration === null) {
throw new Error("Failed to parse registration file"); throw new Error("Failed to parse registration file");
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter