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
data/lib/kuby/docker.rb
CHANGED
@@ -4,10 +4,11 @@ require 'kuby/docker/errors'
|
|
4
4
|
|
5
5
|
module Kuby
|
6
6
|
module Docker
|
7
|
-
LATEST_TAG =
|
7
|
+
LATEST_TAG = 'latest'.freeze
|
8
8
|
|
9
9
|
autoload :Alpine, 'kuby/docker/alpine'
|
10
10
|
autoload :AppImage, 'kuby/docker/app_image'
|
11
|
+
autoload :AppPhase, 'kuby/docker/app_phase'
|
11
12
|
autoload :AssetsPhase, 'kuby/docker/assets_phase'
|
12
13
|
autoload :BundlerPhase, 'kuby/docker/bundler_phase'
|
13
14
|
autoload :CLI, 'kuby/docker/cli'
|
@@ -5,9 +5,9 @@ require 'kube-dsl'
|
|
5
5
|
module Kuby
|
6
6
|
module Kubernetes
|
7
7
|
class BareMetalProvider < Provider
|
8
|
-
extend T::Sig
|
8
|
+
# extend T::Sig
|
9
9
|
|
10
|
-
DEFAULT_STORAGE_CLASS =
|
10
|
+
DEFAULT_STORAGE_CLASS = 'hostpath'.freeze
|
11
11
|
|
12
12
|
class Config
|
13
13
|
extend ::KubeDSL::ValueFields
|
@@ -16,33 +16,33 @@ module Kuby
|
|
16
16
|
value_fields :storage_class
|
17
17
|
end
|
18
18
|
|
19
|
-
sig { returns(Config) }
|
19
|
+
# T::Sig::WithoutRuntime.sig { returns(Config) }
|
20
20
|
attr_reader :config
|
21
21
|
|
22
|
-
sig { params(environment: Environment).void }
|
22
|
+
# T::Sig::WithoutRuntime.sig { params(environment: Environment).void }
|
23
23
|
def initialize(environment)
|
24
|
-
@config =
|
24
|
+
@config = Config.new
|
25
25
|
super
|
26
26
|
end
|
27
27
|
|
28
|
-
sig { params(block: T.proc.void).void }
|
28
|
+
# T::Sig::WithoutRuntime.sig { params(block: T.proc.void).void }
|
29
29
|
def configure(&block)
|
30
30
|
config.instance_eval(&block) if block
|
31
31
|
end
|
32
32
|
|
33
|
-
sig { returns(String) }
|
33
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
34
34
|
def kubeconfig_path
|
35
35
|
config.kubeconfig
|
36
36
|
end
|
37
37
|
|
38
|
-
sig { returns(String) }
|
38
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
39
39
|
def storage_class_name
|
40
40
|
config.storage_class
|
41
41
|
end
|
42
42
|
|
43
43
|
private
|
44
44
|
|
45
|
-
sig { void }
|
45
|
+
# T::Sig::WithoutRuntime.sig { void }
|
46
46
|
def after_initialize
|
47
47
|
configure do
|
48
48
|
# default kubeconfig path
|
@@ -8,10 +8,8 @@ require 'yaml'
|
|
8
8
|
module Kuby
|
9
9
|
module Kubernetes
|
10
10
|
class Deployer
|
11
|
-
extend T::Sig
|
12
|
-
|
13
11
|
attr_reader :environment
|
14
|
-
|
12
|
+
attr_writer :logdev
|
15
13
|
|
16
14
|
def initialize(environment)
|
17
15
|
@environment = environment
|
@@ -19,7 +17,7 @@ module Kuby
|
|
19
17
|
|
20
18
|
def deploy
|
21
19
|
restart_rails_deployment_if_necessary do
|
22
|
-
|
20
|
+
resource_groups = all_resources.group_by do |resource|
|
23
21
|
# Unfortunately we can't use respond_to here because all KubeDSL
|
24
22
|
# objects use ObjectMeta, which has a namespace field. Not sure
|
25
23
|
# why, since it makes no sense for a namespace to have a namespace.
|
@@ -27,8 +25,21 @@ module Kuby
|
|
27
25
|
resource.metadata.namespace
|
28
26
|
end
|
29
27
|
|
30
|
-
deploy_global_resources(
|
31
|
-
|
28
|
+
deploy_global_resources(resource_groups[nil])
|
29
|
+
|
30
|
+
resource_groups.each_pair do |ns, resources|
|
31
|
+
next if !ns
|
32
|
+
|
33
|
+
begin
|
34
|
+
deploy_namespaced_resources(resources, ns)
|
35
|
+
rescue => e
|
36
|
+
puts e.message
|
37
|
+
|
38
|
+
if bt = e.backtrace
|
39
|
+
puts bt.join("\n")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
32
43
|
end
|
33
44
|
end
|
34
45
|
|
@@ -69,10 +80,11 @@ module Kuby
|
|
69
80
|
end
|
70
81
|
rescue KubernetesCLI::InvalidResourceError => e
|
71
82
|
Kuby.logger.fatal(e.message)
|
72
|
-
|
83
|
+
resource = e.resource&.to_resource
|
84
|
+
Kuby.logger.fatal(resource) if resource
|
73
85
|
end
|
74
86
|
|
75
|
-
def deploy_namespaced_resources(resources)
|
87
|
+
def deploy_namespaced_resources(resources, ns)
|
76
88
|
old_kubeconfig = ENV['KUBECONFIG']
|
77
89
|
ENV['KUBECONFIG'] = provider.kubeconfig_path
|
78
90
|
|
@@ -87,7 +99,7 @@ module Kuby
|
|
87
99
|
end
|
88
100
|
|
89
101
|
task = ::Kuby::Kubernetes::DeployTask.new(
|
90
|
-
namespace:
|
102
|
+
namespace: ns,
|
91
103
|
context: cli.current_context,
|
92
104
|
filenames: [tmpdir]
|
93
105
|
)
|
@@ -97,7 +109,7 @@ module Kuby
|
|
97
109
|
task.run!(verify_result: true, prune: false)
|
98
110
|
ensure
|
99
111
|
ENV['KUBECONFIG'] = old_kubeconfig
|
100
|
-
FileUtils.rm_rf(
|
112
|
+
FileUtils.rm_rf(tmpdir)
|
101
113
|
end
|
102
114
|
|
103
115
|
def restart_rails_deployment_if_necessary
|
data/lib/kuby/kubernetes/spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# typed: false
|
2
|
+
|
2
3
|
require 'kube-dsl'
|
4
|
+
require 'rake'
|
3
5
|
|
4
6
|
module Kuby
|
5
7
|
module Kubernetes
|
@@ -13,6 +15,7 @@ module Kuby
|
|
13
15
|
@plugins = TrailingHash.new
|
14
16
|
|
15
17
|
# default plugins
|
18
|
+
add_plugin(:system)
|
16
19
|
add_plugin(:rails_app)
|
17
20
|
end
|
18
21
|
|
@@ -69,17 +72,59 @@ module Kuby
|
|
69
72
|
def after_configuration
|
70
73
|
@plugins.each { |_, plg| plg.after_configuration }
|
71
74
|
provider.after_configuration
|
75
|
+
environment.docker.after_configuration
|
76
|
+
|
77
|
+
spec = self
|
78
|
+
|
79
|
+
# this must be done _after_ docker has been configured
|
80
|
+
registry_secret do
|
81
|
+
docker_config do
|
82
|
+
registry_host spec.docker.image.image_hostname
|
83
|
+
username spec.docker.image.credentials.username
|
84
|
+
password spec.docker.image.credentials.password
|
85
|
+
email spec.docker.image.credentials.email
|
86
|
+
end
|
87
|
+
end
|
72
88
|
end
|
73
89
|
|
74
90
|
def before_deploy
|
75
91
|
@tag ||= docker.image.current_version.main_tag
|
76
92
|
|
93
|
+
check_dependencies!
|
94
|
+
|
77
95
|
provider.before_deploy(resources)
|
78
96
|
@plugins.each { |_, plg| plg.before_deploy(resources) }
|
79
97
|
ensure
|
80
98
|
@tag = nil
|
81
99
|
end
|
82
100
|
|
101
|
+
def check_dependencies!(plugins = @plugins)
|
102
|
+
error_messages = []
|
103
|
+
|
104
|
+
plugins.each do |plg_name, plg|
|
105
|
+
plg.class.dependencies.each do |dependency|
|
106
|
+
dependable = Kuby.dependables[dependency.name]
|
107
|
+
|
108
|
+
unless dependable
|
109
|
+
error_messages << "The #{plg_name} plugin depends on #{dependency.name}, "\
|
110
|
+
"but that dependency has not been registered."
|
111
|
+
|
112
|
+
next
|
113
|
+
end
|
114
|
+
|
115
|
+
unless dependency.satisfied_by?(dependable)
|
116
|
+
error_messages << "The #{plg_name} plugin depends on #{dependency.name} "\
|
117
|
+
"#{dependency.constraints}, but the available version is #{dependable.version}."
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
unless error_messages.empty?
|
123
|
+
error_messages.each { |msg| Kuby.logger.fatal(msg) }
|
124
|
+
exit 1
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
83
128
|
def after_deploy
|
84
129
|
@tag ||= docker.image.current_version.main_tag
|
85
130
|
|
@@ -98,6 +143,8 @@ module Kuby
|
|
98
143
|
end
|
99
144
|
end
|
100
145
|
|
146
|
+
check_dependencies!(plugins)
|
147
|
+
|
101
148
|
if only.empty?
|
102
149
|
provider.before_setup
|
103
150
|
provider.setup
|
@@ -159,13 +206,6 @@ module Kuby
|
|
159
206
|
name "#{spec.selector_app}-registry-secret"
|
160
207
|
namespace spec.namespace.metadata.name
|
161
208
|
end
|
162
|
-
|
163
|
-
docker_config do
|
164
|
-
registry_host spec.docker.image.image_hostname
|
165
|
-
username spec.docker.image.credentials.username
|
166
|
-
password spec.docker.image.credentials.password
|
167
|
-
email spec.docker.image.credentials.email
|
168
|
-
end
|
169
209
|
end
|
170
210
|
|
171
211
|
@registry_secret.instance_eval(&block) if block
|
data/lib/kuby/plugin.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: false
|
2
|
+
|
2
3
|
module Kuby
|
3
4
|
class Plugin
|
4
5
|
attr_reader :environment
|
@@ -8,6 +9,21 @@ module Kuby
|
|
8
9
|
after_initialize
|
9
10
|
end
|
10
11
|
|
12
|
+
class << self
|
13
|
+
# returns an array of directories containing .rake files
|
14
|
+
def task_dirs
|
15
|
+
[]
|
16
|
+
end
|
17
|
+
|
18
|
+
def depends_on(dependable_name, *constraints)
|
19
|
+
dependencies << Kuby::Dependency.new(dependable_name, *constraints)
|
20
|
+
end
|
21
|
+
|
22
|
+
def dependencies
|
23
|
+
@dependencies ||= []
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
11
27
|
def configure(&block)
|
12
28
|
# do nothing by default
|
13
29
|
end
|
@@ -17,6 +33,11 @@ module Kuby
|
|
17
33
|
# do nothing by default
|
18
34
|
end
|
19
35
|
|
36
|
+
# remove all global resources installed by #setup
|
37
|
+
def remove
|
38
|
+
# do nothing by default
|
39
|
+
end
|
40
|
+
|
20
41
|
# additional kubernetes resources that should be deployed
|
21
42
|
def resources
|
22
43
|
[]
|
@@ -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 = '
|
14
|
-
DEFAULT_PROVIDER = 'cloud
|
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/
|
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',
|
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
|
-
|
34
|
-
|
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
|
-
|
43
|
-
|
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,33 +11,42 @@ module Kuby
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def new_version
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
base_image.new_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
|
18
17
|
)
|
19
18
|
end
|
20
19
|
|
21
20
|
def current_version
|
22
|
-
|
21
|
+
duplicate_with_annotated_tags(
|
23
22
|
base_image.current_version
|
24
23
|
)
|
25
24
|
end
|
26
25
|
|
27
26
|
def previous_version
|
28
|
-
|
27
|
+
duplicate_with_annotated_tags(
|
29
28
|
base_image.previous_version
|
30
29
|
)
|
31
30
|
end
|
32
31
|
|
33
|
-
def build(build_args = {}, docker_args = [], context: nil)
|
34
|
-
docker_cli.build(
|
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
|
+
)
|
35
40
|
end
|
36
41
|
|
37
42
|
def push(tag)
|
38
43
|
docker_cli.push(image_url, tag)
|
39
44
|
end
|
40
45
|
|
46
|
+
def pull(tag)
|
47
|
+
docker_cli.pull(image_url, tag)
|
48
|
+
end
|
49
|
+
|
41
50
|
private
|
42
51
|
|
43
52
|
def duplicate_with_annotated_tags(image)
|