+++ dep = 6 title = "draft.toml Format" authors = [ "Matt Fisher [email protected]" ] created = 2017-10-23 +++
Draft configuration is stored in an application's root directory as draft.toml
. This file contains configuration that affects the behaviour of draft up
and draft connect
. This document describes the format of draft.toml
and the reasoning behind the use of TOML.
Draft users need a way to persist feature flags to draft up
without having to invoke the same feature flags every time they call draft up
. Similarly, users that want to collaborate on an app using Draft want to share the same feature flags they used, allowing others to repeat the same feature flags that were enabled on their machine to replicate the same environment.
The format of this file is as follows:
[environments]
[environments.development]
name = "example-go"
registry = "microsoft"
set = ["foo=bar", "car=star"]
watch = true
watch-delay = 1
override-ports = ["8080:8080", "9229:9229"]
auto-connect = false
custom-tags = ["backend-dev"]
chart = "my-app-dev"
dockerfile = "Dockerfile.dev"
[environments.staging]
name = "example-go"
namespace = "kube-system"
build-tar = "build.tar.gz"
chart-tar = "chart.tar.gz"
custom-tags = ["latest", "backend-staging"]
override-ports = ["8080:8080"]
chart = "my-app-staging"
Let's break it down by section:
[environments]
The root of the TOML file. Each definition under this node is considered an "environment". More on that in a second.
[environments.development]
This is the environment name. Applications deployed by Draft can be configured in different manners
based on the present environment. By default, draft up
deploys using the development
environment, but this can be tweaked by either setting $DRAFT_ENV
or by supplying the environment
name at runtime using draft up --environment=staging
.
name = "example-go"
registry = "microsoft"
namespace = "kube-system"
build-tar = "build.tar.gz"
chart-tar = "chart.tar.gz"
container-builder = "docker"
set = ["foo=bar", "car=star"]
wait = false
watch = false
watch-delay = 2
override-ports = ["8080:8080", "9229:9229"]
auto-connect = false
custom-tags = ["latest", "backend-staging"]
chart = "javascript"
dockerfile = "Dockerfile"
resource-group-name = "foo"
Here is a run-down on each of the fields:
name
: the name of the application. This will map directly with the name of the Helm release.registry
: the name of the Docker registry to publish the image to.- This can also be set globally by setting the
registry
field withdraft config set registry <name>
. However, theregistry
field in draft.toml takes precedence.
- This can also be set globally by setting the
namespace
: the kubernetes namespace where the application will be deployed.build-tar
: path to a gzipped build tarball.chart-tar
must also be set.chart-tar
: path to a gzipped chart tarball.build-tar
must also be set.container-builder
: the container image builder used to build the container. Setting this toacrbuild
uses ACR Build; any other value uses Docker.set
: set custom Helm values.wait
: specifies whether or not to wait for all resources to be ready when Helm installs the chart.watch
: whether or not to deploy the app automatically when local files change.watch-delay
: the delay for local file changes to have stopped before deploying again (in seconds).override-ports
: the configuration to be passed to thedraft connect
command, in the formatLOCALHOST_PORT:CONTAINER_PORT
auto-connect
: specifies whether Draft should automatically connect to the application after the deplyoment is successful. The local ports are configurable through theoverride-ports
field.custom-tags
: specifies the custom tags Draft will push to the container registry. Note that Draft will push and use the computed SHA of the application as the tag of your image for the Helm chart.chart
: the name of the directory incharts/
that will be used to release the application for this environmentdockerfile
: the name of the Dockerfile that will be used to build the image for this environmentresource-group-name
: the name of the resource group hosting the container registry. Only used when the container builder is set toacrbuild
Note: It is recommended to avoid fixed image tags (like
latest
,canary
,dev
) in production, and if the image tag is the same in your chart, Helm will not upgrade your release.
For more information on configuring
draft connect
, check dep-007.md.
Note: All updates to
draft.toml
will take effect the next timedraft <command> --environment=<affected environment>
is invoked. This way, you can executedraft up
,draft connect
,draft delete
,draft logs
with different environments and work on your application with different configuration.
Note: The
namespace
key/value pair cannot be modified if the value is changed indraft.toml
. Once a deployment has occurred in the original namespace, it won't be transferred over to another namespace. To do this, you can delete your application usingdraft delete --environment=<affected environment>
and then re-create it usingdraft up --environment=<affected environment>
.
TOML is a minimal configuration file format that is easy to read due to obvious semantics. TOML is designed to map unambiguously to a hash table. TOML should be easy to parse into data structures in a wide variety of languages without ambiguity.
We've learned a few things from using YAML/JSON across multiple OSS projects. Here's a few war stories that justify why we are using TOML instead of other conventional markup languages commonly used.
From personal experience, debugging a YAML file written with improper or mixed indentation has caused more frustration than working with any other markup language. There have been countless times where users broke their manifests by accidentally using tabs instead of spaces (and vice versa) and end up with obscure YAML parser errors. TOML does not care about indentation, which is a really welcome change for a simple markup language.
Secondly, the YAML spec is over 23,000 words. It's bloated, complex, and not at all "simple" or "obvious" to the user on its syntax. There are over 9 different ways to skin the proverbial cat in YAML, and because it is so complex most parsers will not support every feature (or in certain cases, parse it in another format). draft.toml
only needs to support 1 way to write a multi-line string. In TOML, it's just
message = """This is
a multi-line
string."""
There is an excellent blog post by Martin Tournoij who explains the many intricacies and pitfalls of YAML that goes into greater detail.
JSON certainly has its place and is stricter than YAML on field types, but it is not a human-readable markup language. You can't write comments in JSON. That's a non-starter for a file that's meant to be used by developers to express how their application is deployed to production. At the end of the day, we're writing a tool for developers, not machines. For projects that stand up infrastructure like acs-engine or kops, JSON is an excellent fit.