egg 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac6c50558dd050db0f1815e74af300537bc7a600
4
+ data.tar.gz: 047271f09e9961ba6d0fc471fa156f12770e9063
5
+ SHA512:
6
+ metadata.gz: a3b32e62253c64394302b7a48011c6ad6c36a9904dff693f842b9bf44b4a64ff6049076a2fe193e10bb97bb022e73a463848cb448ab67a2e90b43d00d8598766
7
+ data.tar.gz: fdffb864c3ab84bd7ecd5b91ad16f9accc6e02c69708ab4faf03532db7957805c3480f1bd4102a66638a702878e8d39ce140420e352de13fc24005aed457ed95
@@ -0,0 +1,33 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ working_directory: ~/egg
5
+ docker:
6
+ - image: ruby:2.4.0
7
+ steps:
8
+ - run:
9
+ name: build-deps
10
+ command: |
11
+ apt-get -qq update
12
+ apt-get install -qqy cmake
13
+ - checkout
14
+ - type: cache-restore
15
+ key: egg-bundler-{{ checksum "Gemfile.lock" }}
16
+ - run: bundle install --path vendor/bundle
17
+ - type: cache-save
18
+ key: egg-bundler-{{ checksum "Gemfile.lock" }}
19
+ paths:
20
+ - vendor/bundle
21
+ - run:
22
+ name: rspec
23
+ command: |
24
+ mkdir -p "/tmp/test-results"
25
+ export TEST_FILES=$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
26
+ bundle exec rspec --profile 10 \
27
+ -r rspec_junit_formatter \
28
+ --format RspecJunitFormatter \
29
+ --out /tmp/test-results/rspec.xml \
30
+ --format progress \
31
+ ${TEST_FILES}
32
+ - type: store_test_results
33
+ path: /tmp/test-results
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /pkg/
6
+ /spec/reports/
7
+ /tmp/
8
+
9
+ .idea
10
+ /spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,26 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/**/*'
4
+ - 'vendor/**/*'
5
+ - 'spec/fixtures/**/*'
6
+ - 'tmp/**/*'
7
+ - 'db/schema.rb'
8
+ - 'db/migrate/**/*'
9
+ TargetRubyVersion: 2.2
10
+
11
+ Style/FrozenStringLiteralComment:
12
+ EnforcedStyle: when_needed
13
+
14
+ Style/StringLiterals:
15
+ EnforcedStyle: double_quotes
16
+
17
+ Metrics/LineLength:
18
+ Max: 119
19
+ IgnoreCopDirectives: true
20
+
21
+ Metrics/AbcSize:
22
+ Max: 16.5
23
+
24
+ Metrics/BlockLength:
25
+ Exclude:
26
+ - 'spec/**/*_spec.rb'
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.4.1
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at carlthuringer@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in egg.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ egg (0.3.0)
5
+ thor (~> 0.19.4)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ addressable (2.5.1)
11
+ public_suffix (~> 2.0, >= 2.0.2)
12
+ ast (2.3.0)
13
+ builder (3.2.3)
14
+ diff-lcs (1.3)
15
+ faraday (0.12.1)
16
+ multipart-post (>= 1.2, < 3)
17
+ gitlab (4.1.0)
18
+ httparty
19
+ terminal-table
20
+ httparty (0.14.0)
21
+ multi_xml (>= 0.5.2)
22
+ multi_xml (0.6.0)
23
+ multipart-post (2.0.0)
24
+ octokit (4.7.0)
25
+ sawyer (~> 0.8.0, >= 0.5.3)
26
+ parallel (1.11.2)
27
+ parser (2.4.0.0)
28
+ ast (~> 2.2)
29
+ powerpack (0.1.1)
30
+ pronto (0.9.3)
31
+ gitlab (~> 4.0, >= 4.0.0)
32
+ httparty (>= 0.13.7, < 0.15)
33
+ octokit (~> 4.7, >= 4.7.0)
34
+ rainbow (~> 2.1)
35
+ rugged (~> 0.24, >= 0.23.0)
36
+ thor (~> 0.19.0)
37
+ pronto-rubocop (0.9.0)
38
+ pronto (~> 0.9.0)
39
+ rubocop (~> 0.38, >= 0.35.0)
40
+ public_suffix (2.0.5)
41
+ rainbow (2.2.2)
42
+ rake
43
+ rake (12.0.0)
44
+ rspec (3.6.0)
45
+ rspec-core (~> 3.6.0)
46
+ rspec-expectations (~> 3.6.0)
47
+ rspec-mocks (~> 3.6.0)
48
+ rspec-core (3.6.0)
49
+ rspec-support (~> 3.6.0)
50
+ rspec-expectations (3.6.0)
51
+ diff-lcs (>= 1.2.0, < 2.0)
52
+ rspec-support (~> 3.6.0)
53
+ rspec-mocks (3.6.0)
54
+ diff-lcs (>= 1.2.0, < 2.0)
55
+ rspec-support (~> 3.6.0)
56
+ rspec-support (3.6.0)
57
+ rspec_junit_formatter (0.2.3)
58
+ builder (< 4)
59
+ rspec-core (>= 2, < 4, != 2.12.0)
60
+ rubocop (0.49.1)
61
+ parallel (~> 1.10)
62
+ parser (>= 2.3.3.1, < 3.0)
63
+ powerpack (~> 0.1)
64
+ rainbow (>= 1.99.1, < 3.0)
65
+ ruby-progressbar (~> 1.7)
66
+ unicode-display_width (~> 1.0, >= 1.0.1)
67
+ ruby-progressbar (1.8.1)
68
+ rugged (0.25.1.1)
69
+ sawyer (0.8.1)
70
+ addressable (>= 2.3.5, < 2.6)
71
+ faraday (~> 0.8, < 1.0)
72
+ terminal-table (1.8.0)
73
+ unicode-display_width (~> 1.1, >= 1.1.1)
74
+ thor (0.19.4)
75
+ unicode-display_width (1.3.0)
76
+
77
+ PLATFORMS
78
+ ruby
79
+
80
+ DEPENDENCIES
81
+ bundler (~> 1.15)
82
+ egg!
83
+ pronto (~> 0.9.3)
84
+ pronto-rubocop (~> 0.9.0)
85
+ rake (~> 12.0)
86
+ rspec (~> 3.6, >= 3.6.0)
87
+ rspec_junit_formatter (~> 0.2.3)
88
+
89
+ BUNDLED WITH
90
+ 1.15.1
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright [2017] [Carl Thuringer]
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Egg
2
+
3
+ Egg helps prevent code fires! Also he makes it easy to run complex multi-service apps with Docker.
4
+
5
+ Maintainers:
6
+ * [Carl Thuringer](https://github.com/carlthuringer)
7
+ * [Jason Sisk](https://github.com/sisk)
8
+
9
+ This gem is currently heavily focused on Ruby and Rails projects relevant within
10
+ the Belly organization. The eventual goal is for this to become language and
11
+ framework agnostic, though the configuration language will be Ruby.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'egg'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install egg
28
+
29
+ ## Usage
30
+ * `init` - Initialize a repo for use with Egg. Creates the `egg_config.rb`
31
+ * `readme` - Display the Usage readme
32
+ * `setup` - Generates the docker files from the configuration, runs all setup hooks, then boots the application.
33
+
34
+ ## Development
35
+
36
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
+
38
+ 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).
39
+
40
+ ## Contributing
41
+
42
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bellycard/egg. 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.
43
+
44
+
45
+ ## License
46
+
47
+ The gem is available as open source under the terms of the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0).
48
+
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'egg'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ 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/doc/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # Egg
2
+
3
+ Egg makes it easy to set up a cluster of applications for local development, using the magic of docker.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ egg setup
9
+ ```
10
+ Once finished, the services will be running.
11
+
12
+ ### Stopping, Starting, Updating
13
+
14
+ Most docker compose commands can apply to a single service if you follow the command with the service name (app, db)
15
+
16
+ ```bash
17
+ // Pause processes
18
+ docker-compose pause
19
+ // Unpause processes
20
+ docker-compose unpause
21
+ // Kill processes, but keep the containers intact.
22
+ docker-compose kill
23
+ // Start processes from stopped containers.
24
+ docker-compose start
25
+ // Restart services
26
+ docker-compose restart
27
+ // Rebuild all changed images, and start in the background.
28
+ docker-compose up -d
29
+ // List processes
30
+ docker-compose ps
31
+ // Kill and remove all containers.
32
+ docker-compose down
33
+ ```
34
+
35
+ ### Getting into it
36
+ ```bash
37
+ // Get into a running service
38
+ docker-compose exec [service-name] [command]
39
+ // ex. docker-compose exec app bash
40
+ // >> root@156b321e6ec8:/enterprise-admin#
41
+ ```
42
+
43
+ You can run tests, or anything, while inside the container, or run rake tasks and rspec directly without first launching a bash process.
44
+ ```bash
45
+ docker-compose exec app bin/rake db:migrate
46
+ docker-compose exec app rspec spec/controllers/api/v2/chains_controller_spec.rb
47
+ ```
48
+
49
+ More at [docker compose](https://docs.docker.com/compose/compose-file)
data/exe/leash ADDED
@@ -0,0 +1,6 @@
1
+ #! /usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "egg"
5
+
6
+ Egg::CLI.start(ARGV)
data/leash.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "Egg/version"
6
+
7
+ description = <<-EOT
8
+ Egg helps initialize, manage, and execute on complex multi-service architectures using Docker and Docker Compose
9
+ EOT
10
+
11
+ Gem::Specification.new do |spec|
12
+ spec.name = "egg"
13
+ spec.version = Egg::VERSION
14
+ spec.authors = ["Carl Thuringer", "Jason Sisk"]
15
+ spec.email = ["tech@bellycard.com"]
16
+
17
+ spec.summary = "Egg helps you develop with Docker!"
18
+ spec.description = description
19
+ spec.homepage = "http://github.com/bellycard/egg"
20
+ spec.license = "Apache-2.0"
21
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
22
+
23
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
+ f.match(%r{^(test|spec|features)/})
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_runtime_dependency "thor", "~> 0.19.4"
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.15"
33
+ spec.add_development_dependency "rake", "~> 12.0"
34
+ spec.add_development_dependency "rspec", '~> 3.6', '>= 3.6.0'
35
+ spec.add_development_dependency "rspec_junit_formatter", "~> 0.2.3"
36
+ spec.add_development_dependency "pronto", "~> 0.9.3"
37
+ spec.add_development_dependency "pronto-rubocop", "~> 0.9.0"
38
+ end
data/lib/dockerfile.rb ADDED
@@ -0,0 +1,15 @@
1
+ # Module that wraps configuration of Dockerfiles from Templates.
2
+ module Dockerfile
3
+ class NoDockerfileError < StandardError; end
4
+ class MissingPropertyError < StandardError; end
5
+
6
+ def self.use(klass)
7
+ const_get("Dockerfile::#{klass}").new
8
+ rescue NameError
9
+ raise(NoDockerfileError, "No Dockerfile subclass for #{klass}.")
10
+ end
11
+ end
12
+
13
+ require_relative "dockerfile/base"
14
+ require_relative "dockerfile/ruby"
15
+ require_relative "dockerfile/node_js"
@@ -0,0 +1,39 @@
1
+ module Dockerfile
2
+ # Provides shared behavior for dockerfile template classes.
3
+ class Base
4
+ attr_reader :template
5
+ attr_accessor :command
6
+
7
+ def initialize
8
+ @template = []
9
+ end
10
+
11
+ def required_attributes
12
+ [:command]
13
+ end
14
+
15
+ def render
16
+ required_attributes.each do |attr|
17
+ raise(MissingPropertyError, "Must populate #{attr}") if send(attr).nil?
18
+ end
19
+
20
+ unrendered_output = template.reduce("") do |out, (command, string)|
21
+ out << command.to_s.upcase << " " << string << "\n"
22
+ end
23
+
24
+ ERB.new(unrendered_output).result(binding)
25
+ end
26
+
27
+ def run(command, before: [:cmd])
28
+ template.insert(do_before(before), [:run, command])
29
+ end
30
+
31
+ private
32
+
33
+ def do_before(before)
34
+ template.index(before) ||
35
+ template.index { |tc| tc[0] == before[0] } ||
36
+ -1
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ module Dockerfile
2
+ # Wrapper for templating of NodeJS Dockerfile
3
+ class NodeJS < Base
4
+ def required_attributes
5
+ super + [:node_version]
6
+ end
7
+
8
+ attr_accessor :node_version
9
+
10
+ def initialize
11
+ @template = dockerfile
12
+ end
13
+
14
+ private
15
+
16
+ def dockerfile # rubocop:disable Metrics/MethodLength
17
+ [
18
+ [:from, "node:<%= node_version %>"],
19
+ [:env, "APP_HOME /app"],
20
+ [:run, "mkdir $APP_HOME"],
21
+ [:workdir, "$APP_HOME"],
22
+ [:add, "package.json $APP_HOME/"],
23
+ [:add, "yarn.lock $APP_HOME/"],
24
+ [:run, "yarn install"],
25
+ [:add, ". $APP_HOME"],
26
+ [:cmd, "<%= command %>"]
27
+ ]
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ module Dockerfile
2
+ # Ruby Dockerfile Template
3
+ # Required Attributes:
4
+ # @ruby_version: Version of Ruby to use for the ruby image.
5
+ class Ruby < Base
6
+ def required_attributes
7
+ super + [:ruby_version]
8
+ end
9
+
10
+ attr_accessor :ruby_version
11
+
12
+ def initialize
13
+ @template = dockerfile
14
+ end
15
+
16
+ private
17
+
18
+ def dockerfile # rubocop:disable Metrics/MethodLength
19
+ [
20
+ [:from, "ruby:<%= ruby_version %>"],
21
+ [:run, "apt-get update -qq && apt-get upgrade -qqy"],
22
+ [:run, "apt-get -qqy install cmake"],
23
+ [:run, "gem install bundler"],
24
+ [:env, "APP_HOME /app"],
25
+ [:run, "mkdir $APP_HOME"],
26
+ [:workdir, "$APP_HOME"],
27
+ [:add, ".ruby-version $APP_HOME/"],
28
+ [:add, "Gemfile* $APP_HOME/"],
29
+ [:env, "BUNDLE_GEMFILE=$APP_HOME/Gemfile BUNDLE_JOBS=4 BUNDLE_WITHOUT=production:staging"],
30
+ [:run, "bundle install"],
31
+ [:add, ". $APP_HOME"]
32
+ ]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Provides Generic support for manipulating Dotenv files
4
+ class DotenvUtil
5
+ attr_reader :env_text, :env
6
+ def initialize(env_file)
7
+ @env_text = env_file
8
+ @env = parse_env_file
9
+ end
10
+
11
+ def set(target, value)
12
+ env[target] = value
13
+ end
14
+
15
+ def generate_env
16
+ env.collect do |key, val|
17
+ %(#{key}="#{val}")
18
+ end.join("\n")
19
+ end
20
+
21
+ private
22
+
23
+ def parse_env_file
24
+ env_text.split.each_with_object({}) do |line, hash|
25
+ match = line.match(/^([A-Z_]+)="?(.+)?"?$/)
26
+ next unless match
27
+ hash.store(*match.captures)
28
+ hash
29
+ end
30
+ end
31
+ end
data/lib/egg.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Egg
5
+ def self.root_join(*joins)
6
+ path_parts = [File.dirname(__FILE__)] + joins.map(&:to_s)
7
+ joined_path = File.join(*path_parts)
8
+ File.expand_path(joined_path)
9
+ end
10
+ end
11
+
12
+ require_relative "egg/version"
13
+ require_relative "egg/cli"
14
+ require_relative "egg/templates"
15
+ require_relative "egg/configuration"
16
+ require_relative "egg/docker_compose"
data/lib/egg/cli.rb ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require "fileutils"
5
+
6
+ module Egg
7
+ # Defines the CLI interface to egg functions
8
+ class CLI < Thor
9
+ desc "init", "Initialize the current directory as a egg repo."
10
+ option :force
11
+ def init
12
+ config = Templates["egg_config.rb"]
13
+ if File.exist?("egg_config.rb") && !options[:force]
14
+ print "egg has already been initialized! (maybe you want to --force)\n"
15
+ exit(1)
16
+ else
17
+ File.write("egg_config.rb", config.result)
18
+ print "Wrote example egg_config.rb, customize it to suit your app"
19
+ write_git_ignorance
20
+ end
21
+ end
22
+
23
+ desc "readme", "Display readme for egg apps."
24
+ def readme
25
+ # Print out the readme
26
+ readme_path = File.expand_path("../../../doc/README.md", __FILE__)
27
+ File.open(readme_path, "r") do |f|
28
+ print(f.read)
29
+ end
30
+ end
31
+
32
+ desc "setup", "Run all setup"
33
+ def setup
34
+ config = Configuration.load "./egg_config.rb"
35
+ config.run_setup
36
+ end
37
+
38
+ private
39
+
40
+ def write_git_ignorance
41
+ gitignore = File.read(".gitignore")
42
+ gitignore << "Dockerfile\n" unless /^Dockerfile$/ =~ gitignore
43
+ gitignore << ".dockerignore\n" unless /^\.dockerignore$/ =~ gitignore
44
+ gitignore << "docker-compose.yml\n" unless /^docker-compose\.yml$/ =~ gitignore
45
+ File.write(".gitignore", gitignore)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "fileutils"
5
+ require "dotenv_util"
6
+ require "dockerfile"
7
+ require "open3"
8
+
9
+ module Egg
10
+ # Reads and Processes the egg_config.rb file.
11
+ class Configuration
12
+ # Based on rubygems' specification load:
13
+ # https://github.com/rubygems/rubygems/blob/0749715e4bd9e7f0fb631a352ddc649574da91c1/lib/rubygems/specification.rb#L1146
14
+ def self.load(file)
15
+ code = File.read file
16
+ config = eval code, binding, file # rubocop:disable Security/Eval
17
+
18
+ return config if config.is_a? Egg::Configuration
19
+ rescue SignalException, SystemExit
20
+ raise
21
+ rescue SyntaxError, StandardError => e
22
+ warn "Invalid configuration in [#{file}]: #{e}"
23
+ warn e.backtrace.join("\n")
24
+ end
25
+
26
+ attr_accessor :docker_compose,
27
+ :ssh_support,
28
+ :ruby_version,
29
+ :supervisor,
30
+ :dotenv,
31
+ :dockerfile
32
+
33
+ def initialize(&configuration_block)
34
+ self.docker_compose = DockerCompose.new
35
+ self.ssh_support = false
36
+ self.ruby_version = "2.4"
37
+ self.dotenv = DotenvUtil.new(File.read(".env.template"))
38
+ instance_eval(&configuration_block)
39
+ self
40
+ end
41
+
42
+ def after_startup(&block)
43
+ @after_startup = block
44
+ end
45
+
46
+ # You may pass a block to docker_exec to read the output in a controlled manner.
47
+ def docker_exec(app, command)
48
+ print "docker-compose exec #{app} #{command}\n"
49
+ Open3.popen2(%(docker-compose exec #{app} #{command})) do |_input, output, wait_thread|
50
+ output_read = output.read
51
+ print output_read + "\n"
52
+ yield output_read if block_given?
53
+ wait_thread.value.success? || raise(StandardError, "docker_exec exited with #{wait_thread.value.to_i}")
54
+ end
55
+ end
56
+
57
+ def run_setup
58
+ write_docker_files
59
+
60
+ docker_pull_build
61
+ File.write(".env", dotenv.generate_env)
62
+ system("docker-compose up -d")
63
+
64
+ run_after_startup
65
+ end
66
+
67
+ private
68
+
69
+ def run_after_startup
70
+ return unless @after_startup
71
+ print "Running after-startup block\n"
72
+ @after_startup.call
73
+ end
74
+
75
+ def docker_pull_build
76
+ system("docker-compose pull")
77
+ system("docker-compose build") || raise($CHILD_STATUS)
78
+ end
79
+
80
+ def write_docker_files
81
+ File.write("Dockerfile", dockerfile.render) if dockerfile
82
+
83
+ dockerignore = Templates[".dockerignore"].result(binding)
84
+ File.write(".dockerignore", dockerignore)
85
+
86
+ File.write("docker-compose.yml", docker_compose.to_yaml)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ # Wraps the generation of Docker Compose file
6
+ class DockerCompose
7
+ attr_reader :docker_compose,
8
+ :services
9
+
10
+ def initialize(_compose_config = {})
11
+ @services = []
12
+ end
13
+
14
+ def configure
15
+ yield docker_compose
16
+ end
17
+
18
+ def to_yaml
19
+ output = { "version" => "2" }
20
+ output["services"] = services.each_with_object({}) do |service, hash|
21
+ hash[service.name] = service.to_hash
22
+ end
23
+
24
+ output.to_yaml
25
+ end
26
+
27
+ def service(name)
28
+ service = Service.new(name)
29
+ services << service
30
+ service
31
+ end
32
+ end
33
+
34
+ require_relative "docker_compose/service"
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DockerCompose
4
+ # Wraps the definition of docker-compose services
5
+ class Service
6
+ attr_reader :name, :links, :environment
7
+ attr_accessor :dockerfile,
8
+ :command,
9
+ :ports,
10
+ :volumes,
11
+ :image
12
+
13
+ def initialize(name)
14
+ @name = name
15
+
16
+ @links = []
17
+ @environment = []
18
+ end
19
+
20
+ def link(service)
21
+ @links << service.name
22
+ end
23
+
24
+ def env(variable, value)
25
+ @environment << "#{variable}=#{value}"
26
+ end
27
+
28
+ def to_hash
29
+ output = {
30
+ "environment" => environment,
31
+ "links" => links,
32
+ "volumes" => volumes,
33
+ "ports" => ports
34
+ }
35
+
36
+ image ? output["image"] = image : output["build"] = "."
37
+ output["command"] = command if command
38
+ output.each_with_object({}) { |(k, v), hash| hash[k] = v if v }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+
5
+ module Egg
6
+ # Aids in the loading of template files bundled in the gem.
7
+ class Templates
8
+ class TemplateNotFoundError < StandardError; end
9
+
10
+ def self.[](filename)
11
+ template_path = Egg.root_join("..", "templates", filename)
12
+ raise(TemplateNotFoundError, "No #{filename}") unless File.exist?(template_path)
13
+ ERB.new(File.read(template_path))
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Egg
4
+ VERSION = "0.3.1".freeze
5
+ end
@@ -0,0 +1,7 @@
1
+ .git
2
+ .gitignore
3
+ log
4
+ tmp
5
+ node_modules
6
+ coverage
7
+ public/system
@@ -0,0 +1,10 @@
1
+ version: '2'
2
+
3
+ services:
4
+ app: &app
5
+ build: .
6
+ command: rails s -p 3000
7
+ ports:
8
+ - "3000:3000"
9
+ volumes:
10
+ - .:/app
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ Egg::Configuration.new do |config|
4
+ # Do stuff here.
5
+
6
+ # Example dockerfile config.
7
+ # Available arguments for use: ["Ruby", "NodeJS"]
8
+ # self.dockerfile = Dockerfile.use "Ruby"
9
+ # self.dockerfile.ruby_version = "2.4.0"
10
+ # self.dockerfile.command = "bin/rails server -p 3000"
11
+
12
+ # Example docker_compose config:
13
+ # app = config.docker_compose.service "app"
14
+ # app.ports = ["3000:3000"]
15
+ # app.volumes = [".:/app"]
16
+
17
+ # db = config.docker_compose.service "db"
18
+ # db.image = "mysql"
19
+ # db.env "MYSQL_ROOT_PASSWORD", "mysqliswebscale"
20
+ # app.link db
21
+
22
+ # after_startup do
23
+ # docker_exec "app", "rake db:setup db:seed"
24
+ # dotenv.set("foo", "bar")
25
+ # File.write(".env", dotenv.generate_env)
26
+ # end
27
+ end
@@ -0,0 +1,17 @@
1
+ [supervisord]
2
+ nodaemon=true
3
+ loglevel=debug
4
+ logfile=/var/log/supervisor/supervisord.log
5
+ pidfile=/var/run/supervisord.pid
6
+ childlogdir=/var/log/supervisor
7
+
8
+ [program:sshd]
9
+ command=/usr/sbin/sshd -D
10
+
11
+ [program:app]
12
+ command=/bin/bash -c "rails server -p 3000"
13
+ redirect_stderr=true
14
+
15
+ [program:guard]
16
+ command=/bin/bash -c "guard"
17
+ redirect_stderr=true
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: egg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Carl Thuringer
8
+ - Jason Sisk
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2017-08-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 0.19.4
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 0.19.4
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.15'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.15'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '12.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '12.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.6'
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 3.6.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: '3.6'
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.6.0
76
+ - !ruby/object:Gem::Dependency
77
+ name: rspec_junit_formatter
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.3
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.3
90
+ - !ruby/object:Gem::Dependency
91
+ name: pronto
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.9.3
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.3
104
+ - !ruby/object:Gem::Dependency
105
+ name: pronto-rubocop
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.9.0
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.9.0
118
+ description: " Egg helps initialize, manage, and execute on complex multi-service
119
+ architectures using Docker and Docker Compose\n"
120
+ email:
121
+ - tech@bellycard.com
122
+ executables:
123
+ - leash
124
+ extensions: []
125
+ extra_rdoc_files: []
126
+ files:
127
+ - ".circleci/config.yml"
128
+ - ".gitignore"
129
+ - ".rspec"
130
+ - ".rubocop.yml"
131
+ - ".ruby-version"
132
+ - CODE_OF_CONDUCT.md
133
+ - Gemfile
134
+ - Gemfile.lock
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - bin/console
139
+ - bin/setup
140
+ - doc/README.md
141
+ - exe/leash
142
+ - leash.gemspec
143
+ - lib/dockerfile.rb
144
+ - lib/dockerfile/base.rb
145
+ - lib/dockerfile/node_js.rb
146
+ - lib/dockerfile/ruby.rb
147
+ - lib/dotenv_util.rb
148
+ - lib/egg.rb
149
+ - lib/egg/cli.rb
150
+ - lib/egg/configuration.rb
151
+ - lib/egg/docker_compose.rb
152
+ - lib/egg/docker_compose/service.rb
153
+ - lib/egg/templates.rb
154
+ - lib/egg/version.rb
155
+ - templates/.dockerignore
156
+ - templates/docker-compose.yml
157
+ - templates/smokey_config.rb
158
+ - templates/supervisord.conf
159
+ homepage: http://github.com/bellycard/egg
160
+ licenses:
161
+ - Apache-2.0
162
+ metadata:
163
+ allowed_push_host: https://rubygems.org
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubyforge_project:
180
+ rubygems_version: 2.6.11
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: Egg helps you develop with Docker!
184
+ test_files: []