17

I want to have several yaml files for DropWizard. One of them contain sensitive info and one non sensitive.

Can you point me to any docs or example how to have multiple configurations in DropWizard?

Victor Ronin
  • 21,310
  • 16
  • 85
  • 171

3 Answers3

10

ConfigurationSourceProvider is your answer.

bootstrap.setConfigurationSourceProvider(new MyMultipleConfigurationSourceProvider());

The following is how dropwizard does it by default. You can easily change it to your own liking.

public class FileConfigurationSourceProvider implements ConfigurationSourceProvider {
    @Override
    public InputStream open(String path) throws IOException {
        final File file = new File(path);
        if (!file.exists()) {
            throw new FileNotFoundException("File " + file + " not found");
        }

        return new FileInputStream(file);
    }
}
Natan
  • 2,620
  • 14
  • 29
  • What would `MyMultipleConfigurationSourceProvider` look like ? I have no clear picture of how it could provide data from several files. Would you mind explaining ? – Vic Seedoubleyew Jun 27 '17 at 19:19
  • I suppose that would be reading two files (either hardcoded or `|` separated files coming from the `path` parameter), merging them together into an `InputStream` and returning that. – Natan Jun 28 '17 at 07:35
  • Thanks for the swift reply ! If I understand correctly, this would have significant implications, wouldn't it ? For example, fields that were at the root of each file will end up at the root of the "main reconstructed" file, potentially with collisions. – Vic Seedoubleyew Jun 29 '17 at 14:30
  • yes, if arbitrary yaml files are expected, it may be a dangerous thing to do. I suppose in case of collisions, the yaml parser's rules would be applied, which may be throwing exception or taking the first/last occurrence. In this scenario, ideally, the files would have separate responsibilities; i.e. one file for database, one file for server config, another for custom config fields etc.. And that should be somehow enforced or documented well. – Natan Jun 29 '17 at 19:22
5

Ideally you should be configuring your app by putting your sensitive information or configurable data inside Environment Variables, rather than managing multiple files. See twelve factor rule on config: http://12factor.net/config

To enable this approach in Dropwizard, you can either override your config with Environment Variables at run time using the -Ddw flag:

java -Ddw.http.port=$PORT -jar yourapp.jar server yourconfig.yml

or you can use this handy add on: https://github.com/tkrille/dropwizard-template-config to put Environment Variable placeholders inside your config:

server:
  type: simple
  connector:
    type: http
    # replacing environment variables
    port: ${env.PORT}

Both of the above solutions are compatible with Heroku and Docker containers, where the Environment Variable are only available when you run the app.

yunspace
  • 2,242
  • 17
  • 19
  • 1
    Do not like. Where do you maintain your env vars? I mean, what script is setting them? Maybe you'll have a bash script which starts the app, and first sets all the env vars. Now you need multiple scripts, one for each environment (dev, qa, stage, prod, etc), where each script has a different set of env vars. These scripts need to be revision controlled. But now these scripts are just configuration files. At that point, why not just have a file with only the variables (a properties file, or yaml, or json, whatever), and read those in and skip the env var step? – Paul Rademacher May 02 '15 at 21:14
  • Yes the env vars needs to be set, but not for every single deploy, just as you shouldn't need spin up entire environment with every single deploy. You can use scripts, or there are configuration tools – yunspace May 03 '15 at 23:29
  • 2
    ...such as Pupplet, Chef, Ansible etc. Ultimately the idea is you separate your Dev concerns from Ops, so that credentials are not checked into source code, security can be independently audited and that environment changes can be done at a infrastructure level instead of digging into each source code config files. Having shared variable files can also work but how is that better? It means your config need code to read in variables in every service, where as DW config supports Env Var out of box. Also Env Vars works with Continuous Delivery of immutable containers such as Docker/Heroku – yunspace May 04 '15 at 00:12
  • 2
    For applications with large amounts of configuration that change per environment then system vars would be a nightmare. – Ben George Feb 08 '16 at 00:00
  • Large amount of file-based configurations would be equally nightmarish. As I said the point is to separate dev from infrastructure ops and the 12-factor approach is a good candidate. Remember this question is about Dropwizard, which tends to be a minimal, self-contained microservice, not a monolith app requiring config management tools and full time configurators – yunspace Feb 11 '16 at 23:47
4

Firstly, you will write another yml file path in a .yml.

sample.yml

configPath: /another.yml

another.yml

greet: Hello!

and you will be solved by simply using the SnakeYaml.

public void run(SampleConfiguration configuration, Environment environment) {
    Yaml yaml = new Yaml();
    InputStream in = getClass().getResourceAsStream(configuration.getConfigPath());
    AnotherConfig anotherConfig = yaml.loadAs(in, AnotherConfig.class);
    String str = anotherConfig.getGreet(); // Hello!
...
}

For sensitive information, I think it is good to use the environment variable.

For example, use dropwizard-environment-config
https://github.com/tkrille/dropwizard-environment-config

Nishant Kelkar
  • 292
  • 3
  • 18
ko2ic
  • 1,499
  • 11
  • 19
  • 1
    This will work only for custom configurations. But if they want to have let's say `server` configuration that will affect dropwizard itself, then it won't work. For example one might want to obfuscate the private key password of the https certificate. – Natan Mar 15 '15 at 11:58