hoosegow 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Dockerfile +46 -0
- data/Gemfile +9 -0
- data/LICENSE +21 -0
- data/README.md +82 -0
- data/Rakefile +37 -0
- data/bin/hoosegow +14 -0
- data/docs/dispatch-seq.txt +13 -0
- data/docs/dispatch.md +53 -0
- data/docs/dispatch.png +0 -0
- data/hoosegow.gemspec +32 -0
- data/lib/hoosegow.rb +160 -0
- data/lib/hoosegow/docker.rb +236 -0
- data/lib/hoosegow/exceptions.rb +27 -0
- data/lib/hoosegow/image_bundle.rb +111 -0
- data/lib/hoosegow/protocol.rb +133 -0
- data/script/proxy-integration-test +95 -0
- data/spec/hoosegow_docker_spec.rb +109 -0
- data/spec/hoosegow_spec.rb +170 -0
- data/spec/test_inmate/inmate.rb +7 -0
- metadata +159 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 08457775221dac7f850e7f3ba83e41661a45ae62
|
4
|
+
data.tar.gz: 64919e4a0404a832ff1cd700bb8b665af96fd63e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fe8880787a543fca141ec9c2f59df2ae778dc7d791709c7a9f39e304f2ea0f16800d79d3236c0e28f4feff3fb7afc3077c124c4a645be2206a46f4dc85d8e6d6
|
7
|
+
data.tar.gz: edda7d73693b4944a81dc1cbdbf699feb2ffba8507412fb12d0207188fcf74cead9732fd37cad938516eccdb007c2d24e513cfcb350bb915d23ed35eff63669b
|
data/Dockerfile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Ubuntu base image
|
2
|
+
FROM ubuntu
|
3
|
+
|
4
|
+
# Install rbenv deps
|
5
|
+
RUN apt-get update
|
6
|
+
RUN apt-get install -y build-essential zlib1g-dev libssl-dev openssl libreadline-dev sqlite3 libsqlite3-dev libxslt-dev libxml2-dev curl wget git-core
|
7
|
+
|
8
|
+
# Install rbenv
|
9
|
+
RUN git clone https://github.com/sstephenson/rbenv.git /.rbenv
|
10
|
+
RUN echo 'export PATH="/.rbenv/bin:$PATH"' >> /etc/profile
|
11
|
+
RUN echo 'export RBENV_ROOT="/.rbenv"' >> /etc/profile
|
12
|
+
RUN echo 'eval "$(rbenv init -)"' >> /etc/profile
|
13
|
+
RUN echo 'gem: --no-rdoc --no-ri' >> /etc/gemrc
|
14
|
+
|
15
|
+
# Install rbenv build plugin
|
16
|
+
RUN mkdir -p /.rbenv/plugins
|
17
|
+
RUN git clone https://github.com/sstephenson/ruby-build.git /.rbenv/plugins/ruby-build
|
18
|
+
|
19
|
+
# Install specified ruby version
|
20
|
+
RUN /bin/bash -l -c 'RUBY_CONFIGURE_OPTS="--disable-install-doc" rbenv install {{ruby_version}}'
|
21
|
+
RUN /bin/bash -l -c 'rbenv global {{ruby_version}}'
|
22
|
+
RUN /bin/bash -l -c 'gem install bundler'
|
23
|
+
RUN /bin/bash -l -c 'rbenv rehash'
|
24
|
+
|
25
|
+
# Create a user to run as.
|
26
|
+
RUN adduser --no-create-home --disabled-password --gecos "" --shell /bin/false hoosegow
|
27
|
+
|
28
|
+
###########################################################################################
|
29
|
+
# Anything added after the ADD command will not be cached. Try to add changes above here. #
|
30
|
+
###########################################################################################
|
31
|
+
|
32
|
+
# Add this directory to /
|
33
|
+
ADD . /hoosegow
|
34
|
+
RUN chown -R hoosegow:hoosegow /hoosegow
|
35
|
+
|
36
|
+
# Switch to limited user now.
|
37
|
+
USER hoosegow
|
38
|
+
|
39
|
+
# Run all commands in /hoosegow
|
40
|
+
WORKDIR /hoosegow
|
41
|
+
|
42
|
+
# Bundle hoosegow
|
43
|
+
RUN /bin/bash -l -c 'BUNDLE_JOBS=4 bundle install --path .bundle --without development test'
|
44
|
+
|
45
|
+
# Command to run when `docker run hoosegow`
|
46
|
+
ENTRYPOINT /bin/bash -l -c bin/hoosegow
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 GitHub, Inc.
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Hoosegow
|
2
|
+
|
3
|
+
Ephemeral Docker jails for running untrusted Ruby code.
|
4
|
+
|
5
|
+
Hoosegow runs both in your code and in a Docker container. When you call a method on a Hoosegow instance, it proxies the method call to another instance of Hoosegow running inside a Docker container.
|
6
|
+
|
7
|
+
# Security
|
8
|
+
|
9
|
+
Hoosegow is intended to add a layer of security to projects that need to run code that is not fully trusted/audited. Because the untrusted code is running inside a Docker container, an attacker who manages to exploit a vulnerability in the code must also break out of the Docker container before gaining any access to the host system.
|
10
|
+
|
11
|
+
This means that Hoosegow is only as strong as Docker. Docker employs Kernel namespaces, capabilities, and cgroups to contain processes running inside a container. This is not true Virtualization though, and a process running as root inside the container *can* compromise the host system. Any priviledge escalation bugs in the host Kernel could also be used to become root and compromise the host machine. Further hardening of the base Ubuntu image, along with tools like AppArmor or SE-Linux can improve the security posture of an application relying on Hoosegow/Docker.
|
12
|
+
|
13
|
+
The following are some useful resources regarding the security of Docker:
|
14
|
+
|
15
|
+
- The [Docker Security](https://docs.docker.com/articles/security/) article from Docker.io.
|
16
|
+
- The [LXC, Docker, Security](http://www.slideshare.net/jpetazzo/linux-containers-lxc-docker-and-security) slides from Jérôme Petazzoni.
|
17
|
+
- The series of Docker security articles from Daniel J. Walsh ([one](http://opensource.com/business/14/7/docker-security-selinux), [two](http://opensource.com/business/14/9/security-for-docker)).
|
18
|
+
|
19
|
+
#### Installing
|
20
|
+
|
21
|
+
Gems are available from the [releases page](https://github.com/github/hoosegow/releases). Download a gem to
|
22
|
+
your app's `vendor/cache` directory, and add this to your Gemfile:
|
23
|
+
|
24
|
+
gem "hoosegow"
|
25
|
+
|
26
|
+
#### Defining Methods to Proxy
|
27
|
+
|
28
|
+
You need to define the methods you want to have run in the Docker container. To do this, you need to create a `inmate.rb` file that defines a `Hoosegow::Inmate` module. Any methods on this module will be available on `Hoosegow` instances and will be proxied to the Docker container. Here is an example `inmate.rb` file:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class Hoosegow
|
32
|
+
module Inmate
|
33
|
+
def reverse(input)
|
34
|
+
input.reverse
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
The `inmate.rb` file should be in its own folder, with an optional `Gemfile` to specify dependencies. This directory will be copied to the Docker container at build time so your methods are available to be proxied to. You specify the location of the directory containing the `inmate.rb` file when instantiating a `Hoosegow` object:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
hoosegow = Hoosegow.new :inmate_dir => File.join(RAILS_ROOT, "hoosegow_deps")
|
44
|
+
hoosegow.reverse "foobar"
|
45
|
+
#=> "raboof"
|
46
|
+
```
|
47
|
+
|
48
|
+
#### Building the Docker Image
|
49
|
+
|
50
|
+
Before you can start using Hoosegow, you need to build the Docker image that Hoosegow will proxy method calls to. This can be done in a rake task or bootstrap script:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
hoosegow = Hoosegow.new :inmate_dir => File.join(RAILS_ROOT, "hoosegow_deps")
|
54
|
+
hoosegow.build_image
|
55
|
+
hoosegow.image_name
|
56
|
+
#=> "hoosegow:2f8f155e72828ddab9bd8bd0e355c47fb01a5323"
|
57
|
+
```
|
58
|
+
|
59
|
+
The image will need to be rebuilt with any changes to Hoosegow or the `inmate.rb` file. If the image is built ahead of time (by a rake task or bootstrap script), you can pass the name of the image to use when instantiating a Hoosegow instance:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
ENV['HOOSEGOW_IMAGE']
|
63
|
+
#=> "hoosegow:2f8f155e72828ddab9bd8bd0e355c47fb01a5323"
|
64
|
+
hoosegow = Hoosegow.new :inmate_dir => File.join(RAILS_ROOT, "hoosegow_deps")
|
65
|
+
:image_name => ENV['HOOSEGOW_IMAGE']
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Configuring the Connection to Docker
|
69
|
+
|
70
|
+
By default Docker's API listens locally on a Unix socket. If you are running Docker with it's default configuration, you don't need to worry about configuring Hoosegow.
|
71
|
+
|
72
|
+
**Configure Hoosegow to connect to a non-standard Unix socket.**
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
Hoosegow.new :socket => '/path/to/socket'
|
76
|
+
```
|
77
|
+
|
78
|
+
**Configure Hoosegow to connect to a Docker daemon running on another computer.**
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
Hoosegow.new :host => '192.168.1.192', :port => 4243
|
82
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'lib/hoosegow'
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require_relative 'config'
|
7
|
+
rescue LoadError
|
8
|
+
CONFIG = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
inmate_dir = File.join(File.dirname(__FILE__), 'spec', 'test_inmate')
|
12
|
+
CONFIG[:inmate_dir] = inmate_dir
|
13
|
+
CONFIG[:image_name] = Hoosegow.new(CONFIG).image_name
|
14
|
+
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
16
|
+
Rake::Task[:spec].prerequisites << :bootstrap_docker
|
17
|
+
task :default => :spec
|
18
|
+
|
19
|
+
def hoosegow
|
20
|
+
@hoosgow ||= Hoosegow.new CONFIG
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Benchmark render_reverse run in docker"
|
24
|
+
task :benchmark => :bootstrap_docker do
|
25
|
+
10.times do |i|
|
26
|
+
sleep 0.5
|
27
|
+
start = Time.now
|
28
|
+
hoosegow.render_reverse "foobar"
|
29
|
+
puts "render_reverse run ##{i} took #{Time.now - start} seconds"
|
30
|
+
end
|
31
|
+
hoosegow.cleanup
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Building docker image."
|
35
|
+
task :bootstrap_docker do
|
36
|
+
hoosegow.build_image unless hoosegow.image_exists?
|
37
|
+
end
|
data/bin/hoosegow
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# See docs/dispatch.md for more information.
|
3
|
+
|
4
|
+
require_relative '../lib/hoosegow'
|
5
|
+
|
6
|
+
real_stdout = $stdout.dup
|
7
|
+
real_stdout.sync = true
|
8
|
+
intercepted_stdout, intercepting_stdout = IO.pipe # returns reader,writer
|
9
|
+
$stdout.reopen(intercepting_stdout)
|
10
|
+
|
11
|
+
Hoosegow::Protocol::Inmate.run({
|
12
|
+
:stdout => real_stdout,
|
13
|
+
:intercepted => intercepted_stdout,
|
14
|
+
})
|
@@ -0,0 +1,13 @@
|
|
1
|
+
title Hoosegow method dispatch
|
2
|
+
|
3
|
+
App->Hoosegow: do_work(args)
|
4
|
+
Hoosegow->Docker: start and attach to instance
|
5
|
+
Hoosegow->bin/hoosegow: stdin: msgpack(:do_work, args)
|
6
|
+
bin/hoosegow->Inmate: send(:do_work, args)
|
7
|
+
Inmate->bin/hoosegow: yield("message")
|
8
|
+
bin/hoosegow->Hoosegow: stdout: msgpack(:yield, "message")
|
9
|
+
Hoosegow->App: yield("message")
|
10
|
+
Inmate->bin/hoosegow: return :ok
|
11
|
+
bin/hoosegow->Hoosegow: stdout: msgpack(:return, "ok")
|
12
|
+
Hoosegow->Docker: stop container
|
13
|
+
Hoosegow->App: return "ok"
|
data/docs/dispatch.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Hoosegow dispatch
|
2
|
+
|
3
|
+
Calling a method on an inmate involves passing information through several layers. The participants in the flow are:
|
4
|
+
|
5
|
+
* **App** - your app's code, outside of the container.
|
6
|
+
* **Hoosegow** - an instance of the `Hoosegow` class, created outside the container.
|
7
|
+
* **Docker** - the docker daemon.
|
8
|
+
* **`bin/hoosegow`** - the entry point in the docker container.
|
9
|
+
* **Inmate** - an instance of the `Hoosegow` class, inside the container, that has included `Hoosegow::Inmate` (your sandboxed code).
|
10
|
+
|
11
|
+
![](dispatch.png)
|
12
|
+
|
13
|
+
## Interfaces
|
14
|
+
|
15
|
+
### Hoosegow (outside the container)
|
16
|
+
|
17
|
+
The outer instance of `Hoosegow` receives a normal call from the application.
|
18
|
+
|
19
|
+
It encodes the method name and arguments and provides that to an attach call to Docker.
|
20
|
+
|
21
|
+
It reads the Docker response as it comes in. It demultiplexes the docker output into `STDERR` and `STDOUT`. `STDOUT` is further decoded into the actual `STDOUT` from the Inmate, `yield` calls, and the method result.
|
22
|
+
|
23
|
+
### Docker
|
24
|
+
|
25
|
+
Docker receives an HTTP POST with a body, and returns an HTTP response with a body. The HTTP request body is treated as `STDIN`, and the response body contains `STDOUT` and `STDERR`.
|
26
|
+
|
27
|
+
See [documentation for attach](http://docs.docker.io/en/latest/reference/api/docker_remote_api_v1.7/#attach-to-a-container).
|
28
|
+
|
29
|
+
### bin/hoosegow
|
30
|
+
|
31
|
+
`bin/hoosegow` is started by Docker when the container starts. It is the entry point of the container.
|
32
|
+
|
33
|
+
It decodes `STDIN` and calls the requested method on the Inmate.
|
34
|
+
|
35
|
+
`STDOUT` is reopened so that we can encode a few things on it:
|
36
|
+
|
37
|
+
* normal stdout from the inmate or child processes spawned by the inmate
|
38
|
+
* data that is `yield`ed
|
39
|
+
* the return value from the inmate.
|
40
|
+
|
41
|
+
`STDERR` is left as-is.
|
42
|
+
|
43
|
+
### Inmate
|
44
|
+
|
45
|
+
The Inmate is an object that includes the `Hoosegow::Inmate` module.
|
46
|
+
|
47
|
+
Input to the Inmate is a method name and arguments.
|
48
|
+
|
49
|
+
Output from the Inmate can be spread across several things:
|
50
|
+
|
51
|
+
* `STDOUT` and `STDERR` - e.g. puts calls
|
52
|
+
* `yield` to a block
|
53
|
+
* the result of the method
|
data/docs/dispatch.png
ADDED
Binary file
|
data/hoosegow.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'hoosegow'
|
5
|
+
s.version = '1.2.0'
|
6
|
+
s.summary = "A Docker jail for ruby code"
|
7
|
+
s.description = "Hoosegow provides an RPC layer on top of Docker containers so that you can isolate unsafe parts of your application."
|
8
|
+
s.authors = ["Ben Toews", "Matt Burke"]
|
9
|
+
s.email = 'mastahyeti@github.com'
|
10
|
+
s.licenses = ["MIT"]
|
11
|
+
globs = %w[
|
12
|
+
README.md
|
13
|
+
LICENSE
|
14
|
+
Gemfile
|
15
|
+
Rakefile
|
16
|
+
Dockerfile
|
17
|
+
hoosegow.gemspec
|
18
|
+
docs/**/*
|
19
|
+
lib/**/*
|
20
|
+
script/**/*
|
21
|
+
spec/**/*
|
22
|
+
]
|
23
|
+
s.files = Dir[*globs]
|
24
|
+
s.executables = ['hoosegow']
|
25
|
+
s.homepage = 'https://github.com/github/hoosegow'
|
26
|
+
s.required_ruby_version = ">= 1.9.3"
|
27
|
+
s.add_development_dependency 'rake', '>= 10.3.2', '~> 10.3'
|
28
|
+
s.add_development_dependency 'rspec', '>= 2.14.1', '~> 2.14'
|
29
|
+
s.add_runtime_dependency 'msgpack', '>= 0.5.6', '~> 0.5'
|
30
|
+
s.add_runtime_dependency 'yajl-ruby', '>= 1.1.0', '~> 1.1'
|
31
|
+
s.add_runtime_dependency 'docker-api', '~> 1.13.6'
|
32
|
+
end
|
data/lib/hoosegow.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require_relative 'hoosegow/docker'
|
2
|
+
require_relative 'hoosegow/exceptions'
|
3
|
+
require_relative 'hoosegow/image_bundle'
|
4
|
+
require_relative 'hoosegow/protocol'
|
5
|
+
|
6
|
+
class Hoosegow
|
7
|
+
# Public: Initialize a Hoosegow instance.
|
8
|
+
#
|
9
|
+
# options -
|
10
|
+
# :no_proxy - Development mode. Use this if you don't want to
|
11
|
+
# setup Docker on your development instance, but
|
12
|
+
# still need to test rendering files. This is how
|
13
|
+
# Hoosegow runs inside the Docker container.
|
14
|
+
# :inmate_dir - Dependency directory to be coppied to the hoosegow
|
15
|
+
# image. This should include a file called
|
16
|
+
# `inmate.rb` that defines a Hoosegow::Inmate module.
|
17
|
+
# :image_name - The name of the Docker image to use. If this isn't
|
18
|
+
# specified, we will infer the image name from the
|
19
|
+
# hash the files present.
|
20
|
+
# :ruby_version - The Ruby version to install in the Docker
|
21
|
+
# container (Default RUBY_VERSION).
|
22
|
+
# :socket - Path to Unix socket where Docker daemon is
|
23
|
+
# running. (optional. defaults to
|
24
|
+
# "/var/run/docker.sock")
|
25
|
+
# :host - IP or hostname where Docker daemon is running.
|
26
|
+
# Don't set this if Docker is listening locally on a
|
27
|
+
# Unix socket.
|
28
|
+
# :port - TCP port where Docker daemon is running. Don't set
|
29
|
+
# this if Docker is listening locally on a Unix
|
30
|
+
# socket.
|
31
|
+
def initialize(options = {})
|
32
|
+
options = options.dup
|
33
|
+
@no_proxy = options.delete(:no_proxy)
|
34
|
+
@inmate_dir = options.delete(:inmate_dir) || '/hoosegow/inmate'
|
35
|
+
@image_name = options.delete(:image_name)
|
36
|
+
@ruby_version = options.delete(:ruby_version) || RUBY_VERSION
|
37
|
+
@docker_options = options
|
38
|
+
load_inmate_methods
|
39
|
+
|
40
|
+
# Don't want to have to require these in the container.
|
41
|
+
unless no_proxy?
|
42
|
+
require 'tmpdir'
|
43
|
+
require 'fileutils'
|
44
|
+
require 'open3'
|
45
|
+
require 'digest'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Public: The thing that defines which files go into the docker image tarball.
|
50
|
+
def image_bundle
|
51
|
+
@image_bundle ||=
|
52
|
+
Hoosegow::ImageBundle.new.tap do |image|
|
53
|
+
image.add(File.expand_path('../../*', __FILE__), :ignore_hidden => true)
|
54
|
+
image.add(File.join(@inmate_dir, "*"), :prefix => 'inmate')
|
55
|
+
image.ruby_version = @ruby_version
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Proxies method call to instance running in a Docker container.
|
60
|
+
#
|
61
|
+
# name - The method to call in the Docker instance.
|
62
|
+
# args - Arguments that should be passed to the Docker instance method.
|
63
|
+
# block - A block that can be yielded to.
|
64
|
+
#
|
65
|
+
# See docs/dispatch.md for more information.
|
66
|
+
#
|
67
|
+
# Returns the return value from the Docker instance method.
|
68
|
+
def proxy_send(name, args, &block)
|
69
|
+
proxy = Hoosegow::Protocol::Proxy.new(
|
70
|
+
:stdout => $stdout,
|
71
|
+
:stderr => $stderr,
|
72
|
+
:yield => block
|
73
|
+
)
|
74
|
+
encoded_send = proxy.encode_send(name, args)
|
75
|
+
docker.run_container(image_name, encoded_send) do |type, msg|
|
76
|
+
proxy.receive(type, msg)
|
77
|
+
end
|
78
|
+
|
79
|
+
proxy.return_value
|
80
|
+
end
|
81
|
+
|
82
|
+
# Public: Load inmate methods from #{inmate_dir}/inmate.rb and hook them up
|
83
|
+
# to proxied to the Docker container. If we are in the container, the methods
|
84
|
+
# are loaded and setup to be called directly.
|
85
|
+
#
|
86
|
+
# Returns nothing. Raises InmateImportError if there is a problem.
|
87
|
+
def load_inmate_methods
|
88
|
+
inmate_file = File.join @inmate_dir, 'inmate.rb'
|
89
|
+
|
90
|
+
unless File.exist?(inmate_file)
|
91
|
+
raise Hoosegow::InmateImportError, "inmate file doesn't exist"
|
92
|
+
end
|
93
|
+
|
94
|
+
require inmate_file
|
95
|
+
|
96
|
+
unless Hoosegow.const_defined?(:Inmate) && Hoosegow::Inmate.is_a?(Module)
|
97
|
+
raise Hoosegow::InmateImportError,
|
98
|
+
"inmate file doesn't define Hoosegow::Inmate"
|
99
|
+
end
|
100
|
+
|
101
|
+
if no_proxy?
|
102
|
+
self.extend Hoosegow::Inmate
|
103
|
+
else
|
104
|
+
inmate_methods = Hoosegow::Inmate.instance_methods
|
105
|
+
inmate_methods.each do |name|
|
106
|
+
define_singleton_method name do |*args, &block|
|
107
|
+
proxy_send name, args, &block
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Public: We create/start a container after every run to reduce latency. This
|
114
|
+
# needs to be called before the process ends to cleanup that remaining
|
115
|
+
# container.
|
116
|
+
#
|
117
|
+
# Returns nothing.
|
118
|
+
def cleanup
|
119
|
+
docker.stop_container
|
120
|
+
docker.delete_container
|
121
|
+
end
|
122
|
+
|
123
|
+
# Check if the Docker image exists.
|
124
|
+
#
|
125
|
+
# Returns true/false.
|
126
|
+
def image_exists?
|
127
|
+
docker.image_exist? image_name
|
128
|
+
end
|
129
|
+
|
130
|
+
# Public: Build a Docker image from the Dockerfile in the root directory of
|
131
|
+
# the gem.
|
132
|
+
#
|
133
|
+
# Returns build output text. Raises ImageBuildError if there is a problem.
|
134
|
+
def build_image(&block)
|
135
|
+
docker.build_image image_name, image_bundle.tarball, &block
|
136
|
+
end
|
137
|
+
|
138
|
+
# Private: The name of the docker image to use. If not specified manually,
|
139
|
+
# this will be infered from the hash of the tarball.
|
140
|
+
#
|
141
|
+
# Returns string image name.
|
142
|
+
def image_name
|
143
|
+
@image_name || image_bundle.image_name
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
# Private: Get or create a Docker instance.
|
148
|
+
#
|
149
|
+
# Returns an Docker instance.
|
150
|
+
def docker
|
151
|
+
@docker ||= Docker.new @docker_options
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns true if we are in the Docker instance or are in develpment mode.
|
155
|
+
#
|
156
|
+
# Returns true/false.
|
157
|
+
def no_proxy?
|
158
|
+
!!@no_proxy
|
159
|
+
end
|
160
|
+
end
|