Granular config

Because we don't just have dev and prod.

@MrDanack

Press 'c' to toggle code style
Press 's' for speaker notes

In the beginning, there was dev


$dev = [
    'user.authentication_service' => 'spoof',
    'logging.targets' => ['on_screen', 'local_file'],
    'cdn.service' => false,
    'payment.gateway' => 'spoof'
    // 30 more lines here, but they
    // don't fit on the screen.
];

Oh, you want this code deployed somewhere


$live = [
    'user.authentication_service' => 'standard',
    'logging.targets' => ['sas_loggly'],
    'cdn.service' => 'fastly',
    'payment.gateway' => 'sagepay'
];


Stop breaking live pls


$staging = [
    'user.authentication_service' => 'standard',
    'logging.targets' => ['local_file'],
    'cdn.service' => false, // changed
    'payment.gateway' => 'standard'
];

Unit tests are a thing


$ci = [
    'user.authentication_service' => 'spoof',
    'logging.targets' => ['null'], // changed
    'cdn.service' => false,
    'payment.gateway' => 'standard',
    'user_data.service' => 'spoof',
    'repository_type' => 'in_memory', // changed
];

Users....

UX people wanted to be able to change stuff


$ux_research = [
    'user.authentication_service' => 'spoof',
    'logging.targets' => ['on_screen', 'local_file'],
    'cdn.service' => false,
    'payment.gateway' => 'spoof',
    'feature.signup.ui' => 'ui_2016_09',  // changed
    'user_data.service' => 'standard'
];

South west trains

Remote workers can't access internal services


$remote_dev = [
    'user.authentication_service' => 'spoof',
    'logging.targets' => ['on_screen', 'local_file'],
    'cdn.service' => false,
    'payment.gateway' => 'spoof',
    'feature.signup.ui' => 'standard',
    'user_data.service' => 'spoof' // changed
];

Server outage after cleaner unplugged 'the rack'

Deploying to different host


$live_aws = [
    ...
    'logging.targets' => ['s3_logging'],
    'cdn.service' => 'cloudfront',
    'file_storage.service' => 's3',
    ...
];

Seven different configs. All unique.

dev + remote + ux_research + test + staging + live_cupboard + live_aws

\o/

Seven different configs. All unique.

Ծ_Ծ

Problems

  • Need to change settings in multiple places.
  • No record of whether changes are deliberate or not.
  • Can't see easily how one environment is different to another.
  • Setting up a new environment is non-trivial.

Solution - granular config blocks

Shameless self-promotion alert

github.com/danack/configurator

Default block gets applied to everything


$default = [
    'user.authentication_service' => 'standard_auth_service',
    'cdn.service' => 'fastly',
];

Each environment sets only the bits it cares about



$remote = [
    'user.authentication_service' => 'spoof',
];
      
$dev = [
    'cdn.service' => false,
];

$ux_research = [
    'feature.signup.ui' => 'ui_2016_09',
];
    

Magic happens


  • Instead of just choosing "dev"
  • The configurator allows people to say they want the "dev,remote,ux_research" environment.
  • Which means apply the "dev", "remote", "ux_research" settings in that order.

"dev,remote,ux_research"



  $settings = array_merge([], $dev);
  $settings = array_merge($settings, $remote);
  $settings = array_merge($settings, $ux_research);

  return $settings;


Benefits

  • Most of the time, only need to edit a setting in one place, so less chance to forget.
  • Reading what is special for a particular environment becomes trivial.
  • Adding a new specific environment becomes trivial.
  • Can combine configs together for huge number of variation.

Brucie bonus - storing config in code is awesome.


<?php

use AwesomeApp\Config;

$default[
    // This is a class constant - very hard to miespeel
    Config::SCRIPT_VERSION => date('jmyhis'),
    // Oh, also, functions are a thing.

    // Can generate absolute paths
    Config::TEMPLATE_CACHE_DIR => 
            realpath(__DIR__)."/var/cache/template",
];



<?php
// Using variables....
$siteName = 'awesomeapp.com';

//And string concantenation...ah yissss
$dev = [
    Config::LIBRATO_STATS_NAME => 'dev.'.$siteName
];

$staging = [
    Config::LIBRATO_STATS_NAME => 'staging.'.$siteName
];

$live = [
    Config::LIBRATO_STATS_NAME => 'live.'.$siteName
];

Fin

github.com/danack/configurator

Granular config for apps.

Gone are the days where the only environments you had are dev and prod. These days you have many more environments and need a way of managing config that scales.

In this talk, I wibble on about how why you should build your config from granular parts, rather than monolithic blocks, so that you can scale your config to support environments for UX testing, people working remotely, unit-testing, etc etc without going insane.

“For years there has been a theory that millions of monkeys typing at random on millions of typewriters would reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.”