vagabond 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## v0.2.0
2
+ * Migrate to thor
3
+ * Clean up option usage
4
+ * Add support for custom template builds
5
+ * DRY out some reusable stuffs
6
+ * Change Vagabondfile key :boxes to :nodes
7
+ * Start on defined color codes for actions/states (not implemented)
8
+ * Add some validation and error checking
9
+ * Make server stuff work better
10
+ * Add integrated support for test kitchen 1.0
11
+ * Add new 'cluster' support for test kitchen 1.0
12
+
1
13
  ## v0.1.4
2
14
  * Fix color option to do the right thing
3
15
 
data/README.md CHANGED
@@ -14,6 +14,10 @@ easily and most importantly, quickly. It uses Linux containers
14
14
  instead of full blown VMs which means things are faster. Lots
15
15
  faster.
16
16
 
17
+ Vagabond is built for Chef. The tooling within Vagabond is targeted
18
+ at Chef. As the initial development push on Vagabond slows, this
19
+ tooling will become optionally swappable (applicable bits at least).
20
+
17
21
  ## Installation
18
22
 
19
23
  As a rubygem:
@@ -22,16 +26,16 @@ As a rubygem:
22
26
  $ gem install vagabond
23
27
  ```
24
28
 
25
- ## How it is?
29
+ ## How does it work
26
30
 
27
31
  Currently, this is built to run within a classic Chef repository.
28
- It requires a Vagabond file, that simply outputs a Hash. The file
32
+ It requires a `Vagabond` file, that simply outputs a Hash. The file
29
33
  is Ruby though, so you can do lots of crazy stuff to build the
30
34
  Hash you return. Heres a simple example:
31
35
 
32
36
  ```ruby
33
37
  {
34
- :boxes => {
38
+ :nodes => {
35
39
  :precise => {
36
40
  :template => 'ubuntu_1204',
37
41
  :run_list => %w(role[base])
@@ -48,6 +52,12 @@ Hash you return. Heres a simple example:
48
52
  }
49
53
  ```
50
54
 
55
+ Now, to create a node, simply run:
56
+
57
+ ```
58
+ $ vagabond up db
59
+ ```
60
+
51
61
  Pretty simple, right?
52
62
 
53
63
  ### Templates available
@@ -64,49 +74,8 @@ Currently builtin templates:
64
74
 
65
75
  ## Commands
66
76
 
67
- Lots of commands. What to see them all? Just ask:
68
-
69
- ```
70
- $ vagabond --help
71
- Nodes:
72
- vagabond create NODE [options]
73
- vagabond destroy NODE [options]
74
- vagabond freeze NODE [options]
75
- vagabond provision NODE [options]
76
- vagabond rebuild NODE [options]
77
- vagabond ssh NODE [options]
78
- vagabond start NODE [options]
79
- vagabond status NODE [options]
80
- vagabond thaw NODE [options]
81
- vagabond up NODE [options]
82
- Server:
83
- vagabond server auto_upload [options]
84
- vagabond server create [options]
85
- vagabond server destroy [options]
86
- vagabond server freeze [options]
87
- vagabond server provision [options]
88
- vagabond server rebuild [options]
89
- vagabond server ssh [options]
90
- vagabond server start [options]
91
- vagabond server status [options]
92
- vagabond server stop [options]
93
- vagabond server thaw [options]
94
- vagabond server up [options]
95
- vagabond server upload_cookbooks [options]
96
- vagabond server upload_databags [options]
97
- vagabond server upload_environments [options]
98
- vagabond server upload_roles [options]
99
- Knife:
100
- vagabond knife COMMAND [knife_options]
101
- Options:
102
- --color
103
- --debug
104
- --disable-auto-provision
105
- --disable-local-server
106
- --disable-configure
107
- --force-configure
108
- -f, --vagabond-file FILE
109
- ```
77
+ See the `USAGE` file for an overview of available commands and their
78
+ usage.
110
79
 
111
80
  ## Local chef server?
112
81
 
@@ -133,6 +102,35 @@ vagabond knife SOME COOL KNIFE COMMAND
133
102
 
134
103
  This will just push the command into the local chef server.
135
104
 
105
+ ## Test Kitchen
106
+
107
+ Vagabond provides test kitchen 1.0 support. It will map boxes defined
108
+ within platforms to platform templates available (to the best of its
109
+ ability). No need to spin up vagrant VMs, or use another tool. Point
110
+ vagabond at the cookbook, and let it handle the details.
111
+
112
+ In the TODO pipeline is allowing platform mapping in the Vagabondfile
113
+ so custom templates (with memory limits for example) can be used
114
+ instead of the base templates.
115
+
116
+ ### Cluster testing
117
+
118
+ Vagabond adds an extra feature to test kitchen: cluster testing. This
119
+ type of testing uses the local chef server, and provides an extreme
120
+ amount of power to tests. Instead of provisioning a node and simply
121
+ testing it in isolation, cluster testing provides the support to
122
+ provision multiple nodes against the local chef server. Once all
123
+ nodes have been successfully provisioned, vagabond will go back through
124
+ each node and run tests.
125
+
126
+ Seems simple, right? It is, but it's also extremely powerful. Instead
127
+ of testing things individually and isolated, this allows for real
128
+ integration testing. Tests can be applied to discovery, slaving,
129
+ and all the other fun things nodes may be doing that require a
130
+ chef server. Looking for example? See the `USAGE` file!
131
+
132
+ Double awesome
133
+
136
134
  ## Important note
137
135
 
138
136
  Until namespaces hit Linux proper, vagabond `sudo`s its way around. You
@@ -152,8 +150,10 @@ boring old `sudo`, you can do that to:
152
150
 
153
151
  ## Extra note
154
152
 
155
- This is still very much in alpha testing phase. So if you find bugs, please
156
- report them!
153
+ This thing is still very new and shiny with lots of sharp edges. They
154
+ are getting sanded down as quickly as possible. If you find bugs, are
155
+ confused about some of the available functionality, or just want to point
156
+ out some stupidity that I have implemented, please file an issue on github!
157
157
 
158
158
  ## Contributing
159
159
 
data/USAGE.md ADDED
@@ -0,0 +1,197 @@
1
+ # Vagabond USAGE
2
+
3
+ ## Requirements
4
+
5
+ * Chef repository structure
6
+ * Ubuntu >= 12.04
7
+ * This requirement is soft. It is only here because it is the only place it has currently been tested. Testing on centos, debian, and arch is coming soon.
8
+
9
+ ## Setup
10
+
11
+ * Install vagabond either in a Gemfile, or via gem:
12
+
13
+ ```
14
+ $ gem install vagabond
15
+ ```
16
+
17
+ Drop a Vagabondfile in the root of your Chef repository. Here is a
18
+ very simple Vagabond file to start with:
19
+
20
+ ```ruby
21
+ {
22
+ :nodes => {
23
+ :my_precise_node => {
24
+ :template => 'ubuntu_1204',
25
+ :run_list => ['role[base]']
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ This assumes you have a role named base, and that it and its dependencies
32
+ are currently pushed up to your configured chef server. So, we create our
33
+ node:
34
+
35
+ ```
36
+ $ vagabond up my_precise_node
37
+ ```
38
+
39
+ The first time this runs, it will take some time. Vagabond will provision
40
+ your local system (using chef-solo) to install the required LXC tools, and
41
+ to build the templates in use by your Vagabond file. Vagabond will do
42
+ this any time it determines it's required, generally when new templates
43
+ are discovered that does not already have a base container built. So sit
44
+ back, the first build will take a few.
45
+
46
+ ## Custom templates
47
+
48
+ Custom templates are templates that are based on the builtin templates
49
+ but have some restriction placed on them, for example memory usage. Using
50
+ our current Vagabond file example, lets say we wanted to use a container
51
+ that only had 512MB of memory available to it, and no swap space. We
52
+ would provide the details for a custom template, and set the `my_precise_node`
53
+ to then use that template:
54
+
55
+
56
+ ```ruby
57
+ {
58
+ :nodes => {
59
+ :my_precise_node => {
60
+ :template => 'custom_1204_512',
61
+ :run_list => ['role[base]']
62
+ }
63
+ },
64
+ :templates => {
65
+ :custom_1204_512 => {
66
+ :base => 'ubuntu_1204',
67
+ :memory => {
68
+ :ram => '512M',
69
+ :swap => 0
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## vagabond
77
+
78
+ The `vagabond` command is used for interaction with nodes. Simply running:
79
+
80
+ ```
81
+ $ vagabond
82
+ ```
83
+
84
+ will provide a list of available actions.
85
+
86
+ ## vagabond ssh
87
+
88
+ This tool just provides an easy way to SSH into running nodes. Just
89
+ provide the name and it will drop you into a root session:
90
+
91
+ ```
92
+ $ vagabond ssh my_precise_node
93
+ ```
94
+
95
+ ## vagabond server
96
+
97
+ Vagabond will optionally allow the installation of a chef server that is
98
+ localized to the chef repository the Vagabondfile is kept within. This
99
+ is enabled in the Vagabondfile. To do this, our Vagabondfile would now
100
+ look like this:
101
+
102
+ ```ruby
103
+ {
104
+ :nodes => {
105
+ :my_precise_node => {
106
+ :template => 'ubuntu_1204',
107
+ :run_list => ['role[base]']
108
+ }
109
+ },
110
+ :local_chef_server => {
111
+ :enabled => true
112
+ }
113
+ }
114
+ ```
115
+
116
+ The next command run will trigger vagabond to reprovision and will create
117
+ a server container. The chef server will be auto configured using your
118
+ existing client information. It will seamlessly take over while using
119
+ Vagabond. The server commands are explicitly for the server container.
120
+ The commands are similar to the basic `vagabond` commands, with a few
121
+ extra commands as well.
122
+
123
+ The `:local_chef_server` hash also has two helper keys for setting up
124
+ the server:
125
+
126
+ * `:auto_upload` - Uploads all cookbooks, roles, data bags and environments after build
127
+ * `:berkshelf` - Uses berkshelf for cookbook upload instead of knife
128
+
129
+ ## vagabond knife
130
+
131
+ This tool will let you communicate with the chef server provided by Vagabond.
132
+ Just pass arguments to it like you would knife regularly, and they will
133
+ be set to the local chef server instead:
134
+
135
+ ```
136
+ $ vagabond knife cookbook list
137
+ ```
138
+
139
+ # Testing
140
+
141
+ Vagabond has built in support for test-kitchen 1.0. However, it does things
142
+ just a little bit differently. First, it will map the platform defined to an lxc
143
+ template. Second, it will use Librarian to resolve dependencies for the
144
+ cookbook and use those for testing.
145
+
146
+ Usage is straightforward:
147
+
148
+ ```
149
+ $ vagabond kitchen test COOKBOOK
150
+ ```
151
+
152
+ You can limit what you test at once by providing `--platform` and/or `--suites`
153
+ options to the test. Tests are run the same was as t-k 1.0. Run lists will be
154
+ merged, attributes pushed to the node, and solo to provision the node.
155
+
156
+ ## Clusters
157
+
158
+ Vagabond offers an extra type of testing. Instead of simply providing an isolated
159
+ place to test a cookbook (on a single node), Vagabond allows you to run tests against
160
+ a cluster of nodes, with a real chef server. This allows for real integration testing
161
+ within a real isolated environment. Multiple nodes. Real Chef server. A real environment
162
+ that can properly test the behavior of an infrastructure.
163
+
164
+ ## How it works
165
+
166
+ Currently, Vagabond adds an extra key the `.kitchen.yml` file of a cookbook. It's
167
+ the `clusters` key. It's a simple hash. The keys are the names of the cluster. The
168
+ values are arrays of strings that identify the suites to be built for the cluster.
169
+ A simple example looks like this:
170
+
171
+ ```
172
+ clusters:
173
+ default:
174
+ - cool_suite1
175
+ - cool_suite2
176
+ ```
177
+
178
+ And now, we can spin this up doing:
179
+
180
+ ```
181
+ $ vagabond kitchen test COOKBOOK --cluster default --platform ubuntu-12.04
182
+ ```
183
+
184
+ First, this will restrict our testing to just the ubuntu-12.04 platform. Next
185
+ it will upload all assets to the local chef server. It then provisions two
186
+ nodes. First it provisions cool_suite1. Next it provisions cool_suite2. These
187
+ nodes are defined by their configuration in the suites. After the nodes
188
+ have successfully provisioned, test kitchen is then run on each of the nodes
189
+ in the cluster sequentially.
190
+
191
+ Simple, yet so very very awesome. \o/
192
+
193
+ ## More to come
194
+
195
+ Testing support is still very young, just like Vagabond. But there are plans
196
+ in the works for more features. Take a look at the issues section in github
197
+ with `kitchen` tags. Feel free to add more if you see something missing!
data/bin/vagabond CHANGED
@@ -1,6 +1,28 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ Signal.trap('INT'){ exit 255 }
4
+
3
5
  require 'rubygems'
4
- require 'vagabond/commands'
6
+ require 'vagabond'
5
7
 
6
- Vagabond::Commands.new.run!(ARGV)
8
+ if(ARGV.include?('--version') || ARGV.include?('-v'))
9
+ require 'vagabond/vagabond'
10
+ Vagabond::Vagabond.new.send(:version)
11
+ else
12
+ case arg = ARGV.shift
13
+ when 'server'
14
+ require 'vagabond/server'
15
+ Vagabond::Server
16
+ when 'knife'
17
+ require 'vagabond/knife'
18
+ ARGV.unshift(arg) unless ARGV.empty?
19
+ Vagabond::Knife
20
+ when 'test', 'kitchen'
21
+ require 'vagabond/kitchen'
22
+ Vagabond::Kitchen
23
+ else
24
+ require 'vagabond/vagabond'
25
+ ARGV.unshift(arg)
26
+ Vagabond::Vagabond
27
+ end.start
28
+ end
@@ -1,10 +1,11 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Create
4
- def create
4
+ def _create
5
+ name_required!
5
6
  if(lxc.exists?)
6
7
  ui.warn "Node already exists: #{name}" unless name == 'server'
7
- start
8
+ _start
8
9
  else
9
10
  ui.info "#{ui.color('Vagabond:', :bold)} Creating #{ui.color(name, :green)}"
10
11
  do_create
@@ -15,12 +16,20 @@ module Vagabond
15
16
  private
16
17
 
17
18
  def do_create
18
- com = "#{sudo}lxc-start-ephemeral -d -o #{config[:template]}"
19
+ tmpl = config[:template]
20
+ if(internal_config[:template_mappings].keys.include?(tmpl))
21
+ tmpl = internal_config[:template_mappings][tmpl]
22
+ elsif(!BASE_TEMPLATES.include?(tmpl))
23
+ ui.fatal "Template requested for node does not exist: #{tmpl}"
24
+ exit EXIT_CODES[:invalid_template]
25
+ end
26
+ bind_path = File.expand_path(File.dirname(vagabondfile.path))
27
+ com = "#{sudo}lxc-start-ephemeral -d -b #{bind_path} -o #{tmpl}"
19
28
  debug(com)
20
- c = Mixlib::ShellOut.new("#{com} && sleep 3", :live_stream => Config[:debug])
29
+ c = Mixlib::ShellOut.new("#{com} && sleep 3", :live_stream => options[:debug])
21
30
  c.run_command
22
31
  e_name = c.stdout.split("\n").last.split(' ').last.strip
23
- @internal_config[:mappings][name] = e_name
32
+ @internal_config[mappings_key][name] = e_name
24
33
  @internal_config.save
25
34
  @lxc = Lxc.new(e_name)
26
35
  end
@@ -1,7 +1,9 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Destroy
4
- def destroy
4
+
5
+ def _destroy
6
+ name_required!
5
7
  if(lxc.exists?)
6
8
  ui.info "#{ui.color('Vagabond:', :bold)} Destroying node: #{ui.color(name, :red)}"
7
9
  do_destroy
@@ -15,24 +17,24 @@ module Vagabond
15
17
 
16
18
  def do_destroy
17
19
  lxc.stop if lxc.running?
18
- com = "#{Config[:sudo]}lxc-destroy -n #{lxc.name}"
20
+ com = "#{options[:sudo]}lxc-destroy -n #{lxc.name}"
19
21
  debug(com)
20
- cmd = Mixlib::ShellOut.new(com, :live_stream => Config[:debug])
22
+ cmd = Mixlib::ShellOut.new(com, :live_stream => options[:debug])
21
23
  cmd.run_command
22
24
  cmd.error!
23
25
  if(cmd.stderr.include?('skipping'))
24
26
  ui.info ui.color(' -> Failed to unmount some resources. Forcing manually.', :yellow)
25
27
  %w(rootfs ephemeralbind).each do |mnt|
26
- com = "#{Config[:sudo]}umount /var/lib/lxc/#{lxc.name}/#{mnt}"
28
+ com = "#{options[:sudo]}umount /var/lib/lxc/#{lxc.name}/#{mnt}"
27
29
  debug(com)
28
- cmd = Mixlib::ShellOut.new(com, :live_stream => Config[:debug])
30
+ cmd = Mixlib::ShellOut.new(com, :live_stream => options[:debug])
29
31
  cmd.run_command
30
- com = "#{Config[:sudo]}lxc-destroy -n #{lxc.name}"
32
+ com = "#{options[:sudo]}lxc-destroy -n #{lxc.name}"
31
33
  debug(com)
32
- cmd = Mixlib::ShellOut.new(com, :live_stream => Config[:debug])
34
+ cmd = Mixlib::ShellOut.new(com, :live_stream => options[:debug])
33
35
  cmd.run_command
34
36
  cmd.error!
35
- internal_config[:mappings].delete(name)
37
+ internal_config[mappings_key].delete(name)
36
38
  end
37
39
  internal_config.save
38
40
  end
@@ -1,7 +1,8 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Freeze
4
- def freeze
4
+ def _freeze
5
+ name_required!
5
6
  if(lxc.exists?)
6
7
  ui.info "#{ui.color('Vagabond:', :bold)} Freezing node: #{ui.color(name, :blue)}"
7
8
  if(lxc.running?)
@@ -1,7 +1,8 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Provision
4
- def provision
4
+ def _provision
5
+ name_required!
5
6
  if(lxc.exists?)
6
7
  if(lxc.running?)
7
8
  do_provision
@@ -22,8 +23,8 @@ module Vagabond
22
23
  if(config[:environment])
23
24
  com << "-E #{config[:environment]}"
24
25
  end
25
- if(Config[:knife_opts])
26
- com << Config[:knife_opts]
26
+ if(options[:knife_opts])
27
+ com << options[:knife_opts]
27
28
  end
28
29
  debug(com)
29
30
  # Send the live stream out since people will generally want to
@@ -33,8 +34,10 @@ module Vagabond
33
34
  # NOTE: cmd.status.success? won't be valid, so check for FATAL
34
35
  unless(cmd.stdout.split("\n").last.to_s.include?('FATAL'))
35
36
  ui.info ui.color(' -> PROVISIONED', :magenta)
37
+ true
36
38
  else
37
39
  ui.info ui.color(' -> PROVISION FAILED', :red)
40
+ false
38
41
  end
39
42
  end
40
43
 
@@ -1,15 +1,16 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Rebuild
4
- def rebuild
4
+ def _rebuild
5
+ name_required!
5
6
  ui.info "#{ui.color('Vagabond:', :bold)} Rebuilding #{ui.color(name, :blue)}"
6
- destroy
7
+ _destroy
7
8
  @lxc = Lxc.new(name)
8
- destroy
9
- Config[:force_solo] = true
9
+ _destroy
10
+ options[:force_solo] = true
10
11
  ui.info ui.color(' -> DESTROYED!', :red)
11
12
  internal_config.run_solo
12
- internal_config[:mappings].delete(name)
13
+ internal_config[mappings_key].delete(name)
13
14
  internal_config.save
14
15
  ui.info ui.color(' -> REBUILT!', :green)
15
16
  end
@@ -1,11 +1,12 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module SSH
4
- def ssh
4
+ def _ssh
5
+ name_required!
5
6
  if(lxc.exists?)
6
7
  if(lxc.running?)
7
8
  ui.info "#{ui.color('Vagabond:', :bold)} SSH connect to: #{ui.color(name, :cyan)}"
8
- exec("#{Config[:sudo]}ssh root@#{lxc.container_ip(10, true)} -i /opt/hw-lxc-config/id_rsa -oStrictHostKeyChecking=no")
9
+ exec("#{options[:sudo]}ssh root@#{lxc.container_ip(10, true)} -i /opt/hw-lxc-config/id_rsa -oStrictHostKeyChecking=no")
9
10
  else
10
11
  ui.error "Node not running: #{name}"
11
12
  end
@@ -2,7 +2,8 @@ module Vagabond
2
2
  module Actions
3
3
  module Start
4
4
 
5
- def start
5
+ def _start
6
+ name_required!
6
7
  ui.info "#{ui.color('Vagabond:', :bold)} Starting node: #{ui.color(name, :green)}"
7
8
  do_start
8
9
  ui.info ui.color(' -> STARTED', :green)
@@ -1,12 +1,28 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Status
4
- def status
4
+ class << self
5
+ def included(klass)
6
+ klass.class_eval do
7
+ class << self
8
+ def _status_desc
9
+ if(defined?(Server) && self == Server)
10
+ ['status', 'Status of server']
11
+ else
12
+ ['status [NODE]', 'Status of NODE or all nodes']
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def _status
5
21
  ui.info ui.color("Vagabond node status:\n", :bold)
6
22
  if(name)
7
23
  status_for(name)
8
24
  else
9
- (Array(vagabondfile[:boxes].keys) | Array(internal_config[:mappings].keys)).sort.each do |n|
25
+ (Array(vagabondfile[:boxes].keys) | Array(internal_config[mappings_key].keys)).sort.each do |n|
10
26
  status_for(n)
11
27
  end
12
28
  end
@@ -15,7 +31,7 @@ module Vagabond
15
31
  private
16
32
 
17
33
  def status_for(c_name)
18
- m_name = internal_config[:mappings][c_name]
34
+ m_name = internal_config[mappings_key][c_name]
19
35
  state = nil
20
36
  status = []
21
37
  if(Lxc.exists?(m_name))
@@ -1,7 +1,8 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Thaw
4
- def thaw
4
+ def _thaw
5
+ name_required!
5
6
  if(lxc.exists?)
6
7
  if(lxc.frozen?)
7
8
  ui.info "#{ui.color('Vagabond:', :bold)} Thawing node: #{ui.color(name, :yellow)}"
@@ -1,7 +1,20 @@
1
1
  module Vagabond
2
2
  module Actions
3
3
  module Up
4
- def up
4
+ class << self
5
+ def included(klass)
6
+ klass.class_eval do
7
+ class << self
8
+ def _up_options
9
+ [[:auto_provision, :type => :boolean, :default => true]]
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ def _up
17
+ name_required!
5
18
  if(lxc.exists?)
6
19
  if(lxc.running?)
7
20
  ui.error "Node already exists and is running: #{name}"
@@ -11,9 +24,9 @@ module Vagabond
11
24
  ui.info ui.color(' -> STARTED', :green)
12
25
  end
13
26
  else
14
- create
27
+ _create
15
28
  end
16
- do_provision unless Config[:disable_auto_provision]
29
+ do_provision if options[:auto_provision]
17
30
  end
18
31
 
19
32
  end
@@ -0,0 +1,36 @@
1
+ require 'chef/mash'
2
+
3
+ module Vagabond
4
+ BASE_TEMPLATES = File.readlines(
5
+ File.join(File.dirname(__FILE__), 'cookbooks/vagabond/attributes/default.rb')
6
+ ).map do |l|
7
+ l.scan(%r{bases\]\[:([^\]]+)\]}).flatten.first
8
+ end.compact.uniq
9
+
10
+ COLORS = Mash.new(
11
+ :success => :green,
12
+ :create => :green,
13
+ :setup => :blue,
14
+ :error => :red,
15
+ :failed => :red,
16
+ :verified => :yellow,
17
+ :converged => :magenta,
18
+ :destroyed => :red,
19
+ :kitchen => [:cyan, :bold]
20
+ )
21
+
22
+ EXIT_CODES = Mash.new(
23
+ :success => 0,
24
+ :reserved_name => 1,
25
+ :invalid_name => 2,
26
+ :invalid_base_template => 3,
27
+ :invalid_action => 4,
28
+ :invalid_template => 5,
29
+ :kitchen_missing_yml => 6,
30
+ :kitchen_no_cookbook_arg => 7,
31
+ :kitchen_too_many_args => 8,
32
+ :kitchen_invalid_platform => 9,
33
+ :missing_node_name => 10,
34
+ :cluster_invalid => 11
35
+ )
36
+ end