orchestration 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rubocop.yml +14 -0
  4. data/Gemfile +4 -2
  5. data/Makefile +5 -0
  6. data/README.md +82 -16
  7. data/Rakefile +5 -3
  8. data/TODO +2 -0
  9. data/bin/rspec +29 -0
  10. data/bin/rubocop +29 -0
  11. data/config/locales/en.yml +16 -0
  12. data/lib/orchestration/docker_compose/database_service.rb +51 -0
  13. data/lib/orchestration/docker_compose/mongo_service.rb +27 -0
  14. data/lib/orchestration/docker_compose/rabbitmq_service.rb +23 -0
  15. data/lib/orchestration/docker_compose/services.rb +48 -0
  16. data/lib/orchestration/docker_compose.rb +11 -0
  17. data/lib/orchestration/environment.rb +47 -0
  18. data/lib/orchestration/errors.rb +7 -0
  19. data/lib/orchestration/file_helpers.rb +88 -0
  20. data/lib/orchestration/healthcheck_base.rb +21 -0
  21. data/lib/orchestration/install_generator.rb +95 -0
  22. data/lib/orchestration/railtie.rb +9 -0
  23. data/lib/orchestration/service_check.rb +81 -0
  24. data/lib/orchestration/services/database/adapters/mysql2.rb +27 -0
  25. data/lib/orchestration/services/database/adapters/postgresql.rb +27 -0
  26. data/lib/orchestration/services/database/adapters/sqlite3.rb +23 -0
  27. data/lib/orchestration/services/database/adapters.rb +14 -0
  28. data/lib/orchestration/services/database/configuration.rb +114 -0
  29. data/lib/orchestration/services/database/healthcheck.rb +30 -0
  30. data/lib/orchestration/services/database.rb +15 -0
  31. data/lib/orchestration/services/mongo/configuration.rb +55 -0
  32. data/lib/orchestration/services/mongo/healthcheck.rb +34 -0
  33. data/lib/orchestration/services/mongo.rb +12 -0
  34. data/lib/orchestration/services/rabbitmq/configuration.rb +36 -0
  35. data/lib/orchestration/services/rabbitmq/healthcheck.rb +37 -0
  36. data/lib/orchestration/services/rabbitmq.rb +12 -0
  37. data/lib/orchestration/services.rb +10 -0
  38. data/lib/orchestration/settings.rb +43 -0
  39. data/lib/orchestration/templates/Dockerfile.tt +11 -0
  40. data/lib/orchestration/templates/Makefile.tt +53 -0
  41. data/lib/orchestration/terminal.rb +44 -0
  42. data/lib/orchestration/version.rb +3 -1
  43. data/lib/orchestration.rb +25 -2
  44. data/lib/tasks/orchestration.rake +39 -0
  45. data/orchestration.gemspec +34 -17
  46. metadata +213 -7
  47. data/CODE_OF_CONDUCT.md +0 -74
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c8341c788d09b97b9679317cadfd0d97056c7622
4
- data.tar.gz: a859667a0521d233dc4b9d98329e0953678fe180
3
+ metadata.gz: 9c1480a6241a2ea71eaa7a9c9fc3ad4d098a180b
4
+ data.tar.gz: 352354aef228f577185908ea06f9aa332cee5ec9
5
5
  SHA512:
6
- metadata.gz: 4f7ae8f5336e2640da45e54430119be8ba79fe9177aebda2303f3f67bdccdca0abc21a62844f40a70d86757fe39bdc159461036614a8108c2118e41af1863343
7
- data.tar.gz: d81362e8476fa65c56c801da6a9d9fb23bcaf7650833ee921a62da31a77b72ab2a0e03a68920f4d6bf2bd04c49692fee12bbb7676c4fa31ac5c3e1e6c9849e49
6
+ metadata.gz: 9c0ac0ad8b6f5a780a8f9dce28f528175b1d4894b9d18db365035efdb5088b98d6d4665dc327a43dfd8030d278ec4dfbecc88877a080b2e12fda513427ab2316
7
+ data.tar.gz: 985e17427df0c2347892f628ae14fccb144aa6a1767d5a0f0351d73b4cb7f23faf24072d1fd8f924db83a47fcf8333232c2968b506ae5181f541507b1a4ca4a2
data/.gitignore CHANGED
@@ -9,3 +9,17 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ Gemfile.lock
14
+
15
+ *.swp
16
+ *.swo
17
+
18
+ spec/dummy/log/*
19
+ !spec/dummy/log/.keep
20
+ spec/dummy/.gitignore
21
+ spec/dummy/Makefile
22
+ spec/dummy/docker/*
23
+ spec/dummy/docker-compose.yml
24
+
25
+ .byebug_history
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ Style/Documentation:
2
+ Enabled: false
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/**/*'
7
+ - '*.gemspec'
8
+ - 'lib/tasks/orchestration.rake'
9
+
10
+ AllCops:
11
+ Exclude:
12
+ - 'bin/**/*'
13
+ - 'db/schema.rb'
14
+ - 'spec/dummy/**/*'
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in orchestration.gemspec
6
8
  gemspec
data/Makefile ADDED
@@ -0,0 +1,5 @@
1
+ .PHONY: test
2
+
3
+ test:
4
+ ./bin/rspec
5
+ ./bin/rubocop
data/README.md CHANGED
@@ -1,39 +1,105 @@
1
1
  # Orchestration
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/orchestration`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ ## Overview
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ _Orchestration_ provides a toolkit for building and launching _Rails_ applications and dependencies in _Docker_.
6
+
7
+ A suite of tools is provided to assist in creating configuration files, launching service dependencies, verifying that dependencies have launched successfully (e.g. for running tests in contiuous integration tools), and building, tagging, and pushing _Docker_ images.
8
+
9
+ Containers are automatically created for the following dependencies:
10
+
11
+ * MySQL
12
+ * MongoDB
13
+ * PostgreSQL
14
+ * RabbitMQ
6
15
 
7
16
  ## Installation
8
17
 
9
18
  Add this line to your application's Gemfile:
10
19
 
11
20
  ```ruby
12
- gem 'orchestration'
21
+ gem 'orchestration', '~> 0.2.0'
13
22
  ```
14
23
 
15
- And then execute:
24
+ And then build your bundle:
25
+ ``` bash
26
+ $ bundle install
27
+ ```
16
28
 
17
- $ bundle
29
+ ## Usage
18
30
 
19
- Or install it yourself as:
31
+ ### Generating configuration files
20
32
 
21
- $ gem install orchestration
33
+ A _Rake_ task is provided to generate the following files:
22
34
 
23
- ## Usage
35
+ * `Makefile` - provides easy access to all _Orchestration_ utilities.
36
+ * `.gitignore` - ensures any unwanted files created by _Orchestration_ do not clutter your project's version control system.
37
+ * `docker/Dockerfile` - a ready-to-use _Docker_ build script which should need minimal (if any) modification to build your _Rails_ project.
38
+ * `docker-compose.yml` - a custom-made set of services to allow you to run your application's dependencies locally.
39
+ * `.orchestration.yml` - _Orchestration_ internal configuration, e.g. _Docker_ username.
24
40
 
25
- TODO: Write usage instructions here
41
+ ### Building and pushing your project as a _Docker_ image
26
42
 
27
- ## Development
43
+ #### Private Git repository authentication
28
44
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
45
+ If your project has any dependencies on private _Git_ repositories then you will need to create an authentication token. See the relevant documentation for your _Git_ host:
30
46
 
31
- 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).
47
+ * [GitHub](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)
48
+ * [Bitbucket](https://confluence.atlassian.com/bitbucket/app-passwords-828781300.html)
32
49
 
33
- ## Contributing
50
+ Create a file named `.env` in the same directory as your `docker-compose.yml` and add one or both of the following (note that _Bitbucket_ and _GitHub_ use a different format):
34
51
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/orchestration. 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.
52
+ ```bash
53
+ BUNDLE_BITBUCKET__ORG=<bitbucket-username>:<app-password>
54
+ BUNDLE_GITHUB__COM=x-oauth-basic:<auth-token>
55
+ ```
36
56
 
37
- ## Code of Conduct
57
+ #### Docker installation
58
+ _Docker_ must be installed on your system. See the [_Docker_ getting started guide](https://www.docker.com/get-started) for instructions.
59
+
60
+ #### DockerHub account
61
+
62
+ You will need an account with _Docker Hub_ (or your preferred _Docker_ image host) to push your images. Visit the [_Docker Hub_ webpage](https://hub.docker.com/) to sign up, then run the following command and enter your credentials when prompted to log in to your new account:
63
+ ```bash
64
+ $ docker login
65
+ ```
66
+
67
+ #### Using provided `Makefile`
68
+
69
+ To build and push your image run:
70
+ ```bash
71
+ $ make docker
72
+ ```
73
+
74
+ Or run the two steps separately:
75
+ ```bash
76
+ $ make docker-build
77
+ $ make docker-push
78
+ ```
79
+
80
+ ### Starting and waiting for services when running your tests
81
+
82
+ To start services:
83
+
84
+ ```bash
85
+ $ make start
86
+ ```
87
+
88
+ This will launch any dependencies your project needs (e.g. _MySQL_, _MongoDB_, etc.).
89
+
90
+ To wait for all services to be ready:
91
+ ```bash
92
+ $ make wait
93
+ ```
94
+
95
+ It is recommended that you create a `test` command in your `Makefile` which will launch all dependencies and wait for them to be ready before running all tests. For example:
96
+
97
+ ```Makefile
98
+ test: start wait
99
+ bundle exec rspec
100
+ yarn test app/javascript
101
+ bundle exec rubocop
102
+ yarn run eslint app/javascript
103
+ ```
38
104
 
39
- Everyone interacting in the Orchestration project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/orchestration/blob/master/CODE_OF_CONDUCT.md).
105
+ This is especially useful for continuous integration as it provides a uniform command (`make test`) that can be run by your CI tool without any extra setup.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ Be aware of yarn and include build steps in Dockerfile if present. Use dashboard
2
+ front end as a reference.
data/bin/rspec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/rubocop ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
@@ -0,0 +1,16 @@
1
+ en:
2
+ orchestration:
3
+ unknown_scheme: "Unrecognised database adapter for URL scheme: %{scheme}"
4
+ attempt_limit: "Unable to reconnect after %{limit} attempts. Aborting."
5
+ database:
6
+ waiting: "Waiting for database: %{config}"
7
+ ready: "Database is ready."
8
+ missing_default: "database.yml must define a `default` section."
9
+ mongo:
10
+ waiting: "Waiting for Mongo: %{config}"
11
+ ready: "Mongo is ready."
12
+ rabbitmq:
13
+ waiting: "Waiting for RabbitMQ: %{config}"
14
+ ready: "RabbitMQ is ready."
15
+ docker:
16
+ username_request: "Enter your Docker registry username (used for tagging images)"
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module DockerCompose
5
+ class DatabaseService
6
+ # We dictate which port all database services will run on in their
7
+ # container to simplify port mapping.
8
+ PORT = 3354
9
+
10
+ def initialize(config)
11
+ @config = config
12
+ end
13
+
14
+ def definition
15
+ return nil if @config.settings.nil?
16
+
17
+ adapter = @config.settings.fetch('adapter')
18
+ return nil if adapter == 'sqlite3'
19
+
20
+ port = @config.settings.fetch('port')
21
+ {
22
+ 'image' => image_from_adapter(adapter),
23
+ 'environment' => environment_from_adapter(adapter),
24
+ 'ports' => ["#{port}:#{PORT}"]
25
+ }
26
+ end
27
+
28
+ private
29
+
30
+ def image_from_adapter(adapter)
31
+ {
32
+ 'postgresql' => 'library/postgres',
33
+ 'mysql2' => 'library/mysql'
34
+ }.fetch(adapter)
35
+ end
36
+
37
+ def environment_from_adapter(adapter)
38
+ {
39
+ 'postgresql' => {
40
+ 'PGPORT' => PORT.to_s,
41
+ 'POSTGRES_PASSWORD' => 'password'
42
+ },
43
+ 'mysql2' => {
44
+ 'MYSQL_ROOT_PASSWORD' => 'password',
45
+ 'MYSQL_TCP_PORT' => PORT.to_s
46
+ }
47
+ }.fetch(adapter)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module DockerCompose
5
+ class MongoService
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def definition
11
+ return nil if @config.settings.nil?
12
+
13
+ # REVIEW: If the host application defines multiple mongo hosts then we
14
+ # create one service instance and point them all at the same service.
15
+ # Instead we should probably create a separate service for each.
16
+ ports = @config.ports.map do |port|
17
+ "#{port}:#{Orchestration::Services::Mongo::PORT}"
18
+ end
19
+
20
+ {
21
+ 'image' => 'library/mongo',
22
+ 'ports' => ports
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module DockerCompose
5
+ class RabbitMQService
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def definition
11
+ return nil if @config.settings.nil?
12
+
13
+ host_port = @config.settings.fetch('port', 5672)
14
+ container_port = Orchestration::Services::RabbitMQ::PORT
15
+
16
+ {
17
+ 'image' => 'library/rabbitmq',
18
+ 'ports' => ["#{host_port}:#{container_port}"]
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module DockerCompose
5
+ class Services
6
+ def initialize(options = {})
7
+ @configurations = {
8
+ 'database' => options.fetch(:database, nil),
9
+ 'mongo' => options.fetch(:mongo, nil),
10
+ 'rabbitmq' => options.fetch(:rabbitmq, nil)
11
+ }
12
+ end
13
+
14
+ def structure
15
+ { 'version' => '3.7', 'services' => services }
16
+ end
17
+
18
+ def services
19
+ Hash[filtered_services]
20
+ end
21
+
22
+ private
23
+
24
+ def filtered_services
25
+ services_enabled.compact.reject { |_name, definition| definition.nil? }
26
+ end
27
+
28
+ def services_available
29
+ [
30
+ { name: 'database', class: DatabaseService },
31
+ { name: 'mongo', class: MongoService },
32
+ { name: 'rabbitmq', class: RabbitMQService }
33
+ ]
34
+ end
35
+
36
+ def services_enabled
37
+ services_available.map do |service|
38
+ config = @configurations[service[:name]]
39
+ # REVIEW: This is mostly here for testing - we may not need it once
40
+ # everything's implemented.
41
+ next if config.nil?
42
+
43
+ [service[:name], service[:class].new(config).definition]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module DockerCompose
5
+ end
6
+ end
7
+
8
+ require 'orchestration/docker_compose/services'
9
+ require 'orchestration/docker_compose/database_service'
10
+ require 'orchestration/docker_compose/mongo_service'
11
+ require 'orchestration/docker_compose/rabbitmq_service'