keel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9990776275902868c2a1b8a6d21d0fd22513062d
4
+ data.tar.gz: f85d922dbfb13ffe9bff782ff8e0e4f98cd85435
5
+ SHA512:
6
+ metadata.gz: 3009f39f0f6d91b7e2f6fe3d86d18d8fabfe166dd65426efeeb17c8d4a660cd6cd4a2c997574f483ade191124d21f3dbff978c5eafb75587089c19ced0933835
7
+ data.tar.gz: 014e2faea3583f3bb45a62b2b9dce4010a34bd78a5431978c05172ba7e0683c2bfac8fd445a4029d66f2b62dffeedba0aa0e4f210069ede90e236011c906ca1a
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.11.2
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at ychaker@o19s.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in keel.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 OpenSource Connections
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Keel
2
+
3
+ This gem provides a few easy to run rake tasks to deploy your [Rails](http://rubyonrails.org/) application to a [Kubernetes](http://kubernetes.io/) cluster.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'keel'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```
22
+ $ gem install keel
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ First, run:
28
+
29
+ ```
30
+ bin/rails g keel:config
31
+ ```
32
+
33
+ to generate the config file and update the attributes with the appropriate values.
34
+
35
+ ### Rake Tasks
36
+
37
+ This gem mostly provides a set of rake tasks that you can see if you execute `bin/rake -T keel`:
38
+
39
+ ```
40
+ rake keel:deploy[environment,deploy_sha] # Deploy the specified SHA to a given environment
41
+ rake keel:logs[environment] # Pulls logs for a given environment
42
+ rake keel:setup # Configures the local machine for communication with gcloud and k8s
43
+ ```
44
+
45
+ The first thing you'd want to do after you've setup the configs is to run `bin/rake keel:setup` to make sure your local environment is setup with the right tools to communicate with GCloud and Kubernetes. Just follow the instructions in the command prompt.
46
+
47
+ Once you have that setup, you can run `bin/rake keel:deploy` to deploy your code to one of your environments on the Kubernetes cluster. You can provide all the necessary information by following the instructions in the command prompt.
48
+
49
+ ### Generators
50
+
51
+ Other than the config generator that was mentioned above, this gem provides a couple of handy generators to help you work with Kubernetes:
52
+
53
+ ```
54
+ keel:controller
55
+ keel:service
56
+ ```
57
+
58
+ These generators use standard templates to generate a `yml` file that you can use to configure your Kubernetes setup.
59
+
60
+ You can find the generated files under the `ops/` directory of your application.
61
+
62
+ ## LOLz
63
+
64
+ Naming is hard, so why not have fun with it?
65
+
66
+ ```
67
+ Daniel
68
+ Before you commit to that name it, I would like to point out that it is ripe for pun disruption.
69
+ Daniel
70
+ "You're really keeling it @Youssef"
71
+ Matt
72
+ crap, our deployment just keeled over
73
+ Daniel
74
+ "That's a good boy. Down. Sit. Keel."
75
+ Doug
76
+ We've finally found kubernetes keeler app
77
+ Matt
78
+ whoa there doug, lets keep this keel
79
+ Doug
80
+ I know how you keel
81
+ Matt
82
+ I wonder if we can get an endorsement from my favorite comedy duo?
83
+ Matt
84
+ Pey and Keele
85
+ Daniel
86
+ Pen and Keeler
87
+ Matt
88
+ we should probably keel this before it gets out of hand
89
+ ```
90
+
91
+ ## Development
92
+
93
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
94
+
95
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
96
+
97
+ ## Contributing
98
+
99
+ Bug reports and pull requests are welcome on GitHub at https://github.com/o19s/keel. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
100
+
101
+
102
+ ## License
103
+
104
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "keel"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/keel.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'keel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "keel"
8
+ spec.version = Keel::VERSION
9
+ spec.authors = ["Youssef Chaker"]
10
+ spec.email = ["ychaker@o19s.com"]
11
+
12
+ spec.summary = %q{Deploy your Rails app to Kubernetes.}
13
+ spec.description = %q{This gem lets you deploy your Rails application to your Kubernetes cluster.}
14
+ spec.homepage = "https://github.com/o19s/keel"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "minitest", "~> 5.0"
25
+
26
+ spec.add_runtime_dependency "inquirer", "~> 0.2"
27
+ spec.add_runtime_dependency "colorize", "~> 0.7"
28
+ end
@@ -0,0 +1,13 @@
1
+ module Keel
2
+ module Generators
3
+ class ConfigGenerator < ::Rails::Generators::Base
4
+ desc "Generates a the config file for GCloud/Kubernetes."
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def copy_settings
9
+ copy "gcloud.yml", "config/gcloud.yml"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,59 @@
1
+ module Keel
2
+ module Generators
3
+ class ControllerGenerator < ::Rails::Generators::Base
4
+ desc "Generates a Kubernetes replication controller configuration file."
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def generate_template
9
+ config = Keel::GCloud::Config.new
10
+ prompter = Keel::GCloud::Prompter.new
11
+
12
+ # Fetch namespaces from k8s
13
+ namespaces = Keel::GCloud::Kubernetes::Namespace.fetch_all
14
+ unless namespaces
15
+ message = 'Unable to connect to Kubernetes, please try again later...'
16
+ prompter.print message, :error
17
+ return
18
+ end
19
+
20
+ # Prompt the user for the env, database url, and secret key to be used
21
+ deploy_env = prompter.prompt_for_namespace namespaces
22
+ database_url = prompter.prompt_for_database_url
23
+ secret_key = prompter.prompt_for_secret_key
24
+
25
+ if deploy_env.blank? || database_url.blank? || secret_key.blank?
26
+ message = 'Missing required parameters'
27
+ prompter.print message, :error
28
+ return
29
+ end
30
+
31
+ set_params(
32
+ config: config,
33
+ env: deploy_env,
34
+ database_url: database_url,
35
+ secret_key: secret_key
36
+ )
37
+
38
+ template "gc-controller.yml.erb", "ops/#{@params[:app]}-controller.yml"
39
+ end
40
+
41
+ private
42
+
43
+ def set_params config:, env:, **rest
44
+ # Setup variables to fill the template
45
+ @params = {
46
+ app: config.app_name,
47
+ cloud_sql_instance: config.cloud_sql_instance[env.to_sym],
48
+ compute_region: config.compute_region,
49
+ container_app_image_path: config.container_app_image_path,
50
+ container_cloud_sql_image_path: config.container_cloud_sql_image_path,
51
+ container_cluster: config.container_cluster,
52
+ deploy_env: env,
53
+ env_variables: config.env_variables[env.to_sym],
54
+ rails_env: env == 'production' ? 'production' : 'staging',
55
+ }.merge(rest)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,55 @@
1
+ module Keel
2
+ module Generators
3
+ class ServiceGenerator < ::Rails::Generators::Base
4
+ desc "Generates a Kubernetes service configuration file."
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def generate_template
9
+ config = Keel::GCloud::Config.new
10
+ prompter = Keel::GCloud::Prompter.new
11
+
12
+ # Fetch namespaces from k8s
13
+ namespaces = Keel::GCloud::Kubernetes::Namespace.fetch_all
14
+ unless namespaces
15
+ message = 'Unable to connect to Kubernetes, please try again later...'
16
+ prompter.print message, :error
17
+ return
18
+ end
19
+
20
+ # Prompt the user for the env, database url, and secret key to be used
21
+ deploy_env = prompter.prompt_for_namespace namespaces
22
+
23
+ unless deploy_env
24
+ message = 'Missing required parameters: deploy_env'
25
+ prompter.print message, :error
26
+ return
27
+ end
28
+
29
+ set_params(
30
+ config: config,
31
+ env: deploy_env,
32
+ )
33
+
34
+ template "gc-service.yml.erb", "ops/#{@params[:app]}-service.yml"
35
+ end
36
+
37
+ private
38
+
39
+ def set_params config:, env:, **rest
40
+ # Setup variables to fill the template
41
+ @params = {
42
+ app: config.app_name,
43
+ cloud_sql_instance: config.cloud_sql_instance[env.to_sym],
44
+ compute_region: config.compute_region,
45
+ container_app_image_path: config.container_app_image_path,
46
+ container_cloud_sql_image_path: config.container_cloud_sql_image_path,
47
+ container_cluster: config.container_cluster,
48
+ deploy_env: env,
49
+ env_variables: config.env_variables[env.to_sym],
50
+ rails_env: env == 'production' ? 'production' : 'staging',
51
+ }.merge(rest)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+ apiVersion: v1
2
+ kind: ReplicationController
3
+ metadata:
4
+ name: <%= @params[:deploy_env] %>-<%= @params[:app] %>-ctl
5
+ labels:
6
+ app: <%= @params[:app] %>
7
+ namespace: <%= @params[:deploy_env] %>
8
+ spec:
9
+ replicas: 1
10
+ selector:
11
+ app: <%= @params[:app] %>
12
+ template:
13
+ metadata:
14
+ name: <%= @params[:app] %>
15
+ labels:
16
+ app: <%= @params[:app] %>
17
+ spec:
18
+ volumes:
19
+ - name: secret-volume
20
+ secret:
21
+ secretName: cloud-sql-creds
22
+ - name: ssl-certs
23
+ hostPath:
24
+ path: /etc/ssl/certs
25
+ - name: cloudsql
26
+ emptyDir:
27
+ containers:
28
+ - name: <%= @params[:app] %>
29
+ image: <%= @params[:container_app_image_path] %>
30
+ ports:
31
+ - containerPort: 3000
32
+ resources:
33
+ limits:
34
+ cpu: 100m
35
+ env:
36
+ - name: DATABASE_URL
37
+ value: <%= @params[:database_url] %>
38
+ - name: SECRET_KEY_BASE
39
+ value: <%= @params[:secret_key] %>
40
+ - name: RAILS_ENV
41
+ value: <%= @params[:rails_env] %>
42
+ <%- @params[:env_variables].each do |name, value| -%>
43
+ - name: <%= name.to_s.upcase %>
44
+ value: <%= value %>
45
+ <%- end unless @params[:env_variables].blank? -%>
46
+ volumeMounts:
47
+ - name: cloudsql
48
+ mountPath: /cloudsql
49
+ - name: cloud-sql-proxy
50
+ image: <%= @params[:container_cloud_sql_image_path] %>
51
+ volumeMounts:
52
+ - name: cloudsql
53
+ mountPath: /cloudsql
54
+ - name: secret-volume
55
+ mountPath: /secret/
56
+ - name: ssl-certs
57
+ mountPath: /etc/ssl/certs
58
+ command: ["/cloud_sql_proxy", "-dir=/cloudsql", "-credential_file=/secret/creds.json", "-instances=<%= @params[:container_cluster] %>:<%= @params[:compute_region] %>:<%= @params[:cloud_sql_instance] %>"]
@@ -0,0 +1,15 @@
1
+ kind: Service
2
+ apiVersion: v1
3
+ metadata:
4
+ name: <%= @params[:deploy_env] %>-<%= @params[:app] %>-app
5
+ labels:
6
+ app: <%= @params[:app] %>
7
+ namespace: <%= @params[:deploy_env] %>
8
+ spec:
9
+ ports:
10
+ - name: web-http
11
+ port: 80
12
+ targetPort: 3000
13
+ selector:
14
+ app: <%= @params[:app] %>
15
+ type: NodePort
@@ -0,0 +1,19 @@
1
+ :app:
2
+ :name: YOUR-APP-NAME
3
+ :compute:
4
+ :zone: YOUR-ZONE
5
+ :region: YOUR-REGION
6
+ :container:
7
+ :app_image_path: YOUR-APP-IMAGE-PATH
8
+ :cloud_sql_image_path: YOUR-CLOUD-SQL-IMAGE-PATH
9
+ :cluster: YOUR-CLUSTER-NAME
10
+ :project_id: YOUR-PROJECT-ID
11
+ :cloud_sql_instance:
12
+ # Add your own, eg.
13
+ # :production: production
14
+ :env_variables:
15
+ # Add your own, eg.
16
+ # :production:
17
+ # :force_ssl: true
18
+ # :quepid_ga: UA-XXXXXXXX-X
19
+ # :ga_domain: example.com
@@ -0,0 +1,32 @@
1
+ module Keel::GCloud
2
+ #
3
+ # This is a wrapper to call authentication related APIs with GCloud.
4
+ #
5
+ class Auth
6
+ attr_accessor :cli, :config
7
+
8
+ def initialize config:
9
+ @config = config
10
+ @cli = Cli.new
11
+ end
12
+
13
+ #
14
+ # Calls the `login` API for GCLoud.
15
+ #
16
+ # @return [Boolean] whether the call succeeded or not
17
+ #
18
+ def self.authenticate
19
+ Cli.new.system 'gcloud auth login'
20
+ end
21
+
22
+ #
23
+ # Calls the `get-credentials` API for GCLoud for a specific
24
+ # container/cluster.
25
+ #
26
+ # @return [Boolean] whether the call succeeded or not
27
+ #
28
+ def authenticate_k8s
29
+ @cli.system "gcloud container clusters get-credentials #{self.config.container_cluster}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ module Keel::GCloud
2
+ #
3
+ # A helper class to run system commands and handle interrupts.
4
+ #
5
+ class Cli
6
+ def execute command
7
+ begin
8
+ `#{command}`
9
+ rescue Interrupt
10
+ puts 'Task interrupted.'
11
+ end
12
+ end
13
+
14
+ def system command
15
+ begin
16
+ system command
17
+ rescue Interrupt
18
+ puts 'Task interrupted.'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ module Keel::GCloud
2
+ #
3
+ # Class to help manage GCloud components.
4
+ #
5
+ class Component
6
+ #
7
+ # Updates the installed GCloud components.
8
+ #
9
+ # @return [Boolean] whether the call succeeded or not
10
+ #
11
+ def self.update
12
+ Cli.new.system 'gcloud components update'
13
+ end
14
+
15
+ #
16
+ # Installs the Kubernetes controller component.
17
+ #
18
+ # @return [Boolean] whether the call succeeded or not
19
+ #
20
+ def self.install_k8s
21
+ Cli.new.system 'gcloud components install kubectl'
22
+ end
23
+ end
24
+ end