kuby-core 0.7.0 → 0.9.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 +35 -0
- data/Gemfile +1 -0
- data/README.md +11 -1
- data/bin/kuby +4 -0
- data/kuby-core.gemspec +11 -4
- data/lib/kuby.rb +55 -23
- data/lib/kuby/basic_logger.rb +13 -0
- data/lib/kuby/cli_base.rb +81 -8
- data/lib/kuby/commands.rb +220 -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 +19 -39
- 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 +12 -3
- 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 +67 -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 +75 -0
- data/lib/kuby/{kubernetes/plugins → plugins}/rails_app/generators/kuby.rb +3 -15
- data/lib/kuby/plugins/rails_app/mysql.rb +155 -0
- data/lib/kuby/plugins/rails_app/plugin.rb +588 -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 +84 -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 +61 -0
- 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 +177 -0
- 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 +155 -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: f9367e316dfab7a0210bea18ab630b65a5996ce0622960f3be2a76f8ec4482c1
|
4
|
+
data.tar.gz: d48777e79f11eab678545a2d398d3f60463e7d1209e6d15987c3f3665d571b82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbfd215f8b4a7cb2b1a53bc8de8298e4dd85f487f0245da82bd19a390d55500c20e97e155a07fafa09284683ee9c220bb4cdd89194c3e5cb4c6e3c055fbcce74
|
7
|
+
data.tar.gz: 03c15b9ffb8672ef2e45d2d818c3d048e694dae2656db0be6325a1edf6853b1c9c8bc7060b021add66b43d87c9ca3ac46bb71346f2e2a4e68bd89ba6d45635f9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
## 0.9.0
|
2
|
+
* Add support for developing your app using a local Kubernetes cluster.
|
3
|
+
- Includes a default `:development` Kuby environment.
|
4
|
+
* Remove rake tasks in favor of a `kuby` executable powered by [GLI](https://github.com/davetron5000/gli).
|
5
|
+
* Rename the `minikube` provider to `docker_desktop`, which is more accurate.
|
6
|
+
* Add more tests.
|
7
|
+
* Avoid running commands inside pods that aren't running or that are marked for deletion (#15).
|
8
|
+
* Pass `RAILS_MASTER_KEY` to Docker build (#14).
|
9
|
+
* Add `kuby remote restart` command for manually restarting Rails pods.
|
10
|
+
* Automatically restart Rails pods if deploy doesn't change the Docker image URL (#11).
|
11
|
+
|
12
|
+
## 0.8.1
|
13
|
+
* Fix database config rewriter task.
|
14
|
+
- Broke with refactoring of database config code.
|
15
|
+
* More correctly parse Docker image URLs.
|
16
|
+
- 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.
|
17
|
+
- 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."
|
18
|
+
* Add a number of tests and a Rails dummy app in spec/.
|
19
|
+
|
20
|
+
## 0.8.0
|
21
|
+
* Upgrade to Krane >= 1.1.4, < 2.0.
|
22
|
+
* Remove Krane monkeypatch in ext/.
|
23
|
+
* Implement a Rails static asset server.
|
24
|
+
* Move plugins from `Kuby::Kubernetes` namespace to `Kuby` namespace.
|
25
|
+
- This is to eventually enable plugins to modify the Dockerfile and introduce additional Dockerfiles (i.e. to enable a development mode, etc).
|
26
|
+
* Pass `Environment` instead of `Definition` instances around.
|
27
|
+
- 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`.
|
28
|
+
|
29
|
+
## 0.7.2
|
30
|
+
* Fix issue causing `Kuby.environment(...)` to raise an `UndefinedEnvironmentError` for existing environments.
|
31
|
+
|
32
|
+
## 0.7.1
|
33
|
+
* Fix timestamp tag parsing regression caused by adding anchor tags to the regex.
|
34
|
+
- Instead, let's rely on `strptime` and return `nil` if it throws an `ArgumentError`.
|
35
|
+
|
1
36
|
## 0.7.0
|
2
37
|
* Automatically perform `docker login` if not already logged into the Docker registry.
|
3
38
|
* Fix timestamp tag parsing issue causing deploy to fail with no available tags.
|
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,15 +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
|
|
29
|
+
s.add_development_dependency 'rspec'
|
30
|
+
|
25
31
|
s.require_path = 'lib'
|
32
|
+
s.executables << 'kuby'
|
26
33
|
|
27
34
|
s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'kuby-core.gemspec']
|
28
35
|
end
|
data/lib/kuby.rb
CHANGED
@@ -1,29 +1,44 @@
|
|
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
|
18
26
|
|
19
27
|
class UndefinedEnvironmentError < StandardError; end
|
28
|
+
class MissingConfigError < StandardError; end
|
20
29
|
|
21
30
|
class << self
|
22
31
|
attr_reader :definition
|
23
32
|
attr_writer :logger
|
24
33
|
|
25
|
-
def load!
|
26
|
-
|
34
|
+
def load!(config_file = nil)
|
35
|
+
config_file ||= ENV['KUBY_CONFIG'] || File.join('.', 'kuby.rb')
|
36
|
+
|
37
|
+
unless File.exist?(config_file)
|
38
|
+
raise MissingConfigError, "couldn't find Kuby config file at #{config_file}"
|
39
|
+
end
|
40
|
+
|
41
|
+
require config_file
|
27
42
|
end
|
28
43
|
|
29
44
|
def define(name, &block)
|
@@ -32,16 +47,29 @@ module Kuby
|
|
32
47
|
@definition = Definition.new(name.to_s)
|
33
48
|
@definition.instance_eval(&block)
|
34
49
|
|
50
|
+
# default development environment
|
51
|
+
@definition.environment(:development) do
|
52
|
+
kubernetes do
|
53
|
+
add_plugin(:rails_app) do
|
54
|
+
tls_enabled false
|
55
|
+
end
|
56
|
+
|
57
|
+
provider :docker_desktop
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
35
61
|
@definition.environments.each do |_, env|
|
36
62
|
env.kubernetes.after_configuration
|
37
63
|
end
|
64
|
+
|
65
|
+
@definition
|
38
66
|
end
|
39
67
|
|
40
68
|
def environment(name = env)
|
41
|
-
definition.environment(name.to_s)
|
42
|
-
|
43
|
-
|
44
|
-
|
69
|
+
definition.environment(name.to_s) || raise(
|
70
|
+
UndefinedEnvironmentError, "couldn't find a Kuby environment named "\
|
71
|
+
"'#{name}'"
|
72
|
+
)
|
45
73
|
end
|
46
74
|
|
47
75
|
def register_provider(provider_name, provider_klass)
|
@@ -52,8 +80,8 @@ module Kuby
|
|
52
80
|
@providers ||= {}
|
53
81
|
end
|
54
82
|
|
55
|
-
def register_plugin(
|
56
|
-
plugins
|
83
|
+
def register_plugin(*args, **kwargs)
|
84
|
+
plugins.register(*args, **kwargs)
|
57
85
|
end
|
58
86
|
|
59
87
|
def register_distro(distro_name, distro_klass)
|
@@ -65,7 +93,7 @@ module Kuby
|
|
65
93
|
end
|
66
94
|
|
67
95
|
def plugins
|
68
|
-
@plugins ||=
|
96
|
+
@plugins ||= PluginRegistry.new
|
69
97
|
end
|
70
98
|
|
71
99
|
def logger
|
@@ -95,20 +123,24 @@ module Kuby
|
|
95
123
|
@packages ||= {}
|
96
124
|
end
|
97
125
|
|
126
|
+
def env=(env_name)
|
127
|
+
@env = env_name.to_s
|
128
|
+
end
|
129
|
+
|
98
130
|
def env
|
99
131
|
ENV.fetch('KUBY_ENV') do
|
100
|
-
(
|
132
|
+
(@env || Rails.env rescue nil || DEFAULT_ENV).to_s
|
101
133
|
end
|
102
134
|
end
|
103
135
|
end
|
104
136
|
end
|
105
137
|
|
106
138
|
# providers
|
107
|
-
Kuby.register_provider(:
|
139
|
+
Kuby.register_provider(:docker_desktop, Kuby::Kubernetes::DockerDesktopProvider)
|
108
140
|
|
109
141
|
# plugins
|
110
|
-
Kuby.register_plugin(:rails_app, Kuby::
|
111
|
-
Kuby.register_plugin(:nginx_ingress, Kuby::
|
142
|
+
Kuby.register_plugin(:rails_app, Kuby::Plugins::RailsApp::Plugin)
|
143
|
+
Kuby.register_plugin(:nginx_ingress, Kuby::Plugins::NginxIngress)
|
112
144
|
|
113
145
|
# distros
|
114
146
|
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,220 @@
|
|
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')
|
21
|
+
@rails_options = args[(idx + 1)..-1]
|
22
|
+
super(args[0..(idx + 1)])
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end)
|
28
|
+
|
29
|
+
def self.tasks
|
30
|
+
Kuby::Tasks.new(Kuby.definition.environment)
|
31
|
+
end
|
32
|
+
|
33
|
+
program_desc 'Kuby command-line interface. Kuby is a convention '\
|
34
|
+
'over configuration approach for running Rails apps in Kubernetes.'
|
35
|
+
|
36
|
+
version Kuby::VERSION
|
37
|
+
|
38
|
+
subcommand_option_handling :normal
|
39
|
+
arguments :loose
|
40
|
+
|
41
|
+
desc 'The Kuby environment to use. Overrides KUBY_ENV.'
|
42
|
+
flag [:e, :environment], type: String, required: false
|
43
|
+
|
44
|
+
desc 'Path to your Kuby config file. Overrides KUBY_CONFIG.'
|
45
|
+
default_value './kuby.rb'
|
46
|
+
flag [:c, :config]
|
47
|
+
|
48
|
+
pre do |global_options, options, args|
|
49
|
+
Kuby.env = global_options[:environment] if global_options[:environment]
|
50
|
+
Kuby.load!(global_options[:config])
|
51
|
+
|
52
|
+
# GLI will abort unless this block returns a truthy value
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
# These are only stubs included to fill out the help screens. Rails
|
57
|
+
# commands are handled by the RailsCommands class.
|
58
|
+
desc 'Runs a Rails command.'
|
59
|
+
command :rails do |rc|
|
60
|
+
rc.desc 'Runs the rails server (run `rails server --help` for options)'
|
61
|
+
rc.command [:server, :s] do |c|
|
62
|
+
c.action do |global_options, options, args|
|
63
|
+
exit 1 unless tasks.dev_deployment_ok
|
64
|
+
Kuby::RailsCommands.run(@rails_options)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
rc.desc 'Runs a script in the Rails environment (run `rails runner --help` for options)'
|
69
|
+
rc.command [:runner, :r] do |c|
|
70
|
+
c.action do |global_options, options, args|
|
71
|
+
exit 1 unless tasks.dev_deployment_ok
|
72
|
+
Kuby::RailsCommands.run(@rails_options)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
rc.desc 'Starts an interactive Ruby console with the Rails environment loaded '\
|
77
|
+
'(run `rails console --help` for options)'
|
78
|
+
rc.command [:console, :c] do |c|
|
79
|
+
c.action do |global_options, options, args|
|
80
|
+
exit 1 unless tasks.dev_deployment_ok
|
81
|
+
Kuby::RailsCommands.run(@rails_options)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
desc 'Builds the Docker image.'
|
87
|
+
command :build do |c|
|
88
|
+
c.action do |global_options, options, args|
|
89
|
+
tasks.build
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'Pushes the Docker image to the configured registry.'
|
94
|
+
command :push do |c|
|
95
|
+
c.action do |global_options, options, args|
|
96
|
+
tasks.push
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
desc 'Gets your Kubernetes cluster ready to run your Rails app.'
|
101
|
+
command :setup do |c|
|
102
|
+
c.action do |global_options, options, args|
|
103
|
+
tasks.setup
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
desc 'Prints the effective Dockerfile used to build the Docker image.'
|
108
|
+
command :dockerfile do |c|
|
109
|
+
c.action do |global_options, options, args|
|
110
|
+
tasks.print_dockerfile
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
desc 'Deploys the application.'
|
115
|
+
command :deploy do |c|
|
116
|
+
c.desc 'The Docker tag to deploy. Defaults to the most recent tag.'
|
117
|
+
c.flag [:t, :tag], required: false
|
118
|
+
c.action do |global_options, options, args|
|
119
|
+
tasks.deploy(options[:tag])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
desc 'Rolls back to the previous Docker tag.'
|
124
|
+
command :rollback do |c|
|
125
|
+
c.action do |global_options, options, args|
|
126
|
+
tasks.rollback
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
desc 'Prints the effective Kubernetes resources that will be applied on deploy.'
|
131
|
+
command :resources do |c|
|
132
|
+
c.action do |global_options, options, args|
|
133
|
+
tasks.print_resources
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
desc 'Prints out the contents of the kubeconfig Kuby is using to communicate with your cluster.'
|
138
|
+
command :kubeconfig do |c|
|
139
|
+
c.action do |global_options, options, args|
|
140
|
+
tasks.print_kubeconfig
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
desc 'Runs an arbitrary kubectl command.'
|
145
|
+
command :kubectl do |c|
|
146
|
+
c.desc 'Prefixes the kubectl command with the namespace associated with '\
|
147
|
+
'the current environment. For example, if the Kuby env is "production", '\
|
148
|
+
'this option will prefix the kubectl command with "-n myapp-production".'
|
149
|
+
c.switch [:N, :namespaced], default: false
|
150
|
+
c.action do |global_options, options, args|
|
151
|
+
if options[:namespaced]
|
152
|
+
# sorry Demeter
|
153
|
+
namespace = Kuby.definition.environment.kubernetes.namespace.metadata.name
|
154
|
+
args = ['-n', namespace, *args]
|
155
|
+
end
|
156
|
+
|
157
|
+
tasks.kubectl(*args)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
desc 'Runs commands, etc against the Kubernetes cluster.'
|
162
|
+
command :remote do |rc|
|
163
|
+
rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
|
164
|
+
rc.command :logs do |c|
|
165
|
+
c.action do |global_options, options, args|
|
166
|
+
exit 1 unless tasks.dev_deployment_ok
|
167
|
+
tasks.remote_logs
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
rc.desc 'Lists running Kubernetes pods.'
|
172
|
+
rc.command :status do |c|
|
173
|
+
c.action do |global_options, options, args|
|
174
|
+
exit 1 unless tasks.dev_deployment_ok
|
175
|
+
tasks.remote_status
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
180
|
+
rc.command :exec do |c|
|
181
|
+
c.action do |global_options, options, args|
|
182
|
+
exit 1 unless tasks.dev_deployment_ok
|
183
|
+
tasks.remote_exec(args)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
rc.desc 'Establishes a shell inside a running Rails pod.'
|
188
|
+
rc.command :shell do |c|
|
189
|
+
c.action do |global_options, options, args|
|
190
|
+
exit 1 unless tasks.dev_deployment_ok
|
191
|
+
tasks.remote_shell
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
rc.desc 'Establishes a Rails console inside a running Rails pod.'
|
196
|
+
rc.command :console do |c|
|
197
|
+
c.action do |global_options, options, args|
|
198
|
+
exit 1 unless tasks.dev_deployment_ok
|
199
|
+
tasks.remote_console
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
rc.desc 'Establishes a database console inside a running Rails pod.'
|
204
|
+
rc.command :dbconsole do |c|
|
205
|
+
c.action do |global_options, options, args|
|
206
|
+
exit 1 unless tasks.dev_deployment_ok
|
207
|
+
tasks.remote_dbconsole
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
rc.desc "Restarts the Rails app's web pods."
|
212
|
+
rc.command :restart do |c|
|
213
|
+
c.action do |global_options, options, args|
|
214
|
+
exit 1 unless tasks.dev_deployment_ok
|
215
|
+
tasks.remote_restart
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|