docker-compose 0.0.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
+ SHA256:
3
+ metadata.gz: bb5c46f2fc1351385671bc66a27b8a5ae3a92769c91c2f5d3470b91f31d38e07
4
+ data.tar.gz: 19800f852de5921b296eda4d9e64a207ce60a6a1fc7959cfaba11965dfb9b823
5
+ SHA512:
6
+ metadata.gz: 2bf97d99fb8c03cbb2dcbd833d743ef508c7474e6833abf415a0d7534199c67d557585a55ad0dd35d58e92747d8bcada2deb4ce036e7ad86cc79929ad9239a11
7
+ data.tar.gz: 67f91befe87b16d4f2305bba853eff604abec12d0c3a5f63e1a38f2517838e47a2f1b2db49937630876c6acace00f9abd2f176a17974835eef45465e590217c8
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ repo_token: hMWX6XPNvG4Gfy9gCDEvrxhQVKdyN5e2m
@@ -0,0 +1,42 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ branches: [actions]
6
+
7
+ jobs:
8
+ publish:
9
+ name: publish
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ packages: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v3
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: 3.0.0
20
+ bundler-cache: true
21
+ - name: build
22
+ run: |
23
+ release='v0.0.0'
24
+ version=`echo $release | cut -b2-`
25
+ if ! echo $release | grep -q '^v[0-9]\+\.[0-9]\+\.[0-9]\+$'; then
26
+ echo "Release name must be in the format of 'vX.Y.Z', got '$release'"
27
+ exit 1
28
+ fi
29
+ sed -i -r "s/VERSION = '.+'/VERSION = '$version'/" lib/docker/compose/version.rb
30
+ bundle exec rake build
31
+ - name: push
32
+ run: |
33
+ mkdir -p $HOME/.gem
34
+ touch $HOME/.gem/credentials
35
+ chmod 0600 $HOME/.gem/credentials
36
+ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_TOKEN}\n:github: Bearer ${GITHUB_TOKEN}\n" > $HOME/.gem/credentials
37
+ gem push pkg/*.gem
38
+ gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} pkg/*.gem
39
+ env:
40
+ GITHUB_TOKEN: "Bearer ${{ secrets.GITHUB_TOKEN }}"
41
+ OWNER: ${{ github.repository_owner }}
42
+ RUBYGEMS_TOKEN: "${{ secrets.RUBYGEMS_TOKEN }}"
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea
11
+
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,38 @@
1
+ # CODING CONVENTIONS
2
+ # - any cop that can be auto-corrected with `rubocop -a` is mandatory
3
+ # - other cops may be enabled if committer fixes all issues
4
+ AllCops:
5
+ NewCops: enable
6
+ Exclude:
7
+ - features/**/*
8
+ - spec/**/*
9
+ Style/Encoding:
10
+ Enabled: true
11
+ Style/FormatString:
12
+ Enabled: false
13
+ Style/GuardClause:
14
+ Enabled: false
15
+ Layout/LineLength:
16
+ Enabled: false
17
+ Lint/AmbiguousRegexpLiteral:
18
+ Enabled: false
19
+ Metrics/AbcSize:
20
+ Enabled: false
21
+ Metrics/BlockLength:
22
+ Enabled: false
23
+ Metrics/ClassLength:
24
+ Enabled: false
25
+ Metrics/MethodLength:
26
+ Enabled: false
27
+ Metrics/CyclomaticComplexity:
28
+ Enabled: false
29
+ Metrics/PerceivedComplexity:
30
+ Enabled: false
31
+ Style/ClassAndModuleChildren:
32
+ Enabled: false
33
+ Style/Documentation:
34
+ Enabled: false
35
+ Style/RaiseArgs:
36
+ Enabled: false
37
+ Style/Semicolon:
38
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.0
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.3.1
6
+ - 2.7.1
7
+ - 3.0.0
8
+ before_install: gem install bundler -v 1.10.6
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ 1.1
2
+ ---
3
+
4
+ #### New features
5
+
6
+ Add `scale` command to Session methods.
7
+
8
+
9
+ 1.0
10
+ ---
11
+
12
+ No significant changes; the 1.0 increment is to indicate that Docker::Compose now has test coverage, and that we intend to maintain a stable API until 2.0.
13
+
14
+ 0.6
15
+ ---
16
+
17
+ #### Interface-breaking changes
18
+
19
+ - Replaced `docker:compose:server` Rake task with more general `docker:compose:host`
20
+ - Replaced `server_env` option with `host_env`
21
+ - Replaced `extra_server_env` option with `extra_host_env`
22
+ - Stopped mapping values in `extra_host_env`; they are now exported verbatim
23
+
24
+ #### New features
25
+
26
+ Produce `docker:compose:env` output that is compatible with user's login shell.
27
+
28
+ 0.5
29
+ ---
30
+
31
+ Initial public release of prototype. Features work well, but there is no test
32
+ coverage.
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in docker-compose.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'pry'
8
+ gem 'pry-byebug'
9
+ gem 'rubocop'
10
+ gem 'rubocop-rake'
11
+ gem 'rubocop-rspec'
12
+ end
13
+
14
+ group :test do
15
+ gem 'coveralls', require: false
16
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Tony Spataro
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,170 @@
1
+ [![Build Status](https://travis-ci.org/xeger/docker-compose.svg)](https://travis-ci.org/xeger/docker-compose) [![Coverage Status](https://coveralls.io/repos/github/xeger/docker-compose/badge.svg?branch=coveralls)](https://coveralls.io/github/xeger/docker-compose?branch=coveralls) [![Docs](https://img.shields.io/badge/docs-rubydoc-blue.svg)](http://www.rubydoc.info/gems/docker-compose)
2
+
3
+ # Docker::Compose
4
+
5
+ This is a Ruby OOP wrapper for the [docker-compose](https://github.com/docker/compose)
6
+ container orchestration tool from Docker Inc.
7
+
8
+ In addition to wrapping the CLI, this gem provides an environment-variable mapping
9
+ feature that allows you to export environment variables into your _host_ that point
10
+ to network services exposed by containers. This allows you to run an application on
11
+ your host for quicker and easier development, but run all of its dependencies --
12
+ database, cache, adjacent services -- in containers. The dependencies can even run
13
+ on another machine, e.g. a cloud instance or a container cluster, provided your
14
+ development machine has TCP connectivity to every port exposed by a container.
15
+
16
+ Throughout this documentation we will refer to this gem as `Docker::Compose`
17
+ as opposed to the `docker-compose` tool that this gem wraps.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'docker-compose'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ Or install it yourself as:
32
+
33
+ $ gem install docker-compose
34
+
35
+ ## Usage
36
+
37
+ ### Invoking from Ruby code
38
+
39
+ ```ruby
40
+ require 'docker/compose'
41
+
42
+ # Create a new session in Dir.pwd using the file "docker-compose.yml".
43
+ # For fine-grained control over options, see Docker::Compose::Session#new
44
+ compose = Docker::Compose.new
45
+
46
+ compose.version
47
+
48
+ compose.up(detached:true)
49
+
50
+ exited = compose.ps.where { |c| !c.up? }
51
+ puts "We have some exited containers: " + exited.join(', ')
52
+
53
+ sum = compose.ps.inject(0) { |a,c| a + c.size }
54
+ puts format("Composition is using %.1f MiB disk space", sum/1024.0**2)
55
+ ```
56
+
57
+ ### Invoking from Rake
58
+
59
+ Open your Rakefile and add the Docker::Compose tasks.
60
+
61
+ ```ruby
62
+ require 'docker/compose/rake_tasks'
63
+
64
+ Docker::Compose::RakeTasks.new do |tasks|
65
+ # customize by calling setter methods of tasks;
66
+ # see the class documentation for details
67
+ end
68
+
69
+ ```
70
+
71
+ Notice that `rake -T` now has a few additional tasks for invoking gem
72
+ functionality. You can `docker:compose:env` to print shell exports for
73
+ host-to-container environment mapping, or you can `docker:compose:host[foo]`.
74
+
75
+ ### Hosting a Command
76
+
77
+ To run a process on your host and allow it to talk to containers, use
78
+ the `docker:compose:host` task. For example, I could enter a shell
79
+ with `rake docker:compose:host[bash]`.
80
+
81
+ Before "hosting" your command, the Rake task exports some environment
82
+ variables that your command can use to discover services running in
83
+ containers. Your Rakefile specifies which variables your app needs
84
+ (the `host_env` option) and which container information each variable should
85
+ map to.
86
+
87
+ By hosting commands, you benefit from easier debugging and code editing of
88
+ the app you're working on, but still get to rely on containers to provide
89
+ the companion services your app requires to run.
90
+
91
+ ### Mapping container IPs and ports
92
+
93
+ As a trivial example, let's say that your `docker-compose.yml` contains one
94
+ service, the database that your app needs in order to run.
95
+
96
+ ```yaml
97
+ db:
98
+ image: mysql:latest
99
+ environment:
100
+ MYSQL_DATABASE: myapp_development
101
+ MYSQL_ROOT_PASSWORD: opensesame
102
+ ports:
103
+ - "3306"
104
+
105
+ ```
106
+
107
+ Your app needs two inputs, `DATABASE_HOST` and `DATABASE_PORT`. You can specify
108
+ this with the host_env option of the Rake task:
109
+
110
+ ```ruby
111
+ Docker::Compose::RakeTasks.new do |tasks|
112
+ tasks.host_env = {
113
+ 'DATABASE_HOST' => 'db:[3306]',
114
+ 'DATABASE_PORT' => '[db]:3306',
115
+ }
116
+ end
117
+ ```
118
+
119
+ Now, I can run my services, ask Docker::Compose to map the environment values
120
+ to the actual IP and port that `db` has been published to, and run my app:
121
+
122
+ ```bash
123
+ # First, bring up the containers we will be interested in
124
+ user@machine$ docker-compose up -d
125
+
126
+ # The rake task prints bash code resembling the following:
127
+ # export DATABASE_HOST='127.0.0.1'
128
+ # export DATABASE_PORT='34387'
129
+ # We eval it, which makes the variables available to our shell and to all
130
+ # subprocesses.
131
+ user@machine$ eval "$(bundle exec rake docker:compose:env)"
132
+
133
+ user@machine$ bundle exec rackup
134
+ ```
135
+
136
+ The `host_env` option also handles substitution of URLs, and arrays of values
137
+ (which are serialized back to the environment as JSON)
138
+ For example:
139
+
140
+ ```ruby
141
+ tasks.host_env = {
142
+ 'DATABASE_URL' => 'mysql://db:3306/myapp_development',
143
+ 'MIXED_FRUIT' => ['db:[3306]', '[db]:3306']
144
+ }
145
+ ```
146
+
147
+ This would result in the following exports:
148
+
149
+ ```bash
150
+ export DATABASE_URL='mysql://127.0.0.1:34387/myapp_development'
151
+ export MIXED_FRUIT='["127.0.0.1", "34387"]'
152
+ ```
153
+
154
+ To learn more about mapping, read the class documentation for
155
+ `Docker::Compose::Mapper`.
156
+
157
+ ## Development
158
+
159
+ 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.
160
+
161
+ 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).
162
+
163
+ ## Contributing
164
+
165
+ Bug reports and pull requests are welcome on GitHub at https://github.com/xeger/docker-compose. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
166
+
167
+
168
+ ## License
169
+
170
+ 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,7 @@
1
+ # encoding: utf-8
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,18 @@
1
+ #! /usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'bundler/setup'
5
+ require 'docker/compose'
6
+
7
+ @session = Docker::Compose::Session.new
8
+
9
+ begin
10
+ require 'pry'
11
+ Pry.start(@session)
12
+ rescue LoadError
13
+ require 'irb'
14
+ IRB.setup nil
15
+ IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new.context
16
+ require 'irb/ext/multi-irb'
17
+ IRB.irb nil, @session
18
+ end
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'docker/compose/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'docker-compose'
8
+ spec.version = Docker::Compose::VERSION
9
+ spec.authors = ['Tony Spataro']
10
+ spec.email = ['xeger@xeger.net']
11
+
12
+ spec.summary = 'Wrapper docker-compose with added Rake smarts.'
13
+ spec.description = 'Provides an OOP interface to docker-compose and facilitates container-to-host and host-to-container networking.'
14
+ spec.homepage = 'https://github.com/xeger/docker-compose'
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.required_ruby_version = Gem::Requirement.new('>= 2.0', '< 4.0')
23
+
24
+ spec.add_dependency 'backticks', '~> 1.0'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 2.3'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec'
29
+ end
@@ -0,0 +1,11 @@
1
+ # basic smoke test for the gem.
2
+ # TODO: write cucumber features for comprehensive functional tests!
3
+ apple:
4
+ image: busybox
5
+ command: /bin/sh -c 'sleep 3600'
6
+ ports:
7
+ - 123
8
+ - 456
9
+ orange:
10
+ image: busybox
11
+ command: /bin/sh -c 'sleep 3600'
@@ -0,0 +1,13 @@
1
+ module Docker::Compose
2
+ class Collection < Array
3
+ # @example find containers that are up
4
+ # who_is_up = coll.where { |c| c.up? }
5
+ # @example count space taken by all containers
6
+ # coll.map { |c| c.size }.inject(0) { |a, x| a + x }
7
+ def where
8
+ hits = Collection.new
9
+ self.each { |c| hits << c if yield(c) }
10
+ hits
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,80 @@
1
+ module Docker::Compose
2
+ class Container
3
+ # Format string for `docker ps`
4
+ PS_FMT = '({{.ID}}) ({{.Image}}) ({{.Size}}) ({{.Status}}) ({{.Names}}) ({{.Labels}}) ({{.Ports}})'
5
+ # Number of template substitutions in PS_FMT
6
+ PS_FMT_LEN = PS_FMT.count('.')
7
+ # Pattern that parses human-readable values from ps .Status
8
+ PS_STATUS = /^([A-Za-z]+) ?\(?([0-9]*)\)? ?(.*)$/i
9
+ # Pattern that parses FIRST occurrence of container size from a string,
10
+ # along with its units.
11
+ PS_SIZE = /^([0-9.]+)\s*([kmgt]?B)/i
12
+
13
+ attr_reader :id, :image, :size, :status, :exitstatus
14
+ attr_reader :names, :labels, :ports
15
+
16
+ # @param [String] id
17
+ # @param [String] image
18
+ # @param [String,Integer] size e.g. "0B (virtual 100MB)"
19
+ # @param [String,#map] status e.g. ['Exited', '0', '3 minutes ago']
20
+ # @param [String,Array] names list of container names (CSV)
21
+ # @param [String,Array] labels list of container labels (CSV)
22
+ # @param [String,Array] ports list of exposed ports (CSV)
23
+ def initialize(id, image, size, status, names, labels, ports)
24
+ if size.is_a?(String) && (m = PS_SIZE.match(size))
25
+ scalar, units = m[1], m[2]
26
+ scalar = scalar.to_f # lazy: invalid --> 0.0
27
+ mult = case units.downcase
28
+ when 'b' then 1
29
+ when 'kb' then 1_024
30
+ when 'mb' then 1_024**2
31
+ when 'gb' then 1_024**3
32
+ when 'tb' then 1_024**4
33
+ else
34
+ raise Error.new('Service#new', units, 'Impossibly large unit')
35
+ end
36
+ size = scalar * mult
37
+ end
38
+
39
+ if status.is_a?(String)
40
+ status = PS_STATUS.match(status)
41
+ raise Error.new('Service#new', status, 'Unrecognized status') unless status
42
+ end
43
+
44
+ names = names.split(',').map{ |x| x.strip } if names.is_a?(String)
45
+ labels = labels.split(',').map{ |x| x.strip } if labels.is_a?(String)
46
+ ports = ports.split(',').map{ |x| x.strip } if ports.is_a?(String)
47
+
48
+ @id = id
49
+ @image = image
50
+ @size = size
51
+ @status = status[1].downcase.to_sym
52
+
53
+ @exitstatus = case @status
54
+ when :up
55
+ nil
56
+ else
57
+ status[2].to_i
58
+ end
59
+
60
+ @names = names
61
+ @labels = labels
62
+ @ports = ports
63
+ end
64
+
65
+ # static sanity checking ftw!
66
+ unless ( initarity = instance_method(:initialize).arity ) == PS_FMT_LEN
67
+ raise LoadError.new("#{__FILE__}:#{__LINE__} - arity(\#initialize) != PS_FMT_LEN; #{initarity} != #{PS_FMT_LEN}")
68
+ end
69
+
70
+ # @return [String]
71
+ def name
72
+ names.first
73
+ end
74
+
75
+ # @return [Boolean]
76
+ def up?
77
+ self.status == :up
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ module Docker::Compose
3
+ class Error < RuntimeError
4
+ attr_reader :status, :detail
5
+
6
+ # @param [String] cmd
7
+ # @param [Integer] status
8
+ # @param [String] detail
9
+ def initialize(cmd, status, detail)
10
+ @status = status
11
+ @detail = detail
12
+
13
+ brief = detail.split(/[\r\n]+/).select { |l| !l.empty? }.first || '(no output)'
14
+
15
+ case status
16
+ when Numeric
17
+ status = status.to_s
18
+ else
19
+ status = "'#{status}'"
20
+ end
21
+
22
+ message = format("'%s' failed with status %s: %s", cmd, status, brief)
23
+ super(message)
24
+ end
25
+ end
26
+ end