baha 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- M2E1OWQwZWYyYmQxMzc3NmM1ZjAzZGI3ZTA5NmM3NGQyYTBjZGIyOA==
4
+ YTUxODZmMWUzYTBhNzI5YTIzZWU0NjAwNzUyMjRiMTMzY2VjNjkyOA==
5
5
  data.tar.gz: !binary |-
6
- YWJhZDkxNDNhYmNhMmYyMTBiZDNmNzliYTc2YmNmYTk4M2JmYTlmNQ==
6
+ MzU1Nzg5YjQ3Y2RiNzMwYTIzMmU2ZTQ5ZjQ5ZmVmMDMxNWQ0ZDIwZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MmVhNjgyMWFmOTJjZGRiYzE0Zjc1ZjdkOTBiZTlkY2YzYzhhMWRkN2I2ODdl
10
- MzQ3N2IwMzhkMDQyNDJiZjU4ZjNmYWZkNzU3YjE0OWE3OThjNTkxZjQwMDZl
11
- MDA2Zjg2ZTRhZjg2M2MwODZhNGRmMDM1ZjUwYmJhMDA1Y2E1ZGI=
9
+ NGZiYmFmMTY5ZGRmNDQ1MGJkMzIzMmYyYmIyYjAwZjJkZGY3ZTg5OTExN2Rh
10
+ NzRkZjY0MDI3NmQ5MTU2NTg1MjUwMmYwN2ZmNjFiY2RlOWEzMDk4NTJlMmI0
11
+ YjZkMjJlYTJiYTk0ZTk1ODI5M2JmNjMyYzQ3OTczZmQ3YTM5NGM=
12
12
  data.tar.gz: !binary |-
13
- MTJhOGNiYmYwOGI0YmE5NDI3Y2EwODFiZDU5MzNjYzE4ZmI4NTA0YTlkN2M0
14
- ZTgxNmQ5Mzc1ZmZlM2M5NzJiNDg2YjkzYjdmZDlkNjkwYjA5NGUzNzE3YTQz
15
- NGVkMTkzYTJhMzgwNGQwMDFjYzNlMWE2YzA1ZjdlZDZjYmJkMTk=
13
+ YWYzZmFlNjMzMjZkOTgzNjA2N2JhZjNiNTQ4MjRjZTBhNzg1OTFhMzJjZmEw
14
+ MTg1NjYzZjVkNWUwZWI2ZjUxZDU4ZjM1Yzk2MmQ1ZmM5NTkzZDk4ZTIyNDI0
15
+ NDY0ZDE3ZTQyZDRiMzhiYjg2MTcyYWM0YTNkM2Y5YmQ3YmZiYzc=
data/.travis.yml CHANGED
@@ -8,4 +8,7 @@ rvm:
8
8
  - 1.9.2
9
9
  - 1.9.3
10
10
  - 2.0.0
11
- - 2.1.0
11
+ - 2.1.0
12
+ addons:
13
+ code_climate:
14
+ repo_token: 3356d0b9dcd4f188c9ac115df5e27359c336a0db8fb36f79cf8859688d564ac6
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ v0.1.0
2
+ ------
3
+ - (#1) Support for creating images from Dockerfiles, similar to [docker-compile.pl](http://3ofcoins.net/2013/09/22/flat-docker-images/)
4
+ - (#2) CLI Command for converting a Dockerfile to an image.yml format
5
+
6
+ v0.0.1
7
+ ------
8
+ Initial Release
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in Baha.gemspec
4
4
  gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/README.md CHANGED
@@ -3,12 +3,13 @@ Baha
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/baha.png)](http://badge.fury.io/rb/baha)
5
5
  [![Build Status](https://travis-ci.org/justenwalker/baha.png?branch=master)](https://travis-ci.org/justenwalker/baha)
6
+ [![Code Climate](https://codeclimate.com/github/justenwalker/baha/badges/gpa.svg)](https://codeclimate.com/github/justenwalker/baha)
6
7
 
7
8
  Introduction
8
9
  ------------
9
10
 
10
11
  Baha is a command-line utility that assists in the creation of docker images.
11
- It addresses some of `Dockerfile`'s' shortcomings and encourages smaller, reusable, tagged images.
12
+ It addresses some of Dockerfiles shortcomings and encourages smaller, reusable, tagged images.
12
13
 
13
14
  Why not Dockerfiles?
14
15
  --------------------
@@ -18,9 +19,11 @@ Dockerfiles are simple. They are an easy way to make a docker image without need
18
19
  So why would I use Baha?
19
20
  ------------------------
20
21
 
22
+ Baha attempts to address the shortcomings of Dockerfiles by factoring out redundancies and providing a modular interface for creating suites of dependent images.
23
+
21
24
  ### 1. Baha forbids more than 1 layer per image
22
25
 
23
- If you split statements across multiple RUN statements, each of these results in a new layer.
26
+ If you split statements across multiple `RUN` statements, each of these results in a new layer.
24
27
  The more commands you run, the more layers you create. If you want to *minimize the number of layers* (See [Official Recommendations](https://docs.docker.com/articles/dockerfile_best-practices/))
25
28
  then you must ensure that all statements can be condensed into one line - sacrificing maintainability in the process.
26
29
 
@@ -30,25 +33,25 @@ Baha encourages using scripts instead of `RUN` statements to ensure that only on
30
33
 
31
34
  The nature of the way the dockerfiles are processed means that each command you run commits a new image.
32
35
  This means, that if you have a `RUN` statement that downloads packages for installation.
33
- This will commit a layer with the installation files. Later on if you clean up these files with further RUN commands, they will still exist in your image lineage - thus having no space savings. Without proper precautions, you'll end up having unnecessarily large images.
36
+ This will commit a layer with the installation files. Later on if you clean up these files with further `RUN` commands, they will still exist in your image lineage - thus having no space savings. Without proper precautions, you'll end up having unnecessarily large images.
34
37
 
35
38
  Baha ensures that all setup tasks happen in a single commit - so you can write cleanup statements and be assured that they will indeed be absent in the resulting images.
36
39
 
37
40
  ### 3. Baha understands the bigger picture
38
41
 
39
- Another best practice (2, #7) recommends that you use your own base image.
42
+ Another best practice ([2](http://crosbymichael.com/dockerfile-best-practices-take-2.html): #7) recommends that you use your own base image.
40
43
  Dockerfiles make it simple to create your own 'base' image, but how about updates?
41
44
 
42
45
  If you were to just rebuild all of your Dockerfiles, you would create an entirely new tree - even if nothing changed.
43
46
 
44
- Baha will rebuild your entire lineage if the base images changes, but will not rebuild base images if only the children change.
47
+ Baha will rebuild your entire lineage if the base image changes, but will not rebuild base images if only the children change.
45
48
 
46
- **Caveat**:
49
+ **Caveat**
47
50
 
48
51
  Baha relies on tagging your releases, noticing when the tag has changed, and treating tags as immutable.
49
52
  This is analogous to how **git** treats tags.
50
53
 
51
- Tagging your images is another best-practice (2, #5) anyway, so this is encouraged by design.
54
+ Tagging your images is another best-practice ([2](http://crosbymichael.com/dockerfile-best-practices-take-2.html): #5) anyway, so this is encouraged by design.
52
55
 
53
56
  Bottom line is: If you change your image, you should change the tag/version.
54
57
 
@@ -62,8 +65,8 @@ This workspace is made available to the image via a bind mount during build-time
62
65
 
63
66
  **References**
64
67
 
65
- 1. [Official Dockerfile Best Practices](https://docs.docker.com/articles/dockerfile_best-practices/)<a name="r1"></a>
66
- 2. [Dockerfile Best Practices - take 2, by Michael Crosby](http://crosbymichael.com/dockerfile-best-practices-take-2.html)<a name="r2"></a>
68
+ 1. [Official Dockerfile Best Practices](https://docs.docker.com/articles/dockerfile_best-practices/)
69
+ 2. [Dockerfile Best Practices - take 2, by Michael Crosby](http://crosbymichael.com/dockerfile-best-practices-take-2.html)
67
70
 
68
71
  Disclaimer
69
72
  ----------
@@ -83,16 +86,16 @@ Installation
83
86
  ```
84
87
  $ gem install baha
85
88
  ```
86
- ### gem install baha
87
89
 
88
90
  Usage
89
91
  -----
90
92
 
91
93
  ```
92
94
  Baha Commands:
93
- baha build [options] CONFIG # Builds all docker images based on the given config
94
- baha help [COMMAND] # Describe available commands or one specific command
95
- baha version # Print version and exit
95
+ baha build [options] CONFIG # Builds all docker images based on the given config
96
+ baha convert DOCKERFILE n, --name=NAME # Converts an existing dockerfile to a Baha-compatible image.yml
97
+ baha help [COMMAND] # Describe available commands or one specific command
98
+ baha version # Print version and exit
96
99
  ```
97
100
 
98
101
  **build**
@@ -111,7 +114,50 @@ Description:
111
114
  Reads the CONFIG file and builds all of the docker images in the order they appear.
112
115
  ```
113
116
 
114
- Check out the `example` directory for a sample CONFIG file.
117
+ **convert**
118
+
119
+ ```
120
+ Usage:
121
+ baha convert DOCKERFILE n, --name=NAME
122
+
123
+ Options:
124
+ n, --name=NAME # The target image name
125
+ t, [--tag=TAG] # The target image tag
126
+ # Default: latest
127
+ o, [--output=OUTPUT] # Target output file
128
+ # Default: STDOUT
129
+
130
+ Description:
131
+ Reads the given Dockerfile and outputs a Baha-compatible image.yml
132
+ which can be included or embedded within a CONFIG
133
+ ```
134
+
135
+ Example
136
+ -------
137
+
138
+ Check out the **example** directory for a sample CONFIG.
139
+
140
+ To run the example build
141
+
142
+ ```
143
+ ### 1.
144
+ ### If necessary (using boot2docker) export the correct environment variables
145
+ ### You can find this by running boot2docker up
146
+ # export DOCKER_HOST=tcp://192.168.59.103:2376
147
+ # export DOCKER_CERT_PATH=$HOME/.boot2docker/certs/boot2docker-vm
148
+ # export DOCKER_TLS_VERIFY=1
149
+
150
+ ### 2.
151
+ ### Checkout baha
152
+ git clone https://github.com/justenwalker/baha.git
153
+ cd baha
154
+
155
+ ### 3. Install bundle
156
+ bundle install
157
+
158
+ ### 4. Run the example.yml
159
+ bundle exec baha build -d example/example.yml
160
+ ```
115
161
 
116
162
  How it works
117
163
  ------------
@@ -127,13 +173,25 @@ It will build each image in the order they appear by doing the following.
127
173
  1. Create the workspace directory if it doesn't exist
128
174
  2. Run any `pre_build` tasks to prepare dependencies
129
175
 
130
- ### Run the image's `command` inside the image
176
+ ### Run the command inside the image
131
177
  1. Creates a new container and runs it with the `command` given
132
178
  2. Commits the container with the run options specified in the images `config` section.
133
179
 
180
+ ### Tags the resulting image
181
+ Adds the appropriate tags to the image as defined in the image config for both the remote registry and local repository.
182
+
134
183
  How to Contribute
135
184
  -----------------
136
185
 
186
+ Contributions are welcome! Documentation, bug-fixes, patches, or new functionality, or comments/criticism.
187
+
188
+ ### Code Contributions
189
+
190
+ Start by [forking](https://github.com/justenwalker/baha/fork) the github project.
191
+ Work on a topic branch instead of master (`git checkout -b my-feature`) and submit a pull request when you are done.
192
+
193
+ Please add specs to cover the change so that we can avoid regressions and help future commits from breaking existing code.
194
+
137
195
  ### Running the tests
138
196
 
139
197
  $ bundle
@@ -146,11 +204,11 @@ How to Contribute
146
204
 
147
205
  ### Reporting Issues
148
206
 
149
- Please include a reproducible test case.
207
+ Please include a reproducible test case if possible. Otherwise, provide as much detail as you can.
150
208
 
151
209
  License
152
210
  -------
153
211
 
154
212
  Copyright (c) 2014 Justen Walker.
155
213
 
156
- Released under the terms of the MIT License. For further information, please see the file `LICENSE.md`.
214
+ Released under the terms of the MIT License. For further information, please see the file `LICENSE.md`.
data/baha.gemspec CHANGED
@@ -8,9 +8,10 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Baha::VERSION
9
9
  spec.authors = ["Justen Walker"]
10
10
  spec.email = ["justen.walker+github@gmail.com"]
11
- spec.summary = %q{Baha - A tool for describing image builds for Docker}
12
- spec.description = %q{Baha - A tool for describing image builds for Docker}
13
- spec.homepage = ""
11
+ spec.summary = %q{Baha is a command-line utility that assists in the creation of docker images.}
12
+ spec.description = spec.summary + "\n" +
13
+ %q{It addresses some of Dockerfiles shortcomings and encourages smaller, reusable, tagged images.}
14
+ spec.homepage = "https://github.com/justenwalker/baha"
14
15
  spec.license = "MIT"
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
data/example/example.yml CHANGED
@@ -52,3 +52,8 @@ images:
52
52
  ### include them from another file relative to this config.
53
53
  ### Keep things modular and maintainable.
54
54
  - include: rvm/image.yml
55
+ ### You can also build an image from a Dockerfile
56
+ ### Be sure to name and tag it
57
+ - dockerfile: memcached/Dockerfile
58
+ name: memcached
59
+ tag: 2.2
@@ -0,0 +1,24 @@
1
+ # Memcached
2
+ #
3
+ # VERSION 2.2
4
+
5
+ # use the ubuntu base image provided by dotCloud
6
+ FROM ubuntu
7
+
8
+ MAINTAINER Victor Coisne victor.coisne@dotcloud.com
9
+
10
+ # make sure the package repository is up to date
11
+ RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
12
+ RUN apt-get update
13
+
14
+ # install memcached
15
+ RUN apt-get install -y memcached
16
+
17
+ # Launch memcached when launching the container
18
+ ENTRYPOINT ["memcached"]
19
+
20
+ # run memcached as the daemon user
21
+ USER daemon
22
+
23
+ # expose memcached port
24
+ EXPOSE 11211
data/lib/baha/builder.rb CHANGED
@@ -3,6 +3,8 @@ require 'baha/image'
3
3
  require 'baha/log'
4
4
  require 'baha/pre_build'
5
5
  require 'fileutils'
6
+ require 'tempfile'
7
+ require 'shellwords'
6
8
 
7
9
  class Baha::Builder
8
10
  LOG = Baha::Log.for_name("Builder")
@@ -47,6 +49,27 @@ class Baha::Builder
47
49
  FileUtils.mkdir_p workspace.to_s
48
50
  end
49
51
 
52
+ run = false
53
+ ## Image Run Config
54
+ if image.run
55
+ build_log.debug { "Image has RUN commands"}
56
+ run = '.init.sh'
57
+ File.open(workspace + run,'w') do |f|
58
+ f.write("#!/bin/sh\n")
59
+ f.write("set -xe\n")
60
+ image.run.each do |cmd|
61
+ build_log.debug { "Writing command: #{cmd}"}
62
+ case cmd
63
+ when String
64
+ f.write("#{cmd}\n")
65
+ when Array
66
+ safe = Shellwords.shelljoin(cmd)
67
+ f.write("#{safe}\n")
68
+ end
69
+ end
70
+ end
71
+ end
72
+
50
73
  ## Pre-Build tasks
51
74
  build_log.info { "Building #{image.name}" }
52
75
  if image.pre_build
@@ -58,16 +81,20 @@ class Baha::Builder
58
81
  end
59
82
 
60
83
  ## Build Image
84
+ command = image.command
85
+ if run
86
+ command = ["/bin/sh", "#{image.bind}/#{run}"]
87
+ end
61
88
  container_config = {
62
89
  'Image' => image.parent_id,
63
- 'Cmd' => image.command,
90
+ 'Cmd' => command,
64
91
  'Workingdir' => image.bind
65
92
  }
66
93
  build_log.debug { "Creating container for #{image.name} => #{container_config.inspect}" }
67
94
  container = Docker::Container.create(container_config)
68
95
  build_log.debug { "Created container #{container.id} "}
69
96
 
70
- build_log.debug { "Running container for #{image.name}" }
97
+ build_log.debug { "Running container for #{image.name}: #{command}" }
71
98
  container.start({
72
99
  'Binds' => "#{image.workspace.expand_path}:#{image.bind}"
73
100
  })
data/lib/baha/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'thor'
2
2
  require 'baha/builder'
3
3
  require 'baha/log'
4
+ require 'baha/dockerfile'
4
5
 
5
6
  class Baha::CLI < Thor
6
7
  desc "build [options] CONFIG", "Builds all docker images based on the given config"
@@ -62,6 +63,58 @@ class Baha::CLI < Thor
62
63
  Baha::Log.close!
63
64
  end
64
65
  end
66
+ desc "convert DOCKERFILE", "Converts an existing dockerfile to a Baha-compatible image.yml"
67
+ long_desc <<-LONGDESC
68
+ Reads the given Dockerfile and outputs a Baha-compatible image.yml which can be included or embedded within a CONFIG
69
+ LONGDESC
70
+ option :name, {
71
+ :aliases => :n,
72
+ :required => true,
73
+ :type => :string,
74
+ :desc => "The target image name"
75
+ }
76
+ option :tag, {
77
+ :aliases => :t,
78
+ :required => false,
79
+ :type => :string,
80
+ :default => 'latest',
81
+ :desc => 'The target image tag'
82
+ }
83
+ option :output, {
84
+ :aliases => :o,
85
+ :required => false,
86
+ :type => :string,
87
+ :default => 'STDOUT',
88
+ :desc => 'Target output file'
89
+ }
90
+ def convert(dockerfile)
91
+ file = Pathname.new(dockerfile)
92
+ out = options[:output]
93
+ name = options[:name]
94
+ tag = options[:tag]
95
+ Baha::Log.logfile = STDERR
96
+ Baha::Log.level = :info
97
+ log = Baha::Log.for_name("CLI")
98
+ begin
99
+ if file.exist?
100
+ yaml = Baha::Dockerfile.parse(dockerfile)
101
+ yaml = { 'name' => name, 'tag' => tag }.merge(yaml)
102
+ if out == 'STDOUT'
103
+ puts yaml.to_yaml
104
+ else
105
+ File.open(out,'w') do |f|
106
+ f.write yaml.to_yaml
107
+ end
108
+ end
109
+ else
110
+ log.fatal { "DOCKERFILE #{dockerfile} not found" }
111
+ exit 1
112
+ end
113
+ rescue Exception => e
114
+ log.fatal("Error encountered while building images")
115
+ log.fatal(e)
116
+ end
117
+ end
65
118
  desc "version", "Print version and exit"
66
119
  def version
67
120
  puts "baha " + Baha::VERSION
data/lib/baha/config.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
  require 'pathname'
3
3
  require 'baha/log'
4
+ require 'baha/dockerfile'
4
5
 
5
6
  class Baha::Config
6
7
  DEFAULTS = {
@@ -84,6 +85,18 @@ class Baha::Config
84
85
  LOG.error { "Unable to find image include: #{path}"}
85
86
  next
86
87
  end
88
+ elsif image.has_key?('dockerfile')
89
+ path = Pathname.new(image['dockerfile'])
90
+ file = resolve_file(path)
91
+ if file
92
+ dockerfile = Baha::Dockerfile.parse(file)
93
+ dockerfile['name'] = image['name']
94
+ dockerfile['tag'] = image['tag']
95
+ yield Baha::Image.new(self,dockerfile)
96
+ else
97
+ LOG.error { "Unable to find dockerfile: #{path}"}
98
+ next
99
+ end
87
100
  else
88
101
  yield Baha::Image.new(self,image)
89
102
  end
@@ -15,7 +15,11 @@ module Baha
15
15
  when Fixnum
16
16
  config['ExposedPorts']["#{port}/tcp"] = {}
17
17
  when String
18
- config['ExposedPorts'][port] = {}
18
+ if port.match(/^\d+$/)
19
+ config['ExposedPorts']["#{port}/tcp"] = {}
20
+ else
21
+ config['ExposedPorts'][port] = {}
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -24,7 +28,7 @@ module Baha
24
28
  raise ERROR("should be an array") unless @value.kind_of?(Array)
25
29
  @value.each_with_index do |item,index|
26
30
  if item.kind_of?(String)
27
- unless /(\d+)\/(tcp|udp)/ =~ item
31
+ unless /(\d+)(\/(tcp|udp))?/ =~ item
28
32
  raise ERROR("#{index}: '#{item}' should be in the form 8080/tcp")
29
33
  end
30
34
  end
@@ -0,0 +1,150 @@
1
+ require 'docker'
2
+ require 'baha/container_options'
3
+ require 'baha/log'
4
+ require 'set'
5
+ require 'json'
6
+ require 'csv'
7
+ require 'yaml'
8
+
9
+ module Baha
10
+ class DockerfileParseError < RuntimeError
11
+ attr_reader :file, :line, :text
12
+ def initialize(file,line, text)
13
+ super("Unable to parse Dockerfile #{file}:#{line}\n#{text}")
14
+ @file = file
15
+ @line = line
16
+ @text = text
17
+ end
18
+ end
19
+ class Dockerfile
20
+ LOG = Baha::Log.for_name("Dockerfile")
21
+ class << self
22
+ def parse(file)
23
+ LOG.info { "Parsing Dockerfile: #{file}" }
24
+ linenum = 0
25
+ image = {
26
+ 'run' => [],
27
+ 'pre_build' => [],
28
+ 'config' => {}
29
+ }
30
+ multiline = []
31
+ f = File.open(file, "r")
32
+ begin
33
+ f.each_line do |rawline|
34
+ linenum = linenum + 1
35
+ line = rawline.chomp.gsub(/^\s*/,'')
36
+ # Skip empty lines
37
+ next if line.empty?
38
+ # Skip comments
39
+ next if line.match(/^#/)
40
+
41
+ # Buffer multi-lines
42
+ if line.match(/\\$/)
43
+ multiline << line.chop
44
+ next
45
+ end
46
+ multiline << line
47
+
48
+
49
+ line_to_parse = multiline.join("\n")
50
+ LOG.debug { "Parsing #{linenum}: #{line_to_parse}" }
51
+ unless parse_line(image,line_to_parse)
52
+ raise DockerfileParseError.new(file,linenum, line_to_parse)
53
+ end
54
+ multiline = []
55
+ end
56
+ ensure
57
+ f.close
58
+ end
59
+ image
60
+ end
61
+
62
+ def as_array(args)
63
+ begin
64
+ return JSON.parse(args)
65
+ rescue
66
+ return CSV.parse_line(args,{:col_sep => " ", })
67
+ end
68
+ end
69
+
70
+ def as_cmd(cmd)
71
+ begin
72
+ return JSON.parse(cmd)
73
+ rescue
74
+ cmd
75
+ end
76
+ end
77
+
78
+ def append_attr(image,key,value)
79
+ image[key] = [] unless image.has_key?(key)
80
+ case value
81
+ when Array
82
+ image[key].concat(value)
83
+ else
84
+ image[key].push(value)
85
+ end
86
+ end
87
+
88
+ # Resolve environment variables in the string
89
+ def resolve_env(image,value)
90
+ if image['config'].has_key?('env')
91
+ env = image['config']['env']
92
+ env.keys.reduce(value) do |v,k|
93
+ r = Regexp.new("(?<!\\\\)[$](?:\\{#{k}\\}|#{k})")
94
+ v.gsub(r,env[k])
95
+ end
96
+ else
97
+ value
98
+ end
99
+ end
100
+
101
+ # Sets the workdir on the image config
102
+ def set_workdir(image,value)
103
+ wd = image['config']['workingdir']
104
+ if wd
105
+ wd = (Pathname.new(wd) + value).to_s
106
+ else
107
+ wd = value
108
+ end
109
+ image['config']['workingdir'] = resolve_env(image,wd)
110
+ end
111
+
112
+ def set_env(image,value)
113
+ k,v = value.split(/\s+/,2)
114
+ image['config']['env'] ||= {}
115
+ image['config']['env'][k] = v
116
+ end
117
+
118
+ # Parse a line and configure the image
119
+ def parse_line(image,line)
120
+ cmd, args = line.split(/\s+/,2)
121
+ cmd = cmd.downcase.to_sym
122
+ case cmd
123
+ when :from
124
+ image['parent'] = args
125
+ when :maintainer
126
+ image['maintainer'] = args
127
+ when :expose
128
+ append_attr(image['config'],'exposedports',resolve_env(image,args))
129
+ when :volume
130
+ append_attr(image['config'],'volumes',as_array(resolve_env(image,args)))
131
+ when :entrypoint
132
+ image['config']['entrypoint'] = as_cmd(args)
133
+ when :cmd
134
+ image['config']['cmd'] = as_cmd(args)
135
+ when :run
136
+ image['run'] << as_cmd(args)
137
+ when :user
138
+ image['config']['user'] = resolve_env(image,args)
139
+ when :workdir
140
+ set_workdir(image,args)
141
+ when :env
142
+ set_env(image,resolve_env(image,args))
143
+ else
144
+ return false
145
+ end
146
+ true
147
+ end
148
+ end
149
+ end
150
+ end
data/lib/baha/image.rb CHANGED
@@ -65,7 +65,7 @@ module Baha
65
65
  end
66
66
 
67
67
  end
68
- attr_reader :parent, :image, :maintainer, :options, :pre_build, :bind, :command, :timeout, :workspace, :name, :tags
68
+ attr_reader :parent, :image, :maintainer, :options, :pre_build, :bind, :command, :timeout, :workspace, :name, :tags, :run
69
69
 
70
70
  def initialize(config,image)
71
71
  @parent = Baha::Image.parse_with_default(image['parent'] || config.defaults[:parent], config.defaults[:repository])
@@ -76,6 +76,7 @@ module Baha
76
76
  @pre_build = image['pre_build']
77
77
  @bind = image['bind'] || config.defaults[:bind]
78
78
  @command = image['command'] || config.defaults[:command]
79
+ @run = image['run']
79
80
  @timeout = image['timeout'] || config.defaults[:timeout]
80
81
  @workspace = config.workspace + (image['workspace'] || @image[:name])
81
82
  @name = @image[:name]
data/lib/baha/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Baha
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/builder_spec.rb CHANGED
@@ -44,10 +44,15 @@ describe Baha::Builder do
44
44
  let(:image2) {
45
45
  double('image2')
46
46
  }
47
+ let (:init) {
48
+ double('init.sh')
49
+ }
47
50
  before do
48
51
  allow_any_instance_of(Baha::Image).to receive(:needs_update?).and_return(true)
49
52
  allow_any_instance_of(Baha::Image).to receive(:parent_id).and_return('AAAA')
50
53
  allow(Docker::Container).to receive(:create).and_return(container)
54
+ allow(File).to receive(:open).and_call_original
55
+ allow(File).to receive(:open).with(pathname_matching(/init.sh$/),'w').and_yield(init)
51
56
  allow(container).to receive(:start)
52
57
  allow(container).to receive(:stop)
53
58
  allow(container).to receive(:streaming_logs).with({"stdout"=>true, "stderr"=>true, "follow"=>true, "timestamps"=>false}).and_yield(:stdout,"console message").and_yield(:stderr,"error line")
@@ -57,22 +62,30 @@ describe Baha::Builder do
57
62
  allow(Docker::Image).to receive(:get).with('BBBB').and_return(image)
58
63
  allow(image).to receive(:tag)
59
64
  allow(container).to receive(:remove)
65
+ allow(init).to receive(:write)
60
66
  end
61
67
  it 'executes pre_build step' do
62
68
  subject.build!
63
69
  expect(Baha::PreBuild::Module).to have_received(:execute).twice.with(hash_including('download' => "http://www.google.com"))
64
70
  end
71
+ it 'write run script' do
72
+ subject.build!
73
+ expect(init).to have_received(:write).with("#!/bin/sh\n").ordered
74
+ expect(init).to have_received(:write).with("set -xe\n").ordered
75
+ expect(init).to have_received(:write).with("echo \"Hello\"\n").ordered
76
+ expect(init).to have_received(:write).with("/bin/echo World\n").ordered
77
+ end
65
78
  it 'creates containers' do
66
79
  subject.build!
67
80
  expect(Docker::Container).to have_received(:create).twice.with({"Image"=>"AAAA", "Cmd"=>["/bin/bash", "./init.sh"], "Workingdir"=>"/.baha"})
68
81
  end
69
82
  it 'starts containers' do
70
83
  subject.build!
71
- expect(container).to have_received(:start).twice
84
+ expect(container).to have_received(:start).exactly(3).times
72
85
  end
73
86
  it 'commits containers' do
74
87
  subject.build!
75
- expect(container).to have_received(:commit).with({"run"=>{"ExposedPorts"=>{"8080/tcp"=>{}}}}).ordered
88
+ expect(container).to have_received(:commit).with({"run"=>{"ExposedPorts"=>{"8080/tcp"=>{}, "8081/tcp"=>{}, "8009/tcp"=>{}}}}).ordered
76
89
  expect(container).to have_received(:commit).with({'run' => {}}).ordered
77
90
  end
78
91
  it 'tags image' do
data/spec/config_spec.rb CHANGED
@@ -39,6 +39,22 @@ describe Baha::Config do
39
39
  its(:configdir) { should eq(fixture_path) }
40
40
  its(:workspace) { should eq(fixture_path + 'workspace') }
41
41
  end
42
+ context "with dockerfile" do
43
+ subject { Baha::Config.load(fixture('config_dockerfile.yml')) }
44
+ its(:defaults) { should eq(
45
+ {
46
+ :parent=>"ubuntu:14.04.1",
47
+ :bind=>"/.baha",
48
+ :repository=>'docker.example.com/baha',
49
+ :maintainer => "Ishmael <ishmael@example.com>",
50
+ :command => ['/bin/bash','./init.sh'],
51
+ :timeout => 1200
52
+ })
53
+ }
54
+ its(:options) { should eq({}) }
55
+ its(:configdir) { should eq(fixture_path) }
56
+ its(:workspace) { should eq(fixture_path + 'workspace') }
57
+ end
42
58
  context "with DOCKER_CERT_PATH set" do
43
59
  subject { Baha::Config.load(fixture('config_embedded.yml')) }
44
60
  before do
@@ -87,7 +103,7 @@ describe Baha::Config do
87
103
  subject.each_image do |image|
88
104
  images << image
89
105
  end
90
- expect(images.size).to eq(2)
106
+ expect(images.size).to eq(3)
91
107
  end
92
108
  end
93
109
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'baha/config'
3
+
4
+ describe Baha::Config do
5
+ before do
6
+ ENV['DOCKER_CERT_PATH'] = nil
7
+ ENV['DOCKER_TLS_VERIFY'] = nil
8
+ end
9
+ describe "#parse" do
10
+ context "with valid Dockerfile" do
11
+ subject { Baha::Dockerfile.parse(fixture('Dockerfile')) }
12
+ its(['parent']) { should eq('ubuntu:14.04.1')}
13
+ its(['run']) { should eq([
14
+ "echo \"Hello\"",
15
+ ["/bin/echo", "World"],
16
+ "echo Hello \nworld \nmultiline"])}
17
+ its(['config']) { should eq({
18
+ "entrypoint"=>["/bin/bash"],
19
+ "exposedports"=>["8080", "8081", "8009"],
20
+ "env"=>{
21
+ "HOME"=>"/home/user",
22
+ "BIN_DIR"=>"bin",
23
+ "HOME2"=>"/home/user/two",
24
+ "USER"=>"daemon"},
25
+ "workingdir"=>"/home/user/bin/b/c",
26
+ "cmd"=>"-l",
27
+ "user"=>"daemon",
28
+ "volumes"=>[
29
+ "/home/user",
30
+ "/logs",
31
+ "/home/user/logs",
32
+ "/data"]})}
33
+ end
34
+ context "with invalid Dockerfile" do
35
+ it { expect { Baha::Dockerfile.parse(fixture('Dockerfile.invalid')) }.to raise_error(Baha::DockerfileParseError) }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ # Comment
2
+ FROM ubuntu:14.04.1
3
+
4
+ MAINTAINER "Captain Ahab" <ahab@example.com>
5
+
6
+ RUN echo "Hello"
7
+ RUN ["/bin/echo", "World"]
8
+ RUN echo Hello \
9
+ world \
10
+ multiline
11
+
12
+ ENTRYPOINT ["/bin/bash"]
13
+
14
+ EXPOSE 8080
15
+ EXPOSE 8081
16
+ EXPOSE 8009
17
+
18
+ ENV HOME /home/user
19
+ ENV BIN_DIR bin
20
+ ENV HOME2 $HOME/two
21
+ ENV USER daemon
22
+
23
+ WORKDIR ${HOME}
24
+ WORKDIR $BIN_DIR
25
+ WORKDIR b
26
+ WORKDIR c
27
+
28
+ CMD -l
29
+
30
+ USER ${USER}
31
+
32
+ VOLUME $HOME /logs
33
+ VOLUME ["$HOME/logs", "/data"]
@@ -0,0 +1,4 @@
1
+ # Comment
2
+ FROM ubuntu:14.04.1
3
+
4
+ INVALID line here
@@ -9,4 +9,7 @@ images:
9
9
  name: derived
10
10
  tag: 1.0.0
11
11
  pre_build:
12
- - { download: 'http://www.google.com', file: 'myfile.txt' }
12
+ - { download: 'http://www.google.com', file: 'myfile.txt' }
13
+ - name: dockerfile
14
+ tag: 1.0
15
+ dockerfile: Dockerfile
@@ -7,4 +7,6 @@ pre_build:
7
7
  - { download: 'http://www.google.com', file: 'myfile.txt' }
8
8
  config:
9
9
  exposedports:
10
- - 8080
10
+ - 8080
11
+ - '8081'
12
+ - 8009/tcp
@@ -0,0 +1,9 @@
1
+ ---
2
+ defaults:
3
+ parent: ubuntu:14.04.1
4
+ repository: docker.example.com/baha
5
+ maintainer: Ishmael <ishmael@example.com>
6
+ images:
7
+ - dockerfile: Dockerfile
8
+ name: base
9
+ tag: 1.0.0
@@ -9,4 +9,10 @@ images:
9
9
  - parent: 'ubuntu:14.04.1'
10
10
  name: base
11
11
  tag: 1.0.0
12
- maintainer: '"Captain Ahab" <ahab@example.com>'
12
+ maintainer: '"Captain Ahab" <ahab@example.com>'
13
+ - dockerfile: Dockerfile
14
+ name: dockerfile
15
+ tag: 1.0.0
16
+ - dockerfile: no such dockerfile
17
+ name: invalid
18
+ tag: 1.0.0
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
1
4
  require 'simplecov'
2
5
  SimpleCov.start do
3
6
  add_filter '/spec/'
@@ -36,4 +39,15 @@ RSpec.configure do |config|
36
39
  config.before(:each) do
37
40
  Baha::Log.logfile = StringIO.new
38
41
  end
42
+ end
43
+
44
+ RSpec::Matchers.define :pathname_matching do |expected|
45
+ match do |actual|
46
+ case expected
47
+ when Regexp
48
+ expected.match(actual.to_s) != nil
49
+ else
50
+ expected == actual
51
+ end
52
+ end
39
53
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baha
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justen Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-30 00:00:00.000000000 Z
11
+ date: 2014-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -136,7 +136,11 @@ dependencies:
136
136
  - - ~>
137
137
  - !ruby/object:Gem::Version
138
138
  version: 0.9.1
139
- description: Baha - A tool for describing image builds for Docker
139
+ description: ! 'Baha is a command-line utility that assists in the creation of docker
140
+ images.
141
+
142
+ It addresses some of Dockerfiles shortcomings and encourages smaller, reusable,
143
+ tagged images.'
140
144
  email:
141
145
  - justen.walker+github@gmail.com
142
146
  executables:
@@ -146,6 +150,7 @@ extra_rdoc_files: []
146
150
  files:
147
151
  - .gitignore
148
152
  - .travis.yml
153
+ - CHANGELOG.md
149
154
  - Gemfile
150
155
  - LICENSE.txt
151
156
  - README.md
@@ -156,6 +161,7 @@ files:
156
161
  - example/base/init.sh.erb
157
162
  - example/base/test-template.erb
158
163
  - example/example.yml
164
+ - example/memcached/Dockerfile
159
165
  - example/rvm/image.yml
160
166
  - example/rvm/init.sh.erb
161
167
  - lib/baha.rb
@@ -170,6 +176,7 @@ files:
170
176
  - lib/baha/container_options/invalid_option_error.rb
171
177
  - lib/baha/container_options/option.rb
172
178
  - lib/baha/container_options/volumes.rb
179
+ - lib/baha/dockerfile.rb
173
180
  - lib/baha/image.rb
174
181
  - lib/baha/log.rb
175
182
  - lib/baha/pre_build.rb
@@ -186,9 +193,13 @@ files:
186
193
  - spec/container_options/exposed_ports_spec.rb
187
194
  - spec/container_options/option_spec.rb
188
195
  - spec/container_options/volumes_spec.rb
196
+ - spec/dockerfile_spec.rb
197
+ - spec/fixtures/Dockerfile
198
+ - spec/fixtures/Dockerfile.invalid
189
199
  - spec/fixtures/base_image.yml
190
200
  - spec/fixtures/config_build.yml
191
201
  - spec/fixtures/config_build_image.yml
202
+ - spec/fixtures/config_dockerfile.yml
192
203
  - spec/fixtures/config_eachimage.yml
193
204
  - spec/fixtures/config_embedded.yml
194
205
  - spec/fixtures/config_include.yml
@@ -203,7 +214,7 @@ files:
203
214
  - spec/pre_build/template_spec.rb
204
215
  - spec/pre_build_spec.rb
205
216
  - spec/spec_helper.rb
206
- homepage: ''
217
+ homepage: https://github.com/justenwalker/baha
207
218
  licenses:
208
219
  - MIT
209
220
  metadata: {}
@@ -226,7 +237,7 @@ rubyforge_project:
226
237
  rubygems_version: 2.1.11
227
238
  signing_key:
228
239
  specification_version: 4
229
- summary: Baha - A tool for describing image builds for Docker
240
+ summary: Baha is a command-line utility that assists in the creation of docker images.
230
241
  test_files:
231
242
  - spec/builder_spec.rb
232
243
  - spec/config_spec.rb
@@ -236,9 +247,13 @@ test_files:
236
247
  - spec/container_options/exposed_ports_spec.rb
237
248
  - spec/container_options/option_spec.rb
238
249
  - spec/container_options/volumes_spec.rb
250
+ - spec/dockerfile_spec.rb
251
+ - spec/fixtures/Dockerfile
252
+ - spec/fixtures/Dockerfile.invalid
239
253
  - spec/fixtures/base_image.yml
240
254
  - spec/fixtures/config_build.yml
241
255
  - spec/fixtures/config_build_image.yml
256
+ - spec/fixtures/config_dockerfile.yml
242
257
  - spec/fixtures/config_eachimage.yml
243
258
  - spec/fixtures/config_embedded.yml
244
259
  - spec/fixtures/config_include.yml