kuby-core 0.3.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/README.md +3 -160
  4. data/kuby-core.gemspec +2 -1
  5. data/lib/kuby.rb +32 -17
  6. data/lib/kuby/definition.rb +20 -14
  7. data/lib/kuby/docker.rb +2 -1
  8. data/lib/kuby/docker/alpine.rb +0 -1
  9. data/lib/kuby/docker/assets_phase.rb +1 -1
  10. data/lib/kuby/docker/bundler_phase.rb +4 -2
  11. data/lib/kuby/docker/cli.rb +32 -0
  12. data/lib/kuby/docker/copy_phase.rb +1 -1
  13. data/lib/kuby/docker/errors.rb +1 -0
  14. data/lib/kuby/docker/inline_layer.rb +15 -0
  15. data/lib/kuby/docker/{phase.rb → layer.rb} +6 -5
  16. data/lib/kuby/docker/layer_stack.rb +30 -4
  17. data/lib/kuby/docker/metadata.rb +9 -1
  18. data/lib/kuby/docker/package_phase.rb +1 -1
  19. data/lib/kuby/docker/packages.rb +5 -4
  20. data/lib/kuby/docker/packages/simple_managed_package.rb +25 -0
  21. data/lib/kuby/docker/setup_phase.rb +1 -1
  22. data/lib/kuby/docker/spec.rb +4 -4
  23. data/lib/kuby/docker/timestamp_tag.rb +1 -1
  24. data/lib/kuby/docker/webserver_phase.rb +1 -1
  25. data/lib/kuby/docker/yarn_phase.rb +1 -1
  26. data/lib/kuby/environment.rb +22 -0
  27. data/lib/kuby/kubernetes.rb +1 -0
  28. data/lib/kuby/kubernetes/deploy_task.rb +33 -0
  29. data/lib/kuby/kubernetes/deployer.rb +1 -3
  30. data/lib/kuby/kubernetes/minikube_provider.rb +5 -5
  31. data/lib/kuby/kubernetes/plugins/nginx_ingress.rb +12 -0
  32. data/lib/kuby/kubernetes/plugins/rails_app/database.rb +30 -9
  33. data/lib/kuby/kubernetes/plugins/rails_app/generators/kuby.rb +83 -0
  34. data/lib/kuby/kubernetes/plugins/rails_app/mysql.rb +14 -4
  35. data/lib/kuby/kubernetes/plugins/rails_app/plugin.rb +15 -14
  36. data/lib/kuby/kubernetes/plugins/rails_app/postgres.rb +132 -0
  37. data/lib/kuby/kubernetes/plugins/rails_app/sqlite.rb +20 -0
  38. data/lib/kuby/kubernetes/plugins/rails_app/tasks.rake +9 -4
  39. data/lib/kuby/kubernetes/spec.rb +1 -1
  40. data/lib/kuby/railtie.rb +0 -4
  41. data/lib/kuby/tasks.rb +35 -0
  42. data/lib/kuby/tasks/kuby.rake +24 -17
  43. data/lib/kuby/version.rb +1 -1
  44. metadata +10 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42f6ba3c11212d10aeb9d878af3f91e4712f88498ddf1f6d94a29d26dfbd27d4
4
- data.tar.gz: 624f45761eed5d05d45e115697a6f43e4fa4516fed17f1158a05af01266ef0e4
3
+ metadata.gz: 7d3f784993d379920477923911af9c73a7ac0f661a8831a3fdc21feea83e9d89
4
+ data.tar.gz: 97390f124219ba7e697253c551bbef2527b15d7234793a76431ebdde73e996ed
5
5
  SHA512:
6
- metadata.gz: 46fda51d238e517907361f4da89ef9615383e55d3daad4c58eb8a0d947ccae27398ca340b9d2590274ff02ef312e9f8384fa7965a5470b4b3b0d8b0eb63527bb
7
- data.tar.gz: b7589f6ad84cbd44276893466a15350ba24db01dc5183db3554dc8f5cff77b6834ec964c0591de4c3ad1293713e62f6f28766775b6c88074d3f36d6749afe522
6
+ metadata.gz: 95fceaebbb3959fb3b872b570b9202deb4dfd4a44dc363c25b20398f9e2a199091eb5fdecbeb07caceb2be104b94c07f3294e8b8158737416e2b83efe7e65ebe
7
+ data.tar.gz: 248b60b0c0ab90d10c780ce69e3f63ff6aa4b222cef82c5121abf2acb4b462c6534b245556a2683649ccf57440e758d5846e93322828f127c66784701ea11127
@@ -1,3 +1,53 @@
1
+ ## 0.7.0
2
+ * Automatically perform `docker login` if not already logged into the Docker registry.
3
+ * Fix timestamp tag parsing issue causing deploy to fail with no available tags.
4
+ - Issue turned out to be ignoring the month of October in the validation regex.
5
+
6
+ ## 0.6.1
7
+ * Fix issue causing database.yml to not be rewritten to point at correct database host.
8
+
9
+ ## 0.6.0
10
+ * Don't load the Rails environment when running Kuby's rake tasks.
11
+ - Kuby's gems are still part of the bundle, but config has been moved out of the initializer and into kuby.rb in the Rails root directory.
12
+ - Internal classes no longer retain a reference to `Rails.application`.
13
+ - Kuby config now requires `environment` blocks:
14
+ ```ruby
15
+ Kuby.define('my-app') do
16
+ environment(:production) do
17
+ ...
18
+ end
19
+
20
+ environment(:staging) do
21
+ ...
22
+ end
23
+ end
24
+ ```
25
+ * Fix `MissingDistroError` caused by not setting a default distro.
26
+ * Create a .dockerignore file when running the Rails generator.
27
+ * Add ability to insert inline Docker layers without having to create a separate class, eg:
28
+ ```ruby
29
+ insert :hello, before: :bundler_phase do |dockerfile|
30
+ dockerfile.run('echo "hello, world"')
31
+ end
32
+ ```
33
+ * Add Postgres database support.
34
+ * Don't install sqlite libs by default.
35
+ * Modify Rails generator
36
+ - Require kuby and load config safely.
37
+ - Provide manual access to credentials via `ActiveSupport::EncryptedConfiguration`, which is necessary now that our rake tasks don't load the Rails environment.
38
+ * Add a convenience method for requesting the amount of block storage for the database.
39
+ * Add the ability to entirely disable database management via `manage_database false`.
40
+ * Avoid deploying nginx-ingress if it's already deployed.
41
+ * Add rake task for running arbitrary `kubectl` commands.
42
+
43
+ ## 0.5.0
44
+ * Fix Rails generators issue causing crash at startup.
45
+ * Add rake task to run arbitrary kubectl commands.
46
+
47
+ ## 0.4.0
48
+ * Introduce simple managed package.
49
+ * Refactor deploy task into its own class.
50
+
1
51
  ## 0.3.0
2
52
  * Fix Krane issue causing incorrect constant lookup and therefore deploy failures.
3
53
  - See: https://github.com/Shopify/krane/pull/720
data/README.md CHANGED
@@ -8,170 +8,13 @@ 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
- ## Raison d'etre
12
-
13
- One of Rails' most notorious mantras is "convention over configuration," i.e. sane defaults that limit the cognitive overhead of application development. Rails has survived for as long as it has precisely because it makes so many decisions for you, especially compared to other web application frameworks. It's easy to learn and easy to build with. The development experience is fantastic... right up until the point you want to deploy your app to production. It's at that point that the hand-holding stops. Like the Roadrunner, Rails stops right before the cliff and lets you, Wile E. Coyote, sail over the edge.
14
-
15
- ![Wile E. Coytote](coyote.jpg)
16
-
17
- Perhaps [Stefan Wintermeyer](https://twitter.com/wintermeyer) said it best during his appearance on the Ruby Rogues podcast, [episode 403](https://devchat.tv/ruby-rogues/rr-403-rails-needs-active-deployment-with-stefan-wintermeyer/):
18
-
19
- > "In my experience, deployment is one of the major problems of normal Rails users. It is a big pain to set up a deployment system for a Rails application, and I don't see anything out there that makes it easier. [...] I believe that we lose quite a lot of companies and new developers on this step. Because everything else [is] so much easier with Rails. But that last step - and it's a super important step - is still super complicated."
20
-
21
- ## Docker and Kubernetes
22
-
23
- Why bet the farm on Docker and Kubernetes?
24
-
25
- ### Docker
26
-
27
- When Docker came on the scene in 2013 it was seen as a game-changer. Applications that used to be deployed onto hand-provisioned servers can now be bundled up into neat little packages and transferred between computers in their entirety. Since the whole application - dependencies, operating system components, assets, code, etc - can be passed around as a single artifact, Docker images curtail the need for manually provisioned servers and eliminate a whole class of "works on my machine" problems.
28
-
29
- ### Kubernetes
30
-
31
- Kubernetes has taken the ops world by storm. It's resilient to failure, portable across a variety of cloud providers, and backed by industry-leading organizations like the CNCF. Kubernetes configuration is portable enough to be used, without modification, on just about any Kubernetes cluster, making migrations not only feasible, but easy. Many cloud providers like Google GCP, Amazon AWS, Microsoft Azure, DigitalOcean, and Linode support Kubernetes. Most of these providers will manage the Kubernetes cluster for you, and in some cases will even provide it free of charge (you pay only for the compute resources).
32
-
33
11
  ## Getting Started
34
12
 
35
- NOTE: Kuby is designed to work with Rails 5.1 and up.
36
-
37
- ### Choosing a Provider
38
-
39
- The first step in deploying your app is to choose a hosting provider. At the time of this writing, Kuby supports DigitalOcean and Linode, but support for more providers is coming soon. Use your provider's dashboard to spin up a Kubernetes cluster. In most cases, this shouldn't involve more than a few button clicks.
40
-
41
- ### The Container Registry
42
-
43
- Kuby uses Docker to package up your application into a Docker _image_. Images are then pushed (i.e. uploaded) to something called a "container registry." Container registries host Docker images so they can be pulled (i.e. downloaded) later.
44
-
45
- Although there are a number of container registries available (some free and some paid), consider using the Gitlab registry. Gitlab's registry is free and unlimited. You don't have to host your code on Gitlab to take advantage of the registry, but they're great for that too.
46
-
47
- ### Integrating Kuby
48
-
49
- Kuby configuration is done via a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language). There are two main sections, one for Docker and one for Kubernetes. Put the config into a Rails initializer, eg. config/initializers/kuby.rb.
50
-
51
- Here's what a complete config looks like:
52
-
53
- ```ruby
54
- Kuby.define(:production) do
55
- docker do
56
- credentials do
57
- username ENV['DOCKER_USERNAME']
58
- password ENV['DOCKER_PASSWORD']
59
- email ENV['DOCKER_EMAIL']
60
- end
61
-
62
- image_url 'registry.gitlab.com/username/repo'
63
- end
64
-
65
- kubernetes do
66
- provider :digitalocean do
67
- access_token ENV['DIGITALOCEAN_ACCESS_TOKEN']
68
- cluster_id 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
69
- end
70
-
71
- add_plugin :rails_app do
72
- hostname 'mywebsite.com'
73
- end
74
- end
75
- end
76
- ```
77
-
78
- Let's go over this config in detail.
79
-
80
- ### Deploy Environments
81
-
82
- The first line defines the _deploy environment_:
83
-
84
- ```ruby
85
- Kuby.define(:production)
86
- ```
87
-
88
- Deploy environments usually closely mirror your Rails environments. For example, you might create a new Rails environment called "staging" or "preprod" that's used to test production changes before they go live. You'll want to create a "staging" Kuby deploy environment as well.
89
-
90
- If you're a small shop or hobbyist though, chances are the "production" deploy environment is all you need.
91
-
92
- ### Configuring Docker
93
-
94
- Kuby can automatically "dockerize" your application. You just need to tell it where to push images and provide some credentials:
95
-
96
- ```ruby
97
- docker do
98
- credentials do
99
- username ENV['DOCKER_USERNAME']
100
- password ENV['DOCKER_PASSWORD']
101
- email ENV['DOCKER_EMAIL']
102
- end
103
-
104
- image_url 'registry.gitlab.com/username/repo'
105
- end
106
- ```
107
-
108
- The username, password, and email fields are used to authenticate with the Docker registry that hosts your images. For Gitlab, you'll need to create a [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) instead of your password. The `image_url` field is the full URL to your image, including the registry's domain.
109
-
110
- In the example above, the username, password, and email are all provided as environment variables. **NEVER** hard-code sensitive information like this in your Kuby config or check it into source control (i.e. git). Consider using a tool like [dotenv](https://github.com/bkeepers/dotenv) to automatically load the variables from a file when your app starts (NOTE: don't check the .env file into git either!)
111
-
112
- ### Configuring Kubernetes
113
-
114
- Now that your app can be packaged up into a Docker image, it's time to use Kubernetes to run it. There are two top-level concerns in the Kubernetes section of your Kuby config: providers and plugins.
115
-
116
- #### Providers
117
-
118
- Each Kubernetes definition must have a provider configured. Providers correspond to the hosting provider you chose earlier. For example, you'll need to add the `:digitalocean` provider to deploy to a managed DigitalOcean Kubernetes cluster.
119
-
120
- ```ruby
121
- kubernetes do
122
- provider :digitalocean do
123
- access_token ENV['DIGITALOCEAN_ACCESS_TOKEN']
124
- cluster_id 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
125
- end
126
- end
127
- ```
128
-
129
- Kuby providers are distributed as individual rubygems. Add the one you need to your Gemfile, for example:
130
-
131
- ```ruby
132
- gem 'kuby-digitalocean', '~> 0.1'
133
- ```
134
-
135
- Providers can have different config options, so make sure you consult the gem's README for the provider you've chosen.
136
-
137
- #### Plugins
138
-
139
- Nearly all Kuby's functionality is provided via plugins. For example, simply add the `:rails_app` plugin to get your Rails app ready to deploy:
140
-
141
- ```ruby
142
- add_plugin :rails_app
143
- ```
144
-
145
- To indicate your app exists behind a particular domain name, specify the `hostname` option:
146
-
147
- ```ruby
148
- add_plugin :rails_app do
149
- hostname 'mywebsite.com'
150
- end
151
- ```
152
-
153
- Configuring DNS to point to your Kubernetes cluster is outside the scope of this README, but all the hosting providers should have tutorials. For example, [here's the one](https://www.digitalocean.com/community/tutorials/how-to-point-to-digitalocean-nameservers-from-common-domain-registrars) from DigitalOcean.
154
-
155
- ## Deploying
156
-
157
- Now that Kuby is configured and your Kubernetes cluster is ready, it's time to deploy!
158
-
159
- 1. Build the Docker image
160
-
161
- ```sh
162
- bundle exec rake kuby:build
163
- ```
164
- 1. Push the Docker image to the container registry
13
+ See the [Quick Start Guide](https://github.com/getkuby/kuby-core/wiki/Quick-Start-Guide)
165
14
 
166
- ```sh
167
- bundle exec rake kuby:push
168
- ```
169
- 1. Deploy!
15
+ ## More Info
170
16
 
171
- ```sh
172
- bundle exec rake kuby:deploy
173
- ```
174
- 1. Rejoice
17
+ See the [wiki](https://github.com/getkuby/kuby-core/wiki).
175
18
 
176
19
  ## Running Tests
177
20
 
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency 'colorize', '~> 0.8'
16
16
  s.add_dependency 'docker-remote', '~> 0.1'
17
17
  s.add_dependency 'krane', '~> 1.0'
18
- s.add_dependency 'kuby-cert-manager', '~> 0.1'
18
+ s.add_dependency 'kuby-cert-manager', '~> 0.2'
19
19
  s.add_dependency 'kube-dsl', '~> 0.3'
20
20
  s.add_dependency 'kuby-kube-db', '~> 0.4'
21
21
  s.add_dependency 'kubernetes-cli', '~> 0.2'
@@ -23,5 +23,6 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency 'rouge', '~> 3.0'
24
24
 
25
25
  s.require_path = 'lib'
26
+
26
27
  s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'kuby-core.gemspec']
27
28
  end
@@ -1,10 +1,16 @@
1
1
  require 'kuby/railtie'
2
2
 
3
+ begin
4
+ require 'kuby/kubernetes/plugins/rails_app/generators/kuby'
5
+ rescue NameError
6
+ end
7
+
3
8
  module Kuby
4
9
  autoload :BasicLogger, 'kuby/basic_logger'
5
10
  autoload :CLIBase, 'kuby/cli_base'
6
11
  autoload :Definition, 'kuby/definition'
7
12
  autoload :Docker, 'kuby/docker'
13
+ autoload :Environment, 'kuby/environment'
8
14
  autoload :Kubernetes, 'kuby/kubernetes'
9
15
  autoload :Middleware, 'kuby/middleware'
10
16
  autoload :Tasks, 'kuby/tasks'
@@ -14,19 +20,25 @@ module Kuby
14
20
 
15
21
  class << self
16
22
  attr_reader :definition
17
- attr_accessor :logger
23
+ attr_writer :logger
18
24
 
19
- def define(environment, app = Rails.application, &block)
20
- environment = environment.to_s
21
- definitions[environment] ||= Definition.new(environment, app, &block)
25
+ def load!
26
+ require ENV['KUBY_CONFIG'] || File.join('.', 'kuby.rb')
22
27
  end
23
28
 
24
- def definitions
25
- @definitions ||= {}
29
+ def define(name, &block)
30
+ raise 'Kuby is already configured' if @definition
31
+
32
+ @definition = Definition.new(name.to_s)
33
+ @definition.instance_eval(&block)
34
+
35
+ @definition.environments.each do |_, env|
36
+ env.kubernetes.after_configuration
37
+ end
26
38
  end
27
39
 
28
- def definition(environment = env)
29
- definitions.fetch(environment.to_s) do
40
+ def environment(name = env)
41
+ definition.environment(name.to_s) do
30
42
  raise UndefinedEnvironmentError, "couldn't find a Kuby environment named "\
31
43
  "'#{environment}'"
32
44
  end
@@ -56,11 +68,19 @@ module Kuby
56
68
  @plugins ||= {}
57
69
  end
58
70
 
59
- def register_package(package_name, package_def)
71
+ def logger
72
+ @logger ||= BasicLogger.new(STDERR)
73
+ end
74
+
75
+ def register_package(package_name, package_def = nil)
60
76
  packages[package_name] = case package_def
77
+ when NilClass
78
+ Kuby::Docker::Packages::SimpleManagedPackage.new(
79
+ package_name
80
+ )
61
81
  when String
62
- Kuby::Docker::Packages::ManagedPackage.new(
63
- package_name, debian: package_def, alpine: package_def
82
+ Kuby::Docker::Packages::SimpleManagedPackage.new(
83
+ package_def
64
84
  )
65
85
  when Hash
66
86
  Kuby::Docker::Packages::ManagedPackage.new(
@@ -77,7 +97,7 @@ module Kuby
77
97
 
78
98
  def env
79
99
  ENV.fetch('KUBY_ENV') do
80
- (definitions.keys.first || Rails.env).to_s
100
+ (definition.environments.keys.first || Rails.env).to_s
81
101
  end
82
102
  end
83
103
  end
@@ -105,8 +125,3 @@ Kuby.register_package(:c_toolchain,
105
125
  debian: 'build-essential',
106
126
  alpine: 'build-base'
107
127
  )
108
-
109
- Kuby.register_package(:sqlite_dev,
110
- debian: 'libsqlite3-dev',
111
- alpine: 'sqlite-dev'
112
- )
@@ -1,29 +1,35 @@
1
1
  module Kuby
2
2
  class Definition
3
- attr_reader :environment, :app
3
+ attr_reader :app_name
4
4
 
5
- def initialize(environment, app, &block)
6
- @environment = environment
7
- @app = app
5
+ def initialize(app_name, &block)
6
+ @app_name = app_name
7
+ end
8
+
9
+ def environment(name = Kuby.env, &block)
10
+ name = name.to_s
11
+
12
+ if name
13
+ environments[name] ||= Environment.new(name, self)
14
+ end
15
+
16
+ if block_given?
17
+ environments[name].instance_eval(&block)
18
+ end
8
19
 
9
- instance_eval(&block) if block
10
- kubernetes.after_configuration
20
+ environments[name]
11
21
  end
12
22
 
13
23
  def docker(&block)
14
- @docker ||= Docker::Spec.new(self)
15
- @docker.instance_eval(&block) if block
16
- @docker
24
+ environment.docker(&block)
17
25
  end
18
26
 
19
27
  def kubernetes(&block)
20
- @kubernetes ||= Kubernetes::Spec.new(self)
21
- @kubernetes.instance_eval(&block) if block
22
- @kubernetes
28
+ environment.kubernetes(&block)
23
29
  end
24
30
 
25
- def app_name
26
- @app_name ||= app.class.module_parent.name
31
+ def environments
32
+ @environments ||= {}
27
33
  end
28
34
  end
29
35
  end
@@ -10,12 +10,13 @@ module Kuby
10
10
  autoload :Credentials, 'kuby/docker/credentials'
11
11
  autoload :Debian, 'kuby/docker/debian'
12
12
  autoload :Dockerfile, 'kuby/docker/dockerfile'
13
+ autoload :InlineLayer, 'kuby/docker/inline_layer'
14
+ autoload :Layer, 'kuby/docker/layer'
13
15
  autoload :LayerStack, 'kuby/docker/layer_stack'
14
16
  autoload :LocalTags, 'kuby/docker/local_tags'
15
17
  autoload :Metadata, 'kuby/docker/metadata'
16
18
  autoload :Packages, 'kuby/docker/packages'
17
19
  autoload :PackagePhase, 'kuby/docker/package_phase'
18
- autoload :Phase, 'kuby/docker/phase'
19
20
  autoload :RemoteTags, 'kuby/docker/remote_tags'
20
21
  autoload :SetupPhase, 'kuby/docker/setup_phase'
21
22
  autoload :Spec, 'kuby/docker/spec'
@@ -8,7 +8,6 @@ module Kuby
8
8
  [:nodejs, '12.14.1'],
9
9
  [:yarn, '1.21.1'],
10
10
  [:c_toolchain],
11
- [:sqlite_dev],
12
11
  [:tzdata]
13
12
  ].freeze
14
13
 
@@ -1,6 +1,6 @@
1
1
  module Kuby
2
2
  module Docker
3
- class AssetsPhase < Phase
3
+ class AssetsPhase < Layer
4
4
  def apply_to(dockerfile)
5
5
  dockerfile.run(
6
6
  'bundle', 'exec', 'rake', 'assets:precompile'
@@ -1,6 +1,8 @@
1
+ require 'pathname'
2
+
1
3
  module Kuby
2
4
  module Docker
3
- class BundlerPhase < Phase
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(app.root)
53
+ .relative_path_from(Pathname(Dir.getwd))
52
54
  .to_s
53
55
  end
54
56
  end