Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,26 @@ console.log(config);
- It is possible to change `%` to any other character. Just use `replaceEnv` configuration option.
- It is possible to use default values when environmental variable is not set.

### Docker secret replacement

/tmp/config.json:
``` javascript
{ docks1: "%{DOCKER_SECRET1}", docks2: "%{DOCKER_SECRET2|def}" }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be probably '#' instead of '%' in this example ;)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!, will correct it.

```
index.js:
``` javascript
var readConfig = require('read-config'),
config = readConfig('/tmp/config.json');

console.log(config);
// If secret file content DOCKER_SECRET1 is 'abc' and DOCKER_SECRET2 is not defined
// $ node index.js
// { docks1: 'abc', env2: 'def' }
```

- It is possible to change `#` to any other character. Just use `replaceDockerSecret` configuration option.
- It is possible to use default values when docker secret is not present.

### Configuration overriding with system variables

/tmp/config.json:
Expand Down Expand Up @@ -225,7 +245,8 @@ All json files are loaded using [JSON5](https://www.npmjs.com/package/json5) lib
- **optional** - (String/Array, default: []) list of configuration paths that are optional. If any configuration path is not resolved and is not optional it's treated as empty file and no exception is raised.
- **basedir** - (String/Array, default: []) base directory (or directories) used for searching configuration files. Mind that `basedir` has lower priority than a configuration directory, process basedir, and absolute paths.
- **replaceEnv** - (Boolean/String, default: false, constraint: A string value must be different than `replaceLocal`) if specified enables environment variable replacement. Expected string value e.g. `%` that will be used to replace all occurrences of `%{...}` with environment variables. You can use default values like: %{a.b.c|some-default-value}.
- **replaceLocal** - (Boolean/String, default: '@', constraint: A string value must be different than `replaceEnv`) if specified enables configuration variable replacement. Expected string value e.g. `@` that will be used to replace all occurrences of `@{...}` with configuration variables. You can use default values like: @{a.b.c|some-default-value}.
- **replaceDockerSecret** - (Boolean/String, default: false, constraint: A string value must be different than `replaceLocal` and `replaceEnv`) if specified enables docker secret file replacement. Expected string value e.g. `#` that will be used to replace all occurrences of `#{...}` with docker secret file content. You can use default values like: #{DOCKER_SECRET|some-default-value}.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A link to a doc explaining docker secrets would be handy

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, next revision.

- **replaceLocal** - (Boolean/String, default: '@', constraint: A string value must be different than `replaceEnv` and `replaceDockerSecret`) if specified enables configuration variable replacement. Expected string value e.g. `@` that will be used to replace all occurrences of `@{...}` with configuration variables. You can use default values like: @{a.b.c|some-default-value}.
- **override** - (Boolean/String, default: false) If specified enables configuration overriding with environmental variables like `CONFIG_<propertyName>`.
- **skipUnresolved** - (Boolean, default: false) `true` blocks error throwing on unresolved variables.

Expand All @@ -237,6 +258,7 @@ Default **opts** values:
basedir: null,
replaceEnv: "%",
replaceLocal: "@",
replaceDockerSecret: "#",
skipUnresolved: false
}
```
Expand Down
1 change: 1 addition & 0 deletions lib/read-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function defaultOptions(opts) {
basedir: '.',
replaceEnv: '%',
replaceLocal: '@',
replaceDockerSecret: '#',
skipUnresolved: false,
freeze: false
}, opts);
Expand Down
16 changes: 15 additions & 1 deletion lib/resolve/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
const replaceVariables = require('./replace-variables'),
override = require('./override'),
moduleName = '[read-config]',
ReadConfigError = require('../read-config-error');
ReadConfigError = require('../read-config-error'),
secrets = require('./secrets');

module.exports = function(config, opts) {
opts = opts || {};
config = override(opts.override, config, process.env);
config = replaceEnvVariables(config, opts.replaceEnv, opts);
config = replaceLocalVariables(config, opts.replaceLocal, opts);
config = replaceDockerSecrets(config, opts.replaceDockerSecret, opts);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test it

return config;
};

Expand All @@ -36,3 +38,15 @@ function replaceLocalVariables(config, marker, opts) {
return config;
}
}

function replaceDockerSecrets(config, marker, opts) {
if (marker) {
try {
return replaceVariables(marker, config, secrets, opts);
} catch (e) {
throw new ReadConfigError(`${moduleName} Could not resolve docker secret file. ${e.message}`);
}
} else {
return config;
}
}
19 changes: 19 additions & 0 deletions lib/resolve/secrets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const fs = require('fs'),
path = require('path'),
SECRETS_DIR = '/run/secrets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to make it more generic. Make a parameter out of this value.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is not possible, docker always search for secrets in this path.

output = {};

if (fs.existsSync(SECRETS_DIR)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to wrap it in a function. This way it would be easier to test.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working on it.

const files = fs.readdirSync(SECRETS_DIR);

files.forEach((file) => {
const fullPath = path.join(SECRETS_DIR, file),
key = file,
data = fs.readFileSync(fullPath, 'utf8').toString().trim();
output[key] = data;
});
}

module.exports = output;
Loading