Configurations

Configurations allow to change microservice behavior, adjust to deployment environments, and set parameters to connect to infrastructure services and other microservices. For this, the Pip.Services toolkit provides a set of patterns that support design-time, deployment-time, and runtime configurations.

Design-time Configuration

This is the simplest type of configuration. It is initially defined by developers in their code and later used to set components by calling the configure method in components that implement the IConfigurable interface.

let config = ConfigParams.fromTuples(
  'param1', 'XYZ',
  'param2', 345
);
component.configure(config);

/// Also, often components can have hard-coded presets. 
/// The ConfigParams class has methods that allow to easily use them as defaults:

class MyComponent implements IConfigurable {
  private _param1: string = 'ABC';
  private _param2: number = 123;

  public configure(config: ConfigParams) {
    this._param1 = config.getAsStringWithDefault('param1', this._param1);
    this._param2 = config.getAsIntegerWithDefault('param2', this._param2);
  }
}

var config = ConfigParams.FromTuples(
    "param1", "XYZ",
    "param2", 345
);

component.Configure(config);

/// Also, often components can have hard-coded presets. 
/// The ConfigParams class has methods that allow to easily use them as defaults:

class MyComponent : IConfigurable
{
    private string _param1 = "ABC";
    private int _param2 = 123;

    public void Configure(ConfigParams config)
    {
        this._param1 = config.GetAsStringWithDefault("param1", _param1);
        this._param2 = config.GetAsIntegerWithDefault("param2", _param2);
    }
}

import (
	cconf "github.com/pip-services3-gox/pip-services3-commons-gox/config"
)


config := cconf.NewConfigParamsFromTuples(
	"param1", "XYZ",
	"param2", 345,
)

component.Configure(context.Background(), config)

/// Also, often components can have hard-coded presets. 
/// The ConfigParams class has methods that allow to easily use them as defaults:
  
type MyComponent struct { // Implements IConfigurable
 param1 string 
 param2 int
}

func NewMyComponent() MyComponent {
  return MyComponent{
	  param1: "ABC",
	  param2: 123,
  }
}

func (c* MyComponent) Configure(ctx context.Context, config *cconf.ConfigParams) {
  c.param1 = config.GetAsStringWithDefault("param1", c.param1)
  c.param2 = config.GetAsIntegerWithDefault("param2", c.param2)
}
  

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var config = ConfigParams.fromTuples(['param1', 'XYZ', 'param2', 345]);

  component.configure(config);
}

/// Also, often components can have hard-coded presets. 
/// The ConfigParams class has methods that allow to easily use them as defaults:

class MyComponent implements IConfigurable {
  String _param1 = 'ABC';
  int _param2 = 123;

  @override
  void configure(ConfigParams config) {
    _param1 = config.getAsStringWithDefault('param1', _param1);
    _param2 = config.getAsIntegerWithDefault('param2', _param2);
  }
}

config = ConfigParams.from_tuples(
  'param1', 'XYZ',
  'param2', 345
)

component.configure(config)

# Also, often components can have hard-coded presets. 
# The ConfigParams class has methods that allow to easily use them as defaults:

from pip_services3_commons.config import ConfigParams, IConfigurable


class MyComponent(IConfigurable):
    _param1: str = 'ABC'
    _param2: int = 123

    def configure(self, config: ConfigParams):
        self._param1 = config.get_as_string_with_default('param1', self._param1)
        self._param2 = config.get_as_integer_with_default('param2', self._param2)

Not available

Deployment-time Configuration

Deployment-time configuration parameters are set via environment variables or passed to a container via command-line arguments:

export MYCOMPONENT_ENABLED=true
export PARAM1=XYZ
node ./bin/main.js -p PARAM2=345
export MYCOMPONENT_ENABLED=true
export PARAM1=XYZ
dotnet ./bin/main.dll -p PARAM2=345
export MYCOMPONENT_ENABLED=true
export PARAM1=XYZ
go run ./bin/main.go -p PARAM2=345
export MYCOMPONENT_ENABLED=true
export PARAM1=XYZ
dart run ./bin/main.dart -p PARAM2=345
export MYCOMPONENT_ENABLED=true
export PARAM1=XYZ
python ./bin/main.py -p PARAM2=345
Not available

Then those parameters are automatically injected into container configurations using Mustache templates:

{{#if MYCOMPONENT_ENABLED}}
descriptor: myservice:mycomponent:default:default:1.0
param1: {{PARAM1}}
param2: {{PARAM2}}
{{/if}}

The deployment-time parameters can change the composition of the microservice by including or excluding parameters or their configuration blocks, or setting specific parameters values that are passed to already known configure methods in components that implement the IConfigurable interface.

Runtime Configuration

Runtime configurations are typically stored in specialized services like etcd or special microservices. The Pip.Services toolkit has a standard IConfigReader interface that can be implemented by components that retrieve configurations from various sources. In this manner, they can pull configurations by calling the readConfig method or get notified when configurations change via the addChangeListener method.

The Pip.Services toolkit offers a few standard configuration readers:

  • MemoryConfigReader: Stores a configuration in memory.
  • FileConfigReader: Reads a configuration from a file.
  • JsonConfigReader
  • YamlConfigReader

References

For more information about configurations see: