Configuration service

The configuration service provides authorized publication and consumption of identified configuration data with metadata. The service supports bootstrapping.

A pluggable Ruby API is provided in ConfigurationService::Base.

The declarative specification of the service is implemented with cucumber, using a pluggable imperative orchestration providers. This allows for implementations that are not providers to the Ruby API. See ConfigurationService::Test.

A stub service provider is provided in ConfigurationService::Provider::Stub. This is used to validate the test framework architecture, and may be used as a stub configuration service in tests. Other providers are available as gems.

Service providers are registered against the ConfigurationService::ProviderRegistry.

Factories for creating and configuring service instances are provided in ConfigurationService::Factory.

Usage

The recommended approach to creating a configuration service client is to use a Factory.

For example, we can use the EnvironmentContext factory to create and configure a configuration service client backed by the vault provider as follows.

Our main.rb (or config.ru or whatever) is simple:

require 'bundler'
Bundler.require(:default)

service = ConfigurationService::Factory::EnvironmentContext.create
configuraton = service.request_configuration
AcmeApplication.new(configuration.data).run

This relies on a / bundler Gemfile to load the gem that contains whatever service provider we configure in the environment:

source 'https://rubygems.org'

gem 'configuration_service-provider-vault'
gem 'acme_application'

Now we use the process environment to configure the EnvironmentContext factory:

CFGSRV_IDENTIFIER="acme" \
CFGSRV_TOKEN="0b2a80f4-54ce-45f4-8267-f6558fee64af" \
CFGSRV_PROVIDER="vault" \
CFGSRV_PROVIDER_ADDRESS="http://127.0.0.1:8200" \
bundle exec main.rb

Note that main.rb is completely decoupled from the selection of provider and provider configuration. We could swap and/or reconfigure the provider by manipulating only the Gemfile and the environment.

If you prefer to hard-code everything, or if your strategy for bootstrapping the configuration service isn’t expressed by an existing factory yet, you can construct the service yourself:

# Bad example (hardcoding token into source):

require 'configuration_service/provider/vault'
require 'acme_application'

service = ConfigurationService.new(
  "acme",
  "0b2a80f4-54ce-45f4-8267-f6558fee64af",
  ConfigurationService::Provider::Vault.new(
    address: "http://127.0.0.1:8200"
  )
)
configuraton = service.request_configuration
AcmeApplication.new(configuration.data).run