racker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ ## 0.1.0 (2014-02-23)
2
+
3
+ * Initial public release
4
+
5
+ ## 0.0.3 (Internal)
6
+
7
+ * Adding support for outstanding builders (digitalocean,docker,google,openstack and qemu)
8
+ * Added more robust logging support
9
+
10
+ ## 0.0.2 (Internal)
11
+
12
+ * Removed ability to name post-processors due to packer template change.
13
+
14
+ ## 0.0.1 (Internal)
15
+
16
+ * Initial private release
17
+ * Supports Amazon, Virtualbox and VMWare builders
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2013-2014 Anthony Spring (<tony@porkchopsandpaintchips.com>)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/NOTICE ADDED
@@ -0,0 +1,8 @@
1
+ Racker NOTICE
2
+ ===========
3
+
4
+ Racker incorporates code modified from Chef (https://github.com/opscode/chef), which is Copyright (c) 2008-2014 Chef Software, Inc.
5
+
6
+ Racker incorporates code modified from deep_merge (http://trac.misuse.org/science/wiki/DeepMerge), which is Copyright (c) 2008 Steve Midgley
7
+
8
+ Racker incorporates code modified from Vagrant (https://github.com/mitchellh/vagrant) which is Copyright (c) 2010-2014 Mitchell Hashimoto
data/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # Racker
2
+
3
+ * Website: http://github.com/aspring/racker
4
+
5
+ Racker is an opinionated Ruby DSL for generating Packer(www.packer.io) templates.
6
+
7
+ Racker is able to take multiple Racker templates, merge them together, and generate a single Packer template. This process allows for deep merging Packer configuration pieces to give the user a more granular approach for creating and organizing templates, not currently possible with the Packer template format.
8
+
9
+ ## Features
10
+
11
+ * Allows for building Packer templates from DRY modular templates
12
+ * Allows for commenting sections of the template
13
+ * Supports use of knockouts when merging
14
+
15
+ ## Installation
16
+
17
+ $ gem install racker
18
+
19
+ ## Usage
20
+ To generate a Packer template from a Racker template, run:
21
+
22
+ $ racker rackertemplate1.rb packertemplate.json
23
+
24
+ To generate a Packer template from multiple Racker templates, run:
25
+
26
+ $ racker rackertemplate1.rb rackertemplate2.rb packertemplate.json
27
+
28
+ To merge multiple templates you can keep adding Racker templates:
29
+
30
+ $ racker rackertemplate1.rb rackertemplate2.rb rackertemplate3.rb packertemplate.json
31
+
32
+ The output of the previous command will be the template 1 deep merged with template2, the result of this merge is deep merged with template 3 then output as a packer template.
33
+
34
+ ## Racker Template Syntax
35
+ The goal of Racker is to provide a template structure that allows for allowing full control of the template merging process to achieve the desired Packer template.
36
+
37
+ In order to do this Racker takes an opinionated stance on the following:
38
+
39
+ * All arrays within Packer Builder namespace are converted to hashes with well defined keys -- this allows for easy knockout capability based on key name.
40
+ * The provisioners hash uses a Fixnum key to allow for defining an order that provisioners will be written to the Packer template.
41
+
42
+ #### Base Template Syntax
43
+
44
+ The most basic Racker template would be the following:
45
+
46
+ ```ruby
47
+ Racker::Processor.register_template do |t|
48
+ end
49
+ ```
50
+
51
+ This template would not define a variable, builder, provisioner or post-processor and would be a pretty boring template.
52
+
53
+ #### Variables Namespace
54
+
55
+ Racker templates support the `variables` namespace which is a hash. This hash maps one to one to a Packer template's variables section.
56
+
57
+ This is an example of a basic `variables` definition:
58
+
59
+ ```ruby
60
+ Racker::Processor.register_template do |t|
61
+ # Define the variables
62
+ t.variables = {
63
+ 'iso_checksum' => '6232efa014d9c6798396b63152c4c9a08b279f5e',
64
+ 'iso_checksum_type' => 'sha1',
65
+ 'iso_url' => 'http://mirrors.kernel.org/centos/6.4/isos/x86_64/CentOS-6.4-x86_64-minimal.iso',
66
+ 'kickstart_file' => 'template1-ks.cfg',
67
+ 'vagrant_output_file' => "./boxes/centos-6.4-{{.Provider}}.box"
68
+ }
69
+ end
70
+ ```
71
+
72
+ #### Builders Namespace
73
+
74
+ Racker templates support the `builders` namespace which is a hash, keyed by the name of the builder.
75
+
76
+ All Packer arrays inside of this namespace should be represented as hashes in Racker. Racker will use the value when creating the template, the key is there purely for allowing you to override/knockout as necessary.
77
+
78
+ This is an abbreviated example of adding a builder named 'test' that is a 'virtualbox-iso' builder type:
79
+
80
+ ```ruby
81
+ Racker::Processor.register_template do |t|
82
+ # Define the builders
83
+ t.builders['test'] = {
84
+ 'type' => 'virtualbox-iso',
85
+ 'guest_os_type' => 'RedHat_64',
86
+ 'headless' => true,
87
+ 'format' => 'ova',
88
+ 'guest_additions_path' => "VBoxGuestAdditions_{{.Version}}.iso",
89
+ 'iso_checksum' => "{{user `iso_checksum`}}",
90
+ 'iso_checksum_type' => "{{user `iso_checksum_type`}}",
91
+ 'iso_url' => "{{user `iso_url`}}",
92
+ 'virtualbox_version_file' => '.vbox_version',
93
+ 'boot_command' => {
94
+ 0 => '<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/{{user `kickstart_file`}}<enter><wait>'
95
+ },
96
+ 'boot_wait' => '10s',
97
+ 'http_directory' => 'http_directory',
98
+ 'ssh_port' => 22,
99
+ 'ssh_username' => 'root',
100
+ 'ssh_password' => 'asdfasdf',
101
+ 'ssh_wait_timeout' => '10000s',
102
+ 'shutdown_command' => 'shutdown -P now',
103
+ 'disk_size' => 8096,
104
+ 'vboxmanage' => {
105
+ 'memory' => [ 'modifyvm', '{{.Name}}', '--memory', '1024' ],
106
+ 'cpus' => [ 'modifyvm', '{{.Name}}', '--cpus', '1' ],
107
+ 'ioapic' => [ 'modifyvm', '{{.Name}}', '--ioapic', 'on' ]
108
+ }
109
+ }
110
+ end
111
+ ```
112
+ One of the sections of node in this builder is the `vboxmanage`. It has been converted into a Hash to make it easier to knockout.
113
+
114
+ #### Provisioners Namespace
115
+
116
+ Racker templates support the `provisioners` namespace which is a Fixnum keyed hash.
117
+
118
+ When generating the Packer template, Racker will order the provisioners based upon the Fixnum key, this allows complete control on the ordering of provisioners throughout Racker templates.
119
+
120
+ ```ruby
121
+ Racker::Processor.register_template do |t|
122
+ # Define the provisioners
123
+ t.provisioners = {
124
+ 0 => {
125
+ 'update-cacert-bundle' => {
126
+ 'type' => 'shell',
127
+ 'script' => 'scripts/common/update-cacert-bundle.sh'
128
+ },
129
+ },
130
+ 300 => {
131
+ 'install-chef-11.8.0' => {
132
+ 'type' => 'shell',
133
+ 'script' => 'scripts/common/install-chef-11.8.0.sh'
134
+ },
135
+ },
136
+ 500 => {
137
+ 'install-guest-additions-dependencies' => {
138
+ 'type' => 'shell',
139
+ 'scripts' => [
140
+ 'scripts/common/install-guest-additions.sh'
141
+ ],
142
+ },
143
+ },
144
+ 750 => {
145
+ 'disable-services' => {
146
+ 'type' => 'shell',
147
+ 'script' => 'scripts/centos-6/disable-services.sh'
148
+ },
149
+ },
150
+ 900 => {
151
+ 'prepare-vagrant-instance' => {
152
+ 'type' => 'shell',
153
+ 'script' => 'scripts/common/prepare-vagrant-instance.sh',
154
+ 'only' => ['test']
155
+ },
156
+ 'prepare-ec2-instance' => {
157
+ 'type' => 'shell',
158
+ 'script' => 'scripts/common/prepare-ec2-instance.sh',
159
+ 'only' => ['amazon']
160
+ },
161
+ }
162
+ }
163
+ end
164
+ ```
165
+
166
+ #### Post-Processors Namespace
167
+
168
+ Racker templates support the `postprocessors` namespace which is a hash, keyed by the name of the post-processor.
169
+
170
+ ```ruby
171
+ Racker::Processor.register_template do |t|
172
+ # Define the post-processors
173
+ t.postprocessors['vagrant'] = {
174
+ 'type' => 'vagrant',
175
+ 'output' => '{{user `vagrant_output_file`}}',
176
+ 'compression_level' => 7,
177
+ 'keep_input_artifact' => true,
178
+ 'only' => ['virtualbox-vagrant','vmware-vagrant']
179
+ }
180
+ end
181
+ ```
182
+
183
+ ### Putting it all together
184
+
185
+ Racker offers 2 very basic example templates `example/template1.rb` and `example/template2.rb` as well as the resulting packer template from the two templates run through Racker.
186
+
187
+ To experiement with these templates, after installing Racker, and cloning this repo you can execute the following:
188
+
189
+ $ racker ./example/template1rb ./example/tempalte2.rb ./example/packer.json
190
+
191
+ While these two templates are not all inclusive of the capabilities of Racker, it shows off the ability to have a basic template, and a second template that removes the pieces of the template that target Amazon, as well as adds two chef solo provisioner steps.
192
+
193
+ ## Testing
194
+
195
+ TODO: This section needs to be written
196
+
197
+ ## Outstanding Development
198
+
199
+ * The following builders have not been fully tested:
200
+ * docker
201
+ * qemu
202
+ * Implement unit testing
203
+ * Travis CI
204
+ * Additional documentation work
205
+ * Add capability to target specific packer versions should the packer template format change.
206
+ * Add quick init to generate a basic Racker template
207
+
208
+ ## Contributions
209
+
210
+ Feel free to fork and request a pull, or submit a ticket
211
+ https://github.com/aspring/racker/issues
212
+
213
+ ## License
214
+
215
+ This project is available under the MIT license. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'bundler/gem_tasks'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts 'Run `bundle install` to install missing gems'
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'rake'
13
+ require 'rspec/core'
14
+ require 'rspec/core/rake_task'
15
+ require 'rubocop/rake_task'
16
+ RSpec::Core::RakeTask.new(:spec) do |t|
17
+ t.pattern = FileList['spec/**/*_spec.rb']
18
+ end
19
+
20
+ desc 'Run RSpec with code coverage'
21
+ task :coverage do
22
+ ENV['COVERAGE'] = 'true'
23
+ Rake::Task['spec'].execute
24
+ end
25
+
26
+ require 'rubocop/rake_task'
27
+ Rubocop::RakeTask.new(:rubocop) do |t|
28
+ # Specify the files we will look at
29
+ t.patterns = ['bin', File.join('{lib}','**', '*.rb')]
30
+
31
+ # Do not fail on error
32
+ t.fail_on_error = false
33
+ end
34
+
35
+ require 'yard'
36
+ YARD::Rake::YardocTask.new
37
+
38
+ task default: [:spec]
data/bin/racker ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ if RUBY_VERSION >= '1.9.2'
5
+ require 'log4r'
6
+
7
+ begin
8
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
9
+ require 'racker'
10
+
11
+ # Create the initial logger
12
+ log = Log4r::Logger.new('racker')
13
+
14
+ # Set the output to STDOUT
15
+ log.outputters = Log4r::Outputter.stdout
16
+
17
+ # We set the initial log level to ERROR
18
+ log.level = Log4r::ERROR
19
+
20
+ # Let the CLI do its thing
21
+ exit_code = Racker::CLI.new(ARGV.dup).execute!
22
+
23
+ log.info("Exit code: #{exit_code}")
24
+ Kernel.exit!(exit_code)
25
+ rescue Exception => e
26
+ log = Log4r::Logger.new('racker')
27
+ log.outputters = Log4r::Outputter.stdout
28
+ log.error("Rackers encountered an unexpected error!")
29
+ log.error()
30
+ log.error("Details:")
31
+ log.error(e.inspect)
32
+ log.error(e.message)
33
+ log.error(e.backtrace.join('\n'))
34
+ exit e.status_code if e.respond_to?(:status_code)
35
+ exit 999
36
+ end
37
+ else
38
+ puts 'Racker supports only Ruby 1.9.2+'
39
+ exit(-1)
40
+ end
data/lib/racker.rb ADDED
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ # Internal
4
+ require 'racker/cli'
5
+ require 'racker/processor'
6
+ require 'racker/version'
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ require 'racker/builders/builder'
3
+
4
+ module Racker
5
+ module Builders
6
+ # This is the Amazon builder
7
+ class Amazon < Racker::Builders::Builder
8
+ def to_packer(name, config)
9
+ log = Log4r::Logger['racker']
10
+ log.debug("Entering #{self.class}.#{__method__}")
11
+ config = super(name, config)
12
+
13
+ %w(ami_block_device_mappings ami_groups ami_product_codes ami_regions ami_users chroot_mounts copy_files launch_block_device_mappings security_group_ids).each do |key|
14
+ if config.key? key
15
+ log.info("Converting #{key} to packer value...")
16
+ config[key] = convert_hash_to_packer_value(config[key])
17
+ end
18
+ end
19
+
20
+ log.debug("Leaving #{self.class}.#{__method__}")
21
+ config
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module Racker
4
+
5
+ module Builders
6
+ # This is the Builder base class
7
+ class Builder
8
+ def to_packer(name, config)
9
+ log = Log4r::Logger['racker']
10
+ log.debug("Entering #{self.class}.#{__method__}")
11
+
12
+ # Set the name of the builder
13
+ log.info("Setting config name to #{name}")
14
+ config['name'] = name
15
+
16
+ log.debug("Leaving #{self.class}.#{__method__}")
17
+ config
18
+ end
19
+
20
+ def convert_hash_to_packer_value(config)
21
+ config.kind_of?(Hash) ? config.values : config
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ require 'racker/builders/builder'
3
+
4
+ module Racker
5
+ module Builders
6
+ # This is the DigitalOcean builder
7
+ class DigitalOcean < Racker::Builders::Builder
8
+ def to_packer(name, config)
9
+ log = Log4r::Logger['racker']
10
+ log.debug("Entering #{self.class}.#{__method__}")
11
+ config = super(name, config)
12
+
13
+ # There are no special cases at this point
14
+
15
+ # %w().each do |key|
16
+ # if config.key? key
17
+ # log.info("Converting #{key} to packer value...")
18
+ # config[key] = convert_hash_to_packer_value(config[key])
19
+ # end
20
+ # end
21
+
22
+ log.debug("Leaving #{self.class}.#{__method__}")
23
+ config
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ require 'racker/builders/builder'
3
+
4
+ module Racker
5
+ module Builders
6
+ # This is the Docker builder
7
+ class Docker < Racker::Builders::Builder
8
+ def to_packer(name, config)
9
+ log = Log4r::Logger['racker']
10
+ log.debug("Entering #{self.class}.#{__method__}")
11
+ config = super(name, config)
12
+
13
+ %w(run_command).each do |key|
14
+ if config.key? key
15
+ log.info("Converting #{key} to packer value...")
16
+ config[key] = convert_hash_to_packer_value(config[key])
17
+ end
18
+ end
19
+
20
+ log.debug("Leaving #{self.class}.#{__method__}")
21
+ config
22
+ end
23
+ end
24
+ end
25
+ end