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
data/lib/kuby/docker/alpine.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
1
3
|
module Kuby
|
2
4
|
module Docker
|
3
|
-
class BundlerPhase <
|
5
|
+
class BundlerPhase < Layer
|
4
6
|
DEFAULT_WITHOUT = ['development', 'test', 'deploy'].freeze
|
5
7
|
|
6
8
|
attr_accessor :version, :gemfile, :without
|
@@ -48,7 +50,7 @@ module Kuby
|
|
48
50
|
.definition
|
49
51
|
.gemfiles
|
50
52
|
.first
|
51
|
-
.relative_path_from(
|
53
|
+
.relative_path_from(Pathname(Dir.getwd))
|
52
54
|
.to_s
|
53
55
|
end
|
54
56
|
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
module Kuby
|
2
2
|
module Docker
|
3
|
-
class
|
3
|
+
class Layer
|
4
4
|
attr_reader :definition
|
5
5
|
|
6
6
|
def initialize(definition)
|
7
7
|
@definition = definition
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
definition.app
|
10
|
+
def apply_to(dockerfile)
|
11
|
+
raise NotImplementedError,
|
12
|
+
"#{__method__} must be defined in derived classes"
|
14
13
|
end
|
15
14
|
|
15
|
+
private
|
16
|
+
|
16
17
|
def metadata
|
17
18
|
definition.docker.metadata
|
18
19
|
end
|
@@ -15,12 +15,31 @@ module Kuby
|
|
15
15
|
@stack.each { |name| yield layers[name] }
|
16
16
|
end
|
17
17
|
|
18
|
-
def use(name, layer)
|
18
|
+
def use(name, layer = nil, &block)
|
19
19
|
stack << name
|
20
|
-
|
20
|
+
|
21
|
+
if layer
|
22
|
+
layers[name] = layer
|
23
|
+
elsif block_given?
|
24
|
+
layers[name] = InlineLayer.new(block)
|
25
|
+
else
|
26
|
+
raise "Must either pass a layer object or a block to `#{__method__}'"
|
27
|
+
end
|
21
28
|
end
|
22
29
|
|
23
|
-
def insert(name, layer, options = {})
|
30
|
+
def insert(name, layer = nil, options = {}, &block)
|
31
|
+
# this is truly gross but it's the only way I can think of to be able
|
32
|
+
# to call insert these two ways:
|
33
|
+
#
|
34
|
+
# insert :foo, FooLayer.new, before: :bundler_phase
|
35
|
+
# insert :foo, before: :bundler_phase do
|
36
|
+
# ...
|
37
|
+
# end
|
38
|
+
if layer.is_a?(Hash)
|
39
|
+
insert(name, nil, options.merge(layer), &block)
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
24
43
|
existing_name = options[:before] || options[:after]
|
25
44
|
idx = stack.index(existing_name)
|
26
45
|
|
@@ -30,7 +49,14 @@ module Kuby
|
|
30
49
|
|
31
50
|
idx += 1 if options[:after]
|
32
51
|
stack.insert(idx, name)
|
33
|
-
|
52
|
+
|
53
|
+
if layer
|
54
|
+
layers[name] = layer
|
55
|
+
elsif block_given?
|
56
|
+
layers[name] = InlineLayer.new(block)
|
57
|
+
else
|
58
|
+
raise "Must either pass a layer object or a block to `#{__method__}'"
|
59
|
+
end
|
34
60
|
end
|
35
61
|
|
36
62
|
def delete(name)
|
data/lib/kuby/docker/metadata.rb
CHANGED
@@ -8,7 +8,7 @@ module Kuby
|
|
8
8
|
LATEST_TAG = 'latest'
|
9
9
|
|
10
10
|
attr_accessor :image_url
|
11
|
-
attr_reader :definition
|
11
|
+
attr_reader :definition
|
12
12
|
|
13
13
|
def initialize(definition)
|
14
14
|
@definition = definition
|
@@ -40,6 +40,32 @@ module Kuby
|
|
40
40
|
@tags.empty? ? default_tags : @tags
|
41
41
|
end
|
42
42
|
|
43
|
+
def tag
|
44
|
+
t = ENV.fetch('KUBY_DOCKER_TAG') do
|
45
|
+
definition.docker.tags.latest_timestamp_tag
|
46
|
+
end
|
47
|
+
|
48
|
+
unless t
|
49
|
+
raise MissingTagError, 'could not find latest timestamped tag'
|
50
|
+
end
|
51
|
+
|
52
|
+
t.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def previous_tag(current_tag)
|
56
|
+
t = definition.docker.tags.previous_timestamp_tag(current_tag)
|
57
|
+
|
58
|
+
unless t
|
59
|
+
raise MissingTagError, 'could not find previous timestamped tag'
|
60
|
+
end
|
61
|
+
|
62
|
+
t.to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
def distro
|
66
|
+
@distro || DEFAULT_DISTRO
|
67
|
+
end
|
68
|
+
|
43
69
|
def distro=(distro_name)
|
44
70
|
@distro = distro_name
|
45
71
|
end
|
data/lib/kuby/docker/packages.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Kuby
|
2
2
|
module Docker
|
3
3
|
module Packages
|
4
|
-
autoload :ManagedPackage,
|
5
|
-
autoload :Nodejs,
|
6
|
-
autoload :Package,
|
7
|
-
autoload :
|
4
|
+
autoload :ManagedPackage, 'kuby/docker/packages/managed_package'
|
5
|
+
autoload :Nodejs, 'kuby/docker/packages/nodejs'
|
6
|
+
autoload :Package, 'kuby/docker/packages/package'
|
7
|
+
autoload :SimpleManagedPackage, 'kuby/docker/packages/simple_managed_package'
|
8
|
+
autoload :Yarn, 'kuby/docker/packages/yarn'
|
8
9
|
end
|
9
10
|
end
|
10
11
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Kuby
|
2
|
+
module Docker
|
3
|
+
module Packages
|
4
|
+
class SimpleManagedPackage
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def package_name_for(distro)
|
12
|
+
name
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_version(*)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def managed?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/kuby/docker/spec.rb
CHANGED
@@ -50,12 +50,12 @@ module Kuby
|
|
50
50
|
metadata.image_url = url
|
51
51
|
end
|
52
52
|
|
53
|
-
def use(*args)
|
54
|
-
layer_stack.use(*args)
|
53
|
+
def use(*args, &block)
|
54
|
+
layer_stack.use(*args, &block)
|
55
55
|
end
|
56
56
|
|
57
|
-
def insert(*args)
|
58
|
-
layer_stack.insert(*args)
|
57
|
+
def insert(*args, &block)
|
58
|
+
layer_stack.insert(*args, &block)
|
59
59
|
end
|
60
60
|
|
61
61
|
def delete(*args)
|
data/lib/kuby/docker/tags.rb
CHANGED
@@ -19,10 +19,28 @@ module Kuby
|
|
19
19
|
(local.latest_tags + remote.latest_tags).uniq
|
20
20
|
end
|
21
21
|
|
22
|
+
def previous_timestamp_tag(current_tag)
|
23
|
+
current_tag = ::Kuby::Docker::TimestampTag.try_parse(current_tag)
|
24
|
+
all_tags = timestamp_tags.sort
|
25
|
+
|
26
|
+
idx = all_tags.index do |tag|
|
27
|
+
tag.time == current_tag.time
|
28
|
+
end
|
29
|
+
|
30
|
+
idx ||= 0
|
31
|
+
return nil unless idx > 0
|
32
|
+
|
33
|
+
all_tags[idx - 1]
|
34
|
+
end
|
35
|
+
|
22
36
|
def timestamp_tags
|
23
37
|
(local.timestamp_tags + remote.timestamp_tags).uniq
|
24
38
|
end
|
25
39
|
|
40
|
+
def latest_timestamp_tag
|
41
|
+
@latest_timestamp_tag ||= timestamp_tags.sort.last
|
42
|
+
end
|
43
|
+
|
26
44
|
def all
|
27
45
|
self
|
28
46
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Kuby
|
2
|
+
class Environment
|
3
|
+
attr_reader :name, :definition
|
4
|
+
|
5
|
+
def initialize(name, definition, &block)
|
6
|
+
@name = name
|
7
|
+
@definition = definition
|
8
|
+
end
|
9
|
+
|
10
|
+
def docker(&block)
|
11
|
+
@docker ||= Docker::Spec.new(definition)
|
12
|
+
@docker.instance_eval(&block) if block
|
13
|
+
@docker
|
14
|
+
end
|
15
|
+
|
16
|
+
def kubernetes(&block)
|
17
|
+
@kubernetes ||= Kubernetes::Spec.new(definition)
|
18
|
+
@kubernetes.instance_eval(&block) if block
|
19
|
+
@kubernetes
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/kuby/kubernetes.rb
CHANGED
@@ -4,6 +4,7 @@ module Kuby
|
|
4
4
|
module Kubernetes
|
5
5
|
autoload :MinikubeProvider, 'kuby/kubernetes/minikube_provider'
|
6
6
|
autoload :Deployer, 'kuby/kubernetes/deployer'
|
7
|
+
autoload :DeployTask, 'kuby/kubernetes/deploy_task'
|
7
8
|
autoload :DockerConfig, 'kuby/kubernetes/docker_config'
|
8
9
|
autoload :Manifest, 'kuby/kubernetes/manifest'
|
9
10
|
autoload :Monitors, 'kuby/kubernetes/monitors'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'krane'
|
2
|
+
require 'ext/krane/kubernetes_resource'
|
3
|
+
require 'kubectl-rb'
|
4
|
+
|
5
|
+
module Kuby
|
6
|
+
module Kubernetes
|
7
|
+
class DeployTask
|
8
|
+
attr_reader :deploy_task
|
9
|
+
|
10
|
+
def initialize(**kwargs)
|
11
|
+
@deploy_task ||= ::Krane::DeployTask.new(**kwargs)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run!(**kwargs)
|
15
|
+
new_path = "#{File.dirname(KubectlRb.executable)}:#{ENV['PATH']}"
|
16
|
+
|
17
|
+
with_env('PATH' => new_path) do
|
18
|
+
deploy_task.run!(**kwargs)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def with_env(new_env)
|
25
|
+
old_env = ENV.to_h
|
26
|
+
ENV.replace(old_env.merge(new_env))
|
27
|
+
yield
|
28
|
+
ensure
|
29
|
+
ENV.replace(old_env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
require 'krane'
|
3
2
|
require 'securerandom'
|
4
3
|
require 'yaml'
|
5
4
|
|
@@ -62,7 +61,7 @@ module Kuby
|
|
62
61
|
File.write(resource_path, resource.to_resource.to_yaml)
|
63
62
|
end
|
64
63
|
|
65
|
-
task = ::
|
64
|
+
task = ::Kuby::Kubernetes::DeployTask.new(
|
66
65
|
namespace: namespace.metadata.name,
|
67
66
|
context: cli.current_context,
|
68
67
|
filenames: [tmpdir]
|
@@ -26,11 +26,6 @@ module Kuby
|
|
26
26
|
rails_app.resources.delete(rails_app.ingress)
|
27
27
|
rails_app.service.spec { type 'LoadBalancer' }
|
28
28
|
end
|
29
|
-
|
30
|
-
configure do
|
31
|
-
# default kubeconfig path
|
32
|
-
kubeconfig File.join(ENV['HOME'], '.kube', 'config')
|
33
|
-
end
|
34
29
|
end
|
35
30
|
|
36
31
|
def kubeconfig_path
|
@@ -45,6 +40,11 @@ module Kuby
|
|
45
40
|
|
46
41
|
def after_initialize
|
47
42
|
@config = Config.new
|
43
|
+
|
44
|
+
configure do
|
45
|
+
# default kubeconfig path
|
46
|
+
kubeconfig File.join(ENV['HOME'], '.kube', 'config')
|
47
|
+
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -27,6 +27,11 @@ module Kuby
|
|
27
27
|
def setup
|
28
28
|
Kuby.logger.info('Deploying nginx ingress resources')
|
29
29
|
|
30
|
+
if already_deployed?
|
31
|
+
Kuby.logger.info('Nginx ingress already deployed, skipping')
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
30
35
|
SETUP_RESOURCES.each do |uri|
|
31
36
|
uri = uri % { provider: @config.provider || DEFAULT_PROVIDER }
|
32
37
|
kubernetes_cli.apply_uri(uri)
|
@@ -48,6 +53,13 @@ module Kuby
|
|
48
53
|
|
49
54
|
private
|
50
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
|
+
|
51
63
|
def after_initialize
|
52
64
|
@config = Config.new
|
53
65
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
|
1
4
|
module Kuby
|
2
5
|
module Kubernetes
|
3
6
|
module Plugins
|
@@ -11,27 +14,29 @@ module Kuby
|
|
11
14
|
'postgresql' => Postgres
|
12
15
|
}.freeze
|
13
16
|
|
14
|
-
def self.get(
|
15
|
-
|
17
|
+
def self.get(rails_app)
|
18
|
+
if rails_app.manage_database?
|
19
|
+
new(rails_app).database
|
20
|
+
end
|
16
21
|
end
|
17
22
|
|
18
23
|
def self.get_adapter(adapter)
|
19
24
|
ADAPTER_MAP.fetch(adapter) do
|
20
|
-
raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter}'"\
|
25
|
+
raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter}' "\
|
21
26
|
'database adapter'
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
25
|
-
attr_reader :
|
30
|
+
attr_reader :rails_app
|
26
31
|
|
27
|
-
def initialize(
|
28
|
-
@
|
32
|
+
def initialize(rails_app)
|
33
|
+
@rails_app = rails_app
|
29
34
|
end
|
30
35
|
|
31
36
|
def database
|
32
37
|
@database ||= self.class
|
33
38
|
.get_adapter(adapter)
|
34
|
-
.new(
|
39
|
+
.new(rails_app, environment, db_configs)
|
35
40
|
end
|
36
41
|
|
37
42
|
private
|
@@ -45,11 +50,27 @@ module Kuby
|
|
45
50
|
end
|
46
51
|
|
47
52
|
def environment
|
48
|
-
@environment ||= definition.environment
|
53
|
+
@environment ||= rails_app.definition.environment.name
|
49
54
|
end
|
50
55
|
|
51
56
|
def db_configs
|
52
|
-
@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
|
+
)
|
53
74
|
end
|
54
75
|
end
|
55
76
|
end
|