Continuous Delivery

Continuous Integration (CI) is a critical prerequisite of production-like stand-up/tear-down, i.e. if it can’t be build on the engineers machine, it can’t be deployed from the engineers machine.

Configuration Management and Automated Deployment

Configuration Management

CDAF origin was to ensure consistent configuration of servers across environments, based on a source of truth. The partner construct to this approach is tokenisation, i.e. a way of abstracting environment variations away from the syntax of the consuming application.

Tabular Properties

To provide a human readable, single pane-of-glass view of the multiple environment configurations, a tabular approach is used. An example of this follows. The first two columns, context and target are mandatory, all others can be any values needed for your solution.

context  target  property
local    TEST    test.server.comain
local    PROD    production.server.domain

Configuration Management files should never container sensitive data or secrets. These are supplied as variables, see more on sensitive data strategies.

The configuration management tables can be any file name with .cm extension, in your solution root. All .cm files are processed prior to the build task in the CI process.

Extend the Seeded Solution

Based on the seeded solution, add a properties.cm file to the solution root.

Linux

echo 'context  target  property               integer' > .cdaf/properties.cm
echo 'local    LINUX   "Local Context"              1' >> .cdaf/properties.cm
echo 'local    TEST    "Test Property"              2' >> .cdaf/properties.cm

Windows

Set-Content .\.cdaf\properties.cm 'context  target     property               integer'
Add-Content .\.cdaf\properties.cm 'local    WINDOWS    "Local Context"              1'
Add-Content .\.cdaf\properties.cm 'local    WORKGROUP  "Local Context"              1'
Add-Content .\.cdaf\properties.cm 'local    TEST       "Test Property"              2'

Automated Deployment

Retest your solution, but this time, execute the end-to-end process

Linux

cdEmulate.sh

Windows

cdEmulate

The resulting CD process will not perform any action, however, the release package will now be extracted and there will be a directory TasksLocal, and in this will be the sub-directory based on the property context, propertiesForLocalTasks. In this directory will be the two properties files, compiled from the properties.cm file, TEST and PROD respectively, e.g.

property=Test Property
integer=1

Tokenisation

The partner files in source control are in whatever syntax required by the application, with tokens only for values that vary between environment. By default, tokens are in the form %name%. Following examples highlight how the configuration management is intended to provide an abstraction from the complexities of the application configuration files.

ASP.NET

  <connectionStrings>
    <add name="aspdotnetEntities"
      connectionString="metadata=res://*/Models.aspdotnet.csdl|res://*/Models.aspdotnet.ssdl|res://*/Models.aspdotnet.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=%databaseFQDN%;initial catalog=aspdotnetapp;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient"
      xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
  </connectionStrings>
dotnet core
{
  "ConnectionStrings": {
    "appDB": "Server=%databaseFQDN%;Database=dotnetcoreapp;Trusted_Connection=True;"
  }
}

Python

database: 

dbopt:
  host: %databaseFQDN%
  dbname: pythonapp
  user: pythonappdbuser
  password: @dBpassword@

Java

jdbcConnection=jdbc:mysql://%databaseFQDN%/javaapp
jdbcDiver=com.mysql.jdbc.Driver

Ansible

---
spring_fqdn: "%spring_fqdn%"
rails_fqdn: "%rails_fqdn%"

Helm

env:
  name: QUEUE_TRANSPORT value: "%QUEUE_TRANSPORT%"
  name: ORM_CONNECTION value: "%ORM_CONNECTION%"

Deployment Tasks

With the properties for the application defined, now it is time to execute the deployment.