# Managing Multiple Environments

Many applications and use-cases call for managing multiple environments and handling common settings between them. These environments might refer to infrastructure such as `production`, `staging`, or `dev`... or perhaps it might be to handle multiple accounts or regions within an account at a service provider.

The following example outlines one possible approach to managing multiple infrastructure accounts from an application Built on Cement:

myapp.py:

    from cement.core.foundation import CementApp
    from cement.core.controller import CementBaseController, expose
    from cement.utils.misc import init_defaults

    # set default settings for our different environments
    defaults = init_defaults('myapp', 'env.production', 'env.staging', 'env.dev')
    defaults['myapp']['default_env'] = 'production'
    defaults['env.production']['foo'] = 'bar.production'
    defaults['env.staging']['foo'] = 'bar.staging'
    defaults['env.dev']['foo'] = 'bar.dev'

    # do this in a hook so that we can load the default from config
    def set_default_env(app):
        if app.pargs.env is None:
            app.pargs.env = app.config.get('myapp', 'default_env')

    class MyController(CementBaseController):
        class Meta:
            label = 'base'
            arguments = [
                (['-E', '--environment'],
                 dict(help='environment override',
                      action='store',
                      nargs='?',
                      choices=['production', 'staging', 'dev'],
                      dest='env')),
                ]

        @expose(hide=True)
        def default(self):
            print('Inside MyController.default()')

            # shorten things up a bit for clarity
            env_key = self.app.pargs.env
            env = self.app.config.get_section_dict('env.%s' % env_key)

            print('Current Environment: %s' % env_key)
            print('Foo => %s' % env['foo'])

    class MyApp(CementApp):
        class Meta:
            label = 'myapp'
            config_defaults = defaults
            base_controller = MyController

    with MyApp() as app:
        app.hook.register('post_argument_parsing', set_default_env)
        app.run()

myapp.conf

    [myapp]
    default_env = production

    [env.production]
    foo = bar.production

    [env.staging]
    foo = bar.staging

    [env.dev]
    foo = bar.dev

This looks like:

    $ python myapp.py
    Inside MyController.default()
    Current Environment: production
    Foo => bar.production

    $ python myapp.py -E staging
    Inside MyController.default()
    Current Environment: staging
    Foo => bar.staging

    $ python myapp.py -E dev
    Inside MyController.default()
    Current Environment: dev
    Foo => bar.dev

The idea being that you can maintain a single set of operations, but modify what or where those operations happen by simply toggling the configuration section (that has the same configuration settings per environment).