kuby-core 0.7.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/Gemfile +1 -0
- data/README.md +11 -1
- data/bin/kuby +4 -0
- data/kuby-core.gemspec +9 -4
- data/lib/kuby.rb +58 -19
- data/lib/kuby/basic_logger.rb +13 -0
- data/lib/kuby/cli_base.rb +81 -8
- data/lib/kuby/commands.rb +244 -0
- data/lib/kuby/definition.rb +1 -11
- data/lib/kuby/dev_setup.rb +255 -0
- data/lib/kuby/docker.rb +1 -0
- data/lib/kuby/docker/bundler_phase.rb +3 -3
- data/lib/kuby/docker/cli.rb +13 -1
- data/lib/kuby/docker/dev_spec.rb +131 -0
- data/lib/kuby/docker/dockerfile.rb +16 -1
- data/lib/kuby/docker/layer.rb +4 -4
- data/lib/kuby/docker/layer_stack.rb +4 -0
- data/lib/kuby/docker/local_tags.rb +4 -0
- data/lib/kuby/docker/metadata.rb +18 -38
- data/lib/kuby/docker/package_phase.rb +2 -2
- data/lib/kuby/docker/setup_phase.rb +3 -2
- data/lib/kuby/docker/spec.rb +42 -16
- data/lib/kuby/docker/timestamp_tag.rb +6 -0
- data/lib/kuby/environment.rb +15 -2
- data/lib/kuby/kubernetes.rb +9 -11
- data/lib/kuby/kubernetes/deploy_task.rb +4 -1
- data/lib/kuby/kubernetes/deployer.rb +70 -15
- data/lib/kuby/kubernetes/{minikube_provider.rb → docker_desktop_provider.rb} +8 -4
- data/lib/kuby/kubernetes/provider.rb +12 -8
- data/lib/kuby/kubernetes/spec.rb +30 -29
- data/lib/kuby/plugin.rb +59 -0
- data/lib/kuby/plugin_registry.rb +27 -0
- data/lib/kuby/plugins.rb +6 -0
- data/lib/kuby/plugins/nginx_ingress.rb +71 -0
- data/lib/kuby/plugins/rails_app.rb +18 -0
- data/lib/kuby/plugins/rails_app/asset_copy_task.rb +117 -0
- data/lib/kuby/plugins/rails_app/assets.rb +347 -0
- data/lib/kuby/plugins/rails_app/database.rb +74 -0
- data/lib/kuby/{kubernetes/plugins → plugins}/rails_app/generators/kuby.rb +14 -16
- data/lib/kuby/plugins/rails_app/mysql.rb +152 -0
- data/lib/kuby/plugins/rails_app/plugin.rb +593 -0
- data/lib/kuby/plugins/rails_app/postgres.rb +143 -0
- data/lib/kuby/plugins/rails_app/rewrite_db_config.rb +11 -0
- data/lib/kuby/plugins/rails_app/sqlite.rb +32 -0
- data/lib/kuby/plugins/rails_app/tasks.rake +36 -0
- data/lib/kuby/rails_commands.rb +89 -0
- data/lib/kuby/railtie.rb +0 -4
- data/lib/kuby/tasks.rb +85 -31
- data/lib/kuby/version.rb +1 -1
- data/spec/docker/metadata_spec.rb +84 -0
- data/spec/docker/spec_spec.rb +266 -0
- data/spec/docker/timestamp_tag_spec.rb +54 -4
- data/spec/dummy/Gemfile +54 -0
- data/spec/dummy/Gemfile.lock +223 -0
- data/spec/dummy/README.md +24 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/javascript/channels/consumer.js +6 -0
- data/spec/dummy/app/javascript/channels/index.js +5 -0
- data/spec/dummy/app/javascript/packs/application.js +17 -0
- data/spec/dummy/app/jobs/application_job.rb +7 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/bundle +114 -0
- data/spec/dummy/bin/rails +9 -0
- data/spec/dummy/bin/rake +9 -0
- data/spec/dummy/bin/setup +36 -0
- data/spec/dummy/bin/spring +17 -0
- data/spec/dummy/bin/yarn +11 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/config/application.rb +19 -0
- data/spec/dummy/config/boot.rb +4 -0
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/credentials.yml.enc +1 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +62 -0
- data/spec/dummy/config/environments/production.rb +112 -0
- data/spec/dummy/config/environments/test.rb +49 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/assets.rb +14 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/content_security_policy.rb +30 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +33 -0
- data/spec/dummy/config/master.key +1 -0
- data/spec/dummy/config/puma.rb +38 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/config/storage.yml +34 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/package.json +11 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/robots.txt +1 -0
- data/spec/dummy/test/application_system_test_case.rb +5 -0
- data/spec/dummy/test/channels/application_cable/connection_test.rb +11 -0
- data/spec/dummy/test/test_helper.rb +13 -0
- data/spec/dummy/tmp/cache/bootsnap-load-path-cache +0 -0
- data/spec/spec_helper.rb +77 -2
- data/spec/support/docker/fake_cli.rb +54 -0
- data/spec/support/docker/remote/fake_client.rb +16 -0
- data/spec/trailing_hash_spec.rb +23 -0
- metadata +139 -30
- data/lib/ext/krane/kubernetes_resource.rb +0 -16
- data/lib/kuby/kubernetes/plugin.rb +0 -55
- data/lib/kuby/kubernetes/plugins.rb +0 -8
- data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +0 -73
- data/lib/kuby/kubernetes/plugins/rails_app.rb +0 -16
- data/lib/kuby/kubernetes/plugins/rails_app/database.rb +0 -79
- data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +0 -154
- data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +0 -379
- data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +0 -142
- data/lib/kuby/kubernetes/plugins/rails_app/rewrite_db_config.rb +0 -13
- data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +0 -30
- data/lib/kuby/kubernetes/plugins/rails_app/tasks.rake +0 -28
- data/lib/kuby/tasks/kuby.rake +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f61bf7246e7fed1b51421252d1fee25da0bf1ad35da792e9f705d306ad5aeeba
|
4
|
+
data.tar.gz: fcaed876fd5da816cd1458c41c19fc735a7d3e5de2d23879427c526f2f0f94ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78f6cad56fd00b1265a43ac36169da5d46b15c50ceb5afce6f519ef175ff3949f84204ccf40ad9531b9dbb6b357d38ac0396e6969d848bfb17b42ba1c273ba6d
|
7
|
+
data.tar.gz: 056b9a151fd6f11079eb87fd5c0b7c4f92087cd8455a361ac7e668e9b94e4fc99a866b91c4f30d0a3eda582b0c2cafaac2e3ee882daebec0a52f1fd748786871
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,45 @@
|
|
1
|
+
## 0.10.0
|
2
|
+
* Set default database user and password in dev environment.
|
3
|
+
* Add ability to run rake tasks in dev environment.
|
4
|
+
* Disallow running rails and rake tasks in non-dev environments.
|
5
|
+
* Don't run database config through ERB.
|
6
|
+
- Rails env often isn't loaded, so ERB rendering can blow up with `NoMethodError`s, etc.
|
7
|
+
- All we really need to know is what database engine to stand up.
|
8
|
+
* Require database user/password to be added manually to Kuby config.
|
9
|
+
|
10
|
+
## 0.9.1
|
11
|
+
* Run dev setup when asked to.
|
12
|
+
- Bug caused dev setup to be skipped even when requested.
|
13
|
+
* Deployer should be tolerant of missing namespace.
|
14
|
+
|
15
|
+
## 0.9.0
|
16
|
+
* Add support for developing your app using a local Kubernetes cluster.
|
17
|
+
- Includes a default `:development` Kuby environment.
|
18
|
+
* Remove rake tasks in favor of a `kuby` executable powered by [GLI](https://github.com/davetron5000/gli).
|
19
|
+
* Rename the `minikube` provider to `docker_desktop`, which is more accurate.
|
20
|
+
* Add more tests.
|
21
|
+
* Avoid running commands inside pods that aren't running or that are marked for deletion (#15).
|
22
|
+
* Pass `RAILS_MASTER_KEY` to Docker build (#14).
|
23
|
+
* Add `kuby remote restart` command for manually restarting Rails pods.
|
24
|
+
* Automatically restart Rails pods if deploy doesn't change the Docker image URL (#11).
|
25
|
+
|
26
|
+
## 0.8.1
|
27
|
+
* Fix database config rewriter task.
|
28
|
+
- Broke with refactoring of database config code.
|
29
|
+
* More correctly parse Docker image URLs.
|
30
|
+
- It can be challenging to identify the hostname in image URLs because 1) the host can be omitted, and 2) the scheme is often omitted.
|
31
|
+
- The new strategy is to look for a "." in the first segment of the URL if there is no scheme. It's not bulletproof but is better than what we had before, which was to assume the first segment was the host. Eg. for an image URL like camertron/foo, we would identify the host as "camertron."
|
32
|
+
* Add a number of tests and a Rails dummy app in spec/.
|
33
|
+
|
34
|
+
## 0.8.0
|
35
|
+
* Upgrade to Krane >= 1.1.4, < 2.0.
|
36
|
+
* Remove Krane monkeypatch in ext/.
|
37
|
+
* Implement a Rails static asset server.
|
38
|
+
* Move plugins from `Kuby::Kubernetes` namespace to `Kuby` namespace.
|
39
|
+
- This is to eventually enable plugins to modify the Dockerfile and introduce additional Dockerfiles (i.e. to enable a development mode, etc).
|
40
|
+
* Pass `Environment` instead of `Definition` instances around.
|
41
|
+
- Providers, plugins, etc all take `Definition` instances. `Definition#kubernetes`, for example, returns the Kubernetes spec for the `Environment` specified by `KUBY_ENV` (or the first env defined if `KUBY_ENV` is not set). This is a problem for Kuby configs that specify multiple environments, and causes plugins to make changes to the default environment instead of the one they've been specifically added to. For example, if the `:production` env is defined first, the `:development` env still gets a cluster issuer from cert-manager even though `enable_tls` is set to `false`.
|
42
|
+
|
1
43
|
## 0.7.2
|
2
44
|
* Fix issue causing `Kuby.environment(...)` to raise an `UndefinedEnvironmentError` for existing environments.
|
3
45
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,16 @@ At its core, Kuby is a set of tools and smart defaults that encapsulate and codi
|
|
8
8
|
|
9
9
|
Under the hood, Kuby leverages the power of Docker and Kubernetes. It tries to make these technologies accessible to the average Rails dev without requiring a devops black belt.
|
10
10
|
|
11
|
+
## Why Kuby?
|
12
|
+
|
13
|
+
Kuby embraces the same convention-over-configuration approach that Rails does. It aims to reduce the cognitive overhead associated with learning a bunch of ops tools to get your app onto the internet. In other words, Kuby does a whole lot for you. Specifically, it:
|
14
|
+
|
15
|
+
* leverages Docker and Kubernetes, industry-leading infrastructure tools.
|
16
|
+
* automatically configures your app with a TLS certificate from [LetsEncrypt](https://letsencrypt.org/).
|
17
|
+
* automatically spins up a database instance based on what's in your database.yml.
|
18
|
+
* runs a separate server for your static assets.
|
19
|
+
* features a powerful plugin system that allows, for example, easy [Sidekiq integration](https://github.com/getkuby/kuby-sidekiq).
|
20
|
+
|
11
21
|
## Getting Started
|
12
22
|
|
13
23
|
See the [Quick Start Guide](https://github.com/getkuby/kuby-core/wiki/Quick-Start-Guide)
|
@@ -18,7 +28,7 @@ See the [wiki](https://github.com/getkuby/kuby-core/wiki).
|
|
18
28
|
|
19
29
|
## Running Tests
|
20
30
|
|
21
|
-
`bundle exec rspec` should do the trick
|
31
|
+
`bundle exec rspec` should do the trick. Test coverage is very minimal at the moment, however.
|
22
32
|
|
23
33
|
## License
|
24
34
|
|
data/bin/kuby
ADDED
data/kuby-core.gemspec
CHANGED
@@ -14,17 +14,22 @@ Gem::Specification.new do |s|
|
|
14
14
|
|
15
15
|
s.add_dependency 'colorize', '~> 0.8'
|
16
16
|
s.add_dependency 'docker-remote', '~> 0.1'
|
17
|
-
s.add_dependency '
|
18
|
-
s.add_dependency '
|
17
|
+
s.add_dependency 'gli', '~> 2.0'
|
18
|
+
s.add_dependency 'helm-cli', '~> 0.3'
|
19
|
+
# See: https://github.com/Shopify/krane/pull/720
|
20
|
+
# See: https://github.com/Shopify/krane/blob/master/CHANGELOG.md#114
|
21
|
+
s.add_dependency 'krane', '>= 1.1.4', '< 2.0'
|
22
|
+
s.add_dependency 'kuby-cert-manager', '>= 0.3'
|
19
23
|
s.add_dependency 'kube-dsl', '~> 0.3'
|
20
|
-
s.add_dependency 'kuby-kube-db', '
|
21
|
-
s.add_dependency 'kubernetes-cli', '~> 0.
|
24
|
+
s.add_dependency 'kuby-kube-db', '>= 0.6'
|
25
|
+
s.add_dependency 'kubernetes-cli', '~> 0.3'
|
22
26
|
s.add_dependency 'railties', '>= 5.1'
|
23
27
|
s.add_dependency 'rouge', '~> 3.0'
|
24
28
|
|
25
29
|
s.add_development_dependency 'rspec'
|
26
30
|
|
27
31
|
s.require_path = 'lib'
|
32
|
+
s.executables << 'kuby'
|
28
33
|
|
29
34
|
s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'kuby-core.gemspec']
|
30
35
|
end
|
data/lib/kuby.rb
CHANGED
@@ -1,29 +1,46 @@
|
|
1
1
|
require 'kuby/railtie'
|
2
2
|
|
3
3
|
begin
|
4
|
-
require 'kuby/
|
4
|
+
require 'kuby/plugins/rails_app/generators/kuby'
|
5
5
|
rescue NameError
|
6
6
|
end
|
7
7
|
|
8
8
|
module Kuby
|
9
|
-
autoload :BasicLogger,
|
10
|
-
autoload :CLIBase,
|
11
|
-
autoload :
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :
|
15
|
-
autoload :
|
16
|
-
autoload :
|
17
|
-
autoload :
|
9
|
+
autoload :BasicLogger, 'kuby/basic_logger'
|
10
|
+
autoload :CLIBase, 'kuby/cli_base'
|
11
|
+
autoload :Commands, 'kuby/commands'
|
12
|
+
autoload :Definition, 'kuby/definition'
|
13
|
+
autoload :DevSetup, 'kuby/dev_setup'
|
14
|
+
autoload :Docker, 'kuby/docker'
|
15
|
+
autoload :Environment, 'kuby/environment'
|
16
|
+
autoload :Kubernetes, 'kuby/kubernetes'
|
17
|
+
autoload :Middleware, 'kuby/middleware'
|
18
|
+
autoload :Plugin, 'kuby/plugin'
|
19
|
+
autoload :PluginRegistry, 'kuby/plugin_registry'
|
20
|
+
autoload :Plugins, 'kuby/plugins'
|
21
|
+
autoload :RailsCommands, 'kuby/rails_commands'
|
22
|
+
autoload :Tasks, 'kuby/tasks'
|
23
|
+
autoload :TrailingHash, 'kuby/trailing_hash'
|
24
|
+
|
25
|
+
DEFAULT_ENV = 'development'.freeze
|
26
|
+
DEFAULT_DB_USER = 'root'.freeze
|
27
|
+
DEFAULT_DB_PASSWORD = 'password'.freeze
|
18
28
|
|
19
29
|
class UndefinedEnvironmentError < StandardError; end
|
30
|
+
class MissingConfigError < StandardError; end
|
20
31
|
|
21
32
|
class << self
|
22
33
|
attr_reader :definition
|
23
34
|
attr_writer :logger
|
24
35
|
|
25
|
-
def load!
|
26
|
-
|
36
|
+
def load!(config_file = nil)
|
37
|
+
config_file ||= ENV['KUBY_CONFIG'] || File.join('.', 'kuby.rb')
|
38
|
+
|
39
|
+
unless File.exist?(config_file)
|
40
|
+
raise MissingConfigError, "couldn't find Kuby config file at #{config_file}"
|
41
|
+
end
|
42
|
+
|
43
|
+
require config_file
|
27
44
|
end
|
28
45
|
|
29
46
|
def define(name, &block)
|
@@ -32,9 +49,27 @@ module Kuby
|
|
32
49
|
@definition = Definition.new(name.to_s)
|
33
50
|
@definition.instance_eval(&block)
|
34
51
|
|
52
|
+
# default development environment
|
53
|
+
@definition.environment(:development) do
|
54
|
+
kubernetes do
|
55
|
+
add_plugin(:rails_app) do
|
56
|
+
tls_enabled false
|
57
|
+
|
58
|
+
database do
|
59
|
+
user(DEFAULT_DB_USER) if respond_to?(:user)
|
60
|
+
password(DEFAULT_DB_PASSWORD) if respond_to?(:password)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
provider :docker_desktop
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
35
68
|
@definition.environments.each do |_, env|
|
36
69
|
env.kubernetes.after_configuration
|
37
70
|
end
|
71
|
+
|
72
|
+
@definition
|
38
73
|
end
|
39
74
|
|
40
75
|
def environment(name = env)
|
@@ -52,8 +87,8 @@ module Kuby
|
|
52
87
|
@providers ||= {}
|
53
88
|
end
|
54
89
|
|
55
|
-
def register_plugin(
|
56
|
-
plugins
|
90
|
+
def register_plugin(*args, **kwargs)
|
91
|
+
plugins.register(*args, **kwargs)
|
57
92
|
end
|
58
93
|
|
59
94
|
def register_distro(distro_name, distro_klass)
|
@@ -65,7 +100,7 @@ module Kuby
|
|
65
100
|
end
|
66
101
|
|
67
102
|
def plugins
|
68
|
-
@plugins ||=
|
103
|
+
@plugins ||= PluginRegistry.new
|
69
104
|
end
|
70
105
|
|
71
106
|
def logger
|
@@ -95,20 +130,24 @@ module Kuby
|
|
95
130
|
@packages ||= {}
|
96
131
|
end
|
97
132
|
|
133
|
+
def env=(env_name)
|
134
|
+
@env = env_name.to_s
|
135
|
+
end
|
136
|
+
|
98
137
|
def env
|
99
138
|
ENV.fetch('KUBY_ENV') do
|
100
|
-
(
|
139
|
+
(@env || Rails.env rescue nil || DEFAULT_ENV).to_s
|
101
140
|
end
|
102
141
|
end
|
103
142
|
end
|
104
143
|
end
|
105
144
|
|
106
145
|
# providers
|
107
|
-
Kuby.register_provider(:
|
146
|
+
Kuby.register_provider(:docker_desktop, Kuby::Kubernetes::DockerDesktopProvider)
|
108
147
|
|
109
148
|
# plugins
|
110
|
-
Kuby.register_plugin(:rails_app, Kuby::
|
111
|
-
Kuby.register_plugin(:nginx_ingress, Kuby::
|
149
|
+
Kuby.register_plugin(:rails_app, Kuby::Plugins::RailsApp::Plugin)
|
150
|
+
Kuby.register_plugin(:nginx_ingress, Kuby::Plugins::NginxIngress)
|
112
151
|
|
113
152
|
# distros
|
114
153
|
Kuby.register_distro(:debian, Kuby::Docker::Debian)
|
data/lib/kuby/basic_logger.rb
CHANGED
@@ -18,5 +18,18 @@ module Kuby
|
|
18
18
|
def fatal(msg, *args)
|
19
19
|
super(ColorizedString[msg].red, *args)
|
20
20
|
end
|
21
|
+
|
22
|
+
# adhere to the "CLI" interface
|
23
|
+
def with_pipes(out = STDOUT, err = STDERR)
|
24
|
+
previous_logdev = @logdev || STDERR
|
25
|
+
reopen(err)
|
26
|
+
yield
|
27
|
+
ensure
|
28
|
+
reopen(previous_logdev)
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_status
|
32
|
+
nil
|
33
|
+
end
|
21
34
|
end
|
22
35
|
end
|
data/lib/kuby/cli_base.rb
CHANGED
@@ -17,17 +17,59 @@ module Kuby
|
|
17
17
|
@after_execute << block
|
18
18
|
end
|
19
19
|
|
20
|
+
def with_pipes(out = STDOUT, err = STDERR)
|
21
|
+
previous_stdout = self.stdout
|
22
|
+
previous_stderr = self.stderr
|
23
|
+
self.stdout = out
|
24
|
+
self.stderr = err
|
25
|
+
yield
|
26
|
+
ensure
|
27
|
+
self.stdout = previous_stdout
|
28
|
+
self.stderr = previous_stderr
|
29
|
+
end
|
30
|
+
|
31
|
+
def stdout
|
32
|
+
Thread.current[stdout_key] || STDOUT
|
33
|
+
end
|
34
|
+
|
35
|
+
def stdout=(new_stdout)
|
36
|
+
Thread.current[stdout_key] = new_stdout
|
37
|
+
end
|
38
|
+
|
39
|
+
def stderr
|
40
|
+
Thread.current[stderr_key] || STDERR
|
41
|
+
end
|
42
|
+
|
43
|
+
def stderr=(new_stderr)
|
44
|
+
Thread.current[stderr_key] = new_stderr
|
45
|
+
end
|
46
|
+
|
20
47
|
private
|
21
48
|
|
22
49
|
def open3_w(env, cmd, opts = {}, &block)
|
23
50
|
run_before_callbacks(cmd)
|
24
51
|
cmd_s = cmd.join(' ')
|
25
52
|
|
26
|
-
Open3.
|
27
|
-
|
28
|
-
|
29
|
-
|
53
|
+
Open3.popen3(env, cmd_s, opts) do |p_stdin, p_stdout, p_stderr, wait_thread|
|
54
|
+
Thread.new(stdout) do |t_stdout|
|
55
|
+
begin
|
56
|
+
p_stdout.each { |line| t_stdout.puts(line) }
|
57
|
+
rescue IOError
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Thread.new(stderr) do |t_stderr|
|
62
|
+
begin
|
63
|
+
p_stderr.each { |line| t_stderr.puts(line) }
|
64
|
+
rescue IOError
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
yield(p_stdin).tap do
|
69
|
+
p_stdin.close
|
70
|
+
self.last_status = wait_thread.value
|
30
71
|
run_after_callbacks(cmd)
|
72
|
+
wait_thread.join
|
31
73
|
end
|
32
74
|
end
|
33
75
|
end
|
@@ -41,19 +83,42 @@ module Kuby
|
|
41
83
|
def systemm(cmd)
|
42
84
|
run_before_callbacks(cmd)
|
43
85
|
cmd_s = cmd.join(' ')
|
44
|
-
|
45
|
-
|
86
|
+
|
87
|
+
Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
|
88
|
+
Thread.new(stdout) do |t_stdout|
|
89
|
+
p_stdout.each { |line| t_stdout.puts(line) }
|
90
|
+
end
|
91
|
+
|
92
|
+
Thread.new(stderr) do |t_stderr|
|
93
|
+
p_stderr.each { |line| t_stderr.puts(line) }
|
94
|
+
end
|
95
|
+
|
96
|
+
self.last_status = wait_thread.value
|
46
97
|
run_after_callbacks(cmd)
|
98
|
+
wait_thread.join
|
47
99
|
end
|
48
100
|
end
|
49
101
|
|
50
102
|
def backticks(cmd)
|
51
103
|
run_before_callbacks(cmd)
|
52
104
|
cmd_s = cmd.join(' ')
|
53
|
-
|
54
|
-
|
105
|
+
result = StringIO.new
|
106
|
+
|
107
|
+
Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
|
108
|
+
Thread.new do
|
109
|
+
p_stdout.each { |line| result.puts(line) }
|
110
|
+
end
|
111
|
+
|
112
|
+
Thread.new(stderr) do |t_stderr|
|
113
|
+
p_stderr.each { |line| t_stderr.puts(line) }
|
114
|
+
end
|
115
|
+
|
116
|
+
self.last_status = wait_thread.value
|
55
117
|
run_after_callbacks(cmd)
|
118
|
+
wait_thread.join
|
56
119
|
end
|
120
|
+
|
121
|
+
result.string
|
57
122
|
end
|
58
123
|
|
59
124
|
def run_before_callbacks(cmd)
|
@@ -71,5 +136,13 @@ module Kuby
|
|
71
136
|
def status_key
|
72
137
|
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
73
138
|
end
|
139
|
+
|
140
|
+
def stdout_key
|
141
|
+
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
142
|
+
end
|
143
|
+
|
144
|
+
def stderr_key
|
145
|
+
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
146
|
+
end
|
74
147
|
end
|
75
148
|
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'kuby/version'
|
2
|
+
require 'gli'
|
3
|
+
|
4
|
+
module Kuby
|
5
|
+
class Commands
|
6
|
+
extend GLI::App
|
7
|
+
|
8
|
+
# GLI doesn't have a wildcard option, so it's impossible to tell it to
|
9
|
+
# slurp up all args after a certain point. In our case, we want to be
|
10
|
+
# able to invoke `rails` commands and pass through all the original
|
11
|
+
# flags, switches, etc. To get around GLI's limitations, we identify
|
12
|
+
# `rails` commands in this hijacked `run` method and only use GLI to
|
13
|
+
# parse global options (like -e). The rest of the Rails options are
|
14
|
+
# captured in an instance variable and thereby made available to the
|
15
|
+
# Rails command handlers defined below. We use Module#prepend here to
|
16
|
+
# avoid the usual series of cryptic alias_method calls (note that there
|
17
|
+
# is no singleton class version of #prepend in the Ruby language).
|
18
|
+
singleton_class.send(:prepend, Module.new do
|
19
|
+
def run(args)
|
20
|
+
if idx = args.index('rails') || idx = args.index('rake')
|
21
|
+
@rails_options = args[idx..-1]
|
22
|
+
super(args[0..idx])
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end)
|
28
|
+
|
29
|
+
def self.tasks
|
30
|
+
Kuby::Tasks.new(Kuby.environment)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.must_be_dev_env!
|
34
|
+
unless Kuby.environment.development?
|
35
|
+
fail "Command not supported in the '#{Kuby.environment.name}' environment"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
program_desc 'Kuby command-line interface. Kuby is a convention '\
|
40
|
+
'over configuration approach for running Rails apps in Kubernetes.'
|
41
|
+
|
42
|
+
version Kuby::VERSION
|
43
|
+
|
44
|
+
subcommand_option_handling :normal
|
45
|
+
arguments :loose
|
46
|
+
|
47
|
+
desc 'The Kuby environment to use. Overrides KUBY_ENV.'
|
48
|
+
flag [:e, :environment], type: String, required: false
|
49
|
+
|
50
|
+
desc 'Path to your Kuby config file. Overrides KUBY_CONFIG.'
|
51
|
+
default_value './kuby.rb'
|
52
|
+
flag [:c, :config]
|
53
|
+
|
54
|
+
pre do |global_options, options, args|
|
55
|
+
Kuby.env = global_options[:environment] if global_options[:environment]
|
56
|
+
Kuby.load!(global_options[:config])
|
57
|
+
|
58
|
+
# GLI will abort unless this block returns a truthy value
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
# These are only stubs included to fill out the help screens. Rails
|
63
|
+
# commands are handled by the RailsCommands class.
|
64
|
+
desc 'Runs a Rails command.'
|
65
|
+
command :rails do |rc|
|
66
|
+
rc.action do |global_options, options, args|
|
67
|
+
must_be_dev_env!
|
68
|
+
exit 1 unless tasks.dev_deployment_ok
|
69
|
+
Kuby::RailsCommands.run(@rails_options)
|
70
|
+
end
|
71
|
+
|
72
|
+
rc.desc 'Runs the rails server (run `rails server --help` for options)'
|
73
|
+
rc.command [:server, :s] do |c|
|
74
|
+
c.action do |global_options, options, args|
|
75
|
+
must_be_dev_env!
|
76
|
+
exit 1 unless tasks.dev_deployment_ok
|
77
|
+
Kuby::RailsCommands.run(@rails_options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
rc.desc 'Runs a script in the Rails environment (run `rails runner --help` for options)'
|
82
|
+
rc.command [:runner, :r] do |c|
|
83
|
+
c.action do |global_options, options, args|
|
84
|
+
must_be_dev_env!
|
85
|
+
exit 1 unless tasks.dev_deployment_ok
|
86
|
+
Kuby::RailsCommands.run(@rails_options)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
rc.desc 'Starts an interactive Ruby console with the Rails environment loaded '\
|
91
|
+
'(run `rails console --help` for options)'
|
92
|
+
rc.command [:console, :c] do |c|
|
93
|
+
c.action do |global_options, options, args|
|
94
|
+
must_be_dev_env!
|
95
|
+
exit 1 unless tasks.dev_deployment_ok
|
96
|
+
Kuby::RailsCommands.run(@rails_options)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
desc 'Runs a rake task.'
|
102
|
+
command :rake do |rc|
|
103
|
+
rc.action do |global_options, options, args|
|
104
|
+
must_be_dev_env!
|
105
|
+
exit 1 unless tasks.dev_deployment_ok
|
106
|
+
Kuby::RailsCommands.run(@rails_options)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
desc 'Builds the Docker image.'
|
111
|
+
command :build do |c|
|
112
|
+
c.action do |global_options, options, args|
|
113
|
+
tasks.build
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
desc 'Pushes the Docker image to the configured registry.'
|
118
|
+
command :push do |c|
|
119
|
+
c.action do |global_options, options, args|
|
120
|
+
tasks.push
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
desc 'Gets your Kubernetes cluster ready to run your Rails app.'
|
125
|
+
command :setup do |c|
|
126
|
+
c.action do |global_options, options, args|
|
127
|
+
tasks.setup
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
desc 'Prints the effective Dockerfile used to build the Docker image.'
|
132
|
+
command :dockerfile do |c|
|
133
|
+
c.action do |global_options, options, args|
|
134
|
+
tasks.print_dockerfile
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
desc 'Deploys the application.'
|
139
|
+
command :deploy do |c|
|
140
|
+
c.desc 'The Docker tag to deploy. Defaults to the most recent tag.'
|
141
|
+
c.flag [:t, :tag], required: false
|
142
|
+
c.action do |global_options, options, args|
|
143
|
+
tasks.deploy(options[:tag])
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
desc 'Rolls back to the previous Docker tag.'
|
148
|
+
command :rollback do |c|
|
149
|
+
c.action do |global_options, options, args|
|
150
|
+
tasks.rollback
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
desc 'Prints the effective Kubernetes resources that will be applied on deploy.'
|
155
|
+
command :resources do |c|
|
156
|
+
c.action do |global_options, options, args|
|
157
|
+
tasks.print_resources
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
desc 'Prints out the contents of the kubeconfig Kuby is using to communicate with your cluster.'
|
162
|
+
command :kubeconfig do |c|
|
163
|
+
c.action do |global_options, options, args|
|
164
|
+
tasks.print_kubeconfig
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
desc 'Runs an arbitrary kubectl command.'
|
169
|
+
command :kubectl do |c|
|
170
|
+
c.desc 'Prefixes the kubectl command with the namespace associated with '\
|
171
|
+
'the current environment. For example, if the Kuby env is "production", '\
|
172
|
+
'this option will prefix the kubectl command with "-n myapp-production".'
|
173
|
+
c.switch [:N, :namespaced], default: false
|
174
|
+
c.action do |global_options, options, args|
|
175
|
+
if options[:namespaced]
|
176
|
+
# sorry Demeter
|
177
|
+
namespace = Kuby.definition.environment.kubernetes.namespace.metadata.name
|
178
|
+
args = ['-n', namespace, *args]
|
179
|
+
end
|
180
|
+
|
181
|
+
tasks.kubectl(*args)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
desc 'Runs commands, etc against the Kubernetes cluster.'
|
186
|
+
command :remote do |rc|
|
187
|
+
rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
|
188
|
+
rc.command :logs do |c|
|
189
|
+
c.action do |global_options, options, args|
|
190
|
+
exit 1 unless tasks.dev_deployment_ok
|
191
|
+
tasks.remote_logs
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
rc.desc 'Lists running Kubernetes pods.'
|
196
|
+
rc.command :status do |c|
|
197
|
+
c.action do |global_options, options, args|
|
198
|
+
exit 1 unless tasks.dev_deployment_ok
|
199
|
+
tasks.remote_status
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
204
|
+
rc.command :exec do |c|
|
205
|
+
c.action do |global_options, options, args|
|
206
|
+
exit 1 unless tasks.dev_deployment_ok
|
207
|
+
tasks.remote_exec(args)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
rc.desc 'Establishes a shell inside a running Rails pod.'
|
212
|
+
rc.command :shell do |c|
|
213
|
+
c.action do |global_options, options, args|
|
214
|
+
exit 1 unless tasks.dev_deployment_ok
|
215
|
+
tasks.remote_shell
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
rc.desc 'Establishes a Rails console inside a running Rails pod.'
|
220
|
+
rc.command :console do |c|
|
221
|
+
c.action do |global_options, options, args|
|
222
|
+
exit 1 unless tasks.dev_deployment_ok
|
223
|
+
tasks.remote_console
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
rc.desc 'Establishes a database console inside a running Rails pod.'
|
228
|
+
rc.command :dbconsole do |c|
|
229
|
+
c.action do |global_options, options, args|
|
230
|
+
exit 1 unless tasks.dev_deployment_ok
|
231
|
+
tasks.remote_dbconsole
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
rc.desc "Restarts the Rails app's web pods."
|
236
|
+
rc.command :restart do |c|
|
237
|
+
c.action do |global_options, options, args|
|
238
|
+
exit 1 unless tasks.dev_deployment_ok
|
239
|
+
tasks.remote_restart
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|