kuby-core 0.2.0 → 0.6.1
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 +58 -0
- data/Gemfile +0 -4
- data/README.md +3 -160
- data/kuby-core.gemspec +5 -4
- data/lib/ext/krane/kubernetes_resource.rb +16 -0
- data/lib/kuby.rb +32 -17
- data/lib/kuby/definition.rb +20 -14
- data/lib/kuby/docker.rb +2 -1
- data/lib/kuby/docker/alpine.rb +0 -1
- data/lib/kuby/docker/assets_phase.rb +1 -1
- data/lib/kuby/docker/bundler_phase.rb +4 -2
- data/lib/kuby/docker/copy_phase.rb +1 -1
- data/lib/kuby/docker/inline_layer.rb +15 -0
- data/lib/kuby/docker/{phase.rb → layer.rb} +6 -5
- data/lib/kuby/docker/layer_stack.rb +30 -4
- data/lib/kuby/docker/metadata.rb +27 -1
- data/lib/kuby/docker/package_phase.rb +1 -1
- data/lib/kuby/docker/packages.rb +5 -4
- data/lib/kuby/docker/packages/simple_managed_package.rb +25 -0
- data/lib/kuby/docker/setup_phase.rb +1 -1
- data/lib/kuby/docker/spec.rb +4 -4
- data/lib/kuby/docker/tags.rb +18 -0
- data/lib/kuby/docker/webserver_phase.rb +1 -1
- data/lib/kuby/docker/yarn_phase.rb +1 -1
- data/lib/kuby/environment.rb +22 -0
- data/lib/kuby/kubernetes.rb +1 -0
- data/lib/kuby/kubernetes/deploy_task.rb +33 -0
- data/lib/kuby/kubernetes/deployer.rb +1 -2
- data/lib/kuby/kubernetes/minikube_provider.rb +5 -5
- data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +12 -0
- data/lib/kuby/kubernetes/plugins/rails_app/database.rb +30 -9
- data/lib/kuby/kubernetes/plugins/rails_app/generators/kuby.rb +83 -0
- data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +17 -5
- data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +28 -42
- data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +132 -0
- data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +20 -0
- data/lib/kuby/kubernetes/plugins/rails_app/tasks.rake +9 -4
- data/lib/kuby/kubernetes/spec.rb +52 -37
- data/lib/kuby/railtie.rb +0 -4
- data/lib/kuby/tasks.rb +18 -0
- data/lib/kuby/tasks/kuby.rake +24 -17
- data/lib/kuby/version.rb +1 -1
- metadata +21 -15
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/base'
|
3
|
+
|
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
|
+
def create_config_file
|
17
|
+
create_file(
|
18
|
+
'kuby.rb',
|
19
|
+
<<~END
|
20
|
+
require 'active_support/encrypted_configuration'
|
21
|
+
|
22
|
+
# Define a production Kuby deploy environment
|
23
|
+
Kuby.define(:production) do
|
24
|
+
app_creds = ActiveSupport::EncryptedConfiguration.new(
|
25
|
+
config_path: File.join('config', 'credentials.yml.enc'),
|
26
|
+
key_path: File.join('config', 'master.key'),
|
27
|
+
env_key: 'RAILS_MASTER_KEY',
|
28
|
+
raise_if_missing_key: true
|
29
|
+
)
|
30
|
+
|
31
|
+
docker do
|
32
|
+
# Configure your Docker registry credentials here. Add them to your
|
33
|
+
# Rails credentials file by running `bundle exec rake credentials:edit`.
|
34
|
+
credentials do
|
35
|
+
username app_creds[:KUBY_DOCKER_USERNAME]
|
36
|
+
password app_creds[:KUBY_DOCKER_PASSWORD]
|
37
|
+
email app_creds[:KUBY_DOCKER_EMAIL]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Configure the URL to your Docker image here, eg:
|
41
|
+
# image_url 'foo.bar.com/me/myproject'
|
42
|
+
#
|
43
|
+
# If you're using Gitlab's Docker registry, try something like this:
|
44
|
+
# image_url 'registry.gitlab.com/<username>/<repo>'
|
45
|
+
end
|
46
|
+
|
47
|
+
kubernetes do
|
48
|
+
# Add a plugin that facilitates deploying a Rails app.
|
49
|
+
add_plugin :rails_app
|
50
|
+
|
51
|
+
# Use minikube as the provider, which is the default installed by
|
52
|
+
# Docker Desktop.
|
53
|
+
# See: https://github.com/kubernetes/minikube
|
54
|
+
#
|
55
|
+
# Note: you will likely want to use a different provider when deploying
|
56
|
+
# your application into a production environment. To configure a different
|
57
|
+
# provider, add the corresponding gem to your gemfile and update the
|
58
|
+
# following line according to the provider gem's README.
|
59
|
+
provider :minikube
|
60
|
+
end
|
61
|
+
end
|
62
|
+
END
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_dockerignore
|
67
|
+
create_file(
|
68
|
+
'.dockerignore',
|
69
|
+
<<~END
|
70
|
+
.bundle/
|
71
|
+
vendor/bundle
|
72
|
+
node_modules/
|
73
|
+
.node_modules/
|
74
|
+
**/.git*
|
75
|
+
tmp/
|
76
|
+
log/
|
77
|
+
engines/**/log/
|
78
|
+
engines/**/tmp/
|
79
|
+
public/assets
|
80
|
+
END
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
@@ -6,6 +6,8 @@ module Kuby
|
|
6
6
|
module Plugins
|
7
7
|
module RailsApp
|
8
8
|
class MySQL < Kuby::Kubernetes::Plugin
|
9
|
+
ROLE = 'web'.freeze
|
10
|
+
|
9
11
|
attr_reader :definition, :environment, :configs
|
10
12
|
|
11
13
|
def initialize(definition, environment, configs)
|
@@ -54,6 +56,20 @@ module Kuby
|
|
54
56
|
end
|
55
57
|
end
|
56
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
|
+
|
57
73
|
def secret(&block)
|
58
74
|
context = self
|
59
75
|
|
@@ -109,17 +125,13 @@ module Kuby
|
|
109
125
|
end
|
110
126
|
|
111
127
|
def base_name
|
112
|
-
@base_name ||= "#{kubernetes.selector_app}-#{
|
128
|
+
@base_name ||= "#{kubernetes.selector_app}-#{ROLE}"
|
113
129
|
end
|
114
130
|
|
115
131
|
def kubernetes
|
116
132
|
definition.kubernetes
|
117
133
|
end
|
118
134
|
|
119
|
-
def app
|
120
|
-
definition.app
|
121
|
-
end
|
122
|
-
|
123
135
|
private
|
124
136
|
|
125
137
|
def config
|
@@ -13,11 +13,17 @@ module Kuby
|
|
13
13
|
ENV_SECRETS = [MASTER_KEY_VAR].freeze
|
14
14
|
ENV_EXCLUDE = ['RAILS_ENV'].freeze
|
15
15
|
|
16
|
-
|
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
|
17
21
|
|
18
22
|
def initialize(definition)
|
19
23
|
@definition = definition
|
20
24
|
@tls_enabled = true
|
25
|
+
@replicas = 1
|
26
|
+
@manage_database = true
|
21
27
|
end
|
22
28
|
|
23
29
|
def configure(&block)
|
@@ -25,11 +31,7 @@ module Kuby
|
|
25
31
|
end
|
26
32
|
|
27
33
|
def after_configuration
|
28
|
-
|
29
|
-
# is here as a placeholder to indicate we'd like to be able to
|
30
|
-
# handle Rails apps that don't use a database, i.e. don't have
|
31
|
-
# activerecord configured
|
32
|
-
if @database = Database.get(definition)
|
34
|
+
if @database = Database.get(self)
|
33
35
|
definition.kubernetes.plugins[database] = @database
|
34
36
|
definition.kubernetes.add_plugin(:kube_db)
|
35
37
|
|
@@ -42,7 +44,11 @@ module Kuby
|
|
42
44
|
definition.kubernetes.add_plugin(:nginx_ingress)
|
43
45
|
|
44
46
|
if @tls_enabled
|
45
|
-
|
47
|
+
context = self
|
48
|
+
|
49
|
+
definition.kubernetes.add_plugin(:cert_manager) do
|
50
|
+
email context.definition.docker.credentials.email
|
51
|
+
end
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
@@ -53,14 +59,9 @@ module Kuby
|
|
53
59
|
cert_manager.annotate_ingress(ing)
|
54
60
|
end
|
55
61
|
end
|
56
|
-
end
|
57
62
|
|
58
|
-
|
59
|
-
@database.instance_eval(&block) if block
|
60
|
-
@database
|
61
|
-
end
|
63
|
+
image_with_tag = "#{docker.metadata.image_url}:#{kubernetes.tag}"
|
62
64
|
|
63
|
-
def set_image(image_with_tag)
|
64
65
|
deployment do
|
65
66
|
spec do
|
66
67
|
template do
|
@@ -82,6 +83,11 @@ module Kuby
|
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
86
|
+
def database(&block)
|
87
|
+
@database.instance_eval(&block) if block
|
88
|
+
@database
|
89
|
+
end
|
90
|
+
|
85
91
|
def service(&block)
|
86
92
|
spec = self
|
87
93
|
|
@@ -177,9 +183,9 @@ module Kuby
|
|
177
183
|
if master_key = ENV[MASTER_KEY_VAR]
|
178
184
|
add MASTER_KEY_VAR.to_sym, master_key
|
179
185
|
else
|
180
|
-
master_key_path = spec.
|
186
|
+
master_key_path = File.join(spec.root, 'config', 'master.key')
|
181
187
|
|
182
|
-
if
|
188
|
+
if File.exist?(master_key_path)
|
183
189
|
add MASTER_KEY_VAR.to_sym, File.read(master_key_path).strip
|
184
190
|
end
|
185
191
|
end
|
@@ -190,33 +196,12 @@ module Kuby
|
|
190
196
|
@app_secrets
|
191
197
|
end
|
192
198
|
|
193
|
-
def registry_secret(&block)
|
194
|
-
spec = self
|
195
|
-
|
196
|
-
@registry_secret ||= RegistrySecret.new do
|
197
|
-
metadata do
|
198
|
-
name "#{spec.selector_app}-registry-secret"
|
199
|
-
namespace spec.namespace.metadata.name
|
200
|
-
end
|
201
|
-
|
202
|
-
docker_config do
|
203
|
-
registry_host spec.docker.metadata.image_host
|
204
|
-
username spec.docker.credentials.username
|
205
|
-
password spec.docker.credentials.password
|
206
|
-
email spec.docker.credentials.email
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
@registry_secret.instance_eval(&block) if block
|
211
|
-
@registry_secret
|
212
|
-
end
|
213
|
-
|
214
199
|
def deployment(&block)
|
215
200
|
kube_spec = self
|
216
201
|
|
217
202
|
@deployment ||= KubeDSL.deployment do
|
218
203
|
metadata do
|
219
|
-
name "#{kube_spec.selector_app}
|
204
|
+
name "#{kube_spec.selector_app}-#{kube_spec.role}"
|
220
205
|
namespace kube_spec.namespace.metadata.name
|
221
206
|
|
222
207
|
labels do
|
@@ -226,6 +211,8 @@ module Kuby
|
|
226
211
|
end
|
227
212
|
|
228
213
|
spec do
|
214
|
+
replicas kube_spec.replicas
|
215
|
+
|
229
216
|
selector do
|
230
217
|
match_labels do
|
231
218
|
add :app, kube_spec.selector_app
|
@@ -299,7 +286,7 @@ module Kuby
|
|
299
286
|
end
|
300
287
|
|
301
288
|
image_pull_secret do
|
302
|
-
name kube_spec.registry_secret.metadata.name
|
289
|
+
name kube_spec.definition.kubernetes.registry_secret.metadata.name
|
303
290
|
end
|
304
291
|
|
305
292
|
restart_policy 'Always'
|
@@ -360,10 +347,9 @@ module Kuby
|
|
360
347
|
service_account,
|
361
348
|
config_map,
|
362
349
|
app_secrets,
|
363
|
-
registry_secret,
|
364
350
|
deployment,
|
365
351
|
ingress,
|
366
|
-
*database
|
352
|
+
*database&.resources
|
367
353
|
]
|
368
354
|
end
|
369
355
|
|
@@ -379,8 +365,8 @@ module Kuby
|
|
379
365
|
definition.docker
|
380
366
|
end
|
381
367
|
|
382
|
-
def
|
383
|
-
definition.
|
368
|
+
def kubernetes
|
369
|
+
definition.kubernetes
|
384
370
|
end
|
385
371
|
|
386
372
|
def namespace
|
@@ -1,10 +1,142 @@
|
|
1
|
+
require 'kube-dsl'
|
2
|
+
require 'kuby/kube-db'
|
3
|
+
|
1
4
|
module Kuby
|
2
5
|
module Kubernetes
|
3
6
|
module Plugins
|
4
7
|
module RailsApp
|
5
8
|
class Postgres < 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(:postgres_dev)
|
28
|
+
definition.docker.package_phase.add(:postgres_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 :POSTGRES_USER, user
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def password(password)
|
52
|
+
secret do
|
53
|
+
data do
|
54
|
+
set :POSTGRES_PASSWORD, password
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def secret(&block)
|
60
|
+
context = self
|
61
|
+
|
62
|
+
@secret ||= KubeDSL.secret do
|
63
|
+
metadata do
|
64
|
+
name "#{context.base_name}-postgres-secret"
|
65
|
+
namespace context.kubernetes.namespace.metadata.name
|
66
|
+
end
|
67
|
+
|
68
|
+
type 'Opaque'
|
69
|
+
end
|
70
|
+
|
71
|
+
@secret.instance_eval(&block) if block
|
72
|
+
@secret
|
73
|
+
end
|
74
|
+
|
75
|
+
def database(&block)
|
76
|
+
context = self
|
77
|
+
|
78
|
+
@database ||= Kuby::KubeDB.postgres do
|
79
|
+
api_version 'kubedb.com/v1alpha1'
|
80
|
+
|
81
|
+
metadata do
|
82
|
+
name "#{context.base_name}-postgres"
|
83
|
+
namespace context.kubernetes.namespace.metadata.name
|
84
|
+
end
|
85
|
+
|
86
|
+
spec do
|
87
|
+
database_secret do
|
88
|
+
secret_name context.secret.metadata.name
|
89
|
+
end
|
90
|
+
|
91
|
+
version '11.2'
|
92
|
+
standby_mode 'Hot'
|
93
|
+
streaming_mode 'asynchronous'
|
94
|
+
storage_type 'Durable'
|
95
|
+
|
96
|
+
storage do
|
97
|
+
storage_class_name context.kubernetes.provider.storage_class_name
|
98
|
+
access_modes ['ReadWriteOnce']
|
99
|
+
|
100
|
+
resources do
|
101
|
+
requests do
|
102
|
+
add :storage, '10Gi'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
termination_policy 'DoNotTerminate'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
@database.instance_eval(&block) if block
|
112
|
+
@database
|
113
|
+
end
|
114
|
+
|
115
|
+
def base_name
|
116
|
+
@base_name ||= "#{kubernetes.selector_app}-#{ROLE}"
|
117
|
+
end
|
118
|
+
|
119
|
+
def kubernetes
|
120
|
+
definition.kubernetes
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def config
|
126
|
+
configs[environment]
|
127
|
+
end
|
6
128
|
end
|
7
129
|
end
|
8
130
|
end
|
9
131
|
end
|
10
132
|
end
|
133
|
+
|
134
|
+
Kuby.register_package(:postgres_dev,
|
135
|
+
debian: 'postgresql-client',
|
136
|
+
alpine: 'postgresql-dev'
|
137
|
+
)
|
138
|
+
|
139
|
+
Kuby.register_package(:postgres_client,
|
140
|
+
debian: 'postgresql-client',
|
141
|
+
alpine: 'postgresql-client'
|
142
|
+
)
|
@@ -3,8 +3,28 @@ module Kuby
|
|
3
3
|
module Plugins
|
4
4
|
module RailsApp
|
5
5
|
class Sqlite < Kuby::Kubernetes::Plugin
|
6
|
+
attr_reader :definition
|
7
|
+
|
8
|
+
def initialize(definition, *)
|
9
|
+
@definition = definition
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_configuration
|
13
|
+
definition.docker.package_phase.add(:sqlite_dev)
|
14
|
+
definition.docker.package_phase.add(:sqlite_client)
|
15
|
+
end
|
6
16
|
end
|
7
17
|
end
|
8
18
|
end
|
9
19
|
end
|
10
20
|
end
|
21
|
+
|
22
|
+
Kuby.register_package(:sqlite_dev,
|
23
|
+
debian: 'libsqlite3-dev',
|
24
|
+
alpine: 'sqlite-dev'
|
25
|
+
)
|
26
|
+
|
27
|
+
Kuby.register_package(:sqlite_client,
|
28
|
+
debian: 'sqlite3',
|
29
|
+
alpine: 'sqlite'
|
30
|
+
)
|