cluster_chef 3.0.10 → 3.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -0
- data/TODO.md +8 -0
- data/VERSION +1 -1
- data/cluster_chef.gemspec +5 -5
- data/lib/cluster_chef/chef_layer.rb +2 -1
- data/lib/cluster_chef/cluster.rb +1 -1
- data/lib/cluster_chef/compute.rb +11 -1
- data/lib/cluster_chef/facet.rb +1 -1
- data/lib/cluster_chef/private_key.rb +22 -1
- data/lib/cluster_chef/security_group.rb +48 -32
- data/lib/cluster_chef/server.rb +5 -3
- data/lib/cluster_chef/volume.rb +69 -5
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## v3.0.11: We Raid at Dawn
|
2
|
+
|
3
|
+
* You can now assemble raid groups in the cluster definition:
|
4
|
+
- node metadata instructing the volumes recipe to build the raid volume
|
5
|
+
- marks the component volumes as non-mountable, in the appropriate raid group, etc
|
6
|
+
* Changed the order of `cluster_role` and `facet_role` in the run list. It now goes:
|
7
|
+
- `:first` roles (cluster then facet)
|
8
|
+
- `:normal` roles (cluster then facet)
|
9
|
+
- special roles: `cluster_role` then `facet_role`
|
10
|
+
- `:last` roles (cluster then facet)
|
11
|
+
* knife cluster launch uses ClusterBootstrap, not knife's vanilla bootstrap.
|
12
|
+
* can now do group('group_that_wants').authorized_by_group('group_that_grants') so that in cluster A I can request access to cluster B without gaining its group myself.
|
13
|
+
* push the organization (if set) into the node metadata
|
14
|
+
|
1
15
|
## v3.0.10: Cloud fixes
|
2
16
|
|
3
17
|
* security groups are now created/updated in knife cluster sync. This can't help you apply then to a node afer launch though -- nothing can, the API doesn't allow it.
|
data/TODO.md
CHANGED
@@ -6,3 +6,11 @@
|
|
6
6
|
* knife cluster kick fails if service isn't running
|
7
7
|
* make clear directions for installing `cluster_chef` and its initial use.
|
8
8
|
* knife cluster launch should fail differently if you give it a facet that doesn't exist
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
### ssh_user, ssh_identity_file, keypair, template should be set by cluster except when they shouldn't
|
13
|
+
|
14
|
+
### Organization-specific homebase files
|
15
|
+
|
16
|
+
The current organization of the homebase needs to better scope organization-specific customizations
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.
|
1
|
+
3.0.11
|
data/cluster_chef.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "cluster_chef"
|
8
|
-
s.version = "3.0.
|
8
|
+
s.version = "3.0.11"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Infochimps"]
|
12
|
-
s.date = "2012-01-
|
12
|
+
s.date = "2012-01-24"
|
13
13
|
s.description = "cluster_chef allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks."
|
14
14
|
s.email = "coders@infochimps.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -84,7 +84,7 @@ Gem::Specification.new do |s|
|
|
84
84
|
s.add_development_dependency(%q<rspec>, ["~> 2.5"])
|
85
85
|
s.add_development_dependency(%q<yard>, ["~> 0.6"])
|
86
86
|
s.add_development_dependency(%q<configliere>, ["~> 0.4.8"])
|
87
|
-
s.add_runtime_dependency(%q<cluster_chef-knife>, ["= 3.0.
|
87
|
+
s.add_runtime_dependency(%q<cluster_chef-knife>, ["= 3.0.11"])
|
88
88
|
else
|
89
89
|
s.add_dependency(%q<chef>, ["~> 0.10.4"])
|
90
90
|
s.add_dependency(%q<fog>, ["~> 1.1.1"])
|
@@ -95,7 +95,7 @@ Gem::Specification.new do |s|
|
|
95
95
|
s.add_dependency(%q<rspec>, ["~> 2.5"])
|
96
96
|
s.add_dependency(%q<yard>, ["~> 0.6"])
|
97
97
|
s.add_dependency(%q<configliere>, ["~> 0.4.8"])
|
98
|
-
s.add_dependency(%q<cluster_chef-knife>, ["= 3.0.
|
98
|
+
s.add_dependency(%q<cluster_chef-knife>, ["= 3.0.11"])
|
99
99
|
end
|
100
100
|
else
|
101
101
|
s.add_dependency(%q<chef>, ["~> 0.10.4"])
|
@@ -107,7 +107,7 @@ Gem::Specification.new do |s|
|
|
107
107
|
s.add_dependency(%q<rspec>, ["~> 2.5"])
|
108
108
|
s.add_dependency(%q<yard>, ["~> 0.6"])
|
109
109
|
s.add_dependency(%q<configliere>, ["~> 0.4.8"])
|
110
|
-
s.add_dependency(%q<cluster_chef-knife>, ["= 3.0.
|
110
|
+
s.add_dependency(%q<cluster_chef-knife>, ["= 3.0.11"])
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -198,13 +198,14 @@ module ClusterChef
|
|
198
198
|
def set_chef_node_attributes
|
199
199
|
step(" setting node runlist and essential attributes")
|
200
200
|
@chef_node.run_list = Chef::RunList.new(*@settings[:run_list])
|
201
|
+
@chef_node.normal[ :organization] = Chef::Config[:organization] if Chef::Config[:organization]
|
201
202
|
@chef_node.override[:cluster_name] = cluster_name
|
202
203
|
@chef_node.override[:facet_name] = facet_name
|
203
204
|
@chef_node.override[:facet_index] = facet_index
|
204
205
|
end
|
205
206
|
|
206
207
|
def set_chef_node_environment
|
207
|
-
@chef_node.chef_environment(environment.to_s)
|
208
|
+
@chef_node.chef_environment(environment.to_s) if environment.present?
|
208
209
|
end
|
209
210
|
|
210
211
|
#
|
data/lib/cluster_chef/cluster.rb
CHANGED
data/lib/cluster_chef/compute.rb
CHANGED
@@ -70,6 +70,16 @@ module ClusterChef
|
|
70
70
|
volumes[volume_name]
|
71
71
|
end
|
72
72
|
|
73
|
+
def raid_group(rg_name, attrs={}, &block)
|
74
|
+
volumes[rg_name] ||= ClusterChef::RaidGroup.new(:parent => self, :name => rg_name)
|
75
|
+
volumes[rg_name].configure(attrs, &block)
|
76
|
+
p volumes
|
77
|
+
volumes[rg_name].sub_volumes.each do |sv_name|
|
78
|
+
volume(sv_name){ in_raid(rg_name) ; mountable(false) ; tags({}) }
|
79
|
+
end
|
80
|
+
volumes[rg_name]
|
81
|
+
end
|
82
|
+
|
73
83
|
def root_volume(attrs={}, &block)
|
74
84
|
volume(:root, attrs, &block)
|
75
85
|
end
|
@@ -134,7 +144,7 @@ module ClusterChef
|
|
134
144
|
protected
|
135
145
|
|
136
146
|
def add_to_run_list(item, placement)
|
137
|
-
raise "run_list placement must be one of :first, :normal, :last or nil (also means :normal)" unless [:first, :last, nil].include?(placement)
|
147
|
+
raise "run_list placement must be one of :first, :normal, :last or nil (also means :normal)" unless [:first, :last, :own, nil].include?(placement)
|
138
148
|
@@run_list_rank += 1
|
139
149
|
placement ||= :normal
|
140
150
|
@run_list_info[item] ||= { :rank => @@run_list_rank, :placement => placement }
|
data/lib/cluster_chef/facet.rb
CHANGED
@@ -74,6 +74,27 @@ module ClusterChef
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
class DataBagKey < PrivateKey
|
78
|
+
def body
|
79
|
+
return @body if @body
|
80
|
+
@body
|
81
|
+
end
|
82
|
+
|
83
|
+
def random_token
|
84
|
+
require "digest/sha2"
|
85
|
+
digest = Digest::SHA512.hexdigest( Time.now.to_s + (1..10).collect{ rand.to_s }.join )
|
86
|
+
5.times{ digest = Digest::SHA512.hexdigest(digest) }
|
87
|
+
digest
|
88
|
+
end
|
89
|
+
|
90
|
+
def key_dir
|
91
|
+
return Chef::Config.data_bag_key_dir if Chef::Config.data_bag_key_dir
|
92
|
+
dir = "#{ENV['HOME']}/.chef/data_bag_keys"
|
93
|
+
warn "Please set 'data_bag_key_dir' in your knife.rb. Will use #{dir} as a default"
|
94
|
+
dir
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
77
98
|
class Ec2Keypair < PrivateKey
|
78
99
|
def body
|
79
100
|
return @body if @body
|
@@ -100,7 +121,7 @@ module ClusterChef
|
|
100
121
|
return Chef::Config.ec2_key_dir
|
101
122
|
else
|
102
123
|
dir = "#{ENV['HOME']}/.chef/ec2_keys"
|
103
|
-
warn "Please set 'ec2_key_dir' in your knife.rb
|
124
|
+
warn "Please set 'ec2_key_dir' in your knife.rb. Will use #{dir} as a default"
|
104
125
|
dir
|
105
126
|
end
|
106
127
|
end
|
@@ -12,8 +12,9 @@ module ClusterChef
|
|
12
12
|
description group_description || "cluster_chef generated group #{group_name}"
|
13
13
|
@cloud = cloud
|
14
14
|
@group_authorizations = []
|
15
|
+
@group_authorized_by = []
|
15
16
|
@range_authorizations = []
|
16
|
-
owner_id
|
17
|
+
owner_id(group_owner_id || Chef::Config[:knife][:aws_account_id])
|
17
18
|
end
|
18
19
|
|
19
20
|
@@all = nil
|
@@ -26,8 +27,8 @@ module ClusterChef
|
|
26
27
|
end
|
27
28
|
def self.get_all
|
28
29
|
groups_list = ClusterChef.fog_connection.security_groups.all
|
29
|
-
@@all = groups_list.inject(Mash.new) do |hsh,
|
30
|
-
hsh[
|
30
|
+
@@all = groups_list.inject(Mash.new) do |hsh, fog_group|
|
31
|
+
hsh[fog_group.name] = fog_group ; hsh
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
@@ -35,58 +36,73 @@ module ClusterChef
|
|
35
36
|
all[name] || ClusterChef.fog_connection.security_groups.get(name)
|
36
37
|
end
|
37
38
|
|
38
|
-
def self.get_or_create
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
def self.get_or_create(group_name, description)
|
40
|
+
# FIXME: the '|| ClusterChef.fog' part is probably unnecessary
|
41
|
+
fog_group = all[group_name] || ClusterChef.fog_connection.security_groups.get(group_name)
|
42
|
+
unless fog_group
|
43
|
+
self.step(group_name, "creating (#{description})", :green)
|
44
|
+
fog_group = all[group_name] = ClusterChef.fog_connection.security_groups.new(:name => group_name, :description => description, :connection => ClusterChef.fog_connection)
|
45
|
+
fog_group.save
|
44
46
|
end
|
45
|
-
|
47
|
+
fog_group
|
46
48
|
end
|
47
49
|
|
48
|
-
def
|
49
|
-
@group_authorizations << [
|
50
|
+
def authorize_group(group_name, owner_id=nil)
|
51
|
+
@group_authorizations << [group_name.to_s, owner_id]
|
50
52
|
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
authorize_group_and_owner *args
|
54
|
+
def authorized_by_group(other_name)
|
55
|
+
@group_authorized_by << [other_name.to_s, nil]
|
55
56
|
end
|
56
57
|
|
57
|
-
def authorize_port_range
|
58
|
+
def authorize_port_range(range, cidr_ip = '0.0.0.0/0', ip_protocol = 'tcp')
|
58
59
|
range = (range .. range) if range.is_a?(Integer)
|
59
60
|
@range_authorizations << [range, cidr_ip, ip_protocol]
|
60
61
|
end
|
61
62
|
|
62
|
-
def group_permission_already_set?
|
63
|
-
return false if
|
64
|
-
|
65
|
-
existing_permission["groups"].include?({"userId"=>authed_owner, "groupName"=>
|
63
|
+
def group_permission_already_set?(fog_group, other_name, authed_owner)
|
64
|
+
return false if fog_group.ip_permissions.nil?
|
65
|
+
fog_group.ip_permissions.any? do |existing_permission|
|
66
|
+
existing_permission["groups"].include?({"userId" => authed_owner, "groupName" => other_name}) &&
|
66
67
|
existing_permission["fromPort"] == 1 &&
|
67
|
-
existing_permission["toPort"]
|
68
|
+
existing_permission["toPort"] == 65535
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
def range_permission_already_set?
|
72
|
-
return false if
|
73
|
-
|
72
|
+
def range_permission_already_set?(fog_group, range, cidr_ip, ip_protocol)
|
73
|
+
return false if fog_group.ip_permissions.nil?
|
74
|
+
fog_group.ip_permissions.include?(
|
75
|
+
{ "groups"=>[], "ipRanges"=>[{"cidrIp"=>cidr_ip}],
|
76
|
+
"ipProtocol"=>ip_protocol, "fromPort"=>range.first, "toPort"=>range.last})
|
74
77
|
end
|
75
78
|
|
79
|
+
# FIXME: so if you're saying to yourself, "self, this is some soupy gooey
|
80
|
+
# code right here" then you and your self are correct. Much of this is to
|
81
|
+
# work around old limitations in the EC2 api. You can now treat range and
|
82
|
+
# group permissions the same, and we should.
|
83
|
+
|
76
84
|
def run
|
77
|
-
|
78
|
-
@group_authorizations.uniq.each do |
|
85
|
+
fog_group = self.class.get_or_create(name, description)
|
86
|
+
@group_authorizations.uniq.each do |other_name, authed_owner|
|
79
87
|
authed_owner ||= self.owner_id
|
80
|
-
next if group_permission_already_set?(
|
81
|
-
step("authorizing access from all machines in #{
|
82
|
-
self.class.get_or_create(
|
83
|
-
begin
|
88
|
+
next if group_permission_already_set?(fog_group, other_name, authed_owner)
|
89
|
+
step("authorizing access from all machines in #{other_name} to #{name}", :blue)
|
90
|
+
self.class.get_or_create(other_name, "Authorized to access #{name}")
|
91
|
+
begin fog_group.authorize_group_and_owner(other_name, authed_owner)
|
92
|
+
rescue StandardError => e ; ui.warn e ; end
|
93
|
+
end
|
94
|
+
@group_authorized_by.uniq.each do |other_name|
|
95
|
+
authed_owner = self.owner_id
|
96
|
+
other_group = self.class.get_or_create(other_name, "Authorized for access by #{self.name}")
|
97
|
+
next if group_permission_already_set?(other_group, self.name, authed_owner)
|
98
|
+
step("authorizing access to all machines in #{other_name} from #{name}", :blue)
|
99
|
+
begin other_group.authorize_group_and_owner(self.name, authed_owner)
|
84
100
|
rescue StandardError => e ; ui.warn e ; end
|
85
101
|
end
|
86
102
|
@range_authorizations.uniq.each do |range, cidr_ip, ip_protocol|
|
87
|
-
next if range_permission_already_set?(
|
103
|
+
next if range_permission_already_set?(fog_group, range, cidr_ip, ip_protocol)
|
88
104
|
step("opening #{ip_protocol} ports #{range} to #{cidr_ip}", :blue)
|
89
|
-
begin
|
105
|
+
begin fog_group.authorize_port_range(range, { :cidr_ip => cidr_ip, :ip_protocol => ip_protocol })
|
90
106
|
rescue StandardError => e ; ui.warn e ; end
|
91
107
|
end
|
92
108
|
end
|
data/lib/cluster_chef/server.rb
CHANGED
@@ -136,6 +136,7 @@ module ClusterChef
|
|
136
136
|
#
|
137
137
|
# * run_list :first items -- cluster then facet then server
|
138
138
|
# * run_list :normal items -- cluster then facet then server
|
139
|
+
# * own roles: cluster_role then facet_role
|
139
140
|
# * run_list :last items -- cluster then facet then server
|
140
141
|
#
|
141
142
|
# ClusterChef.cluster(:my_cluster) do
|
@@ -152,11 +153,11 @@ module ClusterChef
|
|
152
153
|
# end
|
153
154
|
#
|
154
155
|
# produces
|
155
|
-
# cluster list [a] [c] [fg]
|
156
|
-
# facet list [b] [de] [h]
|
156
|
+
# cluster list [a] [c] [cluster_role] [fg]
|
157
|
+
# facet list [b] [de] [facet_role] [h]
|
157
158
|
#
|
158
159
|
# yielding run_list
|
159
|
-
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
|
160
|
+
# ['a', 'b', 'c', 'd', 'e', 'cr', 'fr', 'f', 'g', 'h']
|
160
161
|
#
|
161
162
|
# Avoid duplicate conflicting declarations. If you say define things more
|
162
163
|
# than once, the *earliest encountered* one wins, even if it is elsewhere
|
@@ -168,6 +169,7 @@ module ClusterChef
|
|
168
169
|
sg = self.run_list_groups
|
169
170
|
[ cg[:first], fg[:first], sg[:first],
|
170
171
|
cg[:normal], fg[:normal], sg[:normal],
|
172
|
+
cg[:own], fg[:own],
|
171
173
|
cg[:last], fg[:last], sg[:last], ].flatten.compact.uniq
|
172
174
|
end
|
173
175
|
|
data/lib/cluster_chef/volume.rb
CHANGED
@@ -9,6 +9,7 @@ module ClusterChef
|
|
9
9
|
:name,
|
10
10
|
# mountable volume attributes
|
11
11
|
:device, :mount_point, :mount_options, :fstype, :mount_dump, :mount_pass,
|
12
|
+
:mountable, :formattable, :resizable, :in_raid,
|
12
13
|
# cloud volume attributes
|
13
14
|
:attachable, :create_at_launch, :volume_id, :snapshot_id, :size, :keep, :availability_zone,
|
14
15
|
# arbitrary tags
|
@@ -18,11 +19,29 @@ module ClusterChef
|
|
18
19
|
VOLUME_DEFAULTS = {
|
19
20
|
:fstype => 'xfs',
|
20
21
|
:mount_options => 'defaults,nouuid,noatime',
|
22
|
+
:keep => true,
|
21
23
|
:attachable => :ebs,
|
22
24
|
:create_at_launch => false,
|
23
|
-
|
25
|
+
#
|
26
|
+
:mountable => true,
|
27
|
+
:resizable => false,
|
28
|
+
:formattable => false,
|
29
|
+
:in_raid => false,
|
24
30
|
}
|
25
31
|
|
32
|
+
# Snapshot for snapshot_name method.
|
33
|
+
# Set your own by adding
|
34
|
+
#
|
35
|
+
# VOLUME_IDS = Mash.new unless defined?(VOLUME_IDS)
|
36
|
+
# VOLUME_IDS.merge!({ :your_id => 'snap-whatever' })
|
37
|
+
#
|
38
|
+
# to your organization's knife.rb
|
39
|
+
#
|
40
|
+
VOLUME_IDS = Mash.new unless defined?(VOLUME_IDS)
|
41
|
+
VOLUME_IDS.merge!({
|
42
|
+
:blank_xfs => 'snap-d9c1edb1',
|
43
|
+
})
|
44
|
+
|
26
45
|
# Describes a volume
|
27
46
|
#
|
28
47
|
# @example
|
@@ -50,6 +69,13 @@ module ClusterChef
|
|
50
69
|
volume_id =~ /^ephemeral/
|
51
70
|
end
|
52
71
|
|
72
|
+
# Named snapshots, as defined in ClusterChef::Volume::VOLUME_IDS
|
73
|
+
def snapshot_name(name)
|
74
|
+
snap_id = VOLUME_IDS[name.to_sym]
|
75
|
+
raise "Unknown snapshot name #{name} - is it defined in ClusterChef::Volume::VOLUME_IDS?" unless snap_id
|
76
|
+
self.snapshot_id(snap_id)
|
77
|
+
end
|
78
|
+
|
53
79
|
# With snapshot specified but volume missing, have it auto-created at launch
|
54
80
|
#
|
55
81
|
# Be careful with this -- you can end up with multiple volumes claiming to
|
@@ -79,10 +105,10 @@ module ClusterChef
|
|
79
105
|
if ephemeral_device?
|
80
106
|
hsh['VirtualName'] = volume_id
|
81
107
|
elsif create_at_launch?
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
108
|
+
raise "Must specify a size or a snapshot ID for #{self}" if snapshot_id.blank? && size.blank?
|
109
|
+
hsh['Ebs.SnapshotId'] = snapshot_id if snapshot_id.present?
|
110
|
+
hsh['Ebs.VolumeSize'] = size.to_s if size.present?
|
111
|
+
hsh['Ebs.DeleteOnTermination'] = (! keep).to_s
|
86
112
|
else
|
87
113
|
return
|
88
114
|
end
|
@@ -90,4 +116,42 @@ module ClusterChef
|
|
90
116
|
end
|
91
117
|
|
92
118
|
end
|
119
|
+
|
120
|
+
|
121
|
+
#
|
122
|
+
# Consider raising the chunk size to 256 and setting read_ahead 65536 if you are raid'ing EBS volumes
|
123
|
+
#
|
124
|
+
# * http://victortrac.com/EC2_Ephemeral_Disks_vs_EBS_Volumes
|
125
|
+
# * http://orion.heroku.com/past/2009/7/29/io_performance_on_ebs/
|
126
|
+
# * http://tech.blog.greplin.com/aws-best-practices-and-benchmarks
|
127
|
+
# * http://stu.mp/2009/12/disk-io-and-throughput-benchmarks-on-amazons-ec2.html
|
128
|
+
#
|
129
|
+
class RaidGroup < Volume
|
130
|
+
has_keys(
|
131
|
+
:sub_volumes, # volumes that comprise this raid group
|
132
|
+
:level, # RAID level (http://en.wikipedia.org/wiki/RAID#Standard_levels)
|
133
|
+
:chunk, # Raid chunk size (https://raid.wiki.kernel.org/articles/r/a/i/RAID_setup_cbb2.html)
|
134
|
+
:read_ahead, # read-ahead buffer
|
135
|
+
)
|
136
|
+
|
137
|
+
def desc
|
138
|
+
"#{name} on #{parent.fullname} (#{volume_id} @ #{device} from #{sub_volumes.join(',')})"
|
139
|
+
end
|
140
|
+
|
141
|
+
def defaults()
|
142
|
+
super
|
143
|
+
fstype 'xfs'
|
144
|
+
mount_options "defaults,nobootwait,noatime,nouuid,comment=cluster_chef"
|
145
|
+
attachable false
|
146
|
+
create_at_launch false
|
147
|
+
#
|
148
|
+
mountable true
|
149
|
+
resizable false
|
150
|
+
formattable true
|
151
|
+
#
|
152
|
+
in_raid false
|
153
|
+
#
|
154
|
+
sub_volumes []
|
155
|
+
end
|
156
|
+
end
|
93
157
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: cluster_chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 3.0.
|
5
|
+
version: 3.0.11
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Infochimps
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-01-
|
13
|
+
date: 2012-01-24 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: chef
|
@@ -118,7 +118,7 @@ dependencies:
|
|
118
118
|
requirements:
|
119
119
|
- - "="
|
120
120
|
- !ruby/object:Gem::Version
|
121
|
-
version: 3.0.
|
121
|
+
version: 3.0.11
|
122
122
|
type: :runtime
|
123
123
|
prerelease: false
|
124
124
|
version_requirements: *id010
|
@@ -191,7 +191,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
191
191
|
requirements:
|
192
192
|
- - ">="
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
hash:
|
194
|
+
hash: 2883280125648369733
|
195
195
|
segments:
|
196
196
|
- 0
|
197
197
|
version: "0"
|