summaryrefslogtreecommitdiff
path: root/yarns.webapp/060-validation.yarn
blob: 29bc7cafb1d6209a6224268662dc0ca79b8d750f (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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
Validation of CONFGIT
=====================

The CONFGIT repository contains two types of files we should validate:
the `lorry-controller.conf` file, and the local Lorry files (specified
by the former file in `lorries` sections).

Validate `lorry-controller.conf`
--------------------------------

We'll start by validating the `lorry-controller.conf` file. There's
several aspects here that need to be tested:

* JSON syntax correctness: if the file doesn't parse as JSON, the
  WEBAPP should cope and shouldn't change STATEDB in any way.
* Semantic correctness: the file should contain a list of dicts, and
  each dict should have the right fields with the right kind of
  values. See the `README` for details. Other fields are also allowed,
  though ignored. Again, if there's an error, WEBAPP should cope, and
  probably shouldn't update STATEDB if there are any problems.

The approach for testing this is to set up an empty STATEDB, then get
WEBAPP to read a `lorry-controller.conf` with various kinds of
brokenness, and after each read verify that STATEDB is still empty.
This doesn't test that if the STATEDB wasn't empty it doesn't change
existing data, but it seems like a reasonable assumption that an
update happens regardless of previous contents of STATEDB, given how
SQL transactions work.

In summary:

* Start WEBAPP without a STATEDB, and have it read its config. Verify
  STATEDB is empty.
* Add a `lorry-controller.conf` that is broken in some specific way.
* Tell WEBAPP to re-read its config.
* Verify that WEBAPP gives an error message.
* Verify that STATEDB is still empty.

Repeat this for each type of brokenness we want to ensure WEBAPP
validates for.

    SCENARIO validate lorry-controller.conf
    GIVEN a new git repository in CONFGIT
    AND WEBAPP uses CONFGIT as its configuration directory
    AND a running WEBAPP

First of all, have WEBAPP read CONFGIT. This should succeed even if
the `lorry-controller.conf` file doesn't actually exist.

    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "Configuration has been updated"
    AND STATEDB is empty

Add an empty configuration file. This is different from a file
containing an empty JSON list. It should be treated as an error.

    GIVEN a lorry-controller.conf in CONFGIT containing ""
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "ERROR"
    AND STATEDB is empty

Add a syntactically invalid JSON file.

    GIVEN a lorry-controller.conf in CONFGIT containing "blah blah blah"
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "ERROR"
    AND STATEDB is empty

Replace the bad JSON file with one that has an unknown section (no
`type` field). Please excuse the non-escaping of double quotes: it's
an artifact of how yarn steps are implemented and is OK.

    GIVEN a lorry-controller.conf in CONFGIT containing "[{"foo": "bar"}]"
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "ERROR"
    AND STATEDB is empty

What about a section that has a `type` field, but it's set to a
non-sensical value?

    GIVEN a lorry-controller.conf in CONFGIT containing "[{"type": "BACKUPS!"}]"
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "ERROR"
    AND STATEDB is empty

Now we're getting to real sections. A `troves` section must have
`trovehost`, `interval`, `ls-interval`, and `prefixmap` set, and may
optionally have `ignore` set. The `trovehost` field can't really be
checked, and `interval` and `ls-interval` don't need much checking: if
they don't parse as sensible intervals, Lorry Controller will just use
a default value.

`prefixmap`, however, can have a reasonable check: it shouldn't map
something to be under the Trove ID of the local Trove, otherwise Lorry
won't be able to push the repositories. However, at this time, we do
not have a reasonable way to get the Trove ID of the local Trove, so
we're skipping implementing that test for now. (FIXME: fix this lack
of testing.)

The `ignore` field in a `trove` section and the `globs` field in a
`lorry` section are expected to be lists of strings, test a non-list
value.

    GIVEN an empty lorry-controller.conf in CONFGIT
    AND lorry-controller.conf in CONFGIT adds trove example-trove
    AND lorry-controller.conf in CONFGIT sets ignore to "foo" for trove example-trove
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "ERROR"
    AND STATEDB is empty

And a non-string list.

    GIVEN lorry-controller.conf in CONFGIT sets ignore to "[1, 2]" for trove example-trove
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "ERROR"
    AND STATEDB is empty

`ignore` is is not a mandatory option, verify this is the case.

    GIVEN lorry-controller.conf in CONFGIT removes field ignore from trove example-trove
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "Configuration has been updated"

Clean up at the end.

    FINALLY WEBAPP terminates


Validate local Lorry files
--------------------------

Lorry files (`.lorry`) are consumed by the Lorry program itself, but
also by Lorry Controller. In fact, the ones that are in CONFGIT are
only consumed by Lorry Controller: it reads them in, parses them,
extracts the relevant information, puts that into STATEDB, and then
generates a whole new (temporary) file for each Lorry run.

Lorry Controller doesn't validate the Lorry files much, only
enough that it can extract each separate Lorry specification and feed
them to Lorry one by one. In other words:

* The `.lorry` file must be valid JSON.
* It must be a dict.
* Each key must map to another dict.
* Each inner dict must have a key `type`, which maps to a string.

Everything else is left for Lorry itself. Lorry Controller only needs
to handle Lorry not working, and it already does that.

Firstly, some setup.

    SCENARIO validate .lorry files
    GIVEN a new git repository in CONFGIT
    AND an empty lorry-controller.conf in CONFGIT
    AND lorry-controller.conf in CONFGIT adds lorries *.lorry using prefix upstream
    AND WEBAPP uses CONFGIT as its configuration directory
    AND a running WEBAPP

Make sure WEBAPP handles there not being any `.lorry` files.

    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"
    AND STATEDB is empty
    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to []

Add a `.lorry` file that contains broken JSON.

    GIVEN Lorry file CONFGIT/notjson.lorry with { THIS IS NOT JSON ]
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"
    AND STATEDB is empty
    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to []

Add a `.lorry` file that is valid JSON, but is not a dict.

    GIVEN Lorry file CONFGIT/notadict.lorry with [1,2,3]
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"
    AND STATEDB is empty
    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to []

Add a `.lorry` that is a dict, but doesn't map keys to dicts.

    GIVEN Lorry file CONFGIT/notadictofdicts.lorry with { "foo": 1 }
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"
    AND STATEDB is empty
    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to []

Add a `.lorry` whose inner dict does not have a `type` field.

    GIVEN Lorry file CONFGIT/notype.lorry with { "foo": { "bar": "yo" }}
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"
    AND STATEDB is empty
    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to []

Add a `.lorry` that is A-OK. This should work even when there are some
broken ones too.

    GIVEN Lorry file CONFGIT/a-ok.lorry with { "foo": { "type": "git", "url": "git://example.com/foo" }}
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"
    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to ["upstream/foo"]

Clean up at the end.

    FINALLY WEBAPP terminates


Load broken Lorry files
-----------------------

This scenario checks that if STATEDB already contains a valid Lorry
file, and we're trying to load an invalid one, then the valid one
doesn't get overwritten or discarded.

First, some setup.

    SCENARIO load broken .lorry files
    GIVEN a new git repository in CONFGIT
    AND an empty lorry-controller.conf in CONFGIT
    AND lorry-controller.conf in CONFGIT adds lorries *.lorry using prefix upstream
    AND WEBAPP uses CONFGIT as its configuration directory
    AND a running WEBAPP

Add a `.lorry` file that contains valid JSON.

    GIVEN Lorry file CONFGIT/a-ok.lorry with { "foo": { "type": "git", "url": "git://example.com/foo" }}
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"

Make sure it's the one we loaded.

    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to ["upstream/foo"]
    WHEN admin makes request GET /1.0/lorry/upstream/foo
    THEN response matches "git://example.com/foo"

Now, add a broken file and try to load that.

    GIVEN Lorry file CONFGIT/notjson.lorry with THIS IS NOT JSON
    WHEN admin makes request POST /1.0/read-configuration
    THEN response matches "has been updated"

Now, make sure we still have what we originally had.

    WHEN admin makes request GET /1.0/list-queue
    THEN response has queue set to ["upstream/foo"]
    WHEN admin makes request GET /1.0/lorry/upstream/foo
    THEN response matches "git://example.com/foo"

Clean up at the end.

    FINALLY WEBAPP terminates