ironfan 4.2.0 → 4.2.1
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/CHANGELOG.md +10 -0
- data/VERSION +1 -1
- data/ironfan.gemspec +4 -3
- data/lib/gorillib/resolution.rb +31 -1
- data/lib/ironfan/broker.rb +1 -1
- data/lib/ironfan/dsl/cluster.rb +0 -6
- data/lib/ironfan/dsl/facet.rb +1 -4
- data/lib/ironfan.rb +10 -8
- data/spec/ironfan/ec2/cloud_provider_spec.rb +35 -0
- data/spec/ironfan/ec2/security_group_spec.rb +71 -18
- metadata +5 -3
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# v4.2.1: @nickmarden rocks the house
|
2
|
+
* More correct merging of cluster and facet objects, with specs
|
3
|
+
* Circumvent memory bloat by resolving just once
|
4
|
+
|
5
|
+
# v4.2.0:
|
6
|
+
* providers now load in parallel
|
7
|
+
* substeps announcements for load are now done in provider, not individual resources
|
8
|
+
* only dump computers full information on -VV
|
9
|
+
* more cleanup of new specs
|
10
|
+
|
1
11
|
# v4.1.1: fixing 'rake spec'
|
2
12
|
* Remove all defunct tests and start fresh (fixes #137)
|
3
13
|
* Failing spec for #158
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.2.
|
1
|
+
4.2.1
|
data/ironfan.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ironfan"
|
8
|
-
s.version = "4.2.
|
8
|
+
s.version = "4.2.1"
|
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-
|
12
|
+
s.date = "2012-10-01"
|
13
13
|
s.description = "Ironfan 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 = [
|
@@ -85,6 +85,7 @@ Gem::Specification.new do |s|
|
|
85
85
|
"lib/ironfan/provider/virtualbox/machine.rb",
|
86
86
|
"lib/ironfan/requirements.rb",
|
87
87
|
"spec/ironfan/cluster_spec.rb",
|
88
|
+
"spec/ironfan/ec2/cloud_provider_spec.rb",
|
88
89
|
"spec/ironfan/ec2/security_group_spec.rb",
|
89
90
|
"spec/spec_helper.rb",
|
90
91
|
"spec/spec_helper/dummy_chef.rb",
|
@@ -96,7 +97,7 @@ Gem::Specification.new do |s|
|
|
96
97
|
s.require_paths = ["lib"]
|
97
98
|
s.rubygems_version = "1.8.24"
|
98
99
|
s.summary = "Ironfan 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."
|
99
|
-
s.test_files = ["spec/spec_helper/dummy_chef.rb", "spec/ironfan/cluster_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
|
100
|
+
s.test_files = ["spec/spec_helper/dummy_chef.rb", "spec/ironfan/cluster_spec.rb", "spec/ironfan/ec2/cloud_provider_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
|
100
101
|
|
101
102
|
if s.respond_to? :specification_version then
|
102
103
|
s.specification_version = 3
|
data/lib/gorillib/resolution.rb
CHANGED
@@ -19,6 +19,28 @@ module Gorillib
|
|
19
19
|
Field.class_eval do
|
20
20
|
field :resolver, Symbol, :default => :read_set_or_underlay_attribute
|
21
21
|
end
|
22
|
+
|
23
|
+
# Modifies the Gorillib metaprogramming to handle deep recursion on
|
24
|
+
# Gorillib::Model collections which would prefer to handle arbitrarily
|
25
|
+
# complex resolution requirements via their (custom) receive! method
|
26
|
+
module ClassMethods
|
27
|
+
def define_collection_receiver(field)
|
28
|
+
collection_field_name = field.name; collection_type = field.type
|
29
|
+
# @param [Array[Object],Hash[Object]] the collection to merge
|
30
|
+
# @return [Gorillib::Collection] the updated collection
|
31
|
+
define_meta_module_method("receive_#{collection_field_name}", true) do |coll, &block|
|
32
|
+
begin
|
33
|
+
existing = read_attribute(collection_field_name)
|
34
|
+
if existing and (not collection_type.native?(coll) or existing.respond_to?(:receive!))
|
35
|
+
existing.receive!(coll, &block)
|
36
|
+
else
|
37
|
+
write_attribute(collection_field_name, coll)
|
38
|
+
end
|
39
|
+
rescue StandardError => err ; err.polish("#{self.class} #{collection_field_name} collection on #{args}'") rescue nil ; raise ; end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
22
44
|
end
|
23
45
|
|
24
46
|
# The attribute :underlay provides an object (preferably another
|
@@ -50,6 +72,14 @@ module Gorillib
|
|
50
72
|
result
|
51
73
|
end
|
52
74
|
|
75
|
+
def resolve!
|
76
|
+
resolved = resolve
|
77
|
+
self.class.fields.each do |field_name, field|
|
78
|
+
write_attribute(field_name, resolved.send(field_name.to_sym))
|
79
|
+
end
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
53
83
|
def deep_resolve(field_name)
|
54
84
|
temp = read_set_or_underlay_attribute(field_name)
|
55
85
|
return if temp.nil?
|
@@ -106,7 +136,7 @@ module Gorillib
|
|
106
136
|
|
107
137
|
def read_underlay_attribute(field_name)
|
108
138
|
return if underlay.nil?
|
109
|
-
underlay.read_resolved_attribute(field_name)
|
139
|
+
Gorillib.deep_copy(underlay.read_resolved_attribute(field_name))
|
110
140
|
end
|
111
141
|
|
112
142
|
def read_set_or_underlay_attribute(field_name)
|
data/lib/ironfan/broker.rb
CHANGED
@@ -13,7 +13,7 @@ module Ironfan
|
|
13
13
|
# corresponding to
|
14
14
|
def discover!(cluster)
|
15
15
|
# Get fully resolved servers, and build Computers using them
|
16
|
-
computers = Computers.new(:cluster => cluster
|
16
|
+
computers = Computers.new(:cluster => cluster)
|
17
17
|
#
|
18
18
|
providers = computers.map{|c| c.providers.values }.flatten.uniq
|
19
19
|
Ironfan.parallel(providers) do |provider|
|
data/lib/ironfan/dsl/cluster.rb
CHANGED
@@ -7,12 +7,6 @@ module Ironfan
|
|
7
7
|
def initialize(attrs={},&block)
|
8
8
|
super
|
9
9
|
self.cluster_role Ironfan::Dsl::Role.new(:name => "#{attrs[:name]}_cluster")
|
10
|
-
self.expand_servers!
|
11
|
-
end
|
12
|
-
|
13
|
-
def expand_servers!
|
14
|
-
facets.each {|facet| facet.expand_servers! }
|
15
|
-
servers
|
16
10
|
end
|
17
11
|
|
18
12
|
# Utility method to reference all servers from constituent facets
|
data/lib/ironfan/dsl/facet.rb
CHANGED
@@ -11,14 +11,11 @@ module Ironfan
|
|
11
11
|
self.name = attrs[:name] unless attrs[:name].nil?
|
12
12
|
self.facet_role Ironfan::Dsl::Role.new(:name => fullname.sub('-','_'))
|
13
13
|
super
|
14
|
+
for i in 0 .. instances-1; server(i); end
|
14
15
|
end
|
15
16
|
|
16
17
|
def fullname() "#{cluster_name}-#{name}"; end
|
17
18
|
|
18
|
-
def expand_servers!
|
19
|
-
for i in 0..(instances-1) do server(i); end
|
20
|
-
end
|
21
|
-
|
22
19
|
end
|
23
20
|
|
24
21
|
end
|
data/lib/ironfan.rb
CHANGED
@@ -15,7 +15,7 @@ module Ironfan
|
|
15
15
|
#
|
16
16
|
# Delegates
|
17
17
|
def self.clusters
|
18
|
-
|
18
|
+
@@clusters
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.ui=(ui) @ui = ui ; end
|
@@ -61,10 +61,15 @@ module Ironfan
|
|
61
61
|
#
|
62
62
|
def self.cluster(name, attrs={}, &block)
|
63
63
|
name = name.to_sym
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
# If this is being called as Ironfan.cluster('foo') with no additional arguments,
|
65
|
+
# return the cached cluster object if it exists
|
66
|
+
if @@clusters[name] and attrs.empty? and not block_given?
|
67
|
+
return @@clusters[name]
|
68
|
+
else # Otherwise we're being asked to (re)initialize and cache a cluster definition
|
69
|
+
cl = Ironfan::Dsl::Cluster.new(:name => name)
|
70
|
+
cl.receive!(attrs, &block)
|
71
|
+
@@clusters[name] = cl.resolve
|
72
|
+
end
|
68
73
|
end
|
69
74
|
|
70
75
|
#
|
@@ -87,9 +92,6 @@ module Ironfan
|
|
87
92
|
require cluster_file
|
88
93
|
unless @@clusters[cluster] then die("#{cluster_file} was supposed to have the definition for the #{cluster_name} cluster, but didn't") end
|
89
94
|
|
90
|
-
# Flesh out the expected servers listed in the facets
|
91
|
-
@@clusters[cluster].expand_servers!
|
92
|
-
|
93
95
|
@@clusters[cluster]
|
94
96
|
end
|
95
97
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'ironfan'
|
4
|
+
|
5
|
+
describe Ironfan::Dsl::Cluster do
|
6
|
+
let (:cluster) do
|
7
|
+
Ironfan.cluster "sparky" do
|
8
|
+
|
9
|
+
cloud(:ec2) do
|
10
|
+
security_group(:ssh).authorize_port_range 22..22
|
11
|
+
flavor 't1.micro'
|
12
|
+
end
|
13
|
+
|
14
|
+
facet :web do
|
15
|
+
instances 3
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'web facet server resolution' do
|
22
|
+
before { @facet = cluster.facets.values.first }
|
23
|
+
subject { @facet }
|
24
|
+
its(:name) { should eql "web" }
|
25
|
+
|
26
|
+
it 'should have the right number of servers' do
|
27
|
+
@facet.servers.length.should == 3
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should have one cloud provider, EC2' do
|
31
|
+
@facet.servers[0].clouds.keys.should == [ :ec2 ]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -5,53 +5,106 @@ require 'ironfan'
|
|
5
5
|
describe Ironfan::Dsl::Cluster do
|
6
6
|
let (:cluster) do
|
7
7
|
Ironfan.cluster "sparky" do
|
8
|
-
|
8
|
+
|
9
|
+
cloud(:ec2) do
|
10
|
+
security_group(:ssh).authorize_port_range 22..22
|
11
|
+
flavor 't1.micro'
|
12
|
+
end
|
13
|
+
|
9
14
|
facet :web do
|
10
15
|
cloud(:ec2).security_group("sparky-web").authorize_port_range(80)
|
16
|
+
cloud(:ec2).flavor 'm1.small'
|
11
17
|
end
|
18
|
+
|
19
|
+
facet :mysql do
|
20
|
+
# My what a permissive database you have.
|
21
|
+
cloud(:ec2).security_group("sparky-mysql").authorize_port_range(3306)
|
22
|
+
cloud(:ec2).flavor 'm1.xlarge'
|
23
|
+
end
|
24
|
+
|
12
25
|
end
|
13
26
|
end
|
14
|
-
|
27
|
+
|
15
28
|
describe 'cluster definition' do
|
16
29
|
subject { cluster }
|
17
|
-
|
30
|
+
|
18
31
|
its(:name) { should eql "sparky" }
|
19
32
|
its(:environment) { should eql :_default }
|
20
33
|
its(:run_list) { should eql [] }
|
21
|
-
|
34
|
+
|
22
35
|
describe 'facets' do
|
23
36
|
before { @facets = cluster.facets }
|
24
37
|
subject { @facets.values }
|
25
|
-
its(:length) { should eql
|
26
|
-
|
38
|
+
its(:length) { should eql 2 }
|
39
|
+
|
27
40
|
describe 'web facet' do
|
28
41
|
before { @facet = @facets.values.first }
|
29
42
|
subject { @facet }
|
30
43
|
its(:name) { should eql "web" }
|
31
|
-
|
44
|
+
|
45
|
+
it 'should have the correct flavor' do
|
46
|
+
@facet.cloud(:ec2).flavor.should == 'm1.small'
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should have the right number of servers' do
|
50
|
+
@facet.servers.length.should == 1
|
51
|
+
end
|
52
|
+
|
32
53
|
describe 'security groups' do
|
33
54
|
before { @groups = @facet.clouds.values.first.security_groups.values }
|
34
55
|
subject { @groups }
|
35
|
-
|
56
|
+
|
36
57
|
its(:length) { should eql 2 }
|
37
|
-
|
58
|
+
|
38
59
|
it 'authorizes ssh on port 22 from anywhere' do
|
39
|
-
ssh_auth = @groups.
|
40
|
-
ssh_auth.
|
60
|
+
ssh_auth = @groups.detect { |g| g.name == 'ssh' }
|
61
|
+
ssh_auth.should_not be_nil
|
62
|
+
ssh_auth.range_authorizations.select { |g| g.eql? [22..22, "0.0.0.0/0", "tcp"] }.should_not be_empty
|
41
63
|
end
|
42
|
-
|
64
|
+
|
43
65
|
it 'authorizes HTTP on port 80 from anywhere' do
|
44
|
-
http_auth = @groups.
|
45
|
-
http_auth.
|
66
|
+
http_auth = @groups.detect { |g| g.name == 'sparky-web' }
|
67
|
+
http_auth.should_not be_nil
|
68
|
+
http_auth.range_authorizations.select { |g| g.eql? [80..80, "0.0.0.0/0", "tcp"] }.should_not be_empty
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'mysql facet' do
|
75
|
+
before { @facet = @facets.values.last }
|
76
|
+
subject { @facet }
|
77
|
+
its(:name) { should eql "mysql" }
|
78
|
+
|
79
|
+
it 'should have the correct flavor' do
|
80
|
+
@facet.cloud(:ec2).flavor.should == 'm1.xlarge'
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'security groups' do
|
84
|
+
before { @groups = @facet.clouds.values.first.security_groups.values }
|
85
|
+
subject { @groups }
|
86
|
+
|
87
|
+
its(:length) { should eql 2 }
|
88
|
+
|
89
|
+
it 'authorizes ssh on port 22 from anywhere' do
|
90
|
+
ssh_auth = @groups.detect { |g| g.name == 'ssh' }
|
91
|
+
ssh_auth.should_not be_nil
|
46
92
|
end
|
93
|
+
|
94
|
+
it 'authorizes MySQL on port 3306 from anywhere' do
|
95
|
+
mysql_auth = @groups.detect { |g| g.name == 'sparky-mysql' }
|
96
|
+
mysql_auth.should_not be_nil
|
97
|
+
mysql_auth.range_authorizations.select { |g| g.eql? [3306..3306, "0.0.0.0/0", "tcp"] }.should_not be_empty
|
98
|
+
end
|
99
|
+
|
47
100
|
end
|
48
101
|
end
|
49
|
-
|
102
|
+
|
103
|
+
|
50
104
|
end
|
51
|
-
|
105
|
+
|
52
106
|
describe 'clouds' do
|
53
|
-
|
107
|
+
|
54
108
|
end
|
55
109
|
end
|
56
110
|
end
|
57
|
-
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ironfan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 4.2.
|
5
|
+
version: 4.2.1
|
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-
|
13
|
+
date: 2012-10-01 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: chef
|
@@ -211,6 +211,7 @@ files:
|
|
211
211
|
- lib/ironfan/provider/virtualbox/machine.rb
|
212
212
|
- lib/ironfan/requirements.rb
|
213
213
|
- spec/ironfan/cluster_spec.rb
|
214
|
+
- spec/ironfan/ec2/cloud_provider_spec.rb
|
214
215
|
- spec/ironfan/ec2/security_group_spec.rb
|
215
216
|
- spec/spec_helper.rb
|
216
217
|
- spec/spec_helper/dummy_chef.rb
|
@@ -229,7 +230,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
229
230
|
requirements:
|
230
231
|
- - ">="
|
231
232
|
- !ruby/object:Gem::Version
|
232
|
-
hash:
|
233
|
+
hash: -2791351356463943124
|
233
234
|
segments:
|
234
235
|
- 0
|
235
236
|
version: "0"
|
@@ -249,6 +250,7 @@ summary: Ironfan allows you to orchestrate not just systems but clusters of mach
|
|
249
250
|
test_files:
|
250
251
|
- spec/spec_helper/dummy_chef.rb
|
251
252
|
- spec/ironfan/cluster_spec.rb
|
253
|
+
- spec/ironfan/ec2/cloud_provider_spec.rb
|
252
254
|
- spec/ironfan/ec2/security_group_spec.rb
|
253
255
|
- spec/spec_helper.rb
|
254
256
|
- spec/test_config.rb
|