kuby-core 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/kuby-core.gemspec +5 -3
  4. data/lib/kuby.rb +5 -3
  5. data/lib/kuby/definition.rb +0 -8
  6. data/lib/kuby/docker/layer.rb +4 -4
  7. data/lib/kuby/docker/metadata.rb +6 -6
  8. data/lib/kuby/docker/package_phase.rb +2 -2
  9. data/lib/kuby/docker/spec.rb +11 -11
  10. data/lib/kuby/environment.rb +6 -2
  11. data/lib/kuby/kubernetes.rb +0 -2
  12. data/lib/kuby/kubernetes/deploy_task.rb +0 -1
  13. data/lib/kuby/kubernetes/deployer.rb +7 -7
  14. data/lib/kuby/kubernetes/minikube_provider.rb +4 -0
  15. data/lib/kuby/kubernetes/provider.rb +5 -5
  16. data/lib/kuby/kubernetes/spec.rb +8 -8
  17. data/lib/kuby/plugin.rb +59 -0
  18. data/lib/kuby/plugins.rb +6 -0
  19. data/lib/kuby/plugins/nginx_ingress.rb +71 -0
  20. data/lib/kuby/plugins/rails_app.rb +18 -0
  21. data/lib/kuby/plugins/rails_app/asset_copy_task.rb +117 -0
  22. data/lib/kuby/plugins/rails_app/assets.rb +347 -0
  23. data/lib/kuby/plugins/rails_app/database.rb +75 -0
  24. data/lib/kuby/{kubernetes/plugins → plugins}/rails_app/generators/kuby.rb +0 -0
  25. data/lib/kuby/plugins/rails_app/mysql.rb +155 -0
  26. data/lib/kuby/plugins/rails_app/plugin.rb +398 -0
  27. data/lib/kuby/plugins/rails_app/postgres.rb +143 -0
  28. data/lib/kuby/plugins/rails_app/rewrite_db_config.rb +11 -0
  29. data/lib/kuby/plugins/rails_app/sqlite.rb +32 -0
  30. data/lib/kuby/{kubernetes/plugins → plugins}/rails_app/tasks.rake +10 -2
  31. data/lib/kuby/tasks.rb +9 -9
  32. data/lib/kuby/tasks/kuby.rake +1 -1
  33. data/lib/kuby/version.rb +1 -1
  34. metadata +34 -27
  35. data/lib/ext/krane/kubernetes_resource.rb +0 -16
  36. data/lib/kuby/kubernetes/plugin.rb +0 -55
  37. data/lib/kuby/kubernetes/plugins.rb +0 -8
  38. data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +0 -73
  39. data/lib/kuby/kubernetes/plugins/rails_app.rb +0 -16
  40. data/lib/kuby/kubernetes/plugins/rails_app/database.rb +0 -79
  41. data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +0 -154
  42. data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +0 -379
  43. data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +0 -142
  44. data/lib/kuby/kubernetes/plugins/rails_app/rewrite_db_config.rb +0 -13
  45. data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +0 -30
@@ -1,8 +0,0 @@
1
- module Kuby
2
- module Kubernetes
3
- module Plugins
4
- autoload :NginxIngress, 'kuby/kubernetes/plugins/nginx_ingress'
5
- autoload :RailsApp, 'kuby/kubernetes/plugins/rails_app'
6
- end
7
- end
8
- end
@@ -1,73 +0,0 @@
1
- require 'kube-dsl'
2
-
3
- module Kuby
4
- module Kubernetes
5
- module Plugins
6
- class NginxIngress < Plugin
7
- class Config
8
- extend ::KubeDSL::ValueFields
9
-
10
- value_fields :provider
11
- end
12
-
13
- VERSION = '0.27.1'.freeze
14
- DEFAULT_PROVIDER = 'cloud-generic'.freeze
15
- NAMESPACE = 'ingress-nginx'.freeze
16
- SERVICE_NAME = 'ingress-nginx'.freeze
17
-
18
- SETUP_RESOURCES = [
19
- "https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-#{VERSION}/deploy/static/mandatory.yaml",
20
- "https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-#{VERSION}/deploy/static/provider/%{provider}.yaml"
21
- ].freeze
22
-
23
- def configure(&block)
24
- @config.instance_eval(&block) if block
25
- end
26
-
27
- def setup
28
- Kuby.logger.info('Deploying nginx ingress resources')
29
-
30
- if already_deployed?
31
- Kuby.logger.info('Nginx ingress already deployed, skipping')
32
- return
33
- end
34
-
35
- SETUP_RESOURCES.each do |uri|
36
- uri = uri % { provider: @config.provider || DEFAULT_PROVIDER }
37
- kubernetes_cli.apply_uri(uri)
38
- end
39
-
40
- Kuby.logger.info('Nginx ingress resources deployed!')
41
- rescue => e
42
- Kuby.logger.fatal(e.message)
43
- raise
44
- end
45
-
46
- def namespace
47
- NAMESPACE
48
- end
49
-
50
- def service_name
51
- SERVICE_NAME
52
- end
53
-
54
- private
55
-
56
- def already_deployed?
57
- kubernetes_cli.get_object('Service', 'ingress-nginx', 'ingress-nginx')
58
- true
59
- rescue KubernetesCLI::GetResourceError
60
- return false
61
- end
62
-
63
- def after_initialize
64
- @config = Config.new
65
- end
66
-
67
- def kubernetes_cli
68
- definition.kubernetes.provider.kubernetes_cli
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,16 +0,0 @@
1
- module Kuby
2
- module Kubernetes
3
- module Plugins
4
- module RailsApp
5
- autoload :Database, 'kuby/kubernetes/plugins/rails_app/database'
6
- autoload :MySQL, 'kuby/kubernetes/plugins/rails_app/mysql'
7
- autoload :Plugin, 'kuby/kubernetes/plugins/rails_app/plugin'
8
- autoload :Postgres, 'kuby/kubernetes/plugins/rails_app/postgres'
9
- autoload :RewriteDbConfig, 'kuby/kubernetes/plugins/rails_app/rewrite_db_config'
10
- autoload :Sqlite, 'kuby/kubernetes/plugins/rails_app/sqlite'
11
- end
12
- end
13
- end
14
- end
15
-
16
- load File.expand_path(File.join('rails_app', 'tasks.rake'), __dir__)
@@ -1,79 +0,0 @@
1
- require 'erb'
2
- require 'yaml'
3
-
4
- module Kuby
5
- module Kubernetes
6
- module Plugins
7
- module RailsApp
8
- class UnsupportedDatabaseError < StandardError; end
9
-
10
- class Database
11
- ADAPTER_MAP = {
12
- 'sqlite3' => Sqlite,
13
- 'mysql2' => MySQL,
14
- 'postgresql' => Postgres
15
- }.freeze
16
-
17
- def self.get(rails_app)
18
- if rails_app.manage_database?
19
- new(rails_app).database
20
- end
21
- end
22
-
23
- def self.get_adapter(adapter)
24
- ADAPTER_MAP.fetch(adapter) do
25
- raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter}' "\
26
- 'database adapter'
27
- end
28
- end
29
-
30
- attr_reader :rails_app
31
-
32
- def initialize(rails_app)
33
- @rails_app = rails_app
34
- end
35
-
36
- def database
37
- @database ||= self.class
38
- .get_adapter(adapter)
39
- .new(rails_app, environment, db_configs)
40
- end
41
-
42
- private
43
-
44
- def adapter
45
- db_config['adapter']
46
- end
47
-
48
- def db_config
49
- @db_config ||= db_configs[environment]
50
- end
51
-
52
- def environment
53
- @environment ||= rails_app.definition.environment.name
54
- end
55
-
56
- def db_configs
57
- @db_configs ||= YAML.load(ERB.new(File.read(db_config_path)).result)
58
- end
59
-
60
- def db_config_path
61
- @db_config_path ||= begin
62
- db_config_paths.first or
63
- raise "Couldn't find database config at #{rails_app.root}"
64
- end
65
- end
66
-
67
- def db_config_paths
68
- @db_config_paths ||=
69
- Dir.glob(
70
- File.join(
71
- rails_app.root, 'config', 'database.{yml,erb,yml.erb,yaml,yaml.erb}'
72
- )
73
- )
74
- end
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,154 +0,0 @@
1
- require 'kube-dsl'
2
- require 'kuby/kube-db'
3
-
4
- module Kuby
5
- module Kubernetes
6
- module Plugins
7
- module RailsApp
8
- class MySQL < Kuby::Kubernetes::Plugin
9
- ROLE = 'web'.freeze
10
-
11
- attr_reader :definition, :environment, :configs
12
-
13
- def initialize(definition, environment, configs)
14
- @definition = definition
15
- @environment = environment
16
- @configs = configs
17
-
18
- user(config['username'])
19
- password(config['password'])
20
- end
21
-
22
- def resources
23
- @resources ||= [secret, database]
24
- end
25
-
26
- def after_configuration
27
- definition.docker.package_phase.add(:mysql_dev)
28
- definition.docker.package_phase.add(:mysql_client)
29
- end
30
-
31
- def host
32
- # host is the same as the name thanks to k8s DNS
33
- @host ||= database.metadata.name
34
- end
35
-
36
- def rewritten_configs
37
- # deep dup
38
- @rewritten_configs ||= Marshal.load(Marshal.dump(configs)).tap do |new_configs|
39
- new_configs[environment]['host'] = host
40
- end
41
- end
42
-
43
- def user(user)
44
- secret do
45
- data do
46
- set :user, user
47
- end
48
- end
49
- end
50
-
51
- def password(password)
52
- secret do
53
- data do
54
- set :password, password
55
- end
56
- end
57
- end
58
-
59
- def storage(amount)
60
- database do
61
- spec do
62
- storage do
63
- resources do
64
- requests do
65
- set :storage, amount
66
- end
67
- end
68
- end
69
- end
70
- end
71
- end
72
-
73
- def secret(&block)
74
- context = self
75
-
76
- @secret ||= KubeDSL.secret do
77
- metadata do
78
- name "#{context.base_name}-mysql-secret"
79
- namespace context.kubernetes.namespace.metadata.name
80
- end
81
-
82
- type 'Opaque'
83
- end
84
-
85
- @secret.instance_eval(&block) if block
86
- @secret
87
- end
88
-
89
- def database(&block)
90
- context = self
91
-
92
- @database ||= Kuby::KubeDB.my_sql do
93
- api_version 'kubedb.com/v1alpha1'
94
-
95
- metadata do
96
- name "#{context.base_name}-mysql"
97
- namespace context.kubernetes.namespace.metadata.name
98
- end
99
-
100
- spec do
101
- database_secret do
102
- secret_name context.secret.metadata.name
103
- end
104
-
105
- version '5.7-v2'
106
- storage_type 'Durable'
107
-
108
- storage do
109
- storage_class_name context.kubernetes.provider.storage_class_name
110
- access_modes ['ReadWriteOnce']
111
-
112
- resources do
113
- requests do
114
- add :storage, '10Gi'
115
- end
116
- end
117
- end
118
-
119
- termination_policy 'DoNotTerminate'
120
- end
121
- end
122
-
123
- @database.instance_eval(&block) if block
124
- @database
125
- end
126
-
127
- def base_name
128
- @base_name ||= "#{kubernetes.selector_app}-#{ROLE}"
129
- end
130
-
131
- def kubernetes
132
- definition.kubernetes
133
- end
134
-
135
- private
136
-
137
- def config
138
- configs[environment]
139
- end
140
- end
141
- end
142
- end
143
- end
144
- end
145
-
146
- Kuby.register_package(:mysql_client,
147
- debian: 'default-mysql-client',
148
- alpine: 'mariadb-client'
149
- )
150
-
151
- Kuby.register_package(:mysql_dev,
152
- debian: 'default-libmysqlclient-dev',
153
- alpine: 'mariadb-dev'
154
- )
@@ -1,379 +0,0 @@
1
- require 'kube-dsl'
2
- require 'kuby/cert-manager'
3
-
4
- module Kuby
5
- module Kubernetes
6
- module Plugins
7
- module RailsApp
8
- class Plugin < Kuby::Kubernetes::Plugin
9
- extend ::KubeDSL::ValueFields
10
-
11
- WEB_ROLE = 'web'.freeze
12
- MASTER_KEY_VAR = 'RAILS_MASTER_KEY'.freeze
13
- ENV_SECRETS = [MASTER_KEY_VAR].freeze
14
- ENV_EXCLUDE = ['RAILS_ENV'].freeze
15
-
16
- value_field :root, default: '.'
17
- value_fields :hostname, :tls_enabled
18
- value_fields :manage_database, :database, :replicas
19
-
20
- alias_method :manage_database?, :manage_database
21
-
22
- def initialize(definition)
23
- @definition = definition
24
- @tls_enabled = true
25
- @replicas = 1
26
- @manage_database = true
27
- end
28
-
29
- def configure(&block)
30
- instance_eval(&block) if block
31
- end
32
-
33
- def after_configuration
34
- if @database = Database.get(self)
35
- definition.kubernetes.plugins[database] = @database
36
- definition.kubernetes.add_plugin(:kube_db)
37
-
38
- definition.docker do
39
- insert :rewrite_db_config, RewriteDbConfig.new, after: :copy_phase
40
- end
41
- end
42
-
43
- # do we always want this?
44
- definition.kubernetes.add_plugin(:nginx_ingress)
45
-
46
- if @tls_enabled
47
- context = self
48
-
49
- definition.kubernetes.add_plugin(:cert_manager) do
50
- email context.definition.docker.credentials.email
51
- end
52
- end
53
- end
54
-
55
- def before_deploy(manifest)
56
- # Make sure plugin has been configured. If not, do nothing.
57
- if cert_manager = definition.kubernetes.plugin(:cert_manager)
58
- if ing = manifest.find(:ingress, ingress.metadata.name)
59
- cert_manager.annotate_ingress(ing)
60
- end
61
- end
62
-
63
- image_with_tag = "#{docker.metadata.image_url}:#{kubernetes.tag}"
64
-
65
- deployment do
66
- spec do
67
- template do
68
- spec do
69
- container(:web) do
70
- image image_with_tag
71
- end
72
-
73
- init_container(:create_db) do
74
- image image_with_tag
75
- end
76
-
77
- init_container(:migrate_db) do
78
- image image_with_tag
79
- end
80
- end
81
- end
82
- end
83
- end
84
- end
85
-
86
- def database(&block)
87
- @database.instance_eval(&block) if block
88
- @database
89
- end
90
-
91
- def service(&block)
92
- spec = self
93
-
94
- @service ||= KubeDSL.service do
95
- metadata do
96
- name "#{spec.selector_app}-svc"
97
- namespace spec.namespace.metadata.name
98
-
99
- labels do
100
- add :app, spec.selector_app
101
- add :role, spec.role
102
- end
103
- end
104
-
105
- spec do
106
- type 'NodePort'
107
-
108
- selector do
109
- add :app, spec.selector_app
110
- add :role, spec.role
111
- end
112
-
113
- port do
114
- name 'http'
115
- port 8080
116
- protocol 'TCP'
117
- target_port 'http'
118
- end
119
- end
120
- end
121
-
122
- @service.instance_eval(&block) if block
123
- @service
124
- end
125
-
126
- def service_account(&block)
127
- spec = self
128
-
129
- @service_account ||= KubeDSL.service_account do
130
- metadata do
131
- name "#{spec.selector_app}-sa"
132
- namespace spec.namespace.metadata.name
133
-
134
- labels do
135
- add :app, spec.selector_app
136
- add :role, spec.role
137
- end
138
- end
139
- end
140
-
141
- @service_account.instance_eval(&block) if block
142
- @service_account
143
- end
144
-
145
- def config_map(&block)
146
- spec = self
147
-
148
- @config_map ||= KubeDSL.config_map do
149
- metadata do
150
- name "#{spec.selector_app}-config"
151
- namespace spec.namespace.metadata.name
152
- end
153
-
154
- data do
155
- ENV.each_pair do |key, val|
156
- include_key = key.start_with?('RAILS_') &&
157
- !ENV_SECRETS.include?(key) &&
158
- !ENV_EXCLUDE.include?(key)
159
-
160
- if include_key
161
- add key.to_sym, val
162
- end
163
- end
164
- end
165
- end
166
-
167
- @config_map.instance_eval(&block) if block
168
- @config_map
169
- end
170
-
171
- def app_secrets(&block)
172
- spec = self
173
-
174
- @app_secrets ||= KubeDSL.secret do
175
- metadata do
176
- name "#{spec.selector_app}-secrets"
177
- namespace spec.namespace.metadata.name
178
- end
179
-
180
- type 'Opaque'
181
-
182
- data do
183
- if master_key = ENV[MASTER_KEY_VAR]
184
- add MASTER_KEY_VAR.to_sym, master_key
185
- else
186
- master_key_path = File.join(spec.root, 'config', 'master.key')
187
-
188
- if File.exist?(master_key_path)
189
- add MASTER_KEY_VAR.to_sym, File.read(master_key_path).strip
190
- end
191
- end
192
- end
193
- end
194
-
195
- @app_secrets.instance_eval(&block) if block
196
- @app_secrets
197
- end
198
-
199
- def deployment(&block)
200
- kube_spec = self
201
-
202
- @deployment ||= KubeDSL.deployment do
203
- metadata do
204
- name "#{kube_spec.selector_app}-#{kube_spec.role}"
205
- namespace kube_spec.namespace.metadata.name
206
-
207
- labels do
208
- add :app, kube_spec.selector_app
209
- add :role, kube_spec.role
210
- end
211
- end
212
-
213
- spec do
214
- replicas kube_spec.replicas
215
-
216
- selector do
217
- match_labels do
218
- add :app, kube_spec.selector_app
219
- add :role, kube_spec.role
220
- end
221
- end
222
-
223
- strategy do
224
- type 'RollingUpdate'
225
-
226
- rolling_update do
227
- max_surge '25%'
228
- max_unavailable 0
229
- end
230
- end
231
-
232
- template do
233
- metadata do
234
- labels do
235
- add :app, kube_spec.selector_app
236
- add :role, kube_spec.role
237
- end
238
- end
239
-
240
- spec do
241
- container(:web) do
242
- name "#{kube_spec.selector_app}-#{kube_spec.role}"
243
- image_pull_policy 'IfNotPresent'
244
-
245
- port do
246
- container_port kube_spec.docker.webserver_phase.port
247
- name 'http'
248
- protocol 'TCP'
249
- end
250
-
251
- env_from do
252
- config_map_ref do
253
- name kube_spec.config_map.metadata.name
254
- end
255
- end
256
-
257
- env_from do
258
- secret_ref do
259
- name kube_spec.app_secrets.metadata.name
260
- end
261
- end
262
-
263
- readiness_probe do
264
- success_threshold 1
265
- failure_threshold 2
266
- initial_delay_seconds 15
267
- period_seconds 3
268
- timeout_seconds 1
269
-
270
- http_get do
271
- path '/healthz'
272
- port kube_spec.docker.webserver_phase.port
273
- scheme 'HTTP'
274
- end
275
- end
276
- end
277
-
278
- init_container(:create_db) do
279
- name "#{kube_spec.selector_app}-create-db"
280
- command %w(bundle exec rake kuby:rails_app:db:create_unless_exists)
281
- end
282
-
283
- init_container(:migrate_db) do
284
- name "#{kube_spec.selector_app}-migrate-db"
285
- command %w(bundle exec rake db:migrate)
286
- end
287
-
288
- image_pull_secret do
289
- name kube_spec.definition.kubernetes.registry_secret.metadata.name
290
- end
291
-
292
- restart_policy 'Always'
293
- service_account_name kube_spec.service_account.metadata.name
294
- end
295
- end
296
- end
297
- end
298
-
299
- @deployment.instance_eval(&block) if block
300
- @deployment
301
- end
302
-
303
- def ingress(&block)
304
- spec = self
305
- tls_enabled = @tls_enabled
306
-
307
- @ingress ||= KubeDSL::DSL::Extensions::V1beta1::Ingress.new do
308
- metadata do
309
- name "#{spec.selector_app}-ingress"
310
- namespace spec.namespace.metadata.name
311
-
312
- annotations do
313
- add :'kubernetes.io/ingress.class', 'nginx'
314
- end
315
- end
316
-
317
- spec do
318
- rule do
319
- host spec.hostname
320
-
321
- http do
322
- path do
323
- backend do
324
- service_name spec.service.metadata.name
325
- service_port spec.service.spec.ports.first.port
326
- end
327
- end
328
- end
329
- end
330
-
331
- if tls_enabled
332
- tls do
333
- secret_name "#{spec.selector_app}-tls"
334
- hosts [spec.hostname]
335
- end
336
- end
337
- end
338
- end
339
-
340
- @ingress.instance_eval(&block) if block
341
- @ingress
342
- end
343
-
344
- def resources
345
- @resources ||= [
346
- service,
347
- service_account,
348
- config_map,
349
- app_secrets,
350
- deployment,
351
- ingress,
352
- *database&.resources
353
- ]
354
- end
355
-
356
- def selector_app
357
- definition.kubernetes.selector_app
358
- end
359
-
360
- def role
361
- WEB_ROLE
362
- end
363
-
364
- def docker
365
- definition.docker
366
- end
367
-
368
- def kubernetes
369
- definition.kubernetes
370
- end
371
-
372
- def namespace
373
- definition.kubernetes.namespace
374
- end
375
- end
376
- end
377
- end
378
- end
379
- end