OSDN Git Service

fixes format version detection of a local `docker-compose.yml`.
[metasearch/grid-chef-repo.git] / cookbooks / concourse-ci / README.md
1 concourse-ci Cookbook
2 =====================
3
4 This cookbook sets up a Concourse CI service by Docker Compose.
5
6 ## Contents
7
8 - [Requirements](#requirements)
9     - [platforms](#platforms)
10     - [packages](#packages)
11     - [cookbooks](#cookbooks)
12 - [Attributes](#attributes)
13 - [Usage](#usage)
14     - [Recipes](#recipes)
15         - [concourse-ci::default](#concourse-cidefault)
16         - [concourse-ci::fly](#concourse-cifly)
17         - [concourse-ci::docker-compose](#concourse-cidocker-compose)
18     - [Role Examples](#role-examples)
19     - [SSL server keys and certificates management by ssl_cert cookbook](#ssl-server-keys-and-certificates-management-by-ssl_cert-cookbook)
20     - [Encryption key management by Chef Vault](#encryption-key-management-by-chef-vault)
21     - [OAuth client ID and secret management by Chef Vault](#oauth-client-id-and-secret-management-by-chef-vault)
22 - [License and Authors](#license-and-authors)
23
24 ## Requirements
25
26 ### platforms
27 - none.
28
29 ### packages
30 - none.
31
32 ### cookbooks
33 - `docker-grid`
34 - `ssl_cert`
35
36 ## Attributes
37
38 |Key|Type|Description, example|Default|
39 |:--|:--|:--|:--|
40 |`['concourse-ci']['fly']['version']`|String||`'3.3.4'`|
41 |`['concourse-ci']['fly']['release_url']`|String||`"https://github.com/concourse/concourse/releases/download/v#{node['concourse-ci']['fly']['version']}/fly_linux_amd64"`|
42 |`['concourse-ci']['fly']['release_checksum']`|String||`nil`|
43 |`['concourse-ci']['fly']['auto_upgrade']`|Boolean||`false`|
44 |`['concourse-ci']['fly']['install_path']`|String||`'/usr/local/bin/fly'`|
45 |`['concourse-ci']['with_ssl_cert_cookbook']`|Boolean|See `attributes/default.rb`|`false`|
46 |`['concourse-ci']['ssl_cert']['ca_names']`|Array|Internal CA names that are imported by the ssl_cert cookbook.|`[]`|
47 |`['concourse-ci']['ssl_cert']['common_name']`|String|Server common name for TLS|`node['fqdn']`|
48 |`['concourse-ci']['docker-image']['entrypoint']`|String|Concourse Docker image's entrypoint setting to import an internal CA certificate.|`'/usr/local/bin/dumb-init /usr/local/bin/concourse'`|
49 |`['concourse-ci']['docker-compose']['import_ca']`|Boolean|whether import internal CA certificates or not.|`false`|
50 |`['concourse-ci']['docker-compose']['app_dir']`|String||`"#{node['docker-grid']['compose']['app_dir']}/concourse"`|
51 |`['concourse-ci']['docker-compose']['pgdata_dir']`|String|Path string or nil (unset).|`"#{node['concourse-ci']['docker-compose']['app_dir']}/database"`|
52 |`['concourse-ci']['docker-compose']['web_keys_dir']`|String|Path string.|`"#{node['concourse-ci']['docker-compose']['app_dir']}/keys/web"`|
53 |`['concourse-ci']['docker-compose']['worker_keys_dir']`|String|Path string.|`"#{node['concourse-ci']['docker-compose']['app_dir']}/keys/worker"`|
54 |`['concourse-ci']['docker-compose']['pgdata_dir']`|String|Path string or nil (unset, non-persistent).|`"#{node['concourse-ci']['docker-compose']['app_dir']}/database"`|
55 |`['concourse-ci']['docker-compose']['db_password_reset']`|String|Only available if the password is automatically generated by Chef.|`false`|
56 |`['concourse-ci']['docker-compose']['db_password_vault_item']`|Hash|See `attributes/default.rb`|`{}`|
57 |`['concourse-ci']['docker-compose']['web_encryption_key_vault_item']`|Hash|See `attributes/default.rb`|`{}`|
58 |`['concourse-ci']['docker-compose']['web_password_reset']`|String|Only available if the password is automatically generated by Chef.|`false`|
59 |`['concourse-ci']['docker-compose']['web_password_vault_item']`|Hash|See `attributes/default.rb`|`{}`|
60 |`['concourse-ci']['docker-compose']['web_oauth_client_id_vault_item']`|Hash|See `attributes/default.rb`|`{}`|
61 |`['concourse-ci']['docker-compose']['web_oauth_client_secret_vault_item']`|Hash|See `attributes/default.rb`|`{}`|
62 |`['concourse-ci']['docker-compose']['ssh_keys_reset']`|String|Resets all SSH keys forcely.|`false`|
63 |`['concourse-ci']['docker-compose']['config_format_version']`|String|`docker-compose.yml` format version. `'1'` or `'2'`|`'1'`|
64 |`['concourse-ci']['docker-compose']['config']`|Hash|`docker-compose.yml` configurations.|See `attributes/default.rb`|
65
66 ## Usage
67
68 ### Recipes
69
70 #### concourse-ci::default
71
72 This recipe does nothing.
73
74 #### concourse-ci::fly
75
76 This recipe installs the `fly` CLI and the `fly_prune_workers` command.
77
78 #### concourse-ci::docker-compose
79
80 This recipe generates SSH keys of each node and a `docker-compose.yml` file for the Concourse CI service.
81
82 ### Role Examples
83
84 - `roles/concourse.rb`
85
86 ```ruby
87 name 'concourse'
88 description 'Concourse'
89
90 run_list(
91   'role[docker]',
92   'recipe[concourse-ci::docker-compose]',
93 )
94
95 image = 'concourse/concourse:latest'
96 port = '18080'
97
98 override_attributes(
99   'concourse-ci' => {
100     'docker-compose' => {
101       # Version 1 docker-compose format (default)
102       'config' => {
103         'concourse-web' => {
104           'image' => image,
105           'ports' => [
106             "#{port}:8080",
107           ],
108           #'volumes' => [
109           #  # These volumes will be set by the concourse-ci::docker-compose recipe automatically.
110           #  #"#{node['concourse-ci']['docker-compose']['web_keys_dir']}:/concourse-keys",
111           #],
112           'environment' => {
113             'CONCOURSE_EXTERNAL_URL' => "http://192.168.1.3:#{port}",
114             #'CONCOURSE_RESOURCE_CHECKING_INTERVAL' => '1m',  # default
115           },
116         },
117         'concourse-worker' => {
118           'image' => image,
119           #'volumes' => [
120           #  # These volumes will be set by the concourse-ci::docker-compose recipe automatically.
121           #  #"#{node['concourse-ci']['docker-compose']['worker_keys_dir']}:/concourse-keys",
122           #],
123         },
124       },
125 =begin
126       # Version 2 docker-compose format
127       'config_format_version' => '2',
128       'config' => {
129         'services' => {
130           'concourse-web' => {
131             'image' => image,
132             'ports' => [
133               "#{port}:8080",
134             ],
135             #'volumes' => [
136             #  # These volumes will be set by the concourse-ci::docker-compose recipe automatically.
137             #  #"#{node['concourse-ci']['docker-compose']['web_keys_dir']}:/concourse-keys",
138             #],
139             'environment' => {
140               'CONCOURSE_EXTERNAL_URL' => "http://192.168.1.3:#{port}",
141               #'CONCOURSE_RESOURCE_CHECKING_INTERVAL' => '1m',  # default
142             },
143           },
144           'concourse-worker' => {
145             'image' => image,
146             #'volumes' => [
147             #  # These volumes will be set by the concourse-ci::docker-compose recipe automatically.
148             #  #"#{node['concourse-ci']['docker-compose']['worker_keys_dir']}:/concourse-keys",
149             #],
150           },
151         },
152       },
153 =end
154     },
155   },
156 )
157 ```
158
159 - `roles/concourse-with-ssl.rb`
160
161 ```ruby
162 name 'concourse-with-ssl'
163 description 'Concourse with SSL'
164
165 run_list(
166   #'recipe[ssl_cert::server_key_pairs]',  # concourse-ci cookbook < 0.2.2
167   'role[docker]',
168   'recipe[concourse-ci::docker-compose]',
169 )
170
171 image = 'concourse/concourse:2.6.0'
172 port = '18443'
173 cn = 'concourse.io.example.com'
174
175 override_attributes(
176   'ssl_cert' => {
177     #'common_names' => [
178     #  cn,  # concourse-ci cookbook < 0.2.3
179     #],
180   },
181   'concourse-ci' => {
182     'with_ssl_cert_cookbook' => true,
183     'ssl_cert' => {
184       'common_name' => cn,
185     },
186     'docker-compose' => {
187       'config' => {
188         # Version 1 docker-compose format
189         'concourse-web' => {
190           'image' => image,
191           'ports' => [
192             "#{port}:8443",
193           ],
194           'environment' => {
195             'CONCOURSE_EXTERNAL_URL' => "https://192.168.1.3:#{port}",
196             'CONCOURSE_TLS_BIND_PORT' => '8443',  # activate HTTPS
197             # These environments will be set by the concourse-ci::docker-compose recipe automatically.
198             #'CONCOURSE_TLS_CERT' => '/root/server.crt',
199             #'CONCOURSE_TLS_KEY' => '/root/server.key',
200           },
201           #'volumes' => [
202           #  # These volumes will be set by the concourse-ci::docker-compose recipe automatically.
203           #  #"#{node['concourse-ci']['docker-compose']['web_keys_dir']}:/concourse-keys",
204           #  #"#{server_cert_path(node['concourse-ci']['ssl_cert']['common_name'])}:/root/server.crt:ro",
205           #  #"#{server_key_path(node['concourse-ci']['ssl_cert']['common_name'])}:/root/server.key:ro",
206           #],
207         },
208         'concourse-worker' => {
209           'image' => image,
210           #'volumes' => [
211           #  # These volumes will be set by the concourse-ci::docker-compose recipe automatically.
212           #  #"#{node['concourse-ci']['docker-compose']['worker_keys_dir']}:/concourse-keys",
213           #],
214         },
215       },
216     },
217   },
218 )
219 ```
220
221 - `roles/concourse-with-oauth.rb`
222
223 ```ruby
224 name 'concourse-with-oauth'
225 description 'Concourse with OAuth'
226
227 run_list(
228   #'recipe[ssl_cert::ca_certs]',  # concourse-ci cookbook < 0.2.2
229   'recipe[ssl_cert::server_key_pairs]',
230   'role[docker]',
231   'recipe[concourse-ci::docker-compose]',
232 )
233
234 image = 'concourse/concourse:latest'
235 port = '18443'
236 ca_name = 'grid_ca'
237 cn = 'concourse.io.example.com'
238 gitlab_cn = 'gitlab.io.example.com'
239
240 override_attributes(
241   'ssl_cert' => {
242     #'ca_names' => [
243     #  ca_name,  # concourse-ci cookbook < 0.2.3
244     #],
245     #'common_names' => [
246     #  cn,  # concourse-ci cookbook < 0.2.3
247     #],
248   },
249   'concourse-ci' => {
250     'with_ssl_cert_cookbook' => true,
251     'ssl_cert' => {
252       'ca_names' => [
253         ca_name,
254       ],
255       'common_name' => cn,
256     },
257     'docker-compose' => {
258       'import_ca' => true,
259       'web_oauth_client_id_vault_item' => {
260         'vault' => 'concourse',
261         'name' => 'web_oauth_client_id',
262         'env_context' => false,
263         'key' => 'cid',
264       },
265       'web_oauth_client_secret_vault_item' => {
266         'vault' => 'concourse',
267         'name' => 'web_oauth_client_secret',
268         'env_context' => false,
269         'key' => 'secret',
270       },
271       'config' => {
272         # Version 1 docker-compose format
273         'concourse-web' => {
274           'ports' => [
275             #'4080:8080',
276             "#{port}:8443",
277           ],
278           'environment' => {
279             'CONCOURSE_TLS_BIND_PORT' => '8443',
280             'CONCOURSE_EXTERNAL_URL' => "https://#{cn}:#{port}",
281             # OAuth for the default `main`` team
282             'CONCOURSE_GENERIC_OAUTH_DISPLAY_NAME' => 'GitLab',
283             # The following 2 variables are set automatically,
284             # if the ['concourse-ci']['docker-compose']['web_oauth_client_(id|secret)_vault_item'] attributes are specified.
285             #'CONCOURSE_GENERIC_OAUTH_CLIENT_ID' => '${CONCOURSE_GENERIC_OAUTH_CLIENT_ID}',
286             #'CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET' => '${CONCOURSE_GENERIC_OAUTH_CLIENT_SECRET}',
287             'CONCOURSE_GENERIC_OAUTH_AUTH_URL' => "https://#{gitlab_cn}/oauth/authorize",
288             'CONCOURSE_GENERIC_OAUTH_TOKEN_URL' => "https://#{gitlab_cn}/oauth/token",
289           },
290         },
291       },
292     },
293   },
294 )
295 ```
296
297 ### SSL server keys and certificates management by ssl_cert cookbook
298
299 - create vault items.
300
301 ```text
302 $ ruby -rjson -e 'puts JSON.generate({"private" => File.read("concourse.io.example.com.prod.key")})' \
303 > > ~/tmp/concourse.io.example.com.prod.key.json
304
305 $ ruby -rjson -e 'puts JSON.generate({"public" => File.read("concourse.io.example.com.prod.crt")})' \
306 > > ~/tmp/concourse.io.example.com.prod.crt.json
307
308 $ cd $CHEF_REPO_PATH
309
310 $ knife vault create ssl_server_keys concourse.io.example.com.prod \
311 > --json ~/tmp/concourse.io.example.com.prod.key.json
312
313 $ knife vault create ssl_server_certs concourse.io.example.com.prod \
314 > --json ~/tmp/concourse.io.example.com.prod.crt.json
315 ```
316
317 - grant reference permission to the Concourse host
318
319 ```text
320 $ knife vault update ssl_server_keys  concourse.io.example.com.prod -S 'name:concourse-host.example.com'
321 $ knife vault update ssl_server_certs concourse.io.example.com.prod -S 'name:concourse-host.example.com'
322 ```
323
324 - modify run_list and attributes
325
326 ```ruby
327 run_list(
328   #'recipe[ssl_cert::server_key_pairs]',  # concourse-ci cookbook < 0.2.2
329   'recipe[concourse-ci::docker-compose]',
330 )
331
332 override_attributes(
333   'ssl_cert' => {
334     #'common_names' => [
335     #  'concourse.io.example.com',  # concourse-ci cookbook < 0.2.3
336     #],
337   },
338   'concourse-ci' => {
339     'with_ssl_cert_cookbook' => true,
340     'ssl_cert' => {
341       'common_name' => 'concourse.io.example.com',
342     },
343     # ...
344   },
345 )
346 ```
347
348 ### Encryption key management by Chef Vault
349
350 - create vault items.
351
352 ```text
353 # a 16 or 32-byte random character sequence.
354 $ cat ~/tmp/concourse_ekey.json
355 {"ekey":"********************************"}
356
357 $ knife vault create concourse web_encryption_key --json ~/tmp/concourse_ekey.json
358 ```
359
360 - grant reference permission to the Concourse host
361
362 ```text
363 $ knife vault update concourse web_encryption_key -S 'name:concourse-host.example.com'
364 ```
365
366 - modify attributes
367
368 ```ruby
369 override_attributes(
370   'concourse-ci' => {
371     # ...
372     'docker-compose' => {
373       'web_encryption_key_vault_item' => {
374         'vault' => 'concourse',
375         'name' => 'web_encryption_key',
376         'env_context' => false,
377         'key' => 'ekey',
378       },
379       # ...
380     },
381   },
382 )
383 ```
384
385 ### OAuth client ID and secret management by Chef Vault
386
387 - create vault items.
388
389 ```text
390 $ cat ~/tmp/concourse_oauth_client_id.json
391 {"cid":"***************************************************************"}
392 $ cat ~/tmp/concourse_oauth_client_secret.json
393 {"secret":"***************************************************************"}
394
395 $ knife vault create concourse web_oauth_client_id --json ~/tmp/concourse_oauth_client_id.json
396 $ knife vault create concourse web_oauth_client_secret --json ~/tmp/concourse_oauth_client_secret.json
397 ```
398
399 - grant reference permission to the Concourse host
400
401 ```text
402 $ knife vault update concourse web_oauth_client_id -S 'name:concourse-host.example.com'
403 $ knife vault update concourse web_oauth_client_secret -S 'name:concourse-host.example.com'
404 ```
405
406 - modify attributes
407
408 ```ruby
409 override_attributes(
410   'concourse-ci' => {
411     # ...
412     'docker-compose' => {
413       'web_oauth_client_id_vault_item' => {
414         'vault' => 'concourse',
415         'name' => 'web_oauth_client_id',
416         'env_context' => false,
417         'key' => 'cid',
418       },
419       'web_oauth_client_secret_vault_item' => {
420         'vault' => 'concourse',
421         'name' => 'web_oauth_client_secret',
422         'env_context' => false,
423         'key' => 'secret',
424       },
425       # ...
426     },
427   },
428 )
429 ```
430
431 ## License and Authors
432
433 - Author:: whitestar at osdn.jp
434
435 ```text
436 Copyright 2017, whitestar
437
438 Licensed under the Apache License, Version 2.0 (the "License");
439 you may not use this file except in compliance with the License.
440 You may obtain a copy of the License at
441
442     http://www.apache.org/licenses/LICENSE-2.0
443
444 Unless required by applicable law or agreed to in writing, software
445 distributed under the License is distributed on an "AS IS" BASIS,
446 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
447 See the License for the specific language governing permissions and
448 limitations under the License.
449 ```