dockit 1.0.0
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 +7 -0
- data/.gitignore +9 -0
- data/Dockerfile +17 -0
- data/Gemfile +4 -0
- data/README.md +124 -0
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/bin/console +10 -0
- data/bin/dockit +8 -0
- data/bin/setup +7 -0
- data/dockit.gemspec +32 -0
- data/lib/dockit.rb +84 -0
- data/lib/dockit/cli.rb +249 -0
- data/lib/dockit/config.rb +63 -0
- data/lib/dockit/container.rb +81 -0
- data/lib/dockit/digitalocean.rb +148 -0
- data/lib/dockit/image.rb +47 -0
- data/lib/dockit/service.rb +90 -0
- data/spec/deploy/Dockit.rb +7 -0
- data/spec/deploy/mod/Dockit.rb +6 -0
- data/spec/deploy/mod/Dockit.yaml +0 -0
- data/spec/deploy/svc/Dockit.yaml +2 -0
- data/spec/dockit/bad.yaml +2 -0
- data/spec/dockit/config_spec.rb +52 -0
- data/spec/dockit/locals.yaml +3 -0
- data/spec/dockit/simple.yaml +2 -0
- data/spec/dockit_spec.rb +80 -0
- data/spec/spec_helper.rb +8 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e774509e3e1c4afab5a44bce1fc3eee91d7d25cf
|
4
|
+
data.tar.gz: daeda4ab4b09f3f9bc7b706fefb77271930ab4fb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d80feb61549460b39bdaa99adc5617ba09bbd75aed6e9bbe63cd20b682215d178a792682a2d202638030251595dbaf5152405b11469523b1db6f0ab3df6e7e2
|
7
|
+
data.tar.gz: 0867cb20ca447aec30f45524d2af9962c8639021a1282e45b7ac94bbc5ed4f1f3fd915aded2498ae38849f96c330e7049fb95066124f98c96c9d3a2503d663cf
|
data/.gitignore
ADDED
data/Dockerfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
FROM cybercode/alpine-ruby:2.2
|
2
|
+
ENV DOCKER_VERSION=1.8.2 BIN=/usr/local/bin/docker
|
3
|
+
|
4
|
+
RUN apk add -u curl ruby-json && curl -sSL -o $BIN \
|
5
|
+
https://get.docker.com/builds/Linux/x86_64/docker-$DOCKER_VERSION \
|
6
|
+
&& chmod +x $BIN && apk del curl
|
7
|
+
|
8
|
+
WORKDIR /app
|
9
|
+
COPY . .
|
10
|
+
RUN apk --update add --virtual build_deps \
|
11
|
+
build-base ruby-dev libc-dev linux-headers git \
|
12
|
+
&& gem build dockit.gemspec \
|
13
|
+
&& gem install --no-rdoc --no-ri dockit*.gem \
|
14
|
+
&& apk del build_deps && rm -rf /app
|
15
|
+
|
16
|
+
WORKDIR /
|
17
|
+
ENTRYPOINT ["dockit"]
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
[docker-api]: https://github.com/swipely/docker-api
|
2
|
+
|
3
|
+
# Dockit
|
4
|
+
|
5
|
+
`Dockit` is an alternative composer for docker projects. Its (IMHO) advantage is that it is scriptable, and rather than a single yaml configuration file, each service has it's own configuration file (`Dockit.yaml`), as well as an optional `Dockit.rb` which can provide scriptable configuration (as `Thor` subcommands) for any phase of the build and deploy process.
|
6
|
+
|
7
|
+
`Dockit` is built on the [Thor](https://github.com/erikhuda/thor) cli and the [docker-api] libraries.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
```sh
|
12
|
+
$ gem install dockit
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
1. Create a top level deployment directory
|
18
|
+
2. Create a sub-directory for each service
|
19
|
+
3. Create a `Dockit.yaml` for each service (and optionally a `Docit.rb`.)
|
20
|
+
4. Optionally, create a top level `Dockit.rb` subcommand file to orchestrate the build and deployment of the services.
|
21
|
+
5. Run `dockit` in the root directory for help.
|
22
|
+
|
23
|
+
## `Dockit.yaml`
|
24
|
+
|
25
|
+
The sections of the config file map directly to the argument sent by the
|
26
|
+
[docker-api] to the corresponding api endpoints (see [docker api](http://docs.docker.com/reference/api/docker_remote_api_v1.9/).)
|
27
|
+
|
28
|
+
The top level sections are:
|
29
|
+
|
30
|
+
- `build`
|
31
|
+
- `create`
|
32
|
+
- `run`
|
33
|
+
|
34
|
+
At least one of the sections `build` or `create` are required. If their is no `build` section, the `create` section must specify an `Image` value. Note that most (all?) of the values specified in the `run` section can be specified in the `create: HostConfig:` instead.
|
35
|
+
|
36
|
+
### Examples
|
37
|
+
|
38
|
+
#### Simple build
|
39
|
+
|
40
|
+
```yaml
|
41
|
+
build:
|
42
|
+
t: my-image
|
43
|
+
```
|
44
|
+
|
45
|
+
Executing `dockit build` in the directory containing the file above, will create an image from the `Dockerfile` in the same directory named my-image.
|
46
|
+
|
47
|
+
Then executing `dockit start` will create and run a container named `my-image`
|
48
|
+
|
49
|
+
[docker hub]: https://registry.hub.docker.com/search?q=library
|
50
|
+
|
51
|
+
#### Pre-generated (or [docker hub]) image
|
52
|
+
```yaml
|
53
|
+
create:
|
54
|
+
Image: postgres
|
55
|
+
name: db
|
56
|
+
```
|
57
|
+
|
58
|
+
Executing `dockit build` will do nothing. Executing `dockit start` will start run a container named `db` from the local (or [docker hub] postgresql image.
|
59
|
+
|
60
|
+
#### Using locals and environment variables
|
61
|
+
|
62
|
+
The yaml file is first processed by the `ERB` template library. The "bindings" passed to the template processor can be specified on the command line with the `--locals` (alias `-l`) option. Also, the command line option `--env` (alias `-e`) is passed as `-<env>` For example, given:
|
63
|
+
|
64
|
+
```yaml
|
65
|
+
create:
|
66
|
+
Image: postgres
|
67
|
+
name: db<%= env %>
|
68
|
+
Env:
|
69
|
+
- MYVAR=<%= myval %>
|
70
|
+
```
|
71
|
+
|
72
|
+
- `dockit start` will generate an error (myval not defined)
|
73
|
+
- `dockit start -l myval:foo` will start a container named `db` with the environment variable `MVAR` set to `foo`.
|
74
|
+
- `dockt start -l myval:foo -e test` will start a container named `db-test`
|
75
|
+
|
76
|
+
## `Dockit.rb`
|
77
|
+
|
78
|
+
The `dockit.rb` file can be used to add new subcommands to the cli on a project-wide or per-service basis. For per-service subcommands, the defined class name should be the "classified" directory name, for the project-wide, it should be named `All`. If the class inherits from `SubCommand` instead of `Thor`, it will inherit two useful methods:
|
79
|
+
|
80
|
+
- `invoke_default(service)` will run the same-named (or specified) dockit command on the specified service.
|
81
|
+
- `invoke_service(service)` will run the same-named (or specifed) subcommand from the `Dockit.rb` for the specified service.
|
82
|
+
- `invoke_git(service, gem=false)` will run the same-name (or specifed) subcommand from the `Dockit.rb` for the specified service after checking out the git repository for the service as a gzip archive to `repos.tar.tz`. By default it used the `master` branch. If `gem` is true, it will checkout the gemfiles as a separate archive (`gemfiles.tar.gz`). Note that the `repos` key must be set in the services yaml file.
|
83
|
+
|
84
|
+
For example:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class All < SubCommand
|
88
|
+
desc 'build', 'build all images'
|
89
|
+
def build
|
90
|
+
invoke_service 'app'
|
91
|
+
invoke_default 'db'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
Would run the `build` method from the file `app/Dockit.rb` and then create a second image using the options from `db/Dockit.yaml`.
|
97
|
+
|
98
|
+
## DigitalOcean integration
|
99
|
+
|
100
|
+
If the `droplet_kit` gem is found at runtime, the `do` service be implemented. see `dockit help do` for available commands.
|
101
|
+
|
102
|
+
## Running as a docker image
|
103
|
+
|
104
|
+
If you don't want to install ruby, etc., the docker image is also available rom docker hub as `cybercode/dockit`. You can create your own version of the docker image from the source code with `docker build -t dockit .` (or `rake docker`). The `Dockerfile` has `dockit` as the entrypoint, so you can pass dockit arguments on the command-line. e.g.:
|
105
|
+
|
106
|
+
```sh
|
107
|
+
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/app dockit help
|
108
|
+
```
|
109
|
+
|
110
|
+
## The Github boilerplate
|
111
|
+
|
112
|
+
### Development
|
113
|
+
|
114
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
115
|
+
|
116
|
+
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` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
117
|
+
|
118
|
+
### Contributing
|
119
|
+
|
120
|
+
1. Fork it ( https://github.com/cybercode/dockit/fork )
|
121
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
122
|
+
3. Commit your changes (`git commit -am [comment]`)
|
123
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
124
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rake/version_task'
|
4
|
+
require 'rdoc/task'
|
5
|
+
|
6
|
+
Rake::VersionTask.new
|
7
|
+
|
8
|
+
desc 'Run all specs'
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
|
11
|
+
task default: :spec
|
12
|
+
task test: :spec
|
13
|
+
|
14
|
+
Rake::RDocTask.new do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'doc'
|
16
|
+
rdoc.main = 'README'
|
17
|
+
rdoc.title = " dockit #{Version.current}"
|
18
|
+
rdoc.rdoc_files.include('README*')
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Generate Documentation"
|
23
|
+
task doc: :rdoc
|
24
|
+
|
25
|
+
desc "Build docker image"
|
26
|
+
task :docker do
|
27
|
+
system 'docker build -t dockit .'
|
28
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/bin/console
ADDED
data/bin/dockit
ADDED
data/bin/setup
ADDED
data/dockit.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dockit"
|
7
|
+
s.version = File.read("VERSION").chomp # file managed by version gem...
|
8
|
+
s.authors = ["Rick Frankel"]
|
9
|
+
s.email = ["dockitk@rickster.com"]
|
10
|
+
|
11
|
+
s.summary = %q{A configuration manager and builder for docker projects.}
|
12
|
+
s.description = %q{Dockit is a builder for complex docker projects. Think scriptable docker-composer.}
|
13
|
+
s.homepage = "https://github.com/cybercode/dockit"
|
14
|
+
s.licenses = ["MIT"]
|
15
|
+
|
16
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
s.test_files = `git ls-files -z -- spec/*`.split("\x0")
|
18
|
+
s.bindir = "bin"
|
19
|
+
s.executables = %w[dockit]
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency "bundler" , "~> 1.9"
|
23
|
+
s.add_development_dependency "rake" , "~> 10.4"
|
24
|
+
s.add_development_dependency "rspec" , "~> 3.2"
|
25
|
+
s.add_development_dependency "simplecov" , "~> 0.10"
|
26
|
+
s.add_development_dependency "pry" , "~> 0.10"
|
27
|
+
|
28
|
+
s.add_dependency "thor", "~> 0.19"
|
29
|
+
s.add_dependency "dotenv", "~> 2.0"
|
30
|
+
s.add_dependency "docker-api", "~> 1.21"
|
31
|
+
s.add_dependency "version", "~> 1.0"
|
32
|
+
end
|
data/lib/dockit.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'docker'
|
2
|
+
require 'yaml'
|
3
|
+
require 'pathname'
|
4
|
+
require 'version'
|
5
|
+
|
6
|
+
require 'dockit/config'
|
7
|
+
require 'dockit/service'
|
8
|
+
require 'dockit/image'
|
9
|
+
require 'dockit/container'
|
10
|
+
|
11
|
+
module Dockit
|
12
|
+
is_versioned
|
13
|
+
|
14
|
+
class Log
|
15
|
+
def debug(msg)
|
16
|
+
$stderr.puts "DEBUG: " + msg.join(' ')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# This class encapsulates the environment used in the Dockit cli.
|
21
|
+
# The class has three main attributes:
|
22
|
+
#
|
23
|
+
# root ::
|
24
|
+
# The (cached) root of the project.
|
25
|
+
# modules ::
|
26
|
+
# The "modules", a map of +Dockit.rb+ files by directory name
|
27
|
+
# services ::
|
28
|
+
# The "services", a map of +Dockit.yaml+ files, by directory name
|
29
|
+
class Env
|
30
|
+
BASENAME = 'Dockit'.freeze
|
31
|
+
attr_reader :services
|
32
|
+
attr_reader :modules
|
33
|
+
|
34
|
+
##
|
35
|
+
# Initialize services and modules in the project.
|
36
|
+
# depth [Integer] :: How deep to recurse looking for modules/services
|
37
|
+
# debug [Boolean] :: Log +docker-api+ calls.
|
38
|
+
def initialize(depth: 2, debug: false)
|
39
|
+
@root = nil
|
40
|
+
@modules = find_subcommands(depth)
|
41
|
+
@services = find_services(depth)
|
42
|
+
|
43
|
+
Docker.logger = Dockit::Log.new if debug
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# The (cached) root of the project
|
48
|
+
# Returns [String] :: The absolute path of the project root.
|
49
|
+
def root
|
50
|
+
return @root if @root
|
51
|
+
@root = dir = Dir.pwd
|
52
|
+
begin
|
53
|
+
dir = File.dirname(dir)
|
54
|
+
return @root = dir if File.exist?(File.join(dir, "#{BASENAME}.rb"))
|
55
|
+
end while dir != '/'
|
56
|
+
|
57
|
+
@root
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def find_services(depth)
|
62
|
+
find_relative(depth, 'yaml')
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_subcommands(depth)
|
66
|
+
find_relative(depth, 'rb')
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_relative(depth, ext)
|
70
|
+
result = {}
|
71
|
+
(0..depth).each do |i|
|
72
|
+
pat = File.join(root, ['*'] * i, "#{BASENAME}.#{ext}")
|
73
|
+
Pathname.glob(pat).inject(result) do |memo, path|
|
74
|
+
name = path.dirname.relative_path_from(Pathname.new(root)).to_s
|
75
|
+
name = 'all' if name == '.'
|
76
|
+
memo[name] = path.to_s
|
77
|
+
|
78
|
+
memo
|
79
|
+
end
|
80
|
+
end
|
81
|
+
result
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/dockit/cli.rb
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
require 'thor'
|
3
|
+
require 'dockit'
|
4
|
+
|
5
|
+
class SubCommand < Thor
|
6
|
+
no_commands do
|
7
|
+
# invoke command against the Dockit.yaml for the given service.
|
8
|
+
def invoke_default(service=nil, cmd: nil, opts: {})
|
9
|
+
service ||= self.class.to_s.downcase
|
10
|
+
cmd ||= current_command_chain[-1]
|
11
|
+
cmd = "default:#{cmd}"
|
12
|
+
invoke cmd, [service], options.merge(opts)
|
13
|
+
instance_variable_get('@_invocations')[Default].slice!(-1)
|
14
|
+
end
|
15
|
+
|
16
|
+
# invoke the method in the Dockit.rb for the given service.
|
17
|
+
def invoke_service(service, cmd: nil, opts: {})
|
18
|
+
cmd ||= current_command_chain[-1]
|
19
|
+
cmd = "#{service}:#{cmd}"
|
20
|
+
|
21
|
+
say "Invoking #{cmd}"
|
22
|
+
invoke cmd, [], options.merge(opts)
|
23
|
+
instance_variable_get('@_invocations')[Default].slice!(-1)
|
24
|
+
end
|
25
|
+
|
26
|
+
# export git repository before running default command
|
27
|
+
def invoke_git(service, gem=false)
|
28
|
+
invoke_default service, cmd: 'git-build', opts: { gem: gem || options.gem }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Default < Thor
|
34
|
+
DOCKIT_FILE = './Dockit.yaml'.freeze
|
35
|
+
@@root_echoed = false
|
36
|
+
|
37
|
+
class_option :host, type: :string, desc: 'override DOCKER_HOST env variable',
|
38
|
+
default: ENV['DOCKER_HOST'], aliases: ['H']
|
39
|
+
class_option :debug, type: :boolean, desc: "Log docker-api calls"
|
40
|
+
class_option :verbose, type: :boolean, aliases: ['v']
|
41
|
+
class_option :env, type: :string, desc: 'e.g., "test", "staging"', aliases: ['e']
|
42
|
+
class_option :locals, type: :hash, aliases: ['l'],
|
43
|
+
banner: "key:value [key:value ...]",
|
44
|
+
desc: "variables to pass to yaml file."
|
45
|
+
|
46
|
+
def initialize(*args)
|
47
|
+
super
|
48
|
+
ENV['DOCKER_HOST'] = options.host
|
49
|
+
unless @@root_echoed
|
50
|
+
puts "Project root: #{dockit.root}"
|
51
|
+
@@root_echoed=true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
no_commands do
|
56
|
+
def _list(what)
|
57
|
+
puts what.to_s.capitalize, dockit.send(what).keys.collect {|s| " #{s}"}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def help(*args)
|
62
|
+
super
|
63
|
+
if args.count < 1
|
64
|
+
say "Run 'dockit list' to see the complete list of SERVICEs."
|
65
|
+
say "Run 'dockit help COMMAND' to see command specific options."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "version", "Print version"
|
70
|
+
def version
|
71
|
+
say "Dockit version #{Dockit::VERSION}"
|
72
|
+
end
|
73
|
+
map %w[--version -V] => :version
|
74
|
+
|
75
|
+
desc "list", "List available services"
|
76
|
+
def list
|
77
|
+
_list :modules
|
78
|
+
_list :services
|
79
|
+
end
|
80
|
+
|
81
|
+
# "run" is a reserved word in thor...
|
82
|
+
desc 'start [SERVICE] [CMD]', 'run a service, optionally override "Cmd"'
|
83
|
+
option :transient, type: :boolean, desc: 'remove container after run'
|
84
|
+
def start(service=nil, *cmd)
|
85
|
+
opts = cmd.length > 0 ? options.merge(create: {Cmd: cmd}) : options
|
86
|
+
exec(service) do |s|
|
87
|
+
s.start(opts)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
desc 'sh [SERVICE] [CMD]', 'run an interactive command (default "bash -l")'
|
92
|
+
def sh(service=nil, *cmd)
|
93
|
+
exec(service) do |s|
|
94
|
+
cmd = %w[bash -l] if cmd.length < 1
|
95
|
+
|
96
|
+
# in case image has an entrypoint, use the cmd as the entrypoint
|
97
|
+
(entrypoint, *cmd) = cmd
|
98
|
+
s.start(
|
99
|
+
transient: true,
|
100
|
+
verbose: options.verbose,
|
101
|
+
create: {
|
102
|
+
Entrypoint: [entrypoint],
|
103
|
+
Cmd: cmd,
|
104
|
+
name: 'sh',
|
105
|
+
Tty: true,
|
106
|
+
AttachStdin: true,
|
107
|
+
AttachStdout: true,
|
108
|
+
AttachStderr: true,
|
109
|
+
OpenStdin: true,
|
110
|
+
StdinOnce: true,
|
111
|
+
})
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "cleanup", "Remove unused containers and images"
|
116
|
+
option :images , type: :boolean, default: true, desc: "remove danging images"
|
117
|
+
option :containers , type: :boolean, default: true, desc: "remove exited containers"
|
118
|
+
option :force, type: :boolean, default: false, desc: "stop and remove all"
|
119
|
+
def cleanup
|
120
|
+
if options[:containers]
|
121
|
+
Dockit::Container.clean(force: options[:force]) if ask_force('containers')
|
122
|
+
end
|
123
|
+
if options[:images]
|
124
|
+
Dockit::Image.clean(force: options[:force]) if ask_force('images')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
desc 'config [SERVICE]', 'show parsed Dockit.yaml config file'
|
129
|
+
def config(service=nil)
|
130
|
+
exec(service) do |s|
|
131
|
+
say s.config.instance_variable_get('@config').to_yaml
|
132
|
+
end
|
133
|
+
end
|
134
|
+
desc 'push REGISTRY [SERVICE]', 'push image for SERVICE to REGSITRY'
|
135
|
+
option :force, type: :boolean, desc: 'overwrite current lastest version'
|
136
|
+
option :tag, desc: 'repos tag (defaults to "latest")', aliases: ['t']
|
137
|
+
def push(registry, service=nil)
|
138
|
+
exec(service) do |s|
|
139
|
+
s.push(registry, options[:tag], options[:force])
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
desc 'pull REGISTRY [SERVICE]', 'pull image for SERVICE from REGSITRY'
|
144
|
+
option :force, type: :boolean, desc: 'overwrite current tagged version'
|
145
|
+
option :tag, desc: 'repos tag (defaults to "latest")', aliases: ['t']
|
146
|
+
def pull(registry, service=nil)
|
147
|
+
exec(service) do |s|
|
148
|
+
s.pull(registry, options[:tag], options[:force])
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
desc 'build [SERVICE]', "Build image from current directory or service name"
|
153
|
+
def build(service=nil)
|
154
|
+
exec(service) do |s|
|
155
|
+
s.build()
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
desc 'git-build', 'build from git (gem) repository'
|
160
|
+
option :branch, desc: '<tree-ish> git reference', default: 'master'
|
161
|
+
option :gem, type: :boolean, desc: "update Gemfiles export"
|
162
|
+
def git_build(service=nil)
|
163
|
+
exec(service) do |s|
|
164
|
+
unless repos = s.config.get(:repos)
|
165
|
+
say "'repos' not defined in config file. Exiting",:red
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
|
169
|
+
say "Exporting in #{Dir.pwd}", :green
|
170
|
+
say "<- #{repos} #{options.branch}", :green
|
171
|
+
if options.gem
|
172
|
+
# grab the Gemfiles separately for the bundler Dockerfile hack
|
173
|
+
say "-> Gemfiles", :green
|
174
|
+
export(repos, 'gemfile.tar.gz', 'Gemfile*')
|
175
|
+
end
|
176
|
+
|
177
|
+
say "-> repos.tar.gz", :green
|
178
|
+
export(repos, 'repos.tar.gz')
|
179
|
+
|
180
|
+
s.build
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
GIT_CMD = 'git archive -o %s --format tar.gz --remote %s %s %s'.freeze
|
186
|
+
def export(repos, archive, args='')
|
187
|
+
cmd = GIT_CMD % [archive, repos, options.branch, args]
|
188
|
+
say "#{cmd}\n", :blue if options.debug
|
189
|
+
|
190
|
+
unless system(cmd)
|
191
|
+
say "Export error", :red
|
192
|
+
exit 1
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def ask_force(type)
|
197
|
+
force = options[:force]
|
198
|
+
say "Removing #{force ? 'ALL' : ''} #{type}...", force ? :red : nil
|
199
|
+
|
200
|
+
return true ### DISABLED# unless force
|
201
|
+
yes? '... Are you sure?'
|
202
|
+
end
|
203
|
+
|
204
|
+
def dockit
|
205
|
+
@@dockit ||= Dockit::Env.new(debug: options[:debug])
|
206
|
+
end
|
207
|
+
|
208
|
+
def exec(service)
|
209
|
+
file = _file(service)
|
210
|
+
if file != DOCKIT_FILE
|
211
|
+
say "Processing #{service}"
|
212
|
+
# problem w/ path length for docker build, so change to local directory
|
213
|
+
Dir.chdir(File.dirname(file))
|
214
|
+
end
|
215
|
+
|
216
|
+
locals = options[:locals]||{}
|
217
|
+
env = options[:env]
|
218
|
+
locals[:env] = env ? "-#{env}" : ""
|
219
|
+
yield Dockit::Service.new(locals: locals)
|
220
|
+
end
|
221
|
+
|
222
|
+
def _file(service)
|
223
|
+
return dockit.services[service] if service && dockit.services[service]
|
224
|
+
return DOCKIT_FILE if File.exist?(DOCKIT_FILE)
|
225
|
+
say "No config file in current directory", :red
|
226
|
+
help
|
227
|
+
exit
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Add digital ocean support if droplet_kit is installed
|
232
|
+
begin
|
233
|
+
require 'dockit/digitalocean'
|
234
|
+
Default.desc 'do', 'manage docker server'
|
235
|
+
Default.subcommand 'do', DO
|
236
|
+
rescue LoadError
|
237
|
+
end
|
238
|
+
|
239
|
+
# it would be nice to do this in the initialization method of the Default
|
240
|
+
# class above, but it hasn't been instantiated yet when invoking a subcommand.
|
241
|
+
Dockit::Env.new.modules.each do |k, v|
|
242
|
+
begin
|
243
|
+
require v
|
244
|
+
Default.desc k, "#{k} submodule, see 'help #{k}'"
|
245
|
+
Default.subcommand k, Module.const_get(k.capitalize)
|
246
|
+
rescue NameError => e
|
247
|
+
STDERR.puts "Can't load #{v}: #{e}"
|
248
|
+
end
|
249
|
+
end
|