kuby-core 0.7.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/Gemfile +1 -0
  4. data/README.md +11 -1
  5. data/bin/kuby +4 -0
  6. data/kuby-core.gemspec +9 -4
  7. data/lib/kuby.rb +58 -19
  8. data/lib/kuby/basic_logger.rb +13 -0
  9. data/lib/kuby/cli_base.rb +81 -8
  10. data/lib/kuby/commands.rb +244 -0
  11. data/lib/kuby/definition.rb +1 -11
  12. data/lib/kuby/dev_setup.rb +255 -0
  13. data/lib/kuby/docker.rb +1 -0
  14. data/lib/kuby/docker/bundler_phase.rb +3 -3
  15. data/lib/kuby/docker/cli.rb +13 -1
  16. data/lib/kuby/docker/dev_spec.rb +131 -0
  17. data/lib/kuby/docker/dockerfile.rb +16 -1
  18. data/lib/kuby/docker/layer.rb +4 -4
  19. data/lib/kuby/docker/layer_stack.rb +4 -0
  20. data/lib/kuby/docker/local_tags.rb +4 -0
  21. data/lib/kuby/docker/metadata.rb +18 -38
  22. data/lib/kuby/docker/package_phase.rb +2 -2
  23. data/lib/kuby/docker/setup_phase.rb +3 -2
  24. data/lib/kuby/docker/spec.rb +42 -16
  25. data/lib/kuby/docker/timestamp_tag.rb +6 -0
  26. data/lib/kuby/environment.rb +15 -2
  27. data/lib/kuby/kubernetes.rb +9 -11
  28. data/lib/kuby/kubernetes/deploy_task.rb +4 -1
  29. data/lib/kuby/kubernetes/deployer.rb +70 -15
  30. data/lib/kuby/kubernetes/{minikube_provider.rb → docker_desktop_provider.rb} +8 -4
  31. data/lib/kuby/kubernetes/provider.rb +12 -8
  32. data/lib/kuby/kubernetes/spec.rb +30 -29
  33. data/lib/kuby/plugin.rb +59 -0
  34. data/lib/kuby/plugin_registry.rb +27 -0
  35. data/lib/kuby/plugins.rb +6 -0
  36. data/lib/kuby/plugins/nginx_ingress.rb +71 -0
  37. data/lib/kuby/plugins/rails_app.rb +18 -0
  38. data/lib/kuby/plugins/rails_app/asset_copy_task.rb +117 -0
  39. data/lib/kuby/plugins/rails_app/assets.rb +347 -0
  40. data/lib/kuby/plugins/rails_app/database.rb +74 -0
  41. data/lib/kuby/{kubernetes/plugins → plugins}/rails_app/generators/kuby.rb +14 -16
  42. data/lib/kuby/plugins/rails_app/mysql.rb +152 -0
  43. data/lib/kuby/plugins/rails_app/plugin.rb +593 -0
  44. data/lib/kuby/plugins/rails_app/postgres.rb +143 -0
  45. data/lib/kuby/plugins/rails_app/rewrite_db_config.rb +11 -0
  46. data/lib/kuby/plugins/rails_app/sqlite.rb +32 -0
  47. data/lib/kuby/plugins/rails_app/tasks.rake +36 -0
  48. data/lib/kuby/rails_commands.rb +89 -0
  49. data/lib/kuby/railtie.rb +0 -4
  50. data/lib/kuby/tasks.rb +85 -31
  51. data/lib/kuby/version.rb +1 -1
  52. data/spec/docker/metadata_spec.rb +84 -0
  53. data/spec/docker/spec_spec.rb +266 -0
  54. data/spec/docker/timestamp_tag_spec.rb +54 -4
  55. data/spec/dummy/Gemfile +54 -0
  56. data/spec/dummy/Gemfile.lock +223 -0
  57. data/spec/dummy/README.md +24 -0
  58. data/spec/dummy/Rakefile +6 -0
  59. data/spec/dummy/app/assets/config/manifest.js +2 -0
  60. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  61. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  62. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  63. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  64. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  65. data/spec/dummy/app/javascript/channels/consumer.js +6 -0
  66. data/spec/dummy/app/javascript/channels/index.js +5 -0
  67. data/spec/dummy/app/javascript/packs/application.js +17 -0
  68. data/spec/dummy/app/jobs/application_job.rb +7 -0
  69. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  70. data/spec/dummy/app/models/application_record.rb +3 -0
  71. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  72. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  73. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  74. data/spec/dummy/bin/bundle +114 -0
  75. data/spec/dummy/bin/rails +9 -0
  76. data/spec/dummy/bin/rake +9 -0
  77. data/spec/dummy/bin/setup +36 -0
  78. data/spec/dummy/bin/spring +17 -0
  79. data/spec/dummy/bin/yarn +11 -0
  80. data/spec/dummy/config.ru +5 -0
  81. data/spec/dummy/config/application.rb +19 -0
  82. data/spec/dummy/config/boot.rb +4 -0
  83. data/spec/dummy/config/cable.yml +10 -0
  84. data/spec/dummy/config/credentials.yml.enc +1 -0
  85. data/spec/dummy/config/database.yml +25 -0
  86. data/spec/dummy/config/environment.rb +5 -0
  87. data/spec/dummy/config/environments/development.rb +62 -0
  88. data/spec/dummy/config/environments/production.rb +112 -0
  89. data/spec/dummy/config/environments/test.rb +49 -0
  90. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  91. data/spec/dummy/config/initializers/assets.rb +14 -0
  92. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  93. data/spec/dummy/config/initializers/content_security_policy.rb +30 -0
  94. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  95. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  96. data/spec/dummy/config/initializers/inflections.rb +16 -0
  97. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  98. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  99. data/spec/dummy/config/locales/en.yml +33 -0
  100. data/spec/dummy/config/master.key +1 -0
  101. data/spec/dummy/config/puma.rb +38 -0
  102. data/spec/dummy/config/routes.rb +3 -0
  103. data/spec/dummy/config/spring.rb +6 -0
  104. data/spec/dummy/config/storage.yml +34 -0
  105. data/spec/dummy/db/seeds.rb +7 -0
  106. data/spec/dummy/package.json +11 -0
  107. data/spec/dummy/public/404.html +67 -0
  108. data/spec/dummy/public/422.html +67 -0
  109. data/spec/dummy/public/500.html +66 -0
  110. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  111. data/spec/dummy/public/apple-touch-icon.png +0 -0
  112. data/spec/dummy/public/favicon.ico +0 -0
  113. data/spec/dummy/public/robots.txt +1 -0
  114. data/spec/dummy/test/application_system_test_case.rb +5 -0
  115. data/spec/dummy/test/channels/application_cable/connection_test.rb +11 -0
  116. data/spec/dummy/test/test_helper.rb +13 -0
  117. data/spec/dummy/tmp/cache/bootsnap-load-path-cache +0 -0
  118. data/spec/spec_helper.rb +77 -2
  119. data/spec/support/docker/fake_cli.rb +54 -0
  120. data/spec/support/docker/remote/fake_client.rb +16 -0
  121. data/spec/trailing_hash_spec.rb +23 -0
  122. metadata +139 -30
  123. data/lib/ext/krane/kubernetes_resource.rb +0 -16
  124. data/lib/kuby/kubernetes/plugin.rb +0 -55
  125. data/lib/kuby/kubernetes/plugins.rb +0 -8
  126. data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +0 -73
  127. data/lib/kuby/kubernetes/plugins/rails_app.rb +0 -16
  128. data/lib/kuby/kubernetes/plugins/rails_app/database.rb +0 -79
  129. data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +0 -154
  130. data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +0 -379
  131. data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +0 -142
  132. data/lib/kuby/kubernetes/plugins/rails_app/rewrite_db_config.rb +0 -13
  133. data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +0 -30
  134. data/lib/kuby/kubernetes/plugins/rails_app/tasks.rake +0 -28
  135. data/lib/kuby/tasks/kuby.rake +0 -70
@@ -0,0 +1,347 @@
1
+ require 'kube-dsl'
2
+
3
+ module Kuby
4
+ module Plugins
5
+ module RailsApp
6
+ class Assets < ::Kuby::Plugin
7
+ extend ::KubeDSL::ValueFields
8
+
9
+ ROLE = 'assets'.freeze
10
+ NGINX_IMAGE = 'nginx:1.9-alpine'.freeze
11
+ NGINX_PORT = 8082
12
+ NGINX_MOUNT_PATH = '/usr/share/nginx/assets'.freeze
13
+ RAILS_MOUNT_PATH = '/usr/share/assets'.freeze
14
+
15
+ value_fields :asset_url, :packs_url, :asset_path
16
+
17
+ def configure(&block)
18
+ instance_eval(&block)
19
+ end
20
+
21
+ def configure_ingress(ingress, hostname)
22
+ spec = self
23
+
24
+ ingress.spec.rule do
25
+ host hostname
26
+
27
+ http do
28
+ path do
29
+ path spec.asset_url
30
+
31
+ backend do
32
+ service_name spec.service.metadata.name
33
+ service_port spec.service.spec.ports.first.port
34
+ end
35
+ end
36
+
37
+ path do
38
+ path spec.packs_url
39
+
40
+ backend do
41
+ service_name spec.service.metadata.name
42
+ service_port spec.service.spec.ports.first.port
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def configure_deployment(deployment, docker_image)
50
+ spec = self
51
+
52
+ deployment.spec.template.spec do
53
+ init_container(:copy_assets) do
54
+ name "#{spec.selector_app}-copy-assets"
55
+ command %w(bundle exec rake kuby:rails_app:assets:copy)
56
+ image docker_image
57
+
58
+ volume_mount do
59
+ name 'assets'
60
+ mount_path RAILS_MOUNT_PATH
61
+ end
62
+ end
63
+
64
+ container(:web) do
65
+ volume_mount do
66
+ name 'assets'
67
+ mount_path NGINX_MOUNT_PATH
68
+ end
69
+ end
70
+
71
+ volume do
72
+ name 'assets'
73
+
74
+ persistent_volume_claim do
75
+ claim_name spec.volume_claim.metadata.name
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def copy_task
82
+ @copy_task ||= AssetCopyTask.new(
83
+ from: asset_path, to: RAILS_MOUNT_PATH
84
+ )
85
+ end
86
+
87
+ def service(&block)
88
+ spec = self
89
+
90
+ @service ||= KubeDSL.service do
91
+ metadata do
92
+ name "#{spec.selector_app}-#{spec.role}-svc"
93
+ namespace spec.namespace.metadata.name
94
+
95
+ labels do
96
+ add :app, spec.selector_app
97
+ add :role, spec.role
98
+ end
99
+ end
100
+
101
+ spec do
102
+ type 'NodePort'
103
+
104
+ selector do
105
+ add :app, spec.selector_app
106
+ add :role, spec.role
107
+ end
108
+
109
+ port do
110
+ name 'http'
111
+ port NGINX_PORT
112
+ protocol 'TCP'
113
+ target_port 'http'
114
+ end
115
+ end
116
+ end
117
+
118
+ @service.instance_eval(&block) if block
119
+ @service
120
+ end
121
+
122
+ def service_account(&block)
123
+ spec = self
124
+
125
+ @service_account ||= KubeDSL.service_account do
126
+ metadata do
127
+ name "#{spec.selector_app}-#{spec.role}-sa"
128
+ namespace spec.namespace.metadata.name
129
+
130
+ labels do
131
+ add :app, spec.selector_app
132
+ add :role, spec.role
133
+ end
134
+ end
135
+ end
136
+
137
+ @service_account.instance_eval(&block) if block
138
+ @service_account
139
+ end
140
+
141
+ def nginx_config(&block)
142
+ spec = self
143
+
144
+ @nginx_config ||= KubeDSL.config_map do
145
+ metadata do
146
+ name "#{spec.selector_app}-#{spec.role}-nginx-config"
147
+ namespace spec.namespace.metadata.name
148
+ end
149
+
150
+ data do
151
+ add 'nginx.conf', <<~END
152
+ user nginx;
153
+ worker_processes 1;
154
+
155
+ error_log /var/log/nginx/error.log warn;
156
+ pid /var/run/nginx.pid;
157
+
158
+ events {
159
+ worker_connections 1024;
160
+ }
161
+
162
+ http {
163
+ include /etc/nginx/mime.types;
164
+ default_type application/octet-stream;
165
+
166
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
167
+ '$status $body_bytes_sent "$http_referer" '
168
+ '"$http_user_agent" "$http_x_forwarded_for"';
169
+
170
+ access_log /var/log/nginx/access.log main;
171
+
172
+ sendfile on;
173
+ keepalive_timeout 65;
174
+ gzip on;
175
+
176
+ server {
177
+ listen #{NGINX_PORT};
178
+ server_name localhost;
179
+
180
+ location / {
181
+ root #{File.join(NGINX_MOUNT_PATH, 'current')};
182
+ }
183
+
184
+ error_page 500 502 503 504 /500.html;
185
+ }
186
+ }
187
+ END
188
+ end
189
+ end
190
+
191
+ @nginx_config.instance_eval(&block) if block
192
+ @nginx_config
193
+ end
194
+
195
+ def deployment(&block)
196
+ kube_spec = self
197
+
198
+ @deployment ||= KubeDSL.deployment do
199
+ metadata do
200
+ name "#{kube_spec.selector_app}-#{kube_spec.role}"
201
+ namespace kube_spec.namespace.metadata.name
202
+
203
+ labels do
204
+ add :app, kube_spec.selector_app
205
+ add :role, kube_spec.role
206
+ end
207
+ end
208
+
209
+ spec do
210
+ replicas 1
211
+
212
+ selector do
213
+ match_labels do
214
+ add :app, kube_spec.selector_app
215
+ add :role, kube_spec.role
216
+ end
217
+ end
218
+
219
+ strategy do
220
+ type 'RollingUpdate'
221
+
222
+ rolling_update do
223
+ max_surge '25%'
224
+ max_unavailable 0
225
+ end
226
+ end
227
+
228
+ template do
229
+ metadata do
230
+ labels do
231
+ add :app, kube_spec.selector_app
232
+ add :role, kube_spec.role
233
+ end
234
+ end
235
+
236
+ spec do
237
+ container(:nginx) do
238
+ name "#{kube_spec.selector_app}-#{kube_spec.role}"
239
+ image_pull_policy 'IfNotPresent'
240
+ image NGINX_IMAGE
241
+
242
+ port do
243
+ container_port NGINX_PORT
244
+ name 'http'
245
+ protocol 'TCP'
246
+ end
247
+
248
+ volume_mount do
249
+ name 'nginx-config'
250
+ mount_path '/etc/nginx/nginx.conf'
251
+ sub_path 'nginx.conf'
252
+ end
253
+
254
+ volume_mount do
255
+ name 'assets'
256
+ mount_path NGINX_MOUNT_PATH
257
+ end
258
+
259
+ readiness_probe do
260
+ success_threshold 1
261
+ failure_threshold 2
262
+ initial_delay_seconds 5
263
+ period_seconds 3
264
+ timeout_seconds 1
265
+
266
+ http_get do
267
+ path '/500.html'
268
+ port NGINX_PORT
269
+ scheme 'HTTP'
270
+ end
271
+ end
272
+ end
273
+
274
+ volume do
275
+ name 'nginx-config'
276
+
277
+ config_map do
278
+ name kube_spec.nginx_config.metadata.name
279
+ end
280
+ end
281
+
282
+ volume do
283
+ name 'assets'
284
+
285
+ persistent_volume_claim do
286
+ claim_name kube_spec.volume_claim.metadata.name
287
+ end
288
+ end
289
+
290
+ restart_policy 'Always'
291
+ service_account_name kube_spec.service_account.metadata.name
292
+ end
293
+ end
294
+ end
295
+ end
296
+
297
+ @deployment.instance_eval(&block) if block
298
+ @deployment
299
+ end
300
+
301
+ def volume_claim
302
+ spec = self
303
+
304
+ @volume_claim ||= KubeDSL.persistent_volume_claim do
305
+ metadata do
306
+ name "#{spec.selector_app}-#{spec.role}"
307
+ namespace spec.namespace.metadata.name
308
+ end
309
+
310
+ spec do
311
+ access_modes ['ReadWriteOnce']
312
+ storage_class_name spec.environment.kubernetes.provider.storage_class_name
313
+
314
+ resources do
315
+ requests do
316
+ add :storage, '10Gi'
317
+ end
318
+ end
319
+ end
320
+ end
321
+ end
322
+
323
+ def resources
324
+ @resources ||= [
325
+ service,
326
+ service_account,
327
+ nginx_config,
328
+ deployment,
329
+ volume_claim
330
+ ]
331
+ end
332
+
333
+ def namespace
334
+ environment.kubernetes.namespace
335
+ end
336
+
337
+ def selector_app
338
+ environment.kubernetes.selector_app
339
+ end
340
+
341
+ def role
342
+ ROLE
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,74 @@
1
+ require 'yaml'
2
+
3
+ module Kuby
4
+ module Plugins
5
+ module RailsApp
6
+ class UnsupportedDatabaseError < StandardError; end
7
+
8
+ class Database
9
+ ADAPTER_MAP = {
10
+ sqlite3: Sqlite,
11
+ mysql2: MySQL,
12
+ postgresql: Postgres
13
+ }.freeze
14
+
15
+ def self.get(rails_app)
16
+ if rails_app.manage_database?
17
+ new(rails_app)
18
+ end
19
+ end
20
+
21
+ def self.get_adapter(adapter_name)
22
+ ADAPTER_MAP.fetch(adapter_name) do
23
+ raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter}' "\
24
+ 'database adapter'
25
+ end
26
+ end
27
+
28
+ attr_reader :rails_app
29
+
30
+ def initialize(rails_app)
31
+ @rails_app = rails_app
32
+ end
33
+
34
+ def plugin
35
+ @plugin ||= self.class
36
+ .get_adapter(adapter_name)
37
+ .new(rails_app.environment, db_configs)
38
+ end
39
+
40
+ def adapter_name
41
+ @adapter_name ||= db_config['adapter'].to_sym
42
+ end
43
+
44
+ alias_method :plugin_name, :adapter_name
45
+
46
+ private
47
+
48
+ def db_config
49
+ @db_config ||= db_configs[rails_app.environment.name]
50
+ end
51
+
52
+ def db_configs
53
+ @db_configs ||= YAML.load(File.read(db_config_path))
54
+ end
55
+
56
+ def db_config_path
57
+ @db_config_path ||= begin
58
+ db_config_paths.first or
59
+ raise "Couldn't find database config at #{rails_app.root}"
60
+ end
61
+ end
62
+
63
+ def db_config_paths
64
+ @db_config_paths ||=
65
+ Dir.glob(
66
+ File.join(
67
+ rails_app.root, 'config', 'database.{yml,erb,yml.erb,yaml,yaml.erb}'
68
+ )
69
+ )
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -2,25 +2,18 @@ require 'rails/generators'
2
2
  require 'rails/generators/base'
3
3
 
4
4
  class KubyGenerator < Rails::Generators::Base
5
- def create_initializer_file
6
- initializer(
7
- 'kuby.rb',
8
- <<~END
9
- require 'kuby'
10
-
11
- Kuby.load!
12
- END
13
- )
14
- end
15
-
16
5
  def create_config_file
17
6
  create_file(
18
7
  'kuby.rb',
19
8
  <<~END
9
+ require 'active_support/core_ext'
20
10
  require 'active_support/encrypted_configuration'
21
11
 
22
12
  # Define a production Kuby deploy environment
23
13
  Kuby.define(:production) do
14
+ # Because the Rails environment isn't always loaded when
15
+ # your Kuby config is loaded, provide access to Rails
16
+ # credentials manually.
24
17
  app_creds = ActiveSupport::EncryptedConfiguration.new(
25
18
  config_path: File.join('config', 'credentials.yml.enc'),
26
19
  key_path: File.join('config', 'master.key'),
@@ -46,17 +39,22 @@ class KubyGenerator < Rails::Generators::Base
46
39
 
47
40
  kubernetes do
48
41
  # Add a plugin that facilitates deploying a Rails app.
49
- add_plugin :rails_app
42
+ add_plugin :rails_app do
43
+ # configure database credentials
44
+ database do
45
+ user app_creds[:KUBY_DB_USER]
46
+ password app_creds[:KUBY_DB_PASSWORD]
47
+ end
48
+ end
50
49
 
51
- # Use minikube as the provider, which is the default installed by
52
- # Docker Desktop.
53
- # See: https://github.com/kubernetes/minikube
50
+ # Use Docker Desktop as the provider.
51
+ # See: https://www.docker.com/products/docker-desktop
54
52
  #
55
53
  # Note: you will likely want to use a different provider when deploying
56
54
  # your application into a production environment. To configure a different
57
55
  # provider, add the corresponding gem to your gemfile and update the
58
56
  # following line according to the provider gem's README.
59
- provider :minikube
57
+ provider :docker_desktop
60
58
  end
61
59
  end
62
60
  END