kuby-core 0.16.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -0
  3. data/Gemfile +6 -2
  4. data/Rakefile +5 -3
  5. data/bin/tapioca +29 -0
  6. data/kuby-core.gemspec +9 -11
  7. data/lib/kuby/basic_logger.rb +34 -34
  8. data/lib/kuby/cli_base.rb +43 -43
  9. data/lib/kuby/commands.rb +135 -21
  10. data/lib/kuby/definition.rb +12 -12
  11. data/lib/kuby/dependable.rb +20 -0
  12. data/lib/kuby/dependency.rb +14 -0
  13. data/lib/kuby/docker/alpine.rb +10 -10
  14. data/lib/kuby/docker/app_image.rb +11 -20
  15. data/lib/kuby/docker/app_phase.rb +36 -0
  16. data/lib/kuby/docker/assets_phase.rb +2 -2
  17. data/lib/kuby/docker/bundler_phase.rb +42 -40
  18. data/lib/kuby/docker/cli.rb +72 -37
  19. data/lib/kuby/docker/copy_phase.rb +7 -7
  20. data/lib/kuby/docker/credentials.rb +1 -0
  21. data/lib/kuby/docker/debian.rb +10 -10
  22. data/lib/kuby/docker/distro.rb +13 -13
  23. data/lib/kuby/docker/docker_uri.rb +20 -20
  24. data/lib/kuby/docker/dockerfile.rb +48 -39
  25. data/lib/kuby/docker/image.rb +66 -54
  26. data/lib/kuby/docker/inline_layer.rb +4 -4
  27. data/lib/kuby/docker/layer.rb +6 -6
  28. data/lib/kuby/docker/layer_stack.rb +35 -35
  29. data/lib/kuby/docker/local_tags.rb +16 -16
  30. data/lib/kuby/docker/package_list.rb +16 -16
  31. data/lib/kuby/docker/package_phase.rb +16 -16
  32. data/lib/kuby/docker/packages/managed_package.rb +13 -13
  33. data/lib/kuby/docker/packages/nodejs.rb +5 -5
  34. data/lib/kuby/docker/packages/package.rb +8 -8
  35. data/lib/kuby/docker/packages/simple_managed_package.rb +7 -7
  36. data/lib/kuby/docker/packages/yarn.rb +6 -6
  37. data/lib/kuby/docker/remote_tags.rb +16 -16
  38. data/lib/kuby/docker/setup_phase.rb +18 -20
  39. data/lib/kuby/docker/spec.rb +93 -72
  40. data/lib/kuby/docker/timestamp_tag.rb +16 -11
  41. data/lib/kuby/docker/timestamped_image.rb +64 -38
  42. data/lib/kuby/docker/webserver_phase.rb +20 -20
  43. data/lib/kuby/docker/yarn_phase.rb +29 -5
  44. data/lib/kuby/docker.rb +2 -1
  45. data/lib/kuby/kubernetes/bare_metal_provider.rb +12 -10
  46. data/lib/kuby/kubernetes/deployer.rb +22 -10
  47. data/lib/kuby/kubernetes/docker_config.rb +1 -0
  48. data/lib/kuby/kubernetes/provider.rb +1 -0
  49. data/lib/kuby/kubernetes/spec.rb +63 -13
  50. data/lib/kuby/plugin.rb +23 -1
  51. data/lib/kuby/plugin_registry.rb +15 -0
  52. data/lib/kuby/plugins/nginx_ingress.rb +8 -6
  53. data/lib/kuby/plugins/rails_app/assets.rb +16 -4
  54. data/lib/kuby/plugins/rails_app/assets_image.rb +18 -11
  55. data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
  56. data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
  57. data/lib/kuby/plugins/rails_app/database.rb +12 -8
  58. data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
  59. data/lib/kuby/plugins/rails_app/plugin.rb +37 -27
  60. data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
  61. data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
  62. data/lib/kuby/plugins/rails_app.rb +1 -0
  63. data/lib/kuby/plugins/system.rb +16 -0
  64. data/lib/kuby/plugins.rb +1 -0
  65. data/lib/kuby/railtie.rb +31 -1
  66. data/lib/kuby/tasks.rb +91 -10
  67. data/lib/kuby/trailing_hash.rb +2 -2
  68. data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
  69. data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
  70. data/lib/kuby/utils/sem_ver/version.rb +49 -0
  71. data/lib/kuby/utils/sem_ver.rb +17 -0
  72. data/lib/kuby/utils/table.rb +35 -0
  73. data/lib/kuby/utils/which.rb +65 -0
  74. data/lib/kuby/utils.rb +11 -0
  75. data/lib/kuby/version.rb +1 -1
  76. data/lib/kuby.rb +37 -2
  77. data/rbi/kuby-core.rbi +2128 -0
  78. data/spec/docker/spec_spec.rb +50 -26
  79. data/spec/docker/timestamped_image_spec.rb +2 -2
  80. data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
  81. data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
  82. data/spec/dummy/app/controllers/application_controller.rb +2 -1
  83. data/spec/dummy/app/jobs/application_job.rb +2 -1
  84. data/spec/dummy/app/mailers/application_mailer.rb +2 -1
  85. data/spec/dummy/app/models/application_record.rb +2 -1
  86. data/spec/dummy/config/application.rb +2 -1
  87. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
  88. data/spec/dummy/config/routes.rb +2 -1
  89. data/spec/dummy/test/application_system_test_case.rb +2 -1
  90. data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
  91. data/spec/spec_helper.rb +13 -1
  92. metadata +46 -39
  93. data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
  94. data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
@@ -1,23 +1,25 @@
1
1
  # typed: true
2
+
2
3
  require 'kube-dsl'
3
4
 
4
5
  module Kuby
5
6
  module Plugins
6
7
  class NginxIngress < ::Kuby::Plugin
8
+ depends_on :kubernetes, '>= 1.20'
9
+
7
10
  class Config
8
11
  extend ::KubeDSL::ValueFields
9
12
 
10
13
  value_fields :provider
11
14
  end
12
15
 
13
- VERSION = '0.27.1'.freeze
14
- DEFAULT_PROVIDER = 'cloud-generic'.freeze
16
+ VERSION = '1.1.1'.freeze
17
+ DEFAULT_PROVIDER = 'cloud'.freeze
15
18
  NAMESPACE = 'ingress-nginx'.freeze
16
- SERVICE_NAME = 'ingress-nginx'.freeze
19
+ SERVICE_NAME = 'ingress-nginx-controller'.freeze
17
20
 
18
21
  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"
22
+ "https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v#{VERSION}/deploy/static/provider/%{provider}/deploy.yaml"
21
23
  ].freeze
22
24
 
23
25
  def configure(&block)
@@ -54,7 +56,7 @@ module Kuby
54
56
  private
55
57
 
56
58
  def already_deployed?
57
- kubernetes_cli.get_object('Service', 'ingress-nginx', 'ingress-nginx')
59
+ kubernetes_cli.get_object('Service', NAMESPACE, SERVICE_NAME)
58
60
  true
59
61
  rescue KubernetesCLI::GetResourceError
60
62
  return false
@@ -28,19 +28,31 @@ module Kuby
28
28
  http do
29
29
  path do
30
30
  path spec.asset_url
31
+ path_type 'Prefix'
31
32
 
32
33
  backend do
33
- service_name spec.service.metadata.name
34
- service_port spec.service.spec.ports.first.port
34
+ service do
35
+ name spec.service.metadata.name
36
+
37
+ port do
38
+ name spec.service.spec.ports.first.name
39
+ end
40
+ end
35
41
  end
36
42
  end
37
43
 
38
44
  path do
39
45
  path spec.packs_url
46
+ path_type 'Prefix'
40
47
 
41
48
  backend do
42
- service_name spec.service.metadata.name
43
- service_port spec.service.spec.ports.first.port
49
+ service do
50
+ name spec.service.metadata.name
51
+
52
+ port do
53
+ name spec.service.spec.ports.first.name
54
+ end
55
+ end
44
56
  end
45
57
  end
46
58
  end
@@ -11,35 +11,42 @@ module Kuby
11
11
  end
12
12
 
13
13
  def new_version
14
- # Asset images track the base image, so return the current version
15
- # here. There can be no asset image without a base image.
16
- current_version
14
+ # asset images track the app image
15
+ duplicate_with_annotated_tags(
16
+ base_image.new_version.exists? ? base_image.new_version : base_image.current_version
17
+ )
17
18
  end
18
19
 
19
20
  def current_version
20
- @current_version ||= duplicate_with_annotated_tags(
21
+ duplicate_with_annotated_tags(
21
22
  base_image.current_version
22
23
  )
23
24
  end
24
25
 
25
26
  def previous_version
26
- @previous_version ||= duplicate_with_annotated_tags(
27
+ duplicate_with_annotated_tags(
27
28
  base_image.previous_version
28
29
  )
29
30
  end
30
31
 
31
- def build(build_args = {}, docker_args = [])
32
- unless ENV.fetch('RAILS_MASTER_KEY', '').empty?
33
- build_args['RAILS_MASTER_KEY'] = ENV['RAILS_MASTER_KEY']
34
- end
35
-
36
- docker_cli.build(current_version, build_args: build_args, docker_args: docker_args)
32
+ def build(build_args = {}, docker_args = [], context: nil, cache_from: nil)
33
+ docker_cli.build(
34
+ self,
35
+ build_args: build_args,
36
+ docker_args: docker_args,
37
+ context: context,
38
+ cache_from: cache_from
39
+ )
37
40
  end
38
41
 
39
42
  def push(tag)
40
43
  docker_cli.push(image_url, tag)
41
44
  end
42
45
 
46
+ def pull(tag)
47
+ docker_cli.pull(image_url, tag)
48
+ end
49
+
43
50
  private
44
51
 
45
52
  def duplicate_with_annotated_tags(image)
@@ -0,0 +1,473 @@
1
+ # typed: ignore
2
+
3
+ require 'fileutils'
4
+ require 'kuby/crdb'
5
+ require 'kube-dsl'
6
+
7
+ module Kuby
8
+ module Plugins
9
+ module RailsApp
10
+ module CRDB
11
+ class Plugin < ::Kuby::Plugin
12
+ ROLE = 'web'.freeze
13
+ VERSION = '21.1.11'.freeze
14
+ BOOTSTRAP_TIMEOUT_INTERVAL = 2
15
+ BOOTSTRAP_TIMEOUT_TOTAL = 60
16
+ CLIENT_PERMISSIONS = %w(create drop select insert delete update).freeze
17
+
18
+ attr_reader :environment, :configs
19
+
20
+ def initialize(environment, configs)
21
+ @environment = environment
22
+ @configs = configs
23
+
24
+ add_client_user('root')
25
+ add_client_user(client_username)
26
+ end
27
+
28
+ def add_client_user(username, &block)
29
+ crdb = self
30
+ safe_username = slugify(username)
31
+
32
+ client_certs[username] ||= Kuby::CertManager.certificate do
33
+ api_version 'cert-manager.io/v1'
34
+
35
+ metadata do
36
+ name "#{crdb.base_name}-crdb-#{safe_username}-cert"
37
+ namespace crdb.kubernetes.namespace.metadata.name
38
+ end
39
+
40
+ spec do
41
+ common_name username
42
+ secret_name "#{crdb.base_name}-crdb-client-#{safe_username}-cert"
43
+
44
+ subject do
45
+ organizations ['Kuby']
46
+ end
47
+
48
+ usages ['client auth']
49
+ duration "#{5 * 365 * 24}h" # 5 years validity (in hours)
50
+
51
+ private_key do
52
+ algorithm 'RSA'
53
+ size 2048
54
+ end
55
+
56
+ issuer_ref do
57
+ name crdb.issuer.metadata.name
58
+ kind 'Issuer'
59
+ group 'cert-manager.io'
60
+ end
61
+ end
62
+ end
63
+
64
+ client_certs[username].instance_eval(&block) if block
65
+ client_certs[username]
66
+ end
67
+
68
+ alias_method :configure_client_user, :add_client_user
69
+
70
+ def client_certs
71
+ @client_certs ||= {}
72
+ end
73
+
74
+ def name
75
+ :cockroachdb
76
+ end
77
+
78
+ def resources
79
+ @resources ||= [
80
+ database,
81
+ cluster_issuer, issuer,
82
+ ca_cert, node_cert, *client_certs.values
83
+ ]
84
+ end
85
+
86
+ def after_configuration
87
+ environment.docker.package_phase.add(:postgres_dev)
88
+ environment.docker.package_phase.add(:postgres_client)
89
+
90
+ environment.kubernetes.add_plugin(:crdb)
91
+ environment.kubernetes.add_plugin(:cert_manager)
92
+ end
93
+
94
+ def bootstrap
95
+ require 'pg'
96
+
97
+ config = configs[environment.name]
98
+ database_name = config['database']
99
+ start_time = Time.now
100
+
101
+ conn = loop do
102
+ Kuby.logger.info('Waiting for successful database connection...')
103
+
104
+ begin
105
+ conn = PG.connect(
106
+ dbname: database_name,
107
+ user: 'root',
108
+ host: host,
109
+ port: 26257,
110
+ sslmode: 'require',
111
+ sslrootcert: '/cockroach/cockroach-certs/ca.crt',
112
+ sslcert: '/cockroach/cockroach-certs/client.root.crt',
113
+ sslkey: '/cockroach/cockroach-certs/client.root.key',
114
+ connect_timeout: BOOTSTRAP_TIMEOUT_INTERVAL
115
+ )
116
+ rescue PG::ConnectionBad => e
117
+ if (Time.now - start_time) > BOOTSTRAP_TIMEOUT_TOTAL
118
+ Kuby.logger.fatal("Database connection failed, waited #{BOOTSTRAP_TIMEOUT_TOTAL}")
119
+ raise e
120
+ end
121
+
122
+ sleep 1 # breathe!
123
+ else
124
+ Kuby.logger.info('Database connection succeeded')
125
+ break conn
126
+ end
127
+ end
128
+
129
+ existing_databases = conn.exec('show databases').to_a
130
+
131
+ if existing_databases.none? { |db| db['database_name'] == database_name }
132
+ conn.exec("create database #{database_name}")
133
+ end
134
+
135
+ existing_users = conn.exec('show users').to_a.map { |u| u['username'] }
136
+
137
+ client_certs.each do |username, _cert|
138
+ unless existing_users.include?(username)
139
+ conn.exec("create user #{username}")
140
+ end
141
+
142
+ conn.exec(
143
+ "grant #{CLIENT_PERMISSIONS.join(',')} "\
144
+ "on database #{database_name} "\
145
+ "to #{username}"
146
+ )
147
+ end
148
+ end
149
+
150
+ def kubernetes_cli
151
+ provider.kubernetes_cli
152
+ end
153
+
154
+ def provider
155
+ environment.kubernetes.provider
156
+ end
157
+
158
+ def configure_pod_spec(pod_spec)
159
+ crdb = self
160
+
161
+ pod_spec.containers.each do |container|
162
+ configure_container(container)
163
+ end
164
+
165
+ pod_spec.init_containers.each do |init_container|
166
+ configure_container(init_container)
167
+ end
168
+
169
+ pod_spec.volume do
170
+ name "#{crdb.base_name}-crdb-certs"
171
+
172
+ projected do
173
+ source do
174
+ secret do
175
+ name crdb.node_cert.spec.secret_name
176
+
177
+ item do
178
+ key 'ca.crt'
179
+ path 'ca.crt'
180
+ end
181
+ end
182
+ end
183
+
184
+ crdb.client_certs.each do |username, cert|
185
+ source do
186
+ secret do
187
+ name cert.spec.secret_name
188
+
189
+ item do
190
+ key 'tls.crt'
191
+ path "client.#{username}.crt"
192
+ end
193
+
194
+ item do
195
+ key 'tls.key'
196
+ path "client.#{username}.key"
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ # read-only for user
203
+ # http://permissions-calculator.org/decode/0400/
204
+ default_mode 0400
205
+ end
206
+ end
207
+ end
208
+
209
+ def configure_container(container)
210
+ crdb = self
211
+
212
+ container.volume_mount do
213
+ name "#{crdb.base_name}-crdb-certs"
214
+ mount_path '/cockroach/cockroach-certs/'
215
+ end
216
+ end
217
+
218
+ def host
219
+ # host is the same as the name thanks to k8s DNS
220
+ @host ||= "#{database.metadata.name}-public"
221
+ end
222
+
223
+ def rewritten_configs
224
+ # deep dup
225
+ @rewritten_configs ||= Marshal.load(Marshal.dump(configs)).tap do |new_configs|
226
+ new_config = new_configs[environment.name]
227
+ new_config.delete('password')
228
+ new_config.merge!(
229
+ 'username' => client_username,
230
+ 'host' => host,
231
+ 'port' => 26257,
232
+ 'sslmode' => 'require',
233
+ 'sslrootcert' => '/cockroach/cockroach-certs/ca.crt',
234
+ 'sslcert' => "/cockroach/cockroach-certs/client.#{client_username}.crt",
235
+ 'sslkey' => "/cockroach/cockroach-certs/client.#{client_username}.key"
236
+ )
237
+ end
238
+ end
239
+
240
+ def storage(amount)
241
+ database do
242
+ spec do
243
+ data_store do
244
+ pvc do
245
+ spec do
246
+ resources do
247
+ requests do
248
+ set :storage, amount
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ def database(&block)
259
+ crdb = self
260
+
261
+ @database ||= Kuby::CRDB.crdb_cluster do
262
+ metadata do
263
+ # this translates to the name of the statefulset that is created
264
+ name "#{crdb.base_name}-crdb"
265
+ namespace crdb.kubernetes.namespace.metadata.name
266
+ end
267
+
268
+ spec do
269
+ data_store do
270
+ pvc do
271
+ spec do
272
+ access_modes ['ReadWriteOnce']
273
+ resources do
274
+ requests do
275
+ add :storage, '10Gi'
276
+ end
277
+ end
278
+
279
+ volume_mode 'Filesystem'
280
+ end
281
+ end
282
+ end
283
+
284
+ resources do
285
+ requests do
286
+ add :cpu, '200m'
287
+ add :memory, '1Gi'
288
+ end
289
+
290
+ limits do
291
+ add :cpu, '200m'
292
+ add :memory, '1Gi'
293
+ end
294
+ end
295
+
296
+ tls_enabled true
297
+ client_tls_secret crdb.client_certs['root'].spec.secret_name
298
+ node_tls_secret crdb.node_cert.spec.secret_name
299
+
300
+ image do
301
+ name "cockroachdb/cockroach:v#{VERSION}"
302
+ end
303
+
304
+ # this is unfortunately the minimum
305
+ nodes 3
306
+ end
307
+ end
308
+ end
309
+
310
+ def cluster_issuer
311
+ crdb = self
312
+
313
+ @cluster_issuer ||= Kuby::CertManager.cluster_issuer do
314
+ api_version 'cert-manager.io/v1'
315
+
316
+ metadata do
317
+ name "#{crdb.base_name}-crdb-ca-issuer"
318
+ end
319
+
320
+ spec do
321
+ self_signed
322
+ end
323
+ end
324
+ end
325
+
326
+ def issuer
327
+ crdb = self
328
+
329
+ @issuer ||= Kuby::CertManager.issuer do
330
+ api_version 'cert-manager.io/v1'
331
+
332
+ metadata do
333
+ name "#{crdb.base_name}-crdb-issuer"
334
+ namespace crdb.kubernetes.namespace.metadata.name
335
+ end
336
+
337
+ spec do
338
+ ca do
339
+ secret_name crdb.ca_cert.spec.secret_name
340
+ end
341
+ end
342
+ end
343
+ end
344
+
345
+ def ca_cert
346
+ crdb = self
347
+
348
+ @ca_cert ||= Kuby::CertManager.certificate do
349
+ api_version 'cert-manager.io/v1'
350
+
351
+ metadata do
352
+ name "#{crdb.base_name}-crdb-ca-cert"
353
+ namespace crdb.kubernetes.namespace.metadata.name
354
+ end
355
+
356
+ spec do
357
+ is_ca true
358
+ common_name 'ca'
359
+ secret_name "#{crdb.base_name}-crdb-ca-cert"
360
+
361
+ subject do
362
+ organizations ['Kuby']
363
+ end
364
+
365
+ usages ['digital signature', 'key encipherment', 'cert sign', 'crl sign']
366
+ duration "#{5 * 365 * 24}h" # 5 years validity (in hours)
367
+
368
+ private_key do
369
+ algorithm 'RSA'
370
+ size 2048
371
+ end
372
+
373
+ issuer_ref do
374
+ name crdb.cluster_issuer.metadata.name
375
+ kind 'ClusterIssuer'
376
+ group 'cert-manager.io'
377
+ end
378
+ end
379
+ end
380
+ end
381
+
382
+ def node_cert
383
+ crdb = self
384
+ ns = kubernetes.namespace.metadata.name
385
+
386
+ @node_cert ||= Kuby::CertManager.certificate do
387
+ api_version 'cert-manager.io/v1'
388
+
389
+ metadata do
390
+ name "#{crdb.base_name}-crdb-node-cert"
391
+ namespace ns
392
+ end
393
+
394
+ spec do
395
+ common_name 'node'
396
+ secret_name "#{crdb.base_name}-crdb-node-cert"
397
+
398
+ subject do
399
+ organizations ['Kuby']
400
+ end
401
+
402
+ usages ['client auth', 'server auth']
403
+ duration "#{5 * 365 * 24}h" # 5 years validity (in hours)
404
+
405
+ svc_name = "#{crdb.base_name}-crdb"
406
+
407
+ dns_names [
408
+ 'localhost',
409
+ "#{svc_name}-public",
410
+ "#{svc_name}-public.#{ns}",
411
+ "#{svc_name}-public.#{ns}.svc.cluster.local",
412
+ "*.#{svc_name}",
413
+ "*.#{svc_name}.#{ns}",
414
+ "*.#{svc_name}.#{ns}.svc.cluster.local",
415
+ ]
416
+
417
+ ip_addresses ['127.0.0.1']
418
+
419
+ private_key do
420
+ algorithm 'RSA'
421
+ size 2048
422
+ end
423
+
424
+ issuer_ref do
425
+ name crdb.issuer.metadata.name
426
+ kind 'Issuer'
427
+ group 'cert-manager.io'
428
+ end
429
+ end
430
+ end
431
+ end
432
+
433
+ def client_username
434
+ @client_username ||= slugify(kubernetes.selector_app)
435
+ end
436
+
437
+ # replaces all non-ascii characters with an underscore
438
+ def slugify(str)
439
+ str.gsub(/\W/, '_')
440
+ end
441
+
442
+ def base_name
443
+ @base_name ||= "#{kubernetes.selector_app}-#{ROLE}"
444
+ end
445
+
446
+ def kubernetes
447
+ environment.kubernetes
448
+ end
449
+
450
+ def rails_app
451
+ kubernetes.plugin(:rails_app)
452
+ end
453
+
454
+ private
455
+
456
+ def config
457
+ configs[environment.name]
458
+ end
459
+ end
460
+ end
461
+ end
462
+ end
463
+ end
464
+
465
+ Kuby.register_package(:postgres_dev,
466
+ debian: 'postgresql-client',
467
+ alpine: 'postgresql-dev'
468
+ )
469
+
470
+ Kuby.register_package(:postgres_client,
471
+ debian: 'postgresql-client',
472
+ alpine: 'postgresql-client'
473
+ )
@@ -0,0 +1,9 @@
1
+ module Kuby
2
+ module Plugins
3
+ module RailsApp
4
+ module CRDB
5
+ autoload :Plugin, 'kuby/plugins/rails_app/crdb/plugin'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,5 @@
1
- # typed: false
1
+ # typed: ignore
2
+
2
3
  require 'yaml'
3
4
 
4
5
  module Kuby
@@ -7,11 +8,8 @@ module Kuby
7
8
  class UnsupportedDatabaseError < StandardError; end
8
9
 
9
10
  class Database
10
- ADAPTER_MAP = {
11
- sqlite3: Sqlite,
12
- mysql2: MySQL,
13
- postgresql: Postgres
14
- }.freeze
11
+ # only support cockroach for now
12
+ ADAPTER_MAP = { cockroachdb: CRDB::Plugin, sqlite3: Sqlite }.freeze
15
13
 
16
14
  def self.get(rails_app)
17
15
  if rails_app.manage_database?
@@ -21,7 +19,7 @@ module Kuby
21
19
 
22
20
  def self.get_adapter(adapter_name)
23
21
  ADAPTER_MAP.fetch(adapter_name) do
24
- raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter}' "\
22
+ raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter_name}' "\
25
23
  'database adapter'
26
24
  end
27
25
  end
@@ -51,7 +49,13 @@ module Kuby
51
49
  end
52
50
 
53
51
  def db_configs
54
- @db_configs ||= YAML.load(File.read(db_config_path))
52
+ @db_configs ||= begin
53
+ if Psych::VERSION > '4'
54
+ YAML.load(File.read(db_config_path), aliases: true)
55
+ else ArgumentError
56
+ YAML.load(File.read(db_config_path))
57
+ end
58
+ end
55
59
  end
56
60
 
57
61
  def db_config_path