OSDN Git Service

adds autopilot features.
[metasearch/grid-chef-repo.git] / cookbooks / screwdriver / recipes / docker-compose.rb
1 #
2 # Cookbook Name:: screwdriver
3 # Recipe:: docker-compose
4 #
5 # Copyright 2017-2018, whitestar
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 #     http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18 #
19
20 require 'securerandom'
21
22 doc_url = 'https://hub.docker.com/r/screwdrivercd/screwdriver/'
23
24 ::Chef::Recipe.send(:include, SSLCert::Helper)
25
26 #include_recipe 'platform_utils::kernel_user_namespace'
27 include_recipe 'docker-grid::compose'
28
29 app_dir = node['screwdriver']['docker-compose']['app_dir']
30 bin_dir = node['screwdriver']['docker-compose']['bin_dir']
31 config_dir = node['screwdriver']['docker-compose']['config_dir']
32 data_dir = node['screwdriver']['docker-compose']['data_dir']
33 etc_dir = node['screwdriver']['docker-compose']['etc_dir']
34
35 [
36   app_dir,
37   bin_dir,
38   config_dir,
39   data_dir,
40   "#{etc_dir}/nginx",
41 ].each {|dir|
42   resources(directory: dir) rescue directory dir do
43     owner 'root'
44     group 'root'
45     mode '0755'
46     recursive true
47   end
48 }
49
50 api_config_file = "#{config_dir}/api-local.yaml"
51 env_file = "#{app_dir}/.env"
52 config_file = "#{app_dir}/docker-compose.yml"
53
54 api_config_local = nil
55 if File.exist?(api_config_file)
56   require 'yaml'
57   api_config_local = YAML.load_file(api_config_file)
58 end
59
60 env_local = {}
61 if File.exist?(env_file)
62   File.open(env_file) do |file|
63     file.each_line do |line|
64       env_local[$1] = $2 if line =~ /^([^=]*)=(.*)$/
65     end
66   end
67 end
68
69 =begin
70 config_srvs_local = nil
71 if File.exist?(config_file)
72   require 'yaml'
73   config_srvs_local = YAML.load_file(config_file)['services']
74 end
75 =end
76
77 # We use plain Hash objects instead of Chef attribute objects for containg secrets (JWT key pair).
78 override_api_config = node['screwdriver']['api']['config'].to_hash
79 override_store_config = node['screwdriver']['store']['config'].to_hash
80 #override_api_config = node.override['screwdriver']['api']['config']      # NG
81 #override_store_config = node.override['screwdriver']['store']['config']  # NG
82
83 config_srvs = node['screwdriver']['docker-compose']['config']['services']
84 override_config_srvs = node.override['screwdriver']['docker-compose']['config']['services']
85 force_override_config_srvs = node.force_override['screwdriver']['docker-compose']['config']['services']
86
87 # api
88 api_envs_org = config_srvs['api']['environment']
89 api_envs = {}
90 api_vols = config_srvs['api']['volumes'].to_a
91 api_links = []
92
93 api_port = '9001'  # default
94 api_in_port = api_envs_org['PORT']
95 ports = config_srvs['api']['ports']
96 if ports.empty?
97   override_config_srvs['api']['ports'] = ["#{api_port}:#{api_in_port}"]
98 else
99   ports.each {|port|
100     elms = port.split(':')
101     api_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == api_in_port
102   }
103 end
104
105 [
106   'jwt_private_key_vault_item',
107   'jwt_public_key_vault_item',
108   'cookie_password_vault_item',
109   'password_vault_item',
110 ].each {|vault_item|
111   # for backward compatibility.
112   if node['screwdriver'][vault_item].empty? && !node['screwdriver']['docker-compose'][vault_item].empty?
113     node.force_override['screwdriver'][vault_item] = node['screwdriver']['docker-compose'][vault_item].to_hash
114   end
115 }
116
117 jwt_private_key_reset = node['screwdriver']['docker-compose']['jwt_private_key_reset']
118 jwt_private_key = nil
119 jwt_public_key  = nil
120 jwt_private_key_vault_item = node['screwdriver']['jwt_private_key_vault_item']
121 jwt_public_key_vault_item  = node['screwdriver']['jwt_public_key_vault_item']
122
123 if !jwt_private_key_vault_item.empty?
124   # 1. from Chef Vault (recommended).
125   jwt_private_key = get_vault_item_value(jwt_private_key_vault_item)
126   jwt_public_key  = get_vault_item_value(jwt_public_key_vault_item)
127   log 'JWT key pair has been loaded from Chef Vault.'
128 else
129   # 2. from Chef attribute (NOT recommended).
130   jwt_private_key = api_envs_org['SECRET_JWT_PRIVATE_KEY']
131   jwt_public_key  = api_envs_org['SECRET_JWT_PUBLIC_KEY']
132   if jwt_private_key.nil? || jwt_private_key.empty?
133     if !api_config_local.nil? && !api_config_local['auth']['jwtPrivateKey'].nil? && !jwt_private_key_reset
134       # 3. preserve it from the local config/api-local.yaml file.
135       jwt_private_key = api_config_local['auth']['jwtPrivateKey']
136       jwt_public_key  = api_config_local['auth']['jwtPublicKey']
137       log 'JWT key pair is preserved from the local config/api-local.yaml file.'
138     # if !env_local['SECRET_JWT_PRIVATE_KEY'].nil? && !jwt_private_key_reset
139     #   # 3. preserve it from the local .env file.
140     #   # Note: Docker env file format does not support backslash escaped string yet.
141     #   eval "jwt_private_key = %Q(#{env_local['SECRET_JWT_PRIVATE_KEY']})"
142     #   eval "jwt_public_key  = %Q(#{env_local['SECRET_JWT_PUBLIC_KEY']})"
143     #   log 'JWT key pair is preserved from the local .env file.'
144     else
145       # 4. auto generate.
146       require 'openssl'
147       rsa = OpenSSL::PKey::RSA.generate(2048)
148       jwt_private_key = rsa.export
149       jwt_public_key  = rsa.public_key.export
150       log 'JWT key pair has been generated.'
151     end
152   end
153 end
154
155 override_api_config['auth']['jwtPrivateKey'] = jwt_private_key
156 override_api_config['auth']['jwtPublicKey'] = jwt_public_key
157 # Note: prevent Chef from logging JWT key attribute values. (=> template variables)
158 # However Docker env file format does not support multi-line value and backslash escaped string yet.
159 #api_envs['SECRET_JWT_PRIVATE_KEY'] = '${SECRET_JWT_PRIVATE_KEY}'  # Useless
160 #api_envs['SECRET_JWT_PUBLIC_KEY']  = '${SECRET_JWT_PUBLIC_KEY}'   # Useless
161 #api_envs['SECRET_JWT_PRIVATE_KEY'] = jwt_private_key  # NG
162 #api_envs['SECRET_JWT_PUBLIC_KEY']  = jwt_public_key   # NG
163
164 cookie_password = nil
165 cookie_password_vault_item = node['screwdriver']['cookie_password_vault_item']
166 cookie_password = get_vault_item_value(cookie_password_vault_item) unless cookie_password_vault_item.empty?
167 cookie_password = env_local['SECRET_COOKIE_PASSWORD'] if cookie_password.nil? && !env_local['SECRET_COOKIE_PASSWORD'].nil?
168 cookie_password = SecureRandom.urlsafe_base64(32) if cookie_password.nil?
169 api_envs['SECRET_COOKIE_PASSWORD'] = '${SECRET_COOKIE_PASSWORD}'
170
171 password = nil
172 password_vault_item = node['screwdriver']['password_vault_item']
173 password = get_vault_item_value(password_vault_item) unless password_vault_item.empty?
174 password = env_local['SECRET_PASSWORD'] if password.nil? && !env_local['SECRET_PASSWORD'].nil?
175 password = SecureRandom.urlsafe_base64(32) if password.nil?
176 api_envs['SECRET_PASSWORD'] = '${SECRET_PASSWORD}'
177
178 hashing_password = nil
179 # for backward compatibility
180 hashing_password = env_local['SECRET_PASSWORD'] if env_local['SECRET_HASHING_PASSWORD'].nil? && !env_local['SECRET_PASSWORD'].nil?
181 hashing_password_vault_item = node['screwdriver']['hashing_password_vault_item']
182 hashing_password = get_vault_item_value(hashing_password_vault_item) unless hashing_password_vault_item.empty?
183 hashing_password = env_local['SECRET_HASHING_PASSWORD'] if hashing_password.nil? && !env_local['SECRET_HASHING_PASSWORD'].nil?
184 hashing_password = SecureRandom.urlsafe_base64(32) if hashing_password.nil?
185 api_envs['SECRET_HASHING_PASSWORD'] = '${SECRET_HASHING_PASSWORD}'
186
187 node['screwdriver']['api']['scms_vault_items'].each {|scm, props|
188   props.each {|prop, vault_item|
189     unless vault_item.empty?
190       secret = get_vault_item_value(vault_item)
191       override_api_config['scms'][scm]['config'][prop] = secret
192     end
193   }
194 }
195 =begin
196 # **DEPRECATED!!**
197 oauth_client_id = nil
198 oauth_client_id_vault_item = node['screwdriver']['docker-compose']['oauth_client_id_vault_item']
199 unless oauth_client_id_vault_item.empty?
200   oauth_client_id = get_vault_item_value(oauth_client_id_vault_item)
201   api_envs['SECRET_OAUTH_CLIENT_ID'] = '${SECRET_OAUTH_CLIENT_ID}'
202 end
203
204 oauth_client_secret = nil
205 oauth_client_secret_vault_item = node['screwdriver']['docker-compose']['oauth_client_secret_vault_item']
206 unless oauth_client_secret_vault_item.empty?
207   oauth_client_secret = get_vault_item_value(oauth_client_secret_vault_item)
208   api_envs['SECRET_OAUTH_CLIENT_SECRET'] = '${SECRET_OAUTH_CLIENT_SECRET}'
209 end
210
211 webhook_github_secret = nil
212 webhook_github_secret_vault_item = node['screwdriver']['docker-compose']['webhook_github_secret_vault_item']
213 unless webhook_github_secret_vault_item.empty?
214   webhook_github_secret = get_vault_item_value(webhook_github_secret_vault_item)
215   api_envs['WEBHOOK_GITHUB_SECRET'] = '${WEBHOOK_GITHUB_SECRET}'
216 end
217 =end
218
219 db_username = nil
220 db_username_vault_item = node['screwdriver']['db_username_vault_item']
221 db_username = get_vault_item_value(db_username_vault_item) unless db_username_vault_item.empty?
222 db_username = env_local['DB_USERNAME'] if db_username.nil? && !env_local['DB_USERNAME'].nil?
223 db_username = 'sd-admin' if db_username.nil?
224 api_envs['DATASTORE_SEQUELIZE_USERNAME'] = '${DB_USERNAME}'
225
226 db_password = nil
227 db_password_vault_item = node['screwdriver']['db_password_vault_item']
228 db_password = get_vault_item_value(db_password_vault_item) unless db_password_vault_item.empty?
229 db_password = env_local['DB_PASSWORD'] if db_password.nil? && !env_local['DB_PASSWORD'].nil?
230 db_password = SecureRandom.urlsafe_base64(32) if db_password.nil?
231 api_envs['DATASTORE_SEQUELIZE_PASSWORD'] = '${DB_PASSWORD}'
232
233 db_root_password = nil
234 db_root_password_vault_item = node['screwdriver']['db_root_password_vault_item']
235 db_root_password = get_vault_item_value(db_root_password_vault_item) unless db_root_password_vault_item.empty?
236 db_root_password = env_local['DB_ROOT_PASSWORD'] if db_root_password.nil? && !env_local['DB_ROOT_PASSWORD'].nil?
237 db_root_password = SecureRandom.urlsafe_base64(32) if db_root_password.nil?
238 # add this env. variable at the MySQL service setup
239
240 db_dialect = api_envs_org['DATASTORE_SEQUELIZE_DIALECT']
241 case db_dialect
242 when 'sqlite'
243   api_vols.push("#{data_dir}:/sd-data:rw")
244   api_envs['DATASTORE_SEQUELIZE_STORAGE'] = '/sd-data/storage.db'
245 when 'mysql', 'postgres'
246   api_links.push('db')
247   api_envs['DATASTORE_SEQUELIZE_HOST'] = 'db'
248 end
249
250 # db
251 if db_dialect != 'sqlite'
252   #db_envs_org = config_srvs['db']['environment']
253   db_envs = {}
254   db_vols = config_srvs['db']['volumes'].to_a
255
256   case db_dialect
257   when 'mysql'
258     mysql_data_dir = "#{data_dir}/mysql"
259     resources(directory: mysql_data_dir) rescue directory mysql_data_dir do
260       owner 999
261       group 'root'
262       mode '0755'
263       recursive true
264     end
265
266     db_vols.push("#{mysql_data_dir}:/var/lib/mysql:rw")
267     db_envs['MYSQL_DATABASE'] = api_envs_org['DATASTORE_SEQUELIZE_DATABASE']
268     db_envs['MYSQL_USER'] = '${DB_USERNAME}' unless db_username.nil?
269     db_envs['MYSQL_PASSWORD'] = '${DB_PASSWORD}' unless db_password.nil?
270     db_envs['MYSQL_ROOT_PASSWORD'] = '${DB_ROOT_PASSWORD}' unless db_root_password.nil?
271   when 'postgres'
272     pg_data_dir = "#{data_dir}/postgres"
273     resources(directory: pg_data_dir) rescue directory pg_data_dir do
274       owner 'root'
275       group 'root'
276       mode '0755'
277       recursive true
278     end
279
280     db_vols.push("#{pg_data_dir}:/database:rw")
281     db_envs['POSTGRES_DB'] = api_envs_org['DATASTORE_SEQUELIZE_DATABASE']
282     db_envs['POSTGRES_USER'] = '${DB_USERNAME}' unless db_username.nil?
283     db_envs['POSTGRES_PASSWORD'] = '${DB_PASSWORD}' unless db_password.nil?
284     db_envs['PGDATA'] = '/database'
285   end
286 end
287
288 # queue
289 executor_queue_enabled = api_envs_org['EXECUTOR_QUEUE_ENABLED'] == 'true' ? true : false
290 if executor_queue_enabled
291   queue_envs = {}
292   queue_vols = config_srvs['queue']['volumes'].to_a
293
294   api_links.push('queue')
295   api_envs['QUEUE_REDIS_HOST'] = 'queue'
296   # TODO: set up env. vars.
297   # QUEUE_REDIS_PORT
298   # QUEUE_REDIS_PASSWORD
299   # QUEUE_REDIS_TLS_ENABLED
300   # QUEUE_REDIS_DATABASE
301 end
302
303 override_config_srvs['api']['links'] = api_links unless api_links.empty?
304
305 # ui
306 #ui_envs_org = config_srvs['ui']['environment']
307 ui_envs = {}
308 ui_vols = config_srvs['ui']['volumes'].to_a
309
310 ui_port = '9000'  # default
311 ui_in_port = '80'
312 ports = config_srvs['ui']['ports']
313 if ports.empty?
314   override_config_srvs['ui']['ports'] = ["#{ui_port}:#{ui_in_port}"]
315 else
316   ports.each {|port|
317     elms = port.split(':')
318     ui_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == ui_in_port
319   }
320 end
321
322 # store
323 store_backend = node['screwdriver']['store']['backend']
324 store_envs_org = config_srvs['store']['environment']
325 store_envs = {}
326 store_vols = config_srvs['store']['volumes'].to_a
327 store_links = []
328
329 store_port = '9002'  # default
330 store_in_port = store_envs_org['PORT']
331 ports = config_srvs['store']['ports']
332 if ports.empty?
333   override_config_srvs['store']['ports'] = ["#{store_port}:#{store_in_port}"]
334 else
335   ports.each {|port|
336     elms = port.split(':')
337     store_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == store_in_port
338   }
339 end
340
341 s3_access_key_id = nil
342 s3_access_key_id_vault_item = node['screwdriver']['s3_access_key_id_vault_item']
343 s3_access_key_id = get_vault_item_value(s3_access_key_id_vault_item) unless s3_access_key_id_vault_item.empty?
344 s3_access_key_id = env_local['S3_ACCESS_KEY_ID'] if s3_access_key_id.nil? && !env_local['S3_ACCESS_KEY_ID'].nil?
345 s3_access_key_id = SecureRandom.urlsafe_base64(16) if s3_access_key_id.nil?
346 store_envs['S3_ACCESS_KEY_ID'] = '${S3_ACCESS_KEY_ID}'
347
348 s3_access_key_secret = nil
349 s3_access_key_secret_vault_item = node['screwdriver']['s3_access_key_secret_vault_item']
350 s3_access_key_secret = get_vault_item_value(s3_access_key_secret_vault_item) unless s3_access_key_secret_vault_item.empty?
351 s3_access_key_secret = env_local['S3_ACCESS_KEY_SECRET'] if s3_access_key_secret.nil? && !env_local['S3_ACCESS_KEY_SECRET'].nil?
352 s3_access_key_secret = SecureRandom.urlsafe_base64(32) if s3_access_key_secret.nil?
353 store_envs['S3_ACCESS_KEY_SECRET'] = '${S3_ACCESS_KEY_SECRET}'
354
355 # S3 compatible server
356 if !store_backend.nil? && !store_backend.empty?
357   store_links.push('screwdriver.s3')
358   store_envs['STRATEGY'] = 's3'
359   store_envs['S3_BUCKET'] = 'screwdriver'
360
361   #s3_envs_org = config_srvs['screwdriver.s3']['environment']
362   s3_envs = {}
363   s3_vols = config_srvs['screwdriver.s3']['volumes'].to_a
364
365   s3_port = '9010'  # default
366   s3_in_port = '9000'
367   ports = config_srvs['screwdriver.s3']['ports']
368
369   case store_backend
370   when 'minio'
371     store_envs['S3_REGION'] = 'us-east-1'
372     store_envs['S3_ENDPOINT'] = "http://s3:#{s3_in_port}/screwdriver"  # for path style
373     store_envs['S3_SIG_VER'] = 'v4'
374
375     if ports.empty?
376       override_config_srvs['screwdriver.s3']['ports'] = ["#{s3_port}:#{s3_in_port}"]
377     else
378       ports.each {|port|
379         elms = port.split(':')
380         s3_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == s3_in_port
381       }
382     end
383
384     minio_data_dir = "#{data_dir}/minio"
385     resources(directory: minio_data_dir) rescue directory minio_data_dir do
386       owner 'root'
387       group 'root'
388       mode '0755'
389       recursive true
390     end
391
392     s3_vols.push("#{minio_data_dir}:/export:rw")
393     s3_envs['MINIO_ACCESS_KEY'] = '${S3_ACCESS_KEY_ID}' unless s3_access_key_id.nil?
394     s3_envs['MINIO_SECRET_KEY'] = '${S3_ACCESS_KEY_SECRET}' unless s3_access_key_secret.nil?
395   end
396 end
397
398 override_config_srvs['store']['links'] = store_links unless store_links.empty?
399
400 override_store_config['auth']['jwtPublicKey'] = jwt_public_key
401 # Note: prevent Chef from logging JWT key attribute value. (=> template variables)
402 # However Docker env file format does not support multi-line value and backslash escaped string yet.
403 #store_envs['SECRET_JWT_PUBLIC_KEY'] = '${SECRET_JWT_PUBLIC_KEY}'  # Useless
404 #store_envs['SECRET_JWT_PUBLIC_KEY']  = jwt_public_key  # NG
405
406 api_uri = api_envs_org['URI']
407 store_uri = store_envs_org['URI']
408 ui_uri = api_uri.gsub(/:\d+/, ":#{ui_port}")  # based on the API URI.
409
410 if node['screwdriver']['with_ssl_cert_cookbook']
411   cn = node['screwdriver']['ssl_cert']['common_name']
412   append_server_ssl_cn(cn)
413   include_recipe 'ssl_cert::server_key_pairs'
414
415   server_cert = server_cert_content(cn)
416   server_key = server_key_content(cn)
417
418   api_uri = api_uri.gsub('http://', 'https://')
419   store_uri = store_uri.gsub('http://', 'https://')
420
421   override_api_config['httpd']['tls'] = {}  # for FalseClass by default.
422   override_api_config['httpd']['tls']['cert'] = server_cert
423   override_api_config['httpd']['tls']['key'] = server_key
424   api_envs['IS_HTTPS'] = 'true'
425
426   override_store_config['httpd']['tls'] = {}  # for FalseClass by default.
427   override_store_config['httpd']['tls']['cert'] = server_cert
428   override_store_config['httpd']['tls']['key'] = server_key
429
430   # Note: Screwdriver UI image does not support TLS settings yet.
431   # https://github.com/screwdriver-cd/screwdriver/issues/377
432
433   if node['screwdriver']['ui']['tls_setup_mode'] == 'reverseproxy'
434     rproxy_in_port = '9000'
435     ports = config_srvs['reverseproxy']['ports']
436     if ports.empty?
437       override_config_srvs['reverseproxy']['ports'] = ["#{ui_port}:#{rproxy_in_port}"]
438     else
439       ports.each {|port|
440         elms = port.split(':')
441         ui_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == rproxy_in_port
442       }
443     end
444     ui_uri = api_uri.gsub(/:\d+/, ":#{ui_port}")  # based on the API URI.
445     # do not expose UI service directly.
446     node.rm('screwdriver', 'docker-compose', 'config', 'services', 'ui', 'ports')
447
448     rproxy_vols = config_srvs['reverseproxy']['volumes'].to_a
449     rproxy_vols.push("#{etc_dir}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro")
450     # Nginx parent process owner is root.
451     rproxy_vols.push("#{server_cert_path(cn)}:/root/server.crt:ro")
452     rproxy_vols.push("#{server_key_path(cn)}:/root/server.key:ro")
453     # reset vlumes array.
454     override_config_srvs['reverseproxy']['volumes'] = rproxy_vols
455
456     template "#{etc_dir}/nginx/nginx.conf" do
457       source 'opt/docker-compose/app/screwdriver/etc/nginx/nginx.conf'
458       owner 'root'
459       group 'root'
460       mode '0644'
461       action :create
462     end
463   else
464     node.rm('screwdriver', 'docker-compose', 'config', 'services', 'reverseproxy')
465     # TODO: in the future.
466   end
467 else
468   node.rm('screwdriver', 'docker-compose', 'config', 'services', 'reverseproxy')
469 end
470
471 # normalize URIs
472 api_envs['URI'] = api_uri
473 api_envs['ECOSYSTEM_STORE'] = store_uri
474 api_envs['ECOSYSTEM_UI'] = ui_uri
475
476 ui_envs['ECOSYSTEM_API'] = api_uri
477 ui_envs['ECOSYSTEM_STORE'] = store_uri
478
479 store_envs['URI'] = store_uri
480 store_envs['ECOSYSTEM_UI'] = ui_uri
481
482 # Common
483 if node['screwdriver']['docker-compose']['import_ca']
484   node['screwdriver']['ssl_cert']['ca_names'].each {|ca_name|
485     append_ca_name(ca_name)
486     ca_cert_vol = "#{ca_cert_path(ca_name)}:/usr/share/ca-certificates/#{ca_name}.crt:ro"
487     api_vols.push(ca_cert_vol)
488     #ui_vols.push(ca_cert_vol)
489   }
490   include_recipe 'ssl_cert::ca_certs'
491
492   import_ca_script = '/usr/local/bin/screwdriver_import_ca'
493   template "#{bin_dir}/screwdriver_import_ca" do
494     source 'opt/docker-compose/app/screwdriver/bin/screwdriver_import_ca'
495     owner 'root'
496     group 'root'
497     mode '0755'
498     action :create
499   end
500   import_ca_script_vol = "#{bin_dir}/screwdriver_import_ca:#{import_ca_script}:ro"
501   api_vols.push(import_ca_script_vol)
502   #ui_vols.push(import_ca_script_vol)
503
504   api_command = config_srvs['api']['command']
505   override_config_srvs['api']['command'] \
506     = "/bin/sh -c \"#{import_ca_script} && #{api_command}\""
507 end
508
509 [
510   'api',
511   'store',
512 ].each {|srv|
513   local_yaml_file = "#{config_dir}/#{srv}-local.yaml"
514   srv_vols = nil
515   srv_config = nil
516   if srv == 'api'
517     srv_vols = api_vols
518     srv_config = override_api_config
519   elsif srv == 'store'
520     srv_vols = store_vols
521     srv_config = override_store_config
522   end
523
524   template local_yaml_file do
525     source "opt/docker-compose/app/screwdriver/config/#{srv}-local.yaml"
526     owner 'root'
527     group 'root'
528     mode '0600'
529     sensitive true
530     # prevent Chef from logging password attribute value.
531     variables(
532       config: srv_config
533     )
534   end
535
536   srv_vols.push("#{local_yaml_file}:/config/local.yaml:ro")
537 }
538
539 # merge environment hash and reset volumes array.
540 force_override_config_srvs['api']['environment'] = api_envs unless api_envs.empty?
541 override_config_srvs['api']['volumes'] = api_vols unless api_vols.empty?
542 force_override_config_srvs['ui']['environment'] = ui_envs unless ui_envs.empty?
543 override_config_srvs['ui']['volumes'] = ui_vols unless ui_vols.empty?
544 force_override_config_srvs['store']['environment'] = store_envs unless store_envs.empty?
545 override_config_srvs['store']['volumes'] = store_vols unless store_vols.empty?
546 if db_dialect != 'sqlite'
547   force_override_config_srvs['db']['environment'] = db_envs unless db_envs.empty?
548   override_config_srvs['db']['volumes'] = db_vols unless db_vols.empty?
549 end
550 if executor_queue_enabled
551   force_override_config_srvs['queue']['environment'] = queue_envs unless queue_envs.empty?
552   override_config_srvs['queue']['volumes'] = queue_vols unless queue_vols.empty?
553 end
554 if !store_backend.nil? && !store_backend.empty?
555   force_override_config_srvs['screwdriver.s3']['environment'] = s3_envs unless s3_envs.empty?
556   override_config_srvs['screwdriver.s3']['volumes'] = s3_vols unless s3_vols.empty?
557 end
558
559 template env_file do
560   source 'opt/docker-compose/app/screwdriver/.env'
561   owner 'root'
562   group 'root'
563   mode '0600'
564   sensitive true
565   # prevent Chef from logging password attribute value.
566   variables(
567     # secrets
568     cookie_password: cookie_password,
569     password: password,
570     hashing_password: hashing_password,
571     db_username: db_username,
572     db_password: db_password,
573     db_root_password: db_root_password,
574     s3_access_key_id: s3_access_key_id,
575     s3_access_key_secret: s3_access_key_secret,
576     # **DEPRECATED!!**
577     # JWT keys setting -> /config/local.yaml
578     #jwt_private_key: jwt_private_key,
579     #jwt_public_key: jwt_public_key,
580     # SCM secrets setting -> /config/local.yaml
581     #oauth_client_id: oauth_client_id,
582     #oauth_client_secret: oauth_client_secret,
583     #webhook_github_secret: webhook_github_secret
584   )
585 end
586
587 template config_file do
588   source 'opt/docker-compose/app/screwdriver/docker-compose.yml'
589   owner 'root'
590   group 'root'
591   mode '0644'
592 end
593
594 # autopilot
595 srv = 'screwdriver'
596 template "/etc/cron.d/#{srv}-local" do
597   source  "etc/cron.d/#{srv}-local"
598   owner 'root'
599   group 'root'
600   mode '0644'
601   action :delete unless node['screwdriver']['docker-compose']['autopilot']['enabled']
602 end
603
604 log 'screwdriver docker-compose post install message' do
605   message <<-"EOM"
606 Note: You must execute the following command manually.
607     See #{doc_url}
608     * Start:
609       $ cd #{app_dir}
610       $ sudo docker-compose up -d
611     * Stop
612       $ sudo docker-compose down
613 EOM
614 end