ronin-wrapper 0.0.13 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53e2dbec8e427757f3f6aa4dd83f44da312e738a
4
- data.tar.gz: d9826525467d51515bd6e17b84a7a4d3f0f02fa9
3
+ metadata.gz: cdc6b1775102883bb73d1df58558de222513bbf8
4
+ data.tar.gz: 82b46f7100cba0e521ba1295fd1ef3f420f0ed11
5
5
  SHA512:
6
- metadata.gz: 3caca00937edd64378164774cac21fa6ffe5f21577a9f69960fdabff2ae180ab14d3ac4006ed0b5d6e693f9b96da786d85ea5f2b459d0226315383b62152d6be
7
- data.tar.gz: 2144ce58a9df7fea7f7d68819660bef0e7a3d9dfc0f54789b26b0a9edc930a452ef43b55aac3060075a019f6e8e08b353a43af15439452e7b1c01e54f5102924
6
+ metadata.gz: 2fcfb230bb3273079f56f57b1d03a42b6cd589c56a2e23fcaa2864ae9dfe4bf83d48b4e3351bc74ee5b6934eb489b53b3a94e14ba87295fc4a8ee87802220984
7
+ data.tar.gz: ded1b2e82e6743935a3d65a02f67302359c39848fb43f1acc57d8120b63aa9ad378fcdcf0ee852bd89e19166b5ff767b07ca8b5d749e136c1fd3ce105d211762
data/README.md CHANGED
@@ -1,4 +1,17 @@
1
- ronin
2
- =====
1
+ ## Ronin [![Build Status](https://api.travis-ci.org/nmilford/ronin.png)](https://travis-ci.org/nmilford/ronin) [![Gem Version](https://badge.fury.io/rb/ronin-wrapper.png)](http://badge.fury.io/rb/ronin-wrapper)
2
+
3
+
4
+ Ronin is a tool to enable masterless configuration management.
5
+
6
+ It is built to use [Chef](https://github.com/opscode/chef) or [Puppet](https://github.com/puppetlabs/puppet) as it's configuration interpretor.
7
+
8
+ ### How it works
9
+
10
+ Ronin can source its runlist from a local YAML file or from an [etcd](https://github.com/coreos/etcd) cluster. It can also grab it's configuration from a etcd cluster as well in lieu of it's local config file.
11
+
12
+ When using etcd, you can also specify multiple keys to grab in an order lowest precedence to highest. This enables you to pull a 'common' configuration with other, per node, overrides.
13
+
14
+ Ronin uses [Git](https://github.com/git/git) to grab configuration management artifacts (Chef Cookbooks or Puppet Modules) and cache them locally. You can also specify that it pulls a different branch of an artifact's git repository to isolate testing.
15
+
16
+ Once cached, Ronin will run your chosen interpretor over the artifacts. By default it will on run the interpretor if git pulls any changes.
3
17
 
4
- A wrapper to enable masterless configuration management, using Chef and/or Puppet.
data/bin/ronin CHANGED
@@ -22,4 +22,4 @@ end
22
22
 
23
23
  require 'ronin'
24
24
 
25
- Ronin.run
25
+ Ronin.run
data/lib/ronin.rb CHANGED
@@ -14,13 +14,3 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
  require 'ronin/ronin'
17
- require 'ronin/config'
18
- require 'ronin/artifact_runner'
19
- require 'ronin/run_list'
20
- require 'ronin/version'
21
- require 'ronin/puppet'
22
- require 'ronin/chef'
23
- require 'ronin/git'
24
- require 'ronin/log'
25
- require 'ronin/etcd'
26
-
@@ -14,6 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.require 'ronin/run_list'
16
16
  require 'ronin/config'
17
+ require 'ronin/run_list'
17
18
  require 'ronin/util'
18
19
  require 'ronin/git'
19
20
  require 'ronin/log'
@@ -71,4 +72,4 @@ module Ronin
71
72
  end
72
73
  end
73
74
  end
74
- end
75
+ end
data/lib/ronin/chef.rb CHANGED
@@ -46,8 +46,8 @@ module Ronin
46
46
  def run
47
47
  self.create_run_list
48
48
  self.create_solo_conf
49
- Ronin::Log.info("Running Chef, logging to #{Ronin::Config[:log_path]}/ronin-chef.log.")
50
- @cmd = Mixlib::ShellOut.new("#{$CHEFSOLO_BIN} --logfile #{Ronin::Config[:log_path]}/ronin-chef.log --config #{@solo_conf} --json-attributes #{@run_list}")
49
+ Ronin::Log.info("Running Chef, logging to #{Ronin::Config[:interpreter_log_path]}/ronin-chef.log.")
50
+ @cmd = Mixlib::ShellOut.new("#{Ronin::Util.find_cmd("chef-solo")} --logfile #{Ronin::Config[:log_path]}/ronin-chef.log --config #{@solo_conf} --json-attributes #{@run_list}")
51
51
  @cmd.run_command
52
52
  self.clean_up
53
53
  end
@@ -69,4 +69,4 @@ module Ronin
69
69
  end
70
70
 
71
71
  end
72
- end
72
+ end
data/lib/ronin/config.rb CHANGED
@@ -14,7 +14,6 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
  require 'mixlib/config'
17
- require 'ronin/etcd'
18
17
 
19
18
  module Ronin
20
19
  class Config
@@ -28,25 +27,28 @@ module Ronin
28
27
  puts "No configuration file at #{config_file}, using defaults."
29
28
  end
30
29
 
31
- config_strict_mode true
32
- default :config_from_etcd, false
33
- default :lock_file, '/var/tmp/ronin.lock'
34
- default :log_path, '/var/log/ronin'
35
- default :log_level, :info
36
- default :update_on_change, true
37
- default :interpreter, 'chef'
38
- default :artifact_path, '/var/lib/ronin/artifacts'
39
- default :run_list_type, 'yaml'
40
- default :run_list_file, '/etc/ronin/artifacts.yaml'
41
- default :etcd_host, '127.0.0.1'
42
- default :etcd_port, 4001
30
+ config_strict_mode true
31
+ default :config_from_etcd, false
32
+ default :cache_etcd_data, true
33
+ default :lock_file, '/var/tmp/ronin.lock'
34
+ default :log_path, 'STDOUT'
35
+ default :interpreter_log_path, '/var/log/ronin'
36
+ default :log_level, :info
37
+ default :update_on_change, true
38
+ default :interpreter, 'chef'
39
+ default :cache_path, '/var/lib/ronin/cache'
40
+ default :artifact_path, '/var/lib/ronin/artifacts'
41
+ default :run_list_type, 'yaml'
42
+ default :run_list_file, '/etc/ronin/artifacts.yaml'
43
+ default :etcd_host, '127.0.0.1'
44
+ default :etcd_port, 4001
43
45
  default :etcd_conn_timeout, 5
44
46
  default :etcd_read_timeout, 5
45
- default :etcd_use_ssl, false
46
- default :etcd_ssl_ca_cert, ''
47
- default :etcd_ssl_cert, ''
48
- default :etcd_ssl_key, ''
49
- default :etcd_keys, [ 'common', 'env', 'node' ]
47
+ default :etcd_use_ssl, false
48
+ default :etcd_ssl_ca_cert, ''
49
+ default :etcd_ssl_cert, ''
50
+ default :etcd_ssl_key, ''
51
+ default :etcd_keys, ['common', 'node']
50
52
 
51
53
  end
52
- end
54
+ end
data/lib/ronin/etcd.rb CHANGED
@@ -13,32 +13,18 @@
13
13
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
- require 'mixlib/config'
16
+ require 'ronin/config'
17
+ require 'ronin/cache'
17
18
  require 'net/https'
18
19
  require 'net/http'
19
20
  require 'socket'
20
21
  require 'json'
21
22
 
22
- # Add test data thus.
23
-
24
- #curl -L http://127.0.0.1:4001/v2/keys/ronin/config/common -X PUT -d value='{
25
- # "artifacts": [
26
- # "https://github.com/opscode-cookbooks/motd-tail"
27
- # ]
28
- #}'
29
-
30
- #curl -L http://127.0.0.1:4001/v2/keys/ronin/config/common -X PUT -d value='{
31
- # "log_path": "/var/log/ronin",
32
- # "interpreter": ":chef",
33
- # "artifact_path": "/var/lib/ronin/artifacts",
34
- # "update_on_change": "true",
35
- # "run_list_type": ":etcd",
36
- # "run_list_file": "/etc/ronin/artifacts.yaml"
37
- #}'
38
-
39
23
  module Ronin
40
24
  module Etcd
41
25
 
26
+ @hostname = Socket.gethostname
27
+
42
28
  def get_key(type, key)
43
29
  # Will add error handling... one day.
44
30
  @path = "/v2/keys/ronin/#{type}/#{key}"
@@ -61,26 +47,79 @@ module Ronin
61
47
  end
62
48
 
63
49
  @request = Net::HTTP::Get.new(@path)
64
- @result = @http.request(@request)
50
+
51
+ begin
52
+ @result = @http.request(@request)
53
+ rescue Exception => e
54
+ if Ronin::Config[:cache_etcd_data]
55
+ return :down
56
+ else
57
+ abort("Connection refused by etcd host #{Ronin::Config[:etcd_host]}:#{Ronin::Config[:etcd_port]}, exiting...")
58
+ end
59
+ end
60
+
61
+ unless @result.kind_of?(Net::HTTPSuccess)
62
+ if @result.code == 404
63
+ Ronin::Log.info("Key http://#{Ronin::Config[:etcd_host]}:#{Ronin::Config[:etcd_port]}#{@path} not found, returning an empty set.")
64
+ return "{}"
65
+ else
66
+ Ronin::Log.info("Got status #{@result.code} querying http://#{Ronin::Config[:etcd_host]}:#{Ronin::Config[:etcd_port]}#{@path}, returning an empty set.")
67
+ return "{}"
68
+ end
69
+ end
70
+
65
71
  return JSON.parse(@result.body)['node']['value']
66
72
  end
67
73
  module_function :get_key
68
74
 
69
75
  def get_config
70
- @hostname = Socket.gethostname
71
- @common = JSON.parse(Ronin::Etcd.get_key('config', 'common'))
72
- #@specific = JSON.parse(Ronin::Etcd.get_key('config', @hostname))
73
- #return @common.merge(@specific)
76
+ @config = {}
77
+ Ronin::Config[:etcd_keys].each do |key|
78
+ key = @hostname if key == 'node'
79
+
80
+ @payload = Ronin::Etcd.get_key('config', key)
81
+
82
+ if @payload == :down
83
+ Ronin::Log.warn("Connection refused by etcd host #{Ronin::Config[:etcd_host]}:#{Ronin::Config[:etcd_port]}, loading config from cache (#{Ronin::Config[:cache_path]}/config.json)")
84
+
85
+ return Ronin::Cache.load_cached_config
86
+ else
87
+ @parsed_payload = JSON.parse(@payload)
88
+ @config = @config.merge(@parsed_payload)
89
+ end
90
+ end
91
+
92
+ if Ronin::Config[:config_from_etcd] and Ronin::Config[:cache_etcd_data]
93
+ Ronin::Cache.cache_config(@config)
94
+ end
95
+
96
+ return @config
74
97
  end
75
98
  module_function :get_config
76
99
 
77
100
  def get_run_list
78
- @hostname = Socket.gethostname
79
- @common = JSON.parse(Ronin::Etcd.get_key('run_list', 'common'))['artifacts']
80
- #@specific = JSON.parse(Ronin::Etcd.get_key('run_list', @hostname))['artifacts']
81
- #return (@common+@specific).uniq
101
+ @run_list = []
102
+ Ronin::Config[:etcd_keys].each do |key|
103
+ key = @hostname if key == 'node'
104
+
105
+ @payload = Ronin::Etcd.get_key('run_list', key)
106
+
107
+ if @payload == :down
108
+ Ronin::Log.warn("Connection refused by etcd host #{Ronin::Config[:etcd_host]}:#{Ronin::Config[:etcd_port]}, loading run_list from cache (#{Ronin::Config[:cache_path]}/run_list.json)")
109
+ return Ronin::Cache.load_cached_run_list
110
+ else
111
+ @parsed_payload = JSON.parse(@payload)['artifacts']
112
+ @run_list += @parsed_payload unless @parsed_payload.nil?
113
+ end
114
+
115
+ if Ronin::Config[:config_from_etcd] and Ronin::Config[:cache_etcd_data]
116
+ Ronin::Cache.cache_run_list(@run_list.uniq)
117
+ end
118
+ end
119
+
120
+ return @run_list.uniq
82
121
  end
83
122
  module_function :get_run_list
84
123
 
85
124
  end
86
- end
125
+ end
data/lib/ronin/git.rb CHANGED
@@ -15,11 +15,12 @@
15
15
  # limitations under the License.
16
16
  require "mixlib/shellout"
17
17
  require 'ronin/config'
18
+ require 'ronin/util'
18
19
 
19
20
  module Ronin
20
21
  module Git
21
22
  def branch(artifact)
22
- @cmd = Mixlib::ShellOut.new("#{$GIT_BIN} --git-dir=#{Ronin::Config[:artifact_path]}/#{artifact}/.git --work-tree=#{Ronin::Config[:artifact_path]}/#{artifact}/ branch")
23
+ @cmd = Mixlib::ShellOut.new("#{Ronin::Util.find_cmd("git")} --git-dir=#{Ronin::Config[:artifact_path]}/#{artifact}/.git --work-tree=#{Ronin::Config[:artifact_path]}/#{artifact}/ branch")
23
24
  @cmd.run_command
24
25
  @branch = @cmd.stdout.chomp.split(' ')[1]
25
26
  @branch
@@ -27,7 +28,7 @@ module Ronin
27
28
  module_function :branch
28
29
 
29
30
  def pull_and_report_updated(artifact)
30
- @cmd = Mixlib::ShellOut.new("git --git-dir=#{Ronin::Config[:artifact_path]}/#{artifact}/.git --work-tree=#{Ronin::Config[:artifact_path]}/#{artifact}/ pull")
31
+ @cmd = Mixlib::ShellOut.new("#{Ronin::Util.find_cmd("git")} --git-dir=#{Ronin::Config[:artifact_path]}/#{artifact}/.git --work-tree=#{Ronin::Config[:artifact_path]}/#{artifact}/ pull")
31
32
  @cmd.run_command
32
33
  @updated = @cmd.stdout.include?("Updating")
33
34
  @updated ? true : false
@@ -35,10 +36,10 @@ module Ronin
35
36
  module_function :pull_and_report_updated
36
37
 
37
38
  def clone(artifact_data)
38
- @cmd = Mixlib::ShellOut.new("git clone #{artifact_data[:repo]} #{Ronin::Config[:artifact_path]}/#{artifact_data[:name]}/ -b #{artifact_data[:branch]}")
39
+ @cmd = Mixlib::ShellOut.new("#{Ronin::Util.find_cmd("git")} clone #{artifact_data[:repo]} #{Ronin::Config[:artifact_path]}/#{artifact_data[:name]}/ -b #{artifact_data[:branch]}")
39
40
  @cmd.run_command
40
41
  @cmd.stdout
41
42
  end
42
43
  module_function :clone
43
44
  end
44
- end
45
+ end
data/lib/ronin/log.rb CHANGED
@@ -20,9 +20,13 @@ module Ronin
20
20
  class Log
21
21
  extend Mixlib::Log
22
22
 
23
- logfile = "#{Ronin::Config[:log_path]}/ronin.log"
24
-
25
- init(logfile)
26
23
  self.level = Ronin::Config[:log_level]
24
+
25
+ if Ronin::Config[:log_path] == 'STDOUT'
26
+ init(STDOUT)
27
+ else
28
+ init("#{Ronin::Config[:log_path]}/ronin.log")
29
+ end
30
+
27
31
  end
28
- end
32
+ end
data/lib/ronin/puppet.rb CHANGED
@@ -37,8 +37,8 @@ module Ronin
37
37
 
38
38
  def run
39
39
  self.create_run_list
40
- Ronin::Log.info("Running Puppet, logging to #{Ronin::Config[:log_path]}/ronin-puppet.log.")
41
- @cmd = Mixlib::ShellOut.new("#{$PUPPET_BIN} apply --verbose --ordering manifest --logdest #{Ronin::Config[:log_path]}/ronin-puppet.log --modulepath #{Ronin::Config[:artifact_path]} #{@run_list}")
40
+ Ronin::Log.info("Running Puppet, logging to #{Ronin::Config[:interpreter_log_path]}/ronin-puppet.log.")
41
+ @cmd = Mixlib::ShellOut.new("#{Ronin::Util.find_cmd("puppet")} apply --ordering manifest --logdest #{Ronin::Config[:log_path]}/ronin-puppet.log --modulepath #{Ronin::Config[:artifact_path]} #{@run_list}")
42
42
  @cmd.run_command
43
43
  self.clean_up
44
44
  end
@@ -49,4 +49,4 @@ module Ronin
49
49
  end
50
50
 
51
51
  end
52
- end
52
+ end
data/lib/ronin/ronin.rb CHANGED
@@ -13,10 +13,11 @@
13
13
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
- $LOAD_PATH << "."
17
16
  require 'ronin/artifact_runner'
18
17
  require 'ronin/run_list'
19
18
  require 'ronin/config'
19
+ require 'ronin/puppet'
20
+ require 'ronin/chef'
20
21
  require 'ronin/util'
21
22
  require 'ronin/log'
22
23
 
@@ -30,7 +31,7 @@ module Ronin
30
31
  Ronin::Log.info("Setting #{k} to #{v}.")
31
32
 
32
33
  if v.start_with?(':')
33
- v = v[1..-1].to_sym
34
+ v = v[1..-1].to_sym
34
35
  end
35
36
 
36
37
  Ronin::Config["#{k}"] = v
@@ -41,20 +42,14 @@ module Ronin
41
42
 
42
43
  if Ronin::Util.find_cmd("git").nil?
43
44
  abort("You need to have git installed to perform this command.")
44
- else
45
- $GIT_BIN = Ronin::Util.find_cmd("git")
46
45
  end
47
46
 
48
- if Ronin::Util.find_cmd("puppet").nil? and Ronin::Config[:interpreter] == :puppet
47
+ if Ronin::Util.find_cmd("puppet").nil? and Ronin::Config[:interpreter] == 'puppet'
49
48
  abort("You need to have Puppet installed to perform this command with Puppet set as the interpreter.")
50
- else
51
- $PUPPET_BIN = Ronin::Util.find_cmd("puppet")
52
49
  end
53
50
 
54
- if Ronin::Util.find_cmd("chef-solo").nil? and Ronin::Config[:interpreter] == :puppet
51
+ if Ronin::Util.find_cmd("chef-solo").nil? and Ronin::Config[:interpreter] == 'chef'
55
52
  abort("You need to have Chef-Solo installed to perform this command with Chef set as the interpreter.")
56
- else
57
- $CHEFSOLO_BIN = Ronin::Util.find_cmd("chef-solo")
58
53
  end
59
54
 
60
55
  unless File.exists?(Ronin::Config[:lock_file])
@@ -31,10 +31,9 @@ module Ronin
31
31
  end
32
32
 
33
33
  unless @artifacts_raw.nil?
34
-
35
34
  @artifacts_raw.each do |a|
36
35
  if a.include?(";")
37
- @repo = a.split(";")[0].sub(/(\/)+$/,'')
36
+ @repo = a.split(";")[0].sub(/(\/)+$/, '')
38
37
  @branch = a.split(";")[1]
39
38
  else
40
39
  @repo = a
@@ -52,15 +51,17 @@ module Ronin
52
51
 
53
52
  def artifacts
54
53
  @arts = []
55
- @run_list.each { |k,v| @arts << k }
54
+ @run_list.each { |k, v| @arts << k }
56
55
  @arts
57
56
  end
58
57
 
59
58
  def items
60
59
  @items = []
61
- @run_list.each { |k,v| @items << { :name => v[:name], :repo => v[:repo], :branch => v[:branch] } }
60
+ @run_list.each do |k, v|
61
+ @items << { :name => v[:name], :repo => v[:repo], :branch => v[:branch] }
62
+ end
62
63
  @items
63
64
  end
64
65
 
65
66
  end
66
- end
67
+ end
data/lib/ronin/util.rb CHANGED
@@ -32,4 +32,4 @@ module Ronin
32
32
  module_function :num_cores
33
33
 
34
34
  end
35
- end
35
+ end
data/lib/ronin/version.rb CHANGED
@@ -13,6 +13,7 @@
13
13
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
+
16
17
  module Ronin
17
- VERSION = '0.0.13'
18
+ VERSION = '0.1.0'
18
19
  end
metadata CHANGED
@@ -1,99 +1,197 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ronin-wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Milford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-30 00:00:00.000000000 Z
11
+ date: 2014-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parallel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.1
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: yajl-ruby
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - '>='
31
+ - - ~>
18
32
  - !ruby/object:Gem::Version
19
33
  version: 1.2.0
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - '>='
38
+ - - ~>
25
39
  - !ruby/object:Gem::Version
26
40
  version: 1.2.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: mixlib-log
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - '>='
45
+ - - ~>
32
46
  - !ruby/object:Gem::Version
33
47
  version: 1.6.0
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - '>='
52
+ - - ~>
39
53
  - !ruby/object:Gem::Version
40
54
  version: 1.6.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: mixlib-config
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - '>='
59
+ - - ~>
46
60
  - !ruby/object:Gem::Version
47
61
  version: 2.1.0
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - '>='
66
+ - - ~>
53
67
  - !ruby/object:Gem::Version
54
68
  version: 2.1.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: mixlib-shellout
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - '>='
73
+ - - ~>
60
74
  - !ruby/object:Gem::Version
61
75
  version: 1.3.0
62
76
  type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - '>='
80
+ - - ~>
67
81
  - !ruby/object:Gem::Version
68
82
  version: 1.3.0
69
83
  - !ruby/object:Gem::Dependency
70
- name: mixlib-shellout
84
+ name: rack
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - '>='
87
+ - - ~>
74
88
  - !ruby/object:Gem::Version
75
- version: 0.9.1
76
- type: :runtime
89
+ version: 1.5.2
90
+ type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - '>='
94
+ - - ~>
81
95
  - !ruby/object:Gem::Version
82
- version: 0.9.1
96
+ version: 1.5.2
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - '>='
101
+ - - ~>
88
102
  - !ruby/object:Gem::Version
89
103
  version: 10.1.1
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - '>='
108
+ - - ~>
95
109
  - !ruby/object:Gem::Version
96
110
  version: 10.1.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: tailor
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 1.3.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 1.3.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: sinatra
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: 1.4.4
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: 1.4.4
139
+ - !ruby/object:Gem::Dependency
140
+ name: travis-lint
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ~>
144
+ - !ruby/object:Gem::Version
145
+ version: 1.7.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ~>
151
+ - !ruby/object:Gem::Version
152
+ version: 1.7.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec-core
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ~>
158
+ - !ruby/object:Gem::Version
159
+ version: 2.14.7
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ~>
165
+ - !ruby/object:Gem::Version
166
+ version: 2.14.7
167
+ - !ruby/object:Gem::Dependency
168
+ name: rspec-mocks
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: 2.14.4
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ~>
179
+ - !ruby/object:Gem::Version
180
+ version: 2.14.4
181
+ - !ruby/object:Gem::Dependency
182
+ name: rspec-expectations
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ~>
186
+ - !ruby/object:Gem::Version
187
+ version: 2.14.4
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ~>
193
+ - !ruby/object:Gem::Version
194
+ version: 2.14.4
97
195
  description: A wrapper to enable masterless configuration management, using Chef and/or
98
196
  Puppet.
99
197
  email: nathan@milford.io