kuby-core 0.17.0 → 0.18.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +44 -0
- data/Gemfile +6 -2
- data/Rakefile +5 -3
- data/bin/tapioca +29 -0
- data/kuby-core.gemspec +9 -11
- data/lib/kuby/basic_logger.rb +34 -34
- data/lib/kuby/cli_base.rb +43 -43
- data/lib/kuby/commands.rb +94 -11
- data/lib/kuby/definition.rb +12 -12
- data/lib/kuby/dependable.rb +20 -0
- data/lib/kuby/dependency.rb +14 -0
- data/lib/kuby/docker/alpine.rb +10 -10
- data/lib/kuby/docker/app_image.rb +11 -11
- data/lib/kuby/docker/app_phase.rb +36 -0
- data/lib/kuby/docker/assets_phase.rb +2 -2
- data/lib/kuby/docker/bundler_phase.rb +42 -40
- data/lib/kuby/docker/cli.rb +71 -43
- data/lib/kuby/docker/copy_phase.rb +7 -7
- data/lib/kuby/docker/credentials.rb +1 -0
- data/lib/kuby/docker/debian.rb +10 -10
- data/lib/kuby/docker/distro.rb +13 -13
- data/lib/kuby/docker/docker_uri.rb +20 -20
- data/lib/kuby/docker/dockerfile.rb +48 -39
- data/lib/kuby/docker/image.rb +66 -54
- data/lib/kuby/docker/inline_layer.rb +4 -4
- data/lib/kuby/docker/layer.rb +6 -6
- data/lib/kuby/docker/layer_stack.rb +35 -35
- data/lib/kuby/docker/local_tags.rb +16 -16
- data/lib/kuby/docker/package_list.rb +16 -16
- data/lib/kuby/docker/package_phase.rb +16 -16
- data/lib/kuby/docker/packages/managed_package.rb +13 -13
- data/lib/kuby/docker/packages/nodejs.rb +5 -5
- data/lib/kuby/docker/packages/package.rb +8 -8
- data/lib/kuby/docker/packages/simple_managed_package.rb +7 -7
- data/lib/kuby/docker/packages/yarn.rb +6 -6
- data/lib/kuby/docker/remote_tags.rb +16 -16
- data/lib/kuby/docker/setup_phase.rb +18 -20
- data/lib/kuby/docker/spec.rb +93 -72
- data/lib/kuby/docker/timestamp_tag.rb +16 -11
- data/lib/kuby/docker/timestamped_image.rb +59 -40
- data/lib/kuby/docker/webserver_phase.rb +20 -20
- data/lib/kuby/docker/yarn_phase.rb +29 -5
- data/lib/kuby/docker.rb +2 -1
- data/lib/kuby/kubernetes/bare_metal_provider.rb +9 -9
- data/lib/kuby/kubernetes/deployer.rb +22 -10
- data/lib/kuby/kubernetes/docker_config.rb +1 -0
- data/lib/kuby/kubernetes/provider.rb +1 -0
- data/lib/kuby/kubernetes/spec.rb +47 -7
- data/lib/kuby/plugin.rb +22 -1
- data/lib/kuby/plugins/nginx_ingress.rb +8 -6
- data/lib/kuby/plugins/rails_app/assets.rb +16 -4
- data/lib/kuby/plugins/rails_app/assets_image.rb +17 -8
- data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
- data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
- data/lib/kuby/plugins/rails_app/database.rb +12 -8
- data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
- data/lib/kuby/plugins/rails_app/plugin.rb +29 -18
- data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
- data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
- data/lib/kuby/plugins/rails_app.rb +1 -0
- data/lib/kuby/plugins/system.rb +16 -0
- data/lib/kuby/plugins.rb +1 -0
- data/lib/kuby/railtie.rb +31 -1
- data/lib/kuby/tasks.rb +72 -5
- data/lib/kuby/trailing_hash.rb +2 -2
- data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
- data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
- data/lib/kuby/utils/sem_ver/version.rb +49 -0
- data/lib/kuby/utils/sem_ver.rb +17 -0
- data/lib/kuby/utils/which.rb +65 -0
- data/lib/kuby/utils.rb +7 -1
- data/lib/kuby/version.rb +1 -1
- data/lib/kuby.rb +37 -2
- data/rbi/kuby-core.rbi +2128 -0
- data/spec/docker/spec_spec.rb +50 -26
- data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
- data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
- data/spec/dummy/app/controllers/application_controller.rb +2 -1
- data/spec/dummy/app/jobs/application_job.rb +2 -1
- data/spec/dummy/app/mailers/application_mailer.rb +2 -1
- data/spec/dummy/app/models/application_record.rb +2 -1
- data/spec/dummy/config/application.rb +2 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
- data/spec/dummy/config/routes.rb +2 -1
- data/spec/dummy/test/application_system_test_case.rb +2 -1
- data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
- data/spec/spec_helper.rb +13 -1
- metadata +44 -39
- data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
- data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
@@ -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
|
+
)
|
@@ -1,4 +1,5 @@
|
|
1
|
-
# typed:
|
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
|
-
|
11
|
-
|
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 '#{
|
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 ||=
|
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
|
@@ -1,4 +1,5 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: false
|
2
|
+
|
2
3
|
require 'rails/generators'
|
3
4
|
require 'rails/generators/base'
|
4
5
|
|
@@ -14,14 +15,6 @@ class KubyGenerator < Rails::Generators::Base
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def create_config_file
|
17
|
-
app_class = Rails.application.class
|
18
|
-
|
19
|
-
app_name = if app_class.respond_to?(:module_parent_name)
|
20
|
-
app_class.module_parent_name
|
21
|
-
else
|
22
|
-
app_class.parent_name
|
23
|
-
end
|
24
|
-
|
25
18
|
create_file(
|
26
19
|
'kuby.rb',
|
27
20
|
<<~END
|
@@ -59,13 +52,7 @@ class KubyGenerator < Rails::Generators::Base
|
|
59
52
|
|
60
53
|
kubernetes do
|
61
54
|
# Add a plugin that facilitates deploying a Rails app.
|
62
|
-
add_plugin :rails_app
|
63
|
-
# configure database credentials
|
64
|
-
database do
|
65
|
-
user app_creds[:KUBY_DB_USER]
|
66
|
-
password app_creds[:KUBY_DB_PASSWORD]
|
67
|
-
end
|
68
|
-
end
|
55
|
+
add_plugin :rails_app
|
69
56
|
|
70
57
|
# Use Docker Desktop as the provider.
|
71
58
|
# See: https://www.docker.com/products/docker-desktop
|
@@ -121,4 +108,18 @@ class KubyGenerator < Rails::Generators::Base
|
|
121
108
|
END
|
122
109
|
)
|
123
110
|
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def app_name
|
115
|
+
@app_name ||= begin
|
116
|
+
app_class = Rails.application.class
|
117
|
+
|
118
|
+
if app_class.respond_to?(:module_parent_name)
|
119
|
+
app_class.module_parent_name
|
120
|
+
else
|
121
|
+
app_class.parent_name
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
124
125
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
|
+
|
2
3
|
require 'kube-dsl'
|
3
4
|
require 'kuby/cert-manager'
|
4
5
|
|
@@ -6,6 +7,8 @@ module Kuby
|
|
6
7
|
module Plugins
|
7
8
|
module RailsApp
|
8
9
|
class Plugin < ::Kuby::Plugin
|
10
|
+
depends_on :kubernetes, '>= 1.20'
|
11
|
+
|
9
12
|
extend ::KubeDSL::ValueFields
|
10
13
|
|
11
14
|
WEB_ROLE = 'web'.freeze
|
@@ -18,8 +21,7 @@ module Kuby
|
|
18
21
|
DEFAULT_ASSET_PATH = './public'.freeze
|
19
22
|
|
20
23
|
value_field :root, default: '.'
|
21
|
-
value_fields :hostname, :tls_enabled
|
22
|
-
value_fields :manage_database, :database, :replicas
|
24
|
+
value_fields :hostname, :tls_enabled, :manage_database, :replicas
|
23
25
|
value_fields :asset_url, :packs_url, :asset_path
|
24
26
|
|
25
27
|
alias_method :manage_database?, :manage_database
|
@@ -45,11 +47,12 @@ module Kuby
|
|
45
47
|
if manage_database? && @database = Database.get(self)
|
46
48
|
@database.plugin.instance_eval(&@database_block) if @database_block
|
47
49
|
environment.kubernetes.plugins[@database.plugin_name] = @database.plugin
|
48
|
-
environment.kubernetes.add_plugin(:kube_db)
|
49
50
|
|
50
51
|
environment.docker do
|
51
52
|
insert :rewrite_db_config, RewriteDbConfig.new, after: :copy_phase
|
52
53
|
end
|
54
|
+
|
55
|
+
@database.plugin.configure_pod_spec(deployment.spec.template.spec)
|
53
56
|
end
|
54
57
|
|
55
58
|
environment.kubernetes.add_plugin(:nginx_ingress)
|
@@ -87,6 +90,15 @@ module Kuby
|
|
87
90
|
spec = self
|
88
91
|
|
89
92
|
deployment do
|
93
|
+
metadata do
|
94
|
+
annotations do
|
95
|
+
add(
|
96
|
+
'getkuby.io/dockerfile-checksum',
|
97
|
+
spec.environment.docker.image.dockerfile.checksum
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
90
102
|
spec do
|
91
103
|
template do
|
92
104
|
spec do
|
@@ -229,13 +241,6 @@ module Kuby
|
|
229
241
|
add :app, kube_spec.selector_app
|
230
242
|
add :role, kube_spec.role
|
231
243
|
end
|
232
|
-
|
233
|
-
annotations do
|
234
|
-
add(
|
235
|
-
'getkuby.io/dockerfile-checksum',
|
236
|
-
kube_spec.environment.docker.image.dockerfile.checksum
|
237
|
-
)
|
238
|
-
end
|
239
244
|
end
|
240
245
|
|
241
246
|
spec do
|
@@ -305,7 +310,7 @@ module Kuby
|
|
305
310
|
|
306
311
|
init_container(:create_db) do
|
307
312
|
name "#{kube_spec.selector_app}-create-db"
|
308
|
-
command %w(bundle exec rake kuby:rails_app:db:
|
313
|
+
command %w(bundle exec rake kuby:rails_app:db:bootstrap)
|
309
314
|
|
310
315
|
env_from do
|
311
316
|
config_map_ref do
|
@@ -322,7 +327,7 @@ module Kuby
|
|
322
327
|
|
323
328
|
init_container(:migrate_db) do
|
324
329
|
name "#{kube_spec.selector_app}-migrate-db"
|
325
|
-
command %w(bundle exec rake db:migrate)
|
330
|
+
command %w(bundle exec rake kuby:rails_app:db:migrate)
|
326
331
|
|
327
332
|
env_from do
|
328
333
|
config_map_ref do
|
@@ -356,7 +361,7 @@ module Kuby
|
|
356
361
|
spec = self
|
357
362
|
tls_enabled = @tls_enabled
|
358
363
|
|
359
|
-
@ingress ||= KubeDSL::DSL::
|
364
|
+
@ingress ||= KubeDSL::DSL::Networking::V1::Ingress.new do
|
360
365
|
metadata do
|
361
366
|
name "#{spec.selector_app}-ingress"
|
362
367
|
namespace spec.namespace.metadata.name
|
@@ -373,10 +378,16 @@ module Kuby
|
|
373
378
|
http do
|
374
379
|
path do
|
375
380
|
path '/'
|
381
|
+
path_type 'Prefix'
|
376
382
|
|
377
383
|
backend do
|
378
|
-
|
379
|
-
|
384
|
+
service do
|
385
|
+
name spec.service.metadata.name
|
386
|
+
|
387
|
+
port do
|
388
|
+
name spec.service.spec.ports.first.name
|
389
|
+
end
|
390
|
+
end
|
380
391
|
end
|
381
392
|
end
|
382
393
|
end
|
@@ -402,8 +413,8 @@ module Kuby
|
|
402
413
|
config_map,
|
403
414
|
app_secrets,
|
404
415
|
deployment,
|
405
|
-
|
406
|
-
|
416
|
+
*database&.plugin&.resources,
|
417
|
+
ingress
|
407
418
|
]
|
408
419
|
end
|
409
420
|
|