kuby-core 0.11.14 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/Gemfile +2 -2
  4. data/README.md +2 -1
  5. data/bin/kuby +2 -0
  6. data/kuby-core.gemspec +2 -2
  7. data/lib/kuby/basic_logger.rb +1 -1
  8. data/lib/kuby/cli_base.rb +9 -4
  9. data/lib/kuby/commands.rb +16 -69
  10. data/lib/kuby/docker/alpine.rb +2 -1
  11. data/lib/kuby/docker/app_image.rb +19 -0
  12. data/lib/kuby/docker/bundler_phase.rb +9 -3
  13. data/lib/kuby/docker/cli.rb +4 -12
  14. data/lib/kuby/docker/docker_uri.rb +18 -7
  15. data/lib/kuby/docker/errors.rb +1 -19
  16. data/lib/kuby/docker/image.rb +115 -0
  17. data/lib/kuby/docker/layer.rb +0 -7
  18. data/lib/kuby/docker/local_tags.rb +9 -10
  19. data/lib/kuby/docker/package_phase.rb +0 -5
  20. data/lib/kuby/docker/packages.rb +1 -0
  21. data/lib/kuby/docker/remote_tags.rb +10 -5
  22. data/lib/kuby/docker/setup_phase.rb +17 -9
  23. data/lib/kuby/docker/spec.rb +29 -62
  24. data/lib/kuby/docker/timestamp_tag.rb +8 -1
  25. data/lib/kuby/docker/timestamped_image.rb +113 -0
  26. data/lib/kuby/docker/yarn_phase.rb +2 -2
  27. data/lib/kuby/docker.rb +27 -25
  28. data/lib/kuby/environment.rb +1 -10
  29. data/lib/kuby/kubernetes/bare_metal_provider.rb +53 -0
  30. data/lib/kuby/kubernetes/deployer.rb +2 -1
  31. data/lib/kuby/kubernetes/docker_desktop_provider.rb +0 -15
  32. data/lib/kuby/kubernetes/spec.rb +21 -17
  33. data/lib/kuby/kubernetes.rb +1 -0
  34. data/lib/kuby/plugin.rb +2 -2
  35. data/lib/kuby/plugins/rails_app/assets.rb +60 -70
  36. data/lib/kuby/plugins/rails_app/assets_image.rb +55 -0
  37. data/lib/kuby/plugins/rails_app/plugin.rb +54 -213
  38. data/lib/kuby/plugins/rails_app.rb +1 -0
  39. data/lib/kuby/tasks.rb +30 -69
  40. data/lib/kuby/version.rb +1 -1
  41. data/lib/kuby.rb +3 -20
  42. data/spec/docker/spec_spec.rb +21 -118
  43. data/spec/docker/timestamped_image_spec.rb +123 -0
  44. data/spec/spec_helper.rb +10 -11
  45. metadata +11 -14
  46. data/lib/kuby/dev_setup.rb +0 -346
  47. data/lib/kuby/docker/dev_spec.rb +0 -202
  48. data/lib/kuby/docker/metadata.rb +0 -90
  49. data/lib/kuby/docker/tags.rb +0 -92
  50. data/lib/kuby/rails_commands.rb +0 -84
  51. data/spec/docker/metadata_spec.rb +0 -73
  52. data/spec/dummy/Gemfile.lock +0 -223
  53. data/spec/dummy/config/master.key +0 -1
  54. data/spec/dummy/tmp/cache/bootsnap-load-path-cache +0 -0
@@ -47,38 +47,6 @@ module Kuby
47
47
  end
48
48
  end
49
49
 
50
- def configure_deployment(deployment, docker_image)
51
- spec = self
52
-
53
- deployment.spec.template.spec do
54
- init_container(:copy_assets) do
55
- name "#{spec.selector_app}-copy-assets"
56
- command %w(bundle exec rake kuby:rails_app:assets:copy)
57
- image docker_image
58
-
59
- volume_mount do
60
- name 'assets'
61
- mount_path RAILS_MOUNT_PATH
62
- end
63
- end
64
-
65
- container(:web) do
66
- volume_mount do
67
- name 'assets'
68
- mount_path NGINX_MOUNT_PATH
69
- end
70
- end
71
-
72
- volume do
73
- name 'assets'
74
-
75
- persistent_volume_claim do
76
- claim_name spec.volume_claim.metadata.name
77
- end
78
- end
79
- end
80
- end
81
-
82
50
  def copy_task
83
51
  @copy_task ||= AssetCopyTask.new(
84
52
  from: asset_path, to: RAILS_MOUNT_PATH
@@ -238,7 +206,7 @@ module Kuby
238
206
  container(:nginx) do
239
207
  name "#{kube_spec.selector_app}-#{kube_spec.role}"
240
208
  image_pull_policy 'IfNotPresent'
241
- image NGINX_IMAGE
209
+ image "#{kube_spec.image.image_url}:#{kube_spec.kubernetes.tag || Kuby::Docker::LATEST_TAG}-assets"
242
210
 
243
211
  port do
244
212
  container_port NGINX_PORT
@@ -252,11 +220,6 @@ module Kuby
252
220
  sub_path 'nginx.conf'
253
221
  end
254
222
 
255
- volume_mount do
256
- name 'assets'
257
- mount_path NGINX_MOUNT_PATH
258
- end
259
-
260
223
  readiness_probe do
261
224
  success_threshold 1
262
225
  failure_threshold 2
@@ -272,6 +235,10 @@ module Kuby
272
235
  end
273
236
  end
274
237
 
238
+ image_pull_secret do
239
+ name kube_spec.environment.kubernetes.registry_secret.metadata.name
240
+ end
241
+
275
242
  volume do
276
243
  name 'nginx-config'
277
244
 
@@ -280,14 +247,6 @@ module Kuby
280
247
  end
281
248
  end
282
249
 
283
- volume do
284
- name 'assets'
285
-
286
- persistent_volume_claim do
287
- claim_name kube_spec.volume_claim.metadata.name
288
- end
289
- end
290
-
291
250
  restart_policy 'Always'
292
251
  service_account_name kube_spec.service_account.metadata.name
293
252
  end
@@ -299,38 +258,19 @@ module Kuby
299
258
  @deployment
300
259
  end
301
260
 
302
- def volume_claim
303
- spec = self
304
-
305
- @volume_claim ||= KubeDSL.persistent_volume_claim do
306
- metadata do
307
- name "#{spec.selector_app}-#{spec.role}"
308
- namespace spec.namespace.metadata.name
309
- end
310
-
311
- spec do
312
- access_modes ['ReadWriteOnce']
313
- storage_class_name spec.environment.kubernetes.provider.storage_class_name
314
-
315
- resources do
316
- requests do
317
- add :storage, '10Gi'
318
- end
319
- end
320
- end
321
- end
322
- end
323
-
324
261
  def resources
325
262
  @resources ||= [
326
263
  service,
327
264
  service_account,
328
265
  nginx_config,
329
- deployment,
330
- volume_claim
266
+ deployment
331
267
  ]
332
268
  end
333
269
 
270
+ def docker_images
271
+ @docker_images ||= [docker_spec]
272
+ end
273
+
334
274
  def namespace
335
275
  environment.kubernetes.namespace
336
276
  end
@@ -342,6 +282,56 @@ module Kuby
342
282
  def role
343
283
  ROLE
344
284
  end
285
+
286
+ def docker
287
+ environment.docker
288
+ end
289
+
290
+ def kubernetes
291
+ environment.kubernetes
292
+ end
293
+
294
+ def docker_images
295
+ @docker_images ||= [image]
296
+ end
297
+
298
+ def image
299
+ @image ||= RailsApp::AssetsImage.new(docker.image, -> { dockerfile })
300
+ end
301
+
302
+ private
303
+
304
+ def dockerfile
305
+ Docker::Dockerfile.new.tap do |df|
306
+ base_image = docker.image.current_version
307
+ cur_tag = base_image.main_tag
308
+ app_name = environment.app_name.downcase
309
+
310
+ tags = begin
311
+ [base_image.previous_timestamp_tag(cur_tag).to_s, cur_tag]
312
+ rescue Kuby::Docker::MissingTagError
313
+ [cur_tag, nil]
314
+ end
315
+
316
+ # this can handle more than 2 tags by virtue of using each_cons :)
317
+ tags.each_cons(2) do |prev_tag, tag|
318
+ prev_image_name = "#{app_name}-#{prev_tag}"
319
+ df.from("#{base_image.image_url}:#{prev_tag}", as: prev_image_name)
320
+ df.run("mkdir -p #{RAILS_MOUNT_PATH}")
321
+ df.run("bundle exec rake kuby:rails_app:assets:copy")
322
+
323
+ if tag
324
+ image_name = "#{app_name}-#{tag}"
325
+ df.from("#{base_image.image_url}:#{tag}", as: image_name)
326
+ df.copy("--from=#{prev_image_name} #{RAILS_MOUNT_PATH}", RAILS_MOUNT_PATH)
327
+ df.run("bundle exec rake kuby:rails_app:assets:copy")
328
+ end
329
+ end
330
+
331
+ df.from(NGINX_IMAGE)
332
+ df.copy("--from=#{"#{app_name}-#{tags.compact.last}"} #{RAILS_MOUNT_PATH}", NGINX_MOUNT_PATH)
333
+ end
334
+ end
345
335
  end
346
336
  end
347
337
  end
@@ -0,0 +1,55 @@
1
+ module Kuby
2
+ module Plugins
3
+ module RailsApp
4
+ class AssetsImage < ::Kuby::Docker::Image
5
+ attr_reader :base_image
6
+
7
+ def initialize(base_image, dockerfile, main_tag = nil, alias_tags = [])
8
+ super(dockerfile, base_image.image_url, base_image.credentials, main_tag, alias_tags)
9
+ @base_image = base_image
10
+ end
11
+
12
+ def new_version
13
+ # Asset images track the base image, so return the current version
14
+ # here. There can be no asset image without a base image.
15
+ current_version
16
+ end
17
+
18
+ def current_version
19
+ @current_version ||= duplicate_with_annotated_tags(
20
+ base_image.current_version
21
+ )
22
+ end
23
+
24
+ def previous_version
25
+ @previous_version ||= duplicate_with_annotated_tags(
26
+ base_image.previous_version
27
+ )
28
+ end
29
+
30
+ def build(build_args = {})
31
+ docker_cli.build(current_version, build_args: build_args)
32
+ end
33
+
34
+ def push(tag)
35
+ docker_cli.push(image_url, tag)
36
+ end
37
+
38
+ private
39
+
40
+ def duplicate_with_annotated_tags(image)
41
+ self.class.new(
42
+ base_image,
43
+ dockerfile,
44
+ annotate_tag(image.main_tag),
45
+ image.alias_tags.map { |at| annotate_tag(at) }
46
+ )
47
+ end
48
+
49
+ def annotate_tag(tag)
50
+ "#{tag}-assets"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -47,27 +47,23 @@ module Kuby
47
47
  environment.kubernetes.plugins[@database.plugin_name] = @database.plugin
48
48
  environment.kubernetes.add_plugin(:kube_db)
49
49
 
50
- unless environment.development?
51
- environment.docker do
52
- insert :rewrite_db_config, RewriteDbConfig.new, after: :copy_phase
53
- end
50
+ environment.docker do
51
+ insert :rewrite_db_config, RewriteDbConfig.new, after: :copy_phase
54
52
  end
55
53
  end
56
54
 
57
- unless environment.development?
58
- environment.kubernetes.add_plugin(:nginx_ingress)
59
- environment.kubernetes.add_plugin(:rails_assets) do
60
- asset_url context.asset_url
61
- packs_url context.packs_url
62
- asset_path context.asset_path
63
- end
55
+ environment.kubernetes.add_plugin(:nginx_ingress)
56
+ environment.kubernetes.add_plugin(:rails_assets) do
57
+ asset_url context.asset_url
58
+ packs_url context.packs_url
59
+ asset_path context.asset_path
60
+ end
64
61
 
65
- if @tls_enabled
66
- context = self
62
+ if @tls_enabled
63
+ context = self
67
64
 
68
- environment.kubernetes.add_plugin(:cert_manager) do
69
- email context.environment.docker.credentials.email
70
- end
65
+ environment.kubernetes.add_plugin(:cert_manager) do
66
+ email context.environment.docker.credentials.email
71
67
  end
72
68
  end
73
69
  end
@@ -79,14 +75,13 @@ module Kuby
79
75
  def before_deploy(manifest)
80
76
  # Make sure plugin has been configured. If not, do nothing.
81
77
  if cert_manager = environment.kubernetes.plugin(:cert_manager)
82
- cert_manager.annotate_ingress(ingress)
78
+ cert_manager.annotate_ingress(ingress) if tls_enabled
83
79
  end
84
80
 
85
- image_with_tag = "#{docker.metadata.image_url}:#{kubernetes.tag}"
81
+ image_with_tag = "#{docker.image.image_url}:#{kubernetes.tag || Kuby::Docker::LATEST_TAG}"
86
82
 
87
83
  if assets = environment.kubernetes.plugin(:rails_assets)
88
84
  assets.configure_ingress(ingress, hostname)
89
- assets.configure_deployment(deployment, image_with_tag)
90
85
  end
91
86
 
92
87
  spec = self
@@ -99,14 +94,12 @@ module Kuby
99
94
  image image_with_tag
100
95
  end
101
96
 
102
- unless spec.environment.development?
103
- init_container(:create_db) do
104
- image image_with_tag
105
- end
97
+ init_container(:create_db) do
98
+ image image_with_tag
99
+ end
106
100
 
107
- init_container(:migrate_db) do
108
- image image_with_tag
109
- end
101
+ init_container(:migrate_db) do
102
+ image image_with_tag
110
103
  end
111
104
  end
112
105
  end
@@ -248,7 +241,7 @@ module Kuby
248
241
  annotations do
249
242
  add(
250
243
  'getkuby.io/dockerfile-checksum',
251
- kube_spec.environment.docker.to_dockerfile.checksum
244
+ kube_spec.environment.docker.image.dockerfile.checksum
252
245
  )
253
246
  end
254
247
  end
@@ -303,93 +296,57 @@ module Kuby
303
296
  end
304
297
  end
305
298
 
306
- unless kube_spec.environment.development?
307
- readiness_probe do
308
- success_threshold 1
309
- failure_threshold 2
310
- initial_delay_seconds 15
311
- period_seconds 3
312
- timeout_seconds 1
313
-
314
- http_get do
315
- path '/healthz'
316
- port kube_spec.docker.webserver_phase.port
317
- scheme 'HTTP'
318
- end
319
- end
320
- end
321
-
322
- if kube_spec.environment.development?
323
- env do
324
- name 'BUNDLE_PATH'
325
- value '/bundle'
326
- end
327
-
328
- env do
329
- name 'GEM_HOME'
330
- value '/bundle'
331
- end
332
-
333
- env do
334
- name 'BOOTSNAP_CACHE_DIR'
335
- value '/usr/src/bootsnap'
336
- end
337
-
338
- volume_mount do
339
- name "#{kube_spec.selector_app}-code"
340
- mount_path '/usr/src/app'
341
- end
342
-
343
- volume_mount do
344
- name "#{kube_spec.selector_app}-bundle"
345
- mount_path '/bundle'
346
- end
347
-
348
- volume_mount do
349
- name "#{kube_spec.selector_app}-bootsnap"
350
- mount_path '/usr/src/bootsnap'
299
+ readiness_probe do
300
+ success_threshold 1
301
+ failure_threshold 2
302
+ initial_delay_seconds 15
303
+ period_seconds 3
304
+ timeout_seconds 1
305
+
306
+ http_get do
307
+ path '/healthz'
308
+ port kube_spec.docker.webserver_phase.port
309
+ scheme 'HTTP'
351
310
  end
352
311
  end
353
312
  end
354
313
 
355
- if kube_spec.environment.development?
356
- volume do
357
- name "#{kube_spec.selector_app}-code"
314
+ init_container(:create_db) do
315
+ name "#{kube_spec.selector_app}-create-db"
316
+ command %w(bundle exec rake kuby:rails_app:db:create_unless_exists)
358
317
 
359
- persistent_volume_claim do
360
- claim_name kube_spec.code_volume_claim.metadata.name
318
+ env_from do
319
+ config_map_ref do
320
+ name kube_spec.config_map.metadata.name
361
321
  end
362
322
  end
363
323
 
364
- volume do
365
- name "#{kube_spec.selector_app}-bundle"
366
-
367
- persistent_volume_claim do
368
- claim_name kube_spec.bundle_volume_claim.metadata.name
324
+ env_from do
325
+ secret_ref do
326
+ name kube_spec.app_secrets.metadata.name
369
327
  end
370
328
  end
329
+ end
371
330
 
372
- volume do
373
- name "#{kube_spec.selector_app}-bootsnap"
331
+ init_container(:migrate_db) do
332
+ name "#{kube_spec.selector_app}-migrate-db"
333
+ command %w(bundle exec rake db:migrate)
374
334
 
375
- persistent_volume_claim do
376
- claim_name kube_spec.bootsnap_volume_claim.metadata.name
335
+ env_from do
336
+ config_map_ref do
337
+ name kube_spec.config_map.metadata.name
377
338
  end
378
339
  end
379
- else
380
- init_container(:create_db) do
381
- name "#{kube_spec.selector_app}-create-db"
382
- command %w(bundle exec rake kuby:rails_app:db:create_unless_exists)
383
- end
384
340
 
385
- init_container(:migrate_db) do
386
- name "#{kube_spec.selector_app}-migrate-db"
387
- command %w(bundle exec rake db:migrate)
341
+ env_from do
342
+ secret_ref do
343
+ name kube_spec.app_secrets.metadata.name
344
+ end
388
345
  end
346
+ end
389
347
 
390
- image_pull_secret do
391
- name kube_spec.environment.kubernetes.registry_secret.metadata.name
392
- end
348
+ image_pull_secret do
349
+ name kube_spec.environment.kubernetes.registry_secret.metadata.name
393
350
  end
394
351
 
395
352
  restart_policy 'Always'
@@ -446,118 +403,6 @@ module Kuby
446
403
  @ingress
447
404
  end
448
405
 
449
- def code_volume(&block)
450
- spec = self
451
-
452
- if environment.development?
453
- @code_volume ||= KubeDSL.persistent_volume do
454
- metadata do
455
- name "#{spec.selector_app}-code"
456
- end
457
-
458
- spec do
459
- access_modes ['ReadWriteMany']
460
-
461
- capacity do
462
- add :storage, '1Mi'
463
- end
464
-
465
- host_path do
466
- path File.expand_path(spec.root)
467
- end
468
-
469
- storage_class_name 'hostpath'
470
- end
471
- end
472
-
473
- @code_volume.instance_eval(&block) if block
474
- @code_volume
475
- end
476
- end
477
-
478
- def code_volume_claim(&block)
479
- spec = self
480
-
481
- if environment.development?
482
- @code_volume_claim ||= KubeDSL.persistent_volume_claim do
483
- metadata do
484
- name "#{spec.selector_app}-code"
485
- namespace spec.namespace.metadata.name
486
- end
487
-
488
- spec do
489
- access_modes ['ReadWriteMany']
490
-
491
- resources do
492
- requests do
493
- add :storage, '1Mi'
494
- end
495
- end
496
-
497
- storage_class_name 'hostpath'
498
- volume_name spec.code_volume.metadata.name
499
- end
500
- end
501
-
502
- @code_volume_claim.instance_eval(&block) if block
503
- @code_volume_claim
504
- end
505
- end
506
-
507
- def bundle_volume_claim(&block)
508
- spec = self
509
-
510
- if environment.development?
511
- @bundle_volume_claim ||= KubeDSL.persistent_volume_claim do
512
- metadata do
513
- name "#{spec.selector_app}-bundle"
514
- namespace spec.namespace.metadata.name
515
- end
516
-
517
- spec do
518
- access_modes ['ReadWriteMany']
519
- storage_class_name 'hostpath'
520
-
521
- resources do
522
- requests do
523
- add :storage, '2Gi'
524
- end
525
- end
526
- end
527
- end
528
-
529
- @bundle_volume_claim.instance_eval(&block) if block
530
- @bundle_volume_claim
531
- end
532
- end
533
-
534
- def bootsnap_volume_claim(&block)
535
- spec = self
536
-
537
- if environment.development?
538
- @bootsnap_volume_claim ||= KubeDSL.persistent_volume_claim do
539
- metadata do
540
- name "#{spec.selector_app}-bootsnap"
541
- namespace spec.namespace.metadata.name
542
- end
543
-
544
- spec do
545
- access_modes ['ReadWriteMany']
546
- storage_class_name 'hostpath'
547
-
548
- resources do
549
- requests do
550
- add :storage, '2Gi'
551
- end
552
- end
553
- end
554
- end
555
-
556
- @bootsnap_volume_claim.instance_eval(&block) if block
557
- @bootsnap_volume_claim
558
- end
559
- end
560
-
561
406
  def resources
562
407
  @resources ||= [
563
408
  service,
@@ -566,10 +411,6 @@ module Kuby
566
411
  app_secrets,
567
412
  deployment,
568
413
  ingress,
569
- code_volume,
570
- code_volume_claim,
571
- bundle_volume_claim,
572
- bootsnap_volume_claim,
573
414
  *database&.plugin&.resources
574
415
  ]
575
416
  end
@@ -3,6 +3,7 @@ module Kuby
3
3
  module Plugins
4
4
  module RailsApp
5
5
  autoload :AssetCopyTask, 'kuby/plugins/rails_app/asset_copy_task'
6
+ autoload :AssetsImage, 'kuby/plugins/rails_app/assets_image'
6
7
  autoload :Assets, 'kuby/plugins/rails_app/assets'
7
8
  autoload :Database, 'kuby/plugins/rails_app/database'
8
9
  autoload :MySQL, 'kuby/plugins/rails_app/mysql'