gusteau 0.4.7 → 0.4.8
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.
- data/README.md +22 -19
- data/gusteau.gemspec +1 -0
- data/lib/gusteau/log.rb +18 -18
- data/lib/gusteau/node.rb +21 -6
- data/lib/gusteau/vagrant.rb +86 -34
- data/lib/gusteau/version.rb +1 -1
- data/spec/lib/gusteau/node_spec.rb +61 -0
- data/spec/lib/gusteau/vagrant_spec.rb +69 -51
- metadata +18 -2
data/README.md
CHANGED
@@ -9,7 +9,7 @@ Gusteau
|
|
9
9
|
Introduction
|
10
10
|
------------
|
11
11
|
|
12
|
-
Gusteau is here to make servers provisioning simple and enjoyable. It provides an efficient interface to Chef Solo as well as some nice features:
|
12
|
+
Gusteau is here to make servers provisioning simple and enjoyable. It's a good choice if you are running a small infrastructure or a VPS and want to use Chef. It provides an efficient interface to Chef Solo as well as some nice features:
|
13
13
|
|
14
14
|
* Uses YAML for readable server configuration definitions
|
15
15
|
* Uses a single SSH connection to stream compressed files and commands
|
@@ -29,7 +29,7 @@ gem install gusteau
|
|
29
29
|
|
30
30
|
A typical Gusteau node configuration looks like this:
|
31
31
|
|
32
|
-
```
|
32
|
+
```
|
33
33
|
json:
|
34
34
|
mysql:
|
35
35
|
server_root_password: ASahiweqwqe2
|
@@ -39,8 +39,7 @@ json:
|
|
39
39
|
- linguini
|
40
40
|
|
41
41
|
roles:
|
42
|
-
-
|
43
|
-
- rails
|
42
|
+
- base
|
44
43
|
|
45
44
|
recipes:
|
46
45
|
- mysql::server
|
@@ -49,7 +48,7 @@ recipes:
|
|
49
48
|
server:
|
50
49
|
host: 33.33.33.20
|
51
50
|
platform: ubuntu
|
52
|
-
password:
|
51
|
+
password: omgsecret
|
53
52
|
```
|
54
53
|
|
55
54
|
Gusteau only needs a node definition to run, but you'll need a few cookbooks to actually cook something :)
|
@@ -68,7 +67,7 @@ Provisioning a server
|
|
68
67
|
The following command will run all roles and recipes from node's YAML file.
|
69
68
|
|
70
69
|
```
|
71
|
-
gusteau
|
70
|
+
gusteau example provision
|
72
71
|
```
|
73
72
|
|
74
73
|
Use the `--bootstrap` or `-b` flag to bootstrap chef-solo (for the first time run).
|
@@ -78,7 +77,7 @@ Running recipes
|
|
78
77
|
You may choose to run a few recipes instead of full provisioning.
|
79
78
|
|
80
79
|
```
|
81
|
-
gusteau
|
80
|
+
gusteau example run redis::server ntp unicorn
|
82
81
|
```
|
83
82
|
|
84
83
|
SSH
|
@@ -86,8 +85,9 @@ SSH
|
|
86
85
|
Gusteau provides a useful shortcut that you may use to ssh into a node. If you haven't got passwordless authentication set up, Gusteau will use `user` and `password` values from the node configuration.
|
87
86
|
|
88
87
|
```
|
89
|
-
gusteau ssh
|
88
|
+
gusteau ssh example
|
90
89
|
```
|
90
|
+
|
91
91
|
Please note that `expect` utility must be installed for `gusteau ssh` to work.
|
92
92
|
|
93
93
|
If you prefer calling ssh directly, you will find the `gusteau ssh_config` subcommand useful:
|
@@ -98,9 +98,9 @@ gusteau ssh_config >> ~/.ssh/config
|
|
98
98
|
|
99
99
|
Using with Vagrant
|
100
100
|
------------------
|
101
|
-
Gusteau
|
101
|
+
Gusteau can save you from writing some Vagrantfile boilerplate code. It also enables you to move node-specific Vagrant configuration away from the Vagrantfile into node yml files.
|
102
102
|
|
103
|
-
```
|
103
|
+
```
|
104
104
|
...
|
105
105
|
vagrant:
|
106
106
|
IP: 192.168.100.20
|
@@ -109,25 +109,28 @@ vagrant:
|
|
109
109
|
box_url: 'https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box'
|
110
110
|
```
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
```ruby
|
115
|
-
Vagrant.require_plugin 'gusteau'
|
112
|
+
The following bit will configure Vagrant for all Gusteau nodes which have `vagrant` section defined.
|
116
113
|
|
114
|
+
```
|
117
115
|
Vagrant.configure('2') do |config|
|
118
|
-
|
119
|
-
|
116
|
+
Gusteau::Vagrant.detect(config) do |setup|
|
117
|
+
setup.prefix = 'loco'
|
118
|
+
setup.defaults.box_url = 'http://example.com/vm/opscode_centos-6.4.box'
|
119
|
+
setup.provision = false
|
120
|
+
end
|
120
121
|
end
|
121
122
|
```
|
122
123
|
|
123
|
-
|
124
|
+
* The `prefix` option lets you prepend your VirtualBox VMs names, e.g. `loco-nodename`.
|
125
|
+
* The `defaults` one lets you provide default values for `cpus`, `memory`, `box_url`.
|
126
|
+
* If you'd like to use Vagrant's own automatic `chef_solo` provisioner, set `provision` to `true`. In this scenario, `gusteau provision` will be just calling `vagrant provision`.
|
127
|
+
|
128
|
+
Please note that the add-on only works with Vagrant ~> 1.2 and needs gusteau to be installed as a Vagrant plugin:
|
124
129
|
|
125
130
|
```
|
126
131
|
vagrant plugin install gusteau
|
127
132
|
```
|
128
133
|
|
129
|
-
Gusteau doesn't automatically provision your Vagrant nodes.
|
130
|
-
|
131
134
|
Notes
|
132
135
|
-----
|
133
136
|
|
data/gusteau.gemspec
CHANGED
data/lib/gusteau/log.rb
CHANGED
@@ -2,24 +2,6 @@ require 'inform'
|
|
2
2
|
|
3
3
|
module Gusteau
|
4
4
|
module Log
|
5
|
-
private
|
6
|
-
|
7
|
-
def timestamp
|
8
|
-
Time.now.strftime('%Y-%m-%dT%H:%M:%S')
|
9
|
-
end
|
10
|
-
|
11
|
-
def indent
|
12
|
-
@level = (@level || 0) + 1
|
13
|
-
end
|
14
|
-
|
15
|
-
def unindent
|
16
|
-
@level = (@level || 0) - 1
|
17
|
-
end
|
18
|
-
|
19
|
-
def prompt
|
20
|
-
"[#{timestamp}] GUSTEAU: #{' ' * (@level || 0)}"
|
21
|
-
end
|
22
|
-
|
23
5
|
def log(msg, opts={})
|
24
6
|
info "%{prompt}#{msg}", opts.merge(:prompt => prompt)
|
25
7
|
if block_given?
|
@@ -41,5 +23,23 @@ module Gusteau
|
|
41
23
|
def info(str, opts={})
|
42
24
|
Inform.info str, opts
|
43
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def timestamp
|
30
|
+
Time.now.strftime('%Y-%m-%dT%H:%M:%S')
|
31
|
+
end
|
32
|
+
|
33
|
+
def indent
|
34
|
+
@level = (@level || 0) + 1
|
35
|
+
end
|
36
|
+
|
37
|
+
def unindent
|
38
|
+
@level = (@level || 0) - 1
|
39
|
+
end
|
40
|
+
|
41
|
+
def prompt
|
42
|
+
"[#{timestamp}] GUSTEAU: #{' ' * (@level || 0)}"
|
43
|
+
end
|
44
44
|
end
|
45
45
|
end
|
data/lib/gusteau/node.rb
CHANGED
@@ -6,7 +6,7 @@ module Gusteau
|
|
6
6
|
class Node
|
7
7
|
include Gusteau::ERB
|
8
8
|
|
9
|
-
attr_reader :server
|
9
|
+
attr_reader :name, :config, :server
|
10
10
|
|
11
11
|
def initialize(path)
|
12
12
|
raise "Node YAML file #{path} not found" unless path && File.exists?(path)
|
@@ -14,21 +14,26 @@ module Gusteau
|
|
14
14
|
@name = File.basename(path).gsub('.yml','')
|
15
15
|
@config = read_erb_yaml(path)
|
16
16
|
|
17
|
+
@server = Server.new(@config['server']) if @config['server']
|
17
18
|
@dna_path = '/tmp/dna.json'
|
18
|
-
|
19
|
-
@server = Server.new(@config['server'])
|
20
19
|
end
|
21
20
|
|
22
21
|
def provision(opts = {})
|
23
|
-
|
22
|
+
wrap_vagrant :provision do
|
23
|
+
server.chef.run opts, dna(true)
|
24
|
+
end
|
24
25
|
end
|
25
26
|
|
26
27
|
def run(opts = {}, *recipes)
|
27
|
-
|
28
|
+
wrap_vagrant :run do
|
29
|
+
server.chef.run opts, dna(false, recipes.flatten)
|
30
|
+
end
|
28
31
|
end
|
29
32
|
|
30
33
|
def ssh
|
31
|
-
|
34
|
+
wrap_vagrant :ssh do
|
35
|
+
server.ssh
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
39
|
private
|
@@ -56,5 +61,15 @@ module Gusteau
|
|
56
61
|
recipes.map { |r| "recipe[#{r}]" }
|
57
62
|
end
|
58
63
|
end
|
64
|
+
|
65
|
+
def wrap_vagrant(method)
|
66
|
+
if server
|
67
|
+
yield
|
68
|
+
elsif @config['vagrant']
|
69
|
+
Vagrant.send(method, @name)
|
70
|
+
else
|
71
|
+
Kernel.abort "Neither 'server' nor 'vagrant' defined for #{@name}. Please provide one."
|
72
|
+
end
|
73
|
+
end
|
59
74
|
end
|
60
75
|
end
|
data/lib/gusteau/vagrant.rb
CHANGED
@@ -1,59 +1,111 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'gusteau/log'
|
3
|
+
|
4
|
+
class Hash; include Hashie::Extensions::SymbolizeKeys; end
|
5
|
+
|
1
6
|
module Gusteau
|
2
7
|
module Vagrant
|
3
8
|
extend self
|
9
|
+
extend Gusteau::Log
|
10
|
+
|
11
|
+
def detect(config)
|
12
|
+
options = Hashie::Mash.new
|
13
|
+
options.defaults = Hashie::Mash.new
|
4
14
|
|
5
|
-
|
6
|
-
|
7
|
-
d[:memory] ||= 1024
|
8
|
-
d[:cpus] ||= 1
|
9
|
-
d
|
15
|
+
yield options if block_given?
|
16
|
+
define_nodes(config, options.to_hash.symbolize_keys)
|
10
17
|
end
|
11
18
|
|
12
|
-
def
|
13
|
-
if
|
14
|
-
|
15
|
-
|
19
|
+
def define_nodes(config, options, prefix = nil)
|
20
|
+
if prefix
|
21
|
+
options[:prefix] = prefix
|
22
|
+
info "The 'prefix' param is deprecated. Please refer to the new Gusteau::Vagrant syntax."
|
23
|
+
end
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
25
|
+
Dir.glob("#{options[:dir] || './nodes'}/**/*.yml").sort.each do |path|
|
26
|
+
node = ::Gusteau::Node.new(path)
|
27
|
+
if node.config['vagrant']
|
28
|
+
define_vm config, node, options
|
20
29
|
end
|
30
|
+
end
|
31
|
+
end
|
21
32
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
33
|
+
def vm_config(node, options)
|
34
|
+
defaults = options[:defaults] || {}
|
35
|
+
config = node.config['vagrant']
|
36
|
+
label = options[:prefix] ? "#{options[:prefix]}-#{node.name}" : node.name
|
37
|
+
|
38
|
+
config = {} if config == true
|
39
|
+
|
40
|
+
box_url = config.fetch 'box_url' do
|
41
|
+
unless defaults[:box_url]
|
42
|
+
raise "Box url can't be determined for #{node.name}"
|
43
|
+
end
|
44
|
+
defaults[:box_url]
|
31
45
|
end
|
46
|
+
|
47
|
+
{
|
48
|
+
:name => node.name,
|
49
|
+
:label => label,
|
50
|
+
:box_url => box_url,
|
51
|
+
:ip => config['IP'] || defaults[:ip],
|
52
|
+
:cpus => config['cpus'] || defaults[:cpus] || 1,
|
53
|
+
:memory => config['memory'] || defaults[:memory] || 1024
|
54
|
+
}
|
32
55
|
end
|
33
56
|
|
34
|
-
def define_vm(
|
35
|
-
|
36
|
-
|
37
|
-
|
57
|
+
def define_vm(config, node, options)
|
58
|
+
vm_config = vm_config(node, options)
|
59
|
+
|
60
|
+
config.vm.define vm_config[:name] do |instance|
|
61
|
+
instance.vm.box = vm_config[:name]
|
62
|
+
instance.vm.box_url = vm_config[:box_url]
|
38
63
|
|
39
64
|
instance.vm.provider :virtualbox do |vb|
|
40
65
|
vb.customize ['modifyvm', :id,
|
41
|
-
'--memory',
|
42
|
-
'--name',
|
43
|
-
'--cpus',
|
66
|
+
'--memory', vm_config[:memory],
|
67
|
+
'--name', vm_config[:label],
|
68
|
+
'--cpus', vm_config[:cpus],
|
69
|
+
'--natdnsproxy1', 'on'
|
44
70
|
]
|
45
71
|
end
|
46
|
-
|
72
|
+
|
73
|
+
if vm_config[:ip]
|
74
|
+
instance.vm.network :private_network, :ip => vm_config[:ip]
|
75
|
+
end
|
76
|
+
|
77
|
+
define_provisioner(instance, node) if options[:provision]
|
47
78
|
end
|
48
79
|
end
|
49
80
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
81
|
+
def define_provisioner(instance, node)
|
82
|
+
instance.vm.provision 'chef_solo' do |chef|
|
83
|
+
chef.data_bags_path = 'data_bags'
|
84
|
+
chef.cookbooks_path = ['cookbooks', 'site-cookbooks']
|
85
|
+
chef.json = node.config['json'] || {}
|
86
|
+
|
87
|
+
(node.config['recipes'] || []).each { |r| chef.add_recipe(r) }
|
88
|
+
(node.config['roles'] || []).each { |r| chef.add_role(r) }
|
55
89
|
end
|
56
90
|
end
|
57
91
|
|
92
|
+
def ssh(nodename)
|
93
|
+
vagrant_cmd("ssh #{nodename}")
|
94
|
+
end
|
95
|
+
|
96
|
+
def provision(nodename)
|
97
|
+
vagrant_cmd("provision #{nodename}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def vagrant_cmd(cmd)
|
101
|
+
info "Running 'vagrant #{cmd}'"
|
102
|
+
Kernel.system("vagrant #{cmd}")
|
103
|
+
Kernel.exit $?.exitstatus
|
104
|
+
end
|
105
|
+
|
106
|
+
def run(nodename)
|
107
|
+
Kernel.abort "'run' is not supported for vagrant-only nodes. Please configure 'server' for #{nodename} node"
|
108
|
+
end
|
58
109
|
end
|
59
110
|
end
|
111
|
+
|
data/lib/gusteau/version.rb
CHANGED
@@ -38,4 +38,65 @@ describe Gusteau::Node do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
describe "#vagrant_wrap" do
|
43
|
+
let(:node) { Gusteau::Node.new('spec/nodes/development.yml') }
|
44
|
+
|
45
|
+
describe "#ssh" do
|
46
|
+
context "server is defined" do
|
47
|
+
it "should call server.ssh" do
|
48
|
+
node.server.expects(:ssh)
|
49
|
+
node.ssh
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "vagrant is defined, server is not" do
|
54
|
+
before do
|
55
|
+
node.stubs(:server).returns(nil)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should call 'vagrant ssh'" do
|
59
|
+
Kernel.expects(:system).with("vagrant ssh development")
|
60
|
+
Kernel.expects(:exit)
|
61
|
+
node.ssh
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "neither server nor vagrant are defined" do
|
66
|
+
before do
|
67
|
+
node.stubs(:server).returns(nil)
|
68
|
+
node.config['vagrant'] = nil
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should exit with an error" do
|
72
|
+
Kernel.expects(:abort)
|
73
|
+
node.ssh
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#run" do
|
79
|
+
context "server is defined" do
|
80
|
+
it "should call server.chef.run" do
|
81
|
+
chef = mock()
|
82
|
+
node.server.expects(:chef).returns(chef)
|
83
|
+
chef.expects(:run)
|
84
|
+
|
85
|
+
node.run('test')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "vagrant is defined, server is not" do
|
90
|
+
before do
|
91
|
+
node.stubs(:server).returns(nil)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should exit with an error" do
|
95
|
+
Kernel.expects(:abort).with("'run' is not supported for vagrant-only nodes. Please configure 'server' for development node")
|
96
|
+
node.run('test')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
41
102
|
end
|
@@ -1,73 +1,91 @@
|
|
1
1
|
require './spec/spec_helper.rb'
|
2
2
|
|
3
3
|
describe Gusteau::Vagrant do
|
4
|
-
let(:defaults) do
|
5
|
-
{
|
6
|
-
:box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
|
7
|
-
:cpus => 64
|
8
|
-
}
|
9
|
-
end
|
10
|
-
let(:label) { 'hyper' }
|
11
|
-
|
12
|
-
describe "#vagrant_config" do
|
13
|
-
subject { Gusteau::Vagrant.vagrant_config(config_path, defaults, label) }
|
14
4
|
|
15
|
-
|
16
|
-
|
5
|
+
describe "#detect" do
|
6
|
+
let(:config) { mock() }
|
7
|
+
let(:vm) { mock() }
|
8
|
+
let(:instance) { mock() }
|
9
|
+
let(:subvm) { stub_everything('subvm') }
|
17
10
|
|
18
|
-
|
19
|
-
|
11
|
+
before do
|
12
|
+
def vm.define(name)
|
13
|
+
yield instance
|
20
14
|
end
|
15
|
+
|
16
|
+
config.expects(:vm).at_least_once.returns(vm)
|
17
|
+
vm.expects(:instance).at_least_once.returns(instance)
|
18
|
+
instance.expects(:vm).at_least_once.returns(subvm)
|
21
19
|
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
:label => expected_label,
|
33
|
-
:box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
|
34
|
-
:ip => '192.168.100.21',
|
35
|
-
:cpus => 4,
|
36
|
-
:memory => expected_memory
|
37
|
-
}
|
21
|
+
it "should define vm instances with correct settings" do
|
22
|
+
subvm.expects('box='.to_sym).with('development')
|
23
|
+
subvm.expects('box_url='.to_sym).with("http://a.com/b.box")
|
24
|
+
subvm.expects(:network).with(:private_network, { :ip => '192.168.100.21' })
|
25
|
+
subvm.expects(:provision).never
|
26
|
+
|
27
|
+
Gusteau::Vagrant.detect(config) do |setup|
|
28
|
+
setup.dir = './spec/nodes'
|
29
|
+
setup.defaults.box_url = "http://a.com/b.box"
|
38
30
|
end
|
31
|
+
end
|
39
32
|
|
40
|
-
|
41
|
-
|
33
|
+
it "should define provisioner" do
|
34
|
+
subvm.expects(:provision).with('chef_solo')
|
35
|
+
|
36
|
+
Gusteau::Vagrant.detect(config) do |setup|
|
37
|
+
setup.dir = './spec/nodes'
|
38
|
+
setup.defaults.box_url = "http://a.com/b.box"
|
39
|
+
setup.provision = true
|
42
40
|
end
|
41
|
+
end
|
42
|
+
end
|
43
43
|
|
44
|
-
|
44
|
+
describe "#vm_config" do
|
45
|
+
subject { Gusteau::Vagrant.vm_config(node, options) }
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
let(:defaults) do
|
48
|
+
{
|
49
|
+
:box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
|
50
|
+
:cpus => 64,
|
51
|
+
:memory => 4096,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
let(:prefix) { 'hyper' }
|
55
|
+
let(:options) { { :defaults => defaults, :prefix => prefix } }
|
49
56
|
|
50
|
-
|
51
|
-
|
57
|
+
let(:node) { ::Gusteau::Node.new('./spec/nodes/development.yml') }
|
58
|
+
|
59
|
+
let(:expected_label) { 'hyper-development' }
|
60
|
+
let(:expected_config) do
|
61
|
+
{
|
62
|
+
:name => 'development',
|
63
|
+
:label => expected_label,
|
64
|
+
:box_url => 'https://opscode.s3.amazonaws.com/centos-6.4.box',
|
65
|
+
:ip => '192.168.100.21',
|
66
|
+
:cpus => 4,
|
67
|
+
:memory => 4096
|
68
|
+
}
|
69
|
+
end
|
52
70
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
let(:expected_memory) { 4096 }
|
71
|
+
it "should merge in defaults" do
|
72
|
+
subject.must_equal(expected_config)
|
73
|
+
end
|
74
|
+
|
75
|
+
context "prefix not specified" do
|
76
|
+
let(:prefix) { nil }
|
77
|
+
let(:expected_label) { 'development' }
|
61
78
|
|
62
|
-
|
79
|
+
it "should omit the prefix" do
|
80
|
+
subject.must_equal(expected_config)
|
63
81
|
end
|
82
|
+
end
|
64
83
|
|
65
|
-
|
66
|
-
|
84
|
+
context "box_url not specified" do
|
85
|
+
let(:defaults) { {} }
|
67
86
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
87
|
+
it "should raise an exception" do
|
88
|
+
proc { subject }.must_raise RuntimeError
|
71
89
|
end
|
72
90
|
end
|
73
91
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gusteau
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-06-
|
13
|
+
date: 2013-06-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: optitron
|
@@ -60,6 +60,22 @@ dependencies:
|
|
60
60
|
- - ! '>='
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: hashie
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
63
79
|
- !ruby/object:Gem::Dependency
|
64
80
|
name: net-ssh
|
65
81
|
requirement: !ruby/object:Gem::Requirement
|