Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[boot] needs to support environment based config / booting. #1609

Closed
virkt25 opened this issue Aug 15, 2018 · 1 comment
Closed

[boot] needs to support environment based config / booting. #1609

virkt25 opened this issue Aug 15, 2018 · 1 comment
Labels

Comments

@virkt25
Copy link
Contributor

virkt25 commented Aug 15, 2018

Description / Steps to reproduce / Feature proposal

From #441

We need to allow DI and Boot to support Environment Based Config. Example would be to boot config for a datasource based on the environment (dev, stage, prod, etc.). Also need support for loading production credentials from an external service / environment. If not, at the very least we need to have docs on this.

Related Discussion

#441 (comment) #4

In your proposal, the configuration (loaded from JSON) is hard-coded in the generated (base) class. At the same time, we need to support different configurations for different environments (dev/test/production) and load configuration from environment variables (https://12factor.net).

It was proposed to parse process.env variables inside datasource files. I consider that as an anti-pattern, because it couples high-level datasources with low/system-level configuration code. It makes the code difficult to test, because tests would have to manipulate global process.env. Instead, we should find a way how to inject ENV variables in such way that the actual usage of process.env stays in the top-level index.ts or application.ts file only.

On a similar topic, @raymondfeng proposed a sort of a registry holding datasource configuration for all environments in the app-level Context. I don't think this is a good solution - consider the case where an application is deployed to different geo location and where each geo location requires different connection strings (to use a colocated database instance). In other words, a production config is not a single object, but a set of location-specific objects.

My conclusion is that we should decouple datasource configuration from datasource implementation class and leverage dependency injection to provide arbitrary runtime-specific configuration from the application level. IMO, this addressed both needs 1) have different datasource config depending on dev/test/prod environment 2) build datasource configuration dynamically, either from process.env or perhaps external config providers like https://www.consul.io.

A mock-up app:

    class MyApp extends RestApplication {
      async boot() {
        const dbConfig = 
          // Figure out what config to use.  @loopback/boot can provide
          // helpers to load config from ENV variables
        this.bind('datasources.db$config').to(dbConfig);
        // etc.
      }
    }

A mock-up datasource:

    // default config is used in tests
    const defaultConfig = require('./db.datasource.json');
    
    class DbDataSource extends juggler.DataSource {
      constructor(
        @inject('datasources.db$config')
        config: DataSourceOptions = defaultConfig
      ) {
        super(config);
      }
    }

Acceptance Criteria

TBD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants