summaryrefslogtreecommitdiff
path: root/yarns/100-mvp.yarn
blob: 4a01b4779a8277d2a799354bbe7977b80f71d09e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
---
title: vmdb2 MVP with echo and error
author: Lars Wirzenius
date: work in progress
...


Introduction
=============================================================================

vmdb2 is a program for producing a disk image with Debian installed.
This document is a manual of sorts, and an automated test suite for it.

[vmdebootstrap][] installs Debian onto a disk, or disk image. It is
like the [debootstrap][] tool, except the end result is a disk or disk
image, not a directory tree. vmdebootstrap takes care of creating
partitions, and filesystems, and allows some more customization than
vmdebootstrap does.

vmdebootstrap is also a messy pile of kludge, and not flexible enough.
vmdb2 is a re-implementation from scratch, without a need for
backwards compatibility. It aims to provide more flexibility than
vmdeboostrap, without becoming anywhere near as complicated. Think of
vmdb2 as "vmdebootstrap the second generation". The name has changed
to allow the two tools to installable in paralllel.

The main user-visible difference between vmdebootstrap and vmdb2 is
that the older program provides extensibitlity via a legion of command
line options and the newer program by having the user user a domain
specific language to express what kind of Debian system they want to
create.

(Lars Wirzenius wrote both vmdebootstrap and vmdb2 and is entitled to
sneer at his younger self.)

[vmdebootstrap]: http://liw.fi/vmdebootstrap/
[debootstrap]: https://packages.debian.org/unstable/debootstrap



Specification files
=============================================================================

A vmdb2 specification file is a YAML file that looks like this (this
is an imaginary example that doens't actually work right now):

    EXAMPLE
    steps:
    - mkimg: raw
      size: 4G
    - mkfs: ext4
      label: vmdb2rootfs
    - debootstrap: jessie
    - shell: |
        rm -rf /usr/share/man
    - adduser: jimbo
      gecos: James Bond
      shell: /bin/zsh
    - sudo: jimbo
    - ifupdown: eth0
      auto: yes
      dhcp: yes
    - apt: openssh-server
    - convert: qcow2
    - compress: xz

The list of steps produces the kind of image that the user wants (or
else an unholy mess). The specification file can easily be shared, and
put under version control.

Every action in a step is provided by a plugin to vmdb2. Each action
(technically, "step runner") is a well-defined task, which may be
parameterised by some of the key/value pairs in the step. For example,
`mkimg` would create a disk image file. In the above example it is a
raw disk image file, as opposed to some other format. The image is 4
gigabytes in size. `mkfs` creates an ext4 filesystem in the image
file; in thie example there are no partitions. And so on.

Steps may need to clean up after themselves. For example, a step that
mounts a filesystem will need to unmount it at the end of the image
creation. Also, if a later step fails, then the unmount needs to
happen as well. This is called a "teardown". Some steps are provided
by a plugin that handles the teardown automatically, others may need
to provide instructions for the teardown in the specification file.

By providing well-defined steps that the user may combine as they
wish, vmdb2 gives great flexibility without much complexity, but at
the cost of forcing the user to write a longer specification file than
a single vmdeboostrap command line.


A happy path
=============================================================================

The first case we look at is one for the happy path: a specification
with two echo steps, and nothing else. It's very simple, and nothing
goes wrong when executing it. In addition to the actual thing to do,
each step may also define a "teardown" thing to do. For example, if
the step mounts a filesystem, the teardown would unmount it.

    SCENARIO happy path
    GIVEN a specification file called happy.vmdb containing
    ... {
    ...     steps: [
    ...         { echo: "foo", teardown: "foo_teardown" },
    ...         { echo: "bar", teardown: "bar_teardown" }
    ...     ]
    ... }
    WHEN user runs vmdb2 -v happy.vmdb
    THEN exit code is 0
    AND stdout contains "foo" followed by "bar"
    AND stdout contains "bar" followed by "bar_teardown"
    AND stdout contains "bar_teardown" followed by "foo_teardown"


Jinja2 templating in specification file values
=============================================================================

Vmdb2 allows values in specification files to be processed by the
Jinja2 templating engine. This allows users to do thing such as write
specifications that use configuration values to determine what
happens. For our simple echo/error steps, we will write a rule that
outputs the image file name given by the user. A more realistic
specification file would instead do thing like create the file.

    SCENARIO jinja2 templating
    GIVEN a specification file called j2.vmdb containing
    ... {
    ...     steps: [
    ...         { echo: "image is {{ output }}" },
    ...         { echo: "bar" },
    ...     ]
    ... }
    WHEN user runs vmdb2 -v --output=foo.img j2.vmdb
    THEN exit code is 0
    AND stdout contains "image is foo.img" followed by "bar"


Error handling
=============================================================================

Sometimes things do not quite go as they should. What does vmdb2 do
then?

    SCENARIO error handling
    GIVEN a specification file called unhappy.vmdb containing
    ... {
    ...     steps: [
    ...         { echo: "foo", teardown: "foo_teardown" },
    ...         { error: "yikes", teardown: "WAT?!" },
    ...         { echo: "bar_step", teardown: "bar_teardown" }
    ...     ]
    ... }
    WHEN user runs vmdb2 -v unhappy.vmdb
    THEN exit code is 1
    AND stdout contains "foo" followed by "yikes"
    AND stdout contains "yikes" followed by "WAT?!"
    AND stdout contains "WAT?!" followed by "foo_teardown"
    AND stdout does NOT contain "bar_step"
    AND stdout does NOT contain "bar_teardown"