kuby-core 0.1.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 +7 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +16 -0
- data/LICENSE +21 -0
- data/README.md +186 -0
- data/Rakefile +14 -0
- data/kuby-core.gemspec +27 -0
- data/lib/kuby.rb +112 -0
- data/lib/kuby/basic_logger.rb +22 -0
- data/lib/kuby/cli_base.rb +75 -0
- data/lib/kuby/definition.rb +29 -0
- data/lib/kuby/docker.rb +27 -0
- data/lib/kuby/docker/alpine.rb +62 -0
- data/lib/kuby/docker/assets_phase.rb +11 -0
- data/lib/kuby/docker/bundler_phase.rb +56 -0
- data/lib/kuby/docker/cli.rb +72 -0
- data/lib/kuby/docker/copy_phase.rb +23 -0
- data/lib/kuby/docker/credentials.rb +11 -0
- data/lib/kuby/docker/debian.rb +66 -0
- data/lib/kuby/docker/dockerfile.rb +128 -0
- data/lib/kuby/docker/errors.rb +22 -0
- data/lib/kuby/docker/layer_stack.rb +42 -0
- data/lib/kuby/docker/local_tags.rb +38 -0
- data/lib/kuby/docker/metadata.rb +69 -0
- data/lib/kuby/docker/package_list.rb +34 -0
- data/lib/kuby/docker/package_phase.rb +59 -0
- data/lib/kuby/docker/packages.rb +10 -0
- data/lib/kuby/docker/packages/managed_package.rb +29 -0
- data/lib/kuby/docker/packages/nodejs.rb +29 -0
- data/lib/kuby/docker/packages/package.rb +22 -0
- data/lib/kuby/docker/packages/yarn.rb +47 -0
- data/lib/kuby/docker/phase.rb +21 -0
- data/lib/kuby/docker/remote_tags.rb +24 -0
- data/lib/kuby/docker/setup_phase.rb +29 -0
- data/lib/kuby/docker/spec.rb +147 -0
- data/lib/kuby/docker/tags.rb +39 -0
- data/lib/kuby/docker/timestamp_tag.rb +36 -0
- data/lib/kuby/docker/webserver_phase.rb +51 -0
- data/lib/kuby/docker/yarn_phase.rb +11 -0
- data/lib/kuby/kubernetes.rb +16 -0
- data/lib/kuby/kubernetes/deployer.rb +94 -0
- data/lib/kuby/kubernetes/docker_config.rb +27 -0
- data/lib/kuby/kubernetes/errors.rb +22 -0
- data/lib/kuby/kubernetes/manifest.rb +56 -0
- data/lib/kuby/kubernetes/minikube_provider.rb +51 -0
- data/lib/kuby/kubernetes/plugin.rb +55 -0
- data/lib/kuby/kubernetes/plugins.rb +8 -0
- data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +61 -0
- data/lib/kuby/kubernetes/plugins/rails_app.rb +16 -0
- data/lib/kuby/kubernetes/plugins/rails_app/database.rb +58 -0
- data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +142 -0
- data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +393 -0
- data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +10 -0
- data/lib/kuby/kubernetes/plugins/rails_app/rewrite_db_config.rb +13 -0
- data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +10 -0
- data/lib/kuby/kubernetes/plugins/rails_app/tasks.rake +23 -0
- data/lib/kuby/kubernetes/provider.rb +77 -0
- data/lib/kuby/kubernetes/registry_secret.rb +26 -0
- data/lib/kuby/kubernetes/spec.rb +152 -0
- data/lib/kuby/middleware.rb +5 -0
- data/lib/kuby/middleware/health_check.rb +16 -0
- data/lib/kuby/railtie.rb +18 -0
- data/lib/kuby/tasks.rb +135 -0
- data/lib/kuby/tasks/kuby.rake +63 -0
- data/lib/kuby/trailing_hash.rb +19 -0
- data/lib/kuby/version.rb +3 -0
- metadata +233 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Kuby
|
2
|
+
module Kubernetes
|
3
|
+
class KubernetesCLIError < StandardError; end
|
4
|
+
|
5
|
+
class InvalidResourceError < KubernetesCLIError
|
6
|
+
attr_accessor :resource
|
7
|
+
end
|
8
|
+
|
9
|
+
class InvalidResourceUriError < KubernetesCLIError
|
10
|
+
attr_accessor :resource_uri
|
11
|
+
end
|
12
|
+
|
13
|
+
class GetResourceError < KubernetesCLIError; end
|
14
|
+
|
15
|
+
class MissingDeploymentError < StandardError; end
|
16
|
+
class MissingProviderError < StandardError; end
|
17
|
+
class MissingPluginError < StandardError; end
|
18
|
+
|
19
|
+
class MissingResourceError < StandardError; end
|
20
|
+
class DuplicateResourceError < StandardError; end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Kuby
|
4
|
+
module Kubernetes
|
5
|
+
class Manifest
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(resources)
|
9
|
+
@resources = resources
|
10
|
+
|
11
|
+
ensure_all_resources_unique!
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
@resources.each(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def find(kind, name)
|
19
|
+
@resources.find do |resource|
|
20
|
+
matches?(resource, kind, name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(kind, name)
|
25
|
+
idx = @resources.index do |resource|
|
26
|
+
matches?(resource, kind, name)
|
27
|
+
end
|
28
|
+
|
29
|
+
resources.delete(idx) if idx
|
30
|
+
end
|
31
|
+
|
32
|
+
def <<(resource)
|
33
|
+
@resources << resource
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def matches?(resource, kind, name)
|
39
|
+
resource.kind_sym == kind && resource.metadata.name == name
|
40
|
+
end
|
41
|
+
|
42
|
+
def ensure_all_resources_unique!
|
43
|
+
seen = Set.new
|
44
|
+
|
45
|
+
@resources.each do |resource|
|
46
|
+
key = "#{resource.kind_sym}-#{resource.metadata.name}"
|
47
|
+
|
48
|
+
if seen.include?(key)
|
49
|
+
raise DuplicateResourceError, "found more than one #{resource.kind.downcase} "\
|
50
|
+
"resource named '#{resource.metadata.name}'"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'kube-dsl'
|
2
|
+
|
3
|
+
module Kuby
|
4
|
+
module Kubernetes
|
5
|
+
class MinikubeProvider < Provider
|
6
|
+
STORAGE_CLASS_NAME = 'hostpath'.freeze
|
7
|
+
|
8
|
+
class Config
|
9
|
+
extend ::KubeDSL::ValueFields
|
10
|
+
|
11
|
+
value_fields :kubeconfig
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :config
|
15
|
+
|
16
|
+
def configure(&block)
|
17
|
+
config.instance_eval(&block) if block
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_configuration
|
21
|
+
if rails_app = spec.plugin(:rails_app)
|
22
|
+
# Remove ingress and change service type from ClusterIP to
|
23
|
+
# LoadBalancer. No need to set up ingress for minikube since
|
24
|
+
# it handles all the localhost mapping, etc if you set up a
|
25
|
+
# service LB.
|
26
|
+
rails_app.resources.delete(rails_app.ingress)
|
27
|
+
rails_app.service.spec { type 'LoadBalancer' }
|
28
|
+
end
|
29
|
+
|
30
|
+
configure do
|
31
|
+
# default kubeconfig path
|
32
|
+
kubeconfig File.join(ENV['HOME'], '.kube', 'config')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def kubeconfig_path
|
37
|
+
config.kubeconfig
|
38
|
+
end
|
39
|
+
|
40
|
+
def storage_class_name
|
41
|
+
STORAGE_CLASS_NAME
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def after_initialize
|
47
|
+
@config = Config.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Kuby
|
2
|
+
module Kubernetes
|
3
|
+
class Plugin
|
4
|
+
attr_reader :definition
|
5
|
+
|
6
|
+
def initialize(definition)
|
7
|
+
@definition = definition
|
8
|
+
after_initialize
|
9
|
+
end
|
10
|
+
|
11
|
+
def configure(&block)
|
12
|
+
# do nothing by default
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
# do nothing by default
|
17
|
+
end
|
18
|
+
|
19
|
+
def resources
|
20
|
+
[]
|
21
|
+
end
|
22
|
+
|
23
|
+
# called after all plugins have been configured
|
24
|
+
def after_configuration
|
25
|
+
# do nothing by default
|
26
|
+
end
|
27
|
+
|
28
|
+
# called before any plugins have been setup
|
29
|
+
def before_setup
|
30
|
+
# do nothing by default
|
31
|
+
end
|
32
|
+
|
33
|
+
# called after all plugins have been setup
|
34
|
+
def after_setup
|
35
|
+
# do nothing by default
|
36
|
+
end
|
37
|
+
|
38
|
+
# called before deploying any resources
|
39
|
+
def before_deploy(manifest)
|
40
|
+
# do nothing by default
|
41
|
+
end
|
42
|
+
|
43
|
+
# called after deploying all resources
|
44
|
+
def after_deploy(manifest)
|
45
|
+
# do nothing by default
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def after_initialize
|
51
|
+
# override this in derived classes
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'kube-dsl'
|
2
|
+
|
3
|
+
module Kuby
|
4
|
+
module Kubernetes
|
5
|
+
module Plugins
|
6
|
+
class NginxIngress < Plugin
|
7
|
+
class Config
|
8
|
+
extend ::KubeDSL::ValueFields
|
9
|
+
|
10
|
+
value_fields :provider
|
11
|
+
end
|
12
|
+
|
13
|
+
VERSION = '0.27.1'.freeze
|
14
|
+
DEFAULT_PROVIDER = 'cloud-generic'.freeze
|
15
|
+
NAMESPACE = 'ingress-nginx'.freeze
|
16
|
+
SERVICE_NAME = 'ingress-nginx'.freeze
|
17
|
+
|
18
|
+
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"
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
def configure(&block)
|
24
|
+
@config.instance_eval(&block) if block
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
Kuby.logger.info('Deploying nginx ingress resources')
|
29
|
+
|
30
|
+
SETUP_RESOURCES.each do |uri|
|
31
|
+
uri = uri % { provider: @config.provider || DEFAULT_PROVIDER }
|
32
|
+
kubernetes_cli.apply_uri(uri)
|
33
|
+
end
|
34
|
+
|
35
|
+
Kuby.logger.info('Nginx ingress resources deployed!')
|
36
|
+
rescue => e
|
37
|
+
Kuby.logger.fatal(e.message)
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
|
41
|
+
def namespace
|
42
|
+
NAMESPACE
|
43
|
+
end
|
44
|
+
|
45
|
+
def service_name
|
46
|
+
SERVICE_NAME
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def after_initialize
|
52
|
+
@config = Config.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def kubernetes_cli
|
56
|
+
definition.kubernetes.provider.kubernetes_cli
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kuby
|
2
|
+
module Kubernetes
|
3
|
+
module Plugins
|
4
|
+
module RailsApp
|
5
|
+
autoload :Database, 'kuby/kubernetes/plugins/rails_app/database'
|
6
|
+
autoload :MySQL, 'kuby/kubernetes/plugins/rails_app/mysql'
|
7
|
+
autoload :Plugin, 'kuby/kubernetes/plugins/rails_app/plugin'
|
8
|
+
autoload :Postgres, 'kuby/kubernetes/plugins/rails_app/postgres'
|
9
|
+
autoload :RewriteDbConfig, 'kuby/kubernetes/plugins/rails_app/rewrite_db_config'
|
10
|
+
autoload :Sqlite, 'kuby/kubernetes/plugins/rails_app/sqlite'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
load File.expand_path(File.join('rails_app', 'tasks.rake'), __dir__)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Kuby
|
2
|
+
module Kubernetes
|
3
|
+
module Plugins
|
4
|
+
module RailsApp
|
5
|
+
class UnsupportedDatabaseError < StandardError; end
|
6
|
+
|
7
|
+
class Database
|
8
|
+
ADAPTER_MAP = {
|
9
|
+
'sqlite3' => Sqlite,
|
10
|
+
'mysql2' => MySQL,
|
11
|
+
'postgresql' => Postgres
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def self.get(definition)
|
15
|
+
new(definition).database
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get_adapter(adapter)
|
19
|
+
ADAPTER_MAP.fetch(adapter) do
|
20
|
+
raise UnsupportedDatabaseError, "Kuby does not support the '#{adapter}'"\
|
21
|
+
'database adapter'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :definition
|
26
|
+
|
27
|
+
def initialize(definition)
|
28
|
+
@definition = definition
|
29
|
+
end
|
30
|
+
|
31
|
+
def database
|
32
|
+
@database ||= self.class
|
33
|
+
.get_adapter(adapter)
|
34
|
+
.new(definition, environment, db_configs)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def adapter
|
40
|
+
db_config['adapter']
|
41
|
+
end
|
42
|
+
|
43
|
+
def db_config
|
44
|
+
@db_config ||= db_configs[environment]
|
45
|
+
end
|
46
|
+
|
47
|
+
def environment
|
48
|
+
@environment ||= definition.environment
|
49
|
+
end
|
50
|
+
|
51
|
+
def db_configs
|
52
|
+
@db_configs ||= definition.app.config.database_configuration
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'kube-dsl'
|
2
|
+
require 'kuby/kube-db'
|
3
|
+
|
4
|
+
module Kuby
|
5
|
+
module Kubernetes
|
6
|
+
module Plugins
|
7
|
+
module RailsApp
|
8
|
+
class MySQL < Kuby::Kubernetes::Plugin
|
9
|
+
attr_reader :definition, :environment, :configs
|
10
|
+
|
11
|
+
def initialize(definition, environment, configs)
|
12
|
+
@definition = definition
|
13
|
+
@environment = environment
|
14
|
+
@configs = configs
|
15
|
+
|
16
|
+
user(config['username'])
|
17
|
+
password(config['password'])
|
18
|
+
end
|
19
|
+
|
20
|
+
def resources
|
21
|
+
@resources ||= [secret, database]
|
22
|
+
end
|
23
|
+
|
24
|
+
def after_configuration
|
25
|
+
definition.docker.package_phase.add(:mysql_dev)
|
26
|
+
definition.docker.package_phase.add(:mysql_client)
|
27
|
+
end
|
28
|
+
|
29
|
+
def host
|
30
|
+
# host is the same as the name thanks to k8s DNS
|
31
|
+
@host ||= database.metadata.name
|
32
|
+
end
|
33
|
+
|
34
|
+
def rewritten_configs
|
35
|
+
# deep dup
|
36
|
+
@rewritten_configs ||= Marshal.load(Marshal.dump(configs)).tap do |new_configs|
|
37
|
+
new_configs[environment]['host'] = host
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def user(user)
|
42
|
+
secret do
|
43
|
+
data do
|
44
|
+
set :user, user
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def password(password)
|
50
|
+
secret do
|
51
|
+
data do
|
52
|
+
set :password, password
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def secret(&block)
|
58
|
+
context = self
|
59
|
+
|
60
|
+
@secret ||= KubeDSL.secret do
|
61
|
+
metadata do
|
62
|
+
name "#{context.base_name}-mysql-secret"
|
63
|
+
namespace context.kubernetes.namespace.metadata.name
|
64
|
+
end
|
65
|
+
|
66
|
+
type 'Opaque'
|
67
|
+
end
|
68
|
+
|
69
|
+
@secret.instance_eval(&block) if block
|
70
|
+
@secret
|
71
|
+
end
|
72
|
+
|
73
|
+
def database(&block)
|
74
|
+
context = self
|
75
|
+
|
76
|
+
@database ||= Kuby::KubeDB.my_sql do
|
77
|
+
api_version 'kubedb.com/v1alpha1'
|
78
|
+
|
79
|
+
metadata do
|
80
|
+
name "#{context.base_name}-mysql"
|
81
|
+
namespace context.kubernetes.namespace.metadata.name
|
82
|
+
end
|
83
|
+
|
84
|
+
spec do
|
85
|
+
database_secret do
|
86
|
+
secret_name context.secret.metadata.name
|
87
|
+
end
|
88
|
+
|
89
|
+
version '5.7-v2'
|
90
|
+
storage_type 'Durable'
|
91
|
+
|
92
|
+
storage do
|
93
|
+
storage_class_name context.kubernetes.provider.storage_class_name
|
94
|
+
access_modes ['ReadWriteOnce']
|
95
|
+
|
96
|
+
resources do
|
97
|
+
requests do
|
98
|
+
add :storage, '10Gi'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
termination_policy 'DoNotTerminate'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
@database.instance_eval(&block) if block
|
108
|
+
@database
|
109
|
+
end
|
110
|
+
|
111
|
+
def base_name
|
112
|
+
@base_name ||= "#{kubernetes.selector_app}-#{environment}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def kubernetes
|
116
|
+
definition.kubernetes
|
117
|
+
end
|
118
|
+
|
119
|
+
def app
|
120
|
+
definition.app
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def config
|
126
|
+
configs[environment]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
Kuby.register_package(:mysql_client,
|
135
|
+
debian: 'default-mysql-client',
|
136
|
+
alpine: 'mariadb-client'
|
137
|
+
)
|
138
|
+
|
139
|
+
Kuby.register_package(:mysql_dev,
|
140
|
+
debian: 'default-libmysqlclient-dev',
|
141
|
+
alpine: 'mariadb-dev'
|
142
|
+
)
|