ironfan 5.0.11 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.gitmodules +3 -0
- data/Gemfile +8 -26
- data/Gemfile.lock +38 -41
- data/NOTES-REALM.md +172 -0
- data/Rakefile +19 -77
- data/config/ubuntu12.04-ironfan.erb +7 -0
- data/ironfan.gemspec +28 -225
- data/lib/chef/cluster_knife.rb +26 -0
- data/lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb +7 -0
- data/lib/chef/knife/cluster_bootstrap.rb +1 -3
- data/lib/chef/knife/cluster_diff.rb +2 -8
- data/lib/chef/knife/cluster_kick.rb +1 -3
- data/lib/chef/knife/cluster_kill.rb +1 -2
- data/lib/chef/knife/cluster_launch.rb +17 -34
- data/lib/chef/knife/cluster_list.rb +6 -5
- data/lib/chef/knife/cluster_proxy.rb +1 -3
- data/lib/chef/knife/cluster_pry.rb +1 -2
- data/lib/chef/knife/cluster_show.rb +6 -7
- data/lib/chef/knife/cluster_ssh.rb +10 -8
- data/lib/chef/knife/cluster_start.rb +1 -2
- data/lib/chef/knife/cluster_stop.rb +1 -2
- data/lib/chef/knife/cluster_sync.rb +2 -3
- data/lib/chef/knife/ironfan_knife_common.rb +58 -18
- data/lib/chef/knife/ironfan_script.rb +0 -3
- data/lib/ironfan/broker/computer.rb +14 -11
- data/lib/ironfan/broker.rb +17 -12
- data/lib/ironfan/cookbook_requirements.rb +155 -0
- data/lib/ironfan/dsl/cloud.rb +2 -0
- data/lib/ironfan/dsl/cluster.rb +25 -15
- data/lib/ironfan/dsl/component.rb +12 -15
- data/lib/ironfan/dsl/compute.rb +10 -8
- data/lib/ironfan/dsl/ec2.rb +2 -26
- data/lib/ironfan/dsl/facet.rb +16 -14
- data/lib/ironfan/dsl/openstack.rb +147 -0
- data/lib/ironfan/dsl/realm.rb +23 -16
- data/lib/ironfan/dsl/security_group.rb +29 -0
- data/lib/ironfan/dsl/server.rb +14 -5
- data/lib/ironfan/dsl/static.rb +63 -0
- data/lib/ironfan/dsl/vsphere.rb +1 -0
- data/lib/ironfan/dsl.rb +1 -134
- data/lib/ironfan/headers.rb +19 -0
- data/lib/ironfan/provider/chef/node.rb +3 -2
- data/lib/ironfan/provider/ec2/machine.rb +10 -14
- data/lib/ironfan/provider/ec2/security_group.rb +58 -43
- data/lib/ironfan/provider/openstack/elastic_ip.rb +96 -0
- data/lib/ironfan/provider/openstack/keypair.rb +78 -0
- data/lib/ironfan/provider/openstack/machine.rb +371 -0
- data/lib/ironfan/provider/openstack/security_group.rb +224 -0
- data/lib/ironfan/provider/openstack.rb +69 -0
- data/lib/ironfan/provider/static/machine.rb +192 -0
- data/lib/ironfan/provider/static.rb +23 -0
- data/lib/ironfan/provider.rb +58 -1
- data/lib/ironfan/requirements.rb +17 -1
- data/lib/ironfan/version.rb +3 -0
- data/lib/ironfan.rb +107 -172
- data/spec/chef/cluster_bootstrap_spec.rb +2 -7
- data/spec/chef/cluster_launch_spec.rb +1 -2
- data/spec/fixtures/realms/samurai.rb +26 -0
- data/spec/integration/minimal-chef-repo/clusters/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/config/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/.gitignore +1 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/certificates/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/client_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/data_bag_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ec2_certs/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ec2_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ironfantest-validator.pem +27 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ironfantester.pem +27 -0
- data/spec/integration/minimal-chef-repo/tasks/.gitkeep +0 -0
- data/spec/ironfan/cluster_spec.rb +1 -2
- data/spec/ironfan/diff_spec.rb +0 -2
- data/spec/ironfan/dsl_spec.rb +6 -3
- data/spec/ironfan/ec2/cloud_provider_spec.rb +17 -18
- data/spec/ironfan/ec2/elb_spec.rb +44 -41
- data/spec/ironfan/ec2/security_group_spec.rb +45 -47
- data/spec/ironfan/manifest_spec.rb +0 -1
- data/spec/ironfan/plugin_spec.rb +55 -40
- data/spec/ironfan/realm_spec.rb +42 -30
- data/spec/spec_helper.rb +17 -31
- data/spec/{spec_helper → support}/dummy_chef.rb +0 -0
- data/spec/{spec_helper → support}/dummy_diff_drawer.rb +0 -0
- metadata +78 -155
- data/.rspec +0 -2
- data/.yardopts +0 -19
- data/VERSION +0 -2
- data/chefignore +0 -41
- data/notes/Future-development-proposals.md +0 -266
- data/notes/Home.md +0 -55
- data/notes/INSTALL-cloud_setup.md +0 -103
- data/notes/INSTALL.md +0 -134
- data/notes/Ironfan-Roadmap.md +0 -70
- data/notes/Upgrading-to-v4.md +0 -66
- data/notes/advanced-superpowers.md +0 -16
- data/notes/aws_servers.jpg +0 -0
- data/notes/aws_user_key.png +0 -0
- data/notes/cookbook-versioning.md +0 -11
- data/notes/core_concepts.md +0 -200
- data/notes/declaring_volumes.md +0 -3
- data/notes/design_notes-aspect_oriented_devops.md +0 -36
- data/notes/design_notes-ci_testing.md +0 -169
- data/notes/design_notes-cookbook_event_ordering.md +0 -249
- data/notes/design_notes-meta_discovery.md +0 -59
- data/notes/ec2-pricing_and_capacity.md +0 -75
- data/notes/ec2-pricing_and_capacity.numbers +0 -0
- data/notes/homebase-layout.txt +0 -102
- data/notes/knife-cluster-commands.md +0 -21
- data/notes/named-cloud-objects.md +0 -11
- data/notes/opscode_org_key.png +0 -0
- data/notes/opscode_user_key.png +0 -0
- data/notes/philosophy.md +0 -13
- data/notes/rake_tasks.md +0 -24
- data/notes/renamed-recipes.txt +0 -142
- data/notes/silverware.md +0 -85
- data/notes/style_guide.md +0 -300
- data/notes/tips_and_troubleshooting.md +0 -92
- data/notes/walkthrough-hadoop.md +0 -168
- data/notes/walkthrough-web.md +0 -166
- data/spec/fixtures/gunbai.rb +0 -24
- data/spec/test_config.rb +0 -20
- data/tasks/chef_config.rake +0 -38
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Ironfan
|
4
|
+
class Dsl
|
5
|
+
|
6
|
+
class Compute < Ironfan::Dsl
|
7
|
+
def openstack(*attrs,&block) cloud(:openstack,*attrs,&block); end
|
8
|
+
end
|
9
|
+
|
10
|
+
class OpenStack < Cloud
|
11
|
+
magic :availability_zones, Array, :default => ['nova']
|
12
|
+
magic :backing, String, :default => 'ebs'
|
13
|
+
magic :bits, Integer, :default => ->{ flavor_info[:bits] }
|
14
|
+
magic :bootstrap_distro, String, :default => ->{ image_info[:bootstrap_distro] }
|
15
|
+
magic :chef_client_script, String
|
16
|
+
magic :default_availability_zone, String, :default => ->{ availability_zones.first }
|
17
|
+
#collection :elastic_load_balancers, Ironfan::Dsl::Ec2::ElasticLoadBalancer, :key_method => :name
|
18
|
+
magic :ebs_optimized, :boolean, :default => false
|
19
|
+
magic :flavor, String, :default => 't1.micro'
|
20
|
+
#collection :iam_server_certificates, Ironfan::Dsl::Ec2::IamServerCertificate, :key_method => :name
|
21
|
+
magic :image_id, String
|
22
|
+
magic :image_name, String
|
23
|
+
magic :keypair, String
|
24
|
+
magic :monitoring, String
|
25
|
+
magic :mount_ephemerals, Hash, :default => {}
|
26
|
+
magic :permanent, :boolean, :default => false
|
27
|
+
magic :placement_group, String
|
28
|
+
magic :provider, Whatever, :default => Ironfan::Provider::OpenStack
|
29
|
+
magic :elastic_ip, String
|
30
|
+
magic :auto_elastic_ip, String
|
31
|
+
magic :allocation_id, String
|
32
|
+
magic :region, String, :default => ->{ default_region }
|
33
|
+
collection :security_groups, Ironfan::Dsl::SecurityGroup, :key_method => :name
|
34
|
+
magic :ssh_user, String, :default => ->{ image_info[:ssh_user] }
|
35
|
+
magic :ssh_identity_dir, String, :default => ->{ Chef::Config.openstack_key_dir }
|
36
|
+
magic :subnet, String
|
37
|
+
magic :validation_key, String, :default => ->{ IO.read(Chef::Config.validation_key) rescue '' }
|
38
|
+
magic :vpc, String
|
39
|
+
magic :dns_search_domain, String, :default => 'novalocal'
|
40
|
+
|
41
|
+
def domain; vpc.nil? ? 'standard' : 'vpc'; end
|
42
|
+
|
43
|
+
def image_info
|
44
|
+
bit_str = "#{self.bits.to_i}-bit" # correct for legacy image info.
|
45
|
+
keys = [region, bit_str, backing, image_name]
|
46
|
+
info = Chef::Config[:openstack_image_info][ keys ]
|
47
|
+
ui.warn("Can't find image for #{[region, bit_str, backing, image_name].inspect}") if info.blank?
|
48
|
+
return info || {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def image_id
|
52
|
+
result = read_attribute(:image_id) || image_info[:image_id]
|
53
|
+
end
|
54
|
+
|
55
|
+
def ssh_key_name(computer)
|
56
|
+
keypair ? keypair.to_s : computer.server.cluster_name
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_region
|
60
|
+
default_availability_zone ? default_availability_zone.gsub(/^(\w+-\w+-\d)[a-z]/, '\1') : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_display(style,values={})
|
64
|
+
return values if style == :minimal
|
65
|
+
|
66
|
+
values["Flavor"] = flavor
|
67
|
+
values["AZ"] = default_availability_zone
|
68
|
+
return values if style == :default
|
69
|
+
|
70
|
+
values["Public IP"] = elastic_ip if elastic_ip
|
71
|
+
values
|
72
|
+
end
|
73
|
+
|
74
|
+
def flavor_info
|
75
|
+
if not Chef::Config[:openstack_flavor_info].has_key?(flavor)
|
76
|
+
ui.warn("Unknown machine image flavor '#{flavor}'")
|
77
|
+
list_flavors
|
78
|
+
return nil
|
79
|
+
end
|
80
|
+
Chef::Config[:openstack_flavor_info][flavor]
|
81
|
+
end
|
82
|
+
|
83
|
+
def implied_volumes
|
84
|
+
result = []
|
85
|
+
if backing == 'ebs'
|
86
|
+
result << Ironfan::Dsl::Volume.new(:name => 'root') do
|
87
|
+
device '/dev/sda1'
|
88
|
+
fstype 'ext4'
|
89
|
+
keep false
|
90
|
+
mount_point '/'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
return result unless (mount_ephemerals and (flavor_info[:ephemeral_volumes] > 0))
|
94
|
+
|
95
|
+
layout = { 0 => ['/dev/sdb','/mnt'],
|
96
|
+
1 => ['/dev/sdc','/mnt2'],
|
97
|
+
2 => ['/dev/sdd','/mnt3'],
|
98
|
+
3 => ['/dev/sde','/mnt4'] }
|
99
|
+
( 0 .. (flavor_info[:ephemeral_volumes]-1) ).each do |idx|
|
100
|
+
dev, mnt = layout[idx]
|
101
|
+
ephemeral = Ironfan::Dsl::Volume.new(:name => "ephemeral#{idx}") do
|
102
|
+
attachable 'ephemeral'
|
103
|
+
fstype 'ext3'
|
104
|
+
device dev
|
105
|
+
mount_point mnt
|
106
|
+
mount_options 'defaults,noatime'
|
107
|
+
tags({:bulk => true, :local => true, :fallback => true})
|
108
|
+
end
|
109
|
+
ephemeral_attrs = mount_ephemerals.clone
|
110
|
+
if ephemeral_attrs.has_key?(:disks)
|
111
|
+
disk_attrs = mount_ephemerals[:disks][idx] || { }
|
112
|
+
ephemeral_attrs.delete(:disks)
|
113
|
+
ephemeral_attrs.merge!(disk_attrs)
|
114
|
+
end
|
115
|
+
ephemeral.receive! ephemeral_attrs
|
116
|
+
result << ephemeral
|
117
|
+
end
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
def receive_provider(obj)
|
122
|
+
if obj.is_a?(String)
|
123
|
+
write_attribute :provider, Gorillib::Inflector.constantize(Gorillib::Inflector.camelize(obj.gsub(/\./, '/')))
|
124
|
+
else
|
125
|
+
super(obj)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
Chef::Config[:openstack_flavor_info] ||= {}
|
133
|
+
Chef::Config[:openstack_flavor_info].merge!({
|
134
|
+
# 32-or-64: m1.small, m1.medium, t1.micro, c1.medium
|
135
|
+
't1.micro' => { :price => 0.02, :bits => 64, :ram => 686, :cores => 1, :core_size => 0.25, :inst_disks => 0, :inst_disk_size => 0, :ephemeral_volumes => 0 },
|
136
|
+
'm1.small' => { :price => 0.08, :bits => 64, :ram => 1740, :cores => 1, :core_size => 1, :inst_disks => 1, :inst_disk_size => 160, :ephemeral_volumes => 1 },
|
137
|
+
'm1.medium' => { :price => 0.165, :bits => 64, :ram => 3840, :cores => 2, :core_size => 1, :inst_disks => 1, :inst_disk_size => 410, :ephemeral_volumes => 1 },
|
138
|
+
'c1.medium' => { :price => 0.17, :bits => 64, :ram => 1740, :cores => 2, :core_size => 2.5, :inst_disks => 1, :inst_disk_size => 350, :ephemeral_volumes => 1 },
|
139
|
+
#
|
140
|
+
'm1.large' => { :price => 0.32, :bits => 64, :ram => 7680, :cores => 2, :core_size => 2, :inst_disks => 1, :inst_disk_size => 850, :ephemeral_volumes => 2, },
|
141
|
+
'm2.xlarge' => { :price => 0.45, :bits => 64, :ram => 18124, :cores => 2, :core_size => 3.25, :inst_disks => 1, :inst_disk_size => 420, :ephemeral_volumes => 1, },
|
142
|
+
'c1.xlarge' => { :price => 0.64, :bits => 64, :ram => 7168, :cores => 8, :core_size => 2.5, :inst_disks => 1, :inst_disk_size => 1690, :ephemeral_volumes => 4, },
|
143
|
+
'm1.xlarge' => { :price => 0.66, :bits => 64, :ram => 15360, :cores => 4, :core_size => 2, :inst_disks => 1, :inst_disk_size => 1690, :ephemeral_volumes => 4, },
|
144
|
+
})
|
145
|
+
|
146
|
+
Chef::Config[:openstack_image_info] ||= {}
|
147
|
+
|
data/lib/ironfan/dsl/realm.rb
CHANGED
@@ -1,37 +1,44 @@
|
|
1
1
|
module Ironfan
|
2
2
|
class Dsl
|
3
|
-
|
4
3
|
class Realm < Ironfan::Dsl::Compute
|
5
4
|
collection :clusters, Ironfan::Dsl::Cluster, :resolver => :deep_resolve
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
magic :cluster_suffixes, Whatever
|
7
|
+
|
8
|
+
def self.definitions
|
9
|
+
@realms ||= {}
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
+
def self.define(attrs = {}, &blk)
|
13
|
+
rlm = new(attrs)
|
14
|
+
rlm.receive!({}, &blk)
|
15
|
+
definitions[attrs[:name].to_sym] = rlm
|
16
|
+
end
|
12
17
|
|
13
|
-
def initialize(attrs={}
|
14
|
-
cluster_names
|
18
|
+
def initialize(attrs = {}, &blk)
|
19
|
+
cluster_names Hash.new
|
15
20
|
realm_name attrs[:name] if attrs[:name]
|
16
21
|
attrs[:environment] = realm_name unless attrs.has_key?(:environment)
|
17
|
-
super(attrs, &
|
22
|
+
super(attrs, &blk)
|
18
23
|
end
|
19
24
|
|
20
|
-
def cluster(label, attrs={}
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
clusters[new_name].tap do |cl|
|
25
|
-
cl.receive!(attrs)
|
25
|
+
def cluster(label, attrs = {}, &blk)
|
26
|
+
if clusters.keys.include? label
|
27
|
+
clusters[label].tap do |cl|
|
28
|
+
cl.receive! attrs
|
26
29
|
cl.instance_eval(&blk) if block_given?
|
27
30
|
end
|
28
31
|
else
|
29
|
-
cluster = Ironfan::Dsl::Cluster.
|
30
|
-
cluster_names[label] =
|
32
|
+
cluster = Ironfan::Dsl::Cluster.define(name: label, owner: self, cluster_names: cluster_names)
|
33
|
+
cluster_names[label] = label
|
31
34
|
cluster.receive!(attrs, &blk)
|
32
|
-
super(
|
35
|
+
super(label, cluster)
|
33
36
|
end
|
34
37
|
end
|
38
|
+
|
39
|
+
def children
|
40
|
+
clusters.to_a
|
41
|
+
end
|
35
42
|
end
|
36
43
|
end
|
37
44
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Dsl
|
3
|
+
class SecurityGroup < Ironfan::Dsl
|
4
|
+
field :name, String
|
5
|
+
field :group_authorized, Array, :default => []
|
6
|
+
field :group_authorized_by, Array, :default => []
|
7
|
+
field :range_authorizations, Array, :default => []
|
8
|
+
|
9
|
+
def authorize_port_range(range, cidr_ip = '0.0.0.0/0', ip_protocol = 'tcp')
|
10
|
+
range = (range .. range) if range.is_a?(Integer)
|
11
|
+
range_authorizations << [range, cidr_ip, ip_protocol]
|
12
|
+
range_authorizations.compact!
|
13
|
+
range_authorizations.uniq!
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorized_by_group(other_name)
|
17
|
+
group_authorized_by << other_name.to_s
|
18
|
+
group_authorized_by.compact!
|
19
|
+
group_authorized_by.uniq!
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorize_group(other_name)
|
23
|
+
group_authorized << other_name.to_s
|
24
|
+
group_authorized.compact!
|
25
|
+
group_authorized.uniq!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/ironfan/dsl/server.rb
CHANGED
@@ -8,6 +8,7 @@ module Ironfan
|
|
8
8
|
field :environment, Symbol
|
9
9
|
field :name, String
|
10
10
|
field :cluster_name, String
|
11
|
+
field :realm_name, String
|
11
12
|
field :facet_name, String
|
12
13
|
field :components, Array, of: Ironfan::Dsl::Component, default: []
|
13
14
|
field :run_list, Array, of: String, default: []
|
@@ -63,11 +64,13 @@ module Ironfan
|
|
63
64
|
# field :validation_key, String
|
64
65
|
#-----------------------------------------------------------------------------------
|
65
66
|
|
67
|
+
|
66
68
|
# Reconstruct machine manifest from a computer, pulling
|
67
69
|
# information from remote sources as necessary.
|
68
70
|
def self.from_computer(computer)
|
69
71
|
node = get_node(computer.name)
|
70
72
|
cluster_name = node['cluster_name']
|
73
|
+
Chef::Log.info "name is whoa: #{cluster_name}"
|
71
74
|
facet_name = node['facet_name']
|
72
75
|
instance = node['facet_index']
|
73
76
|
|
@@ -228,16 +231,22 @@ module Ironfan
|
|
228
231
|
super
|
229
232
|
end
|
230
233
|
|
231
|
-
def full_name
|
234
|
+
def full_name
|
235
|
+
"#{realm_name}-#{cluster_name}-#{facet_name}-#{name}"
|
236
|
+
end
|
237
|
+
def host_name() full_name.gsub('_','-'); end;
|
238
|
+
def fqdn() [self.host_name, self.dns_domain].compact.join("."); end
|
239
|
+
|
232
240
|
def index() name.to_i; end
|
233
|
-
def implied_volumes()
|
241
|
+
def implied_volumes() selected_cloud.implied_volumes; end
|
234
242
|
|
235
243
|
def to_display(style,values={})
|
236
244
|
selected_cloud.to_display(style,values)
|
237
245
|
|
238
246
|
return values if style == :minimal
|
239
247
|
|
240
|
-
values["Env"]
|
248
|
+
values["Env"] = environment
|
249
|
+
values["Realm"] = realm_name
|
241
250
|
values
|
242
251
|
end
|
243
252
|
|
@@ -279,10 +288,10 @@ module Ironfan
|
|
279
288
|
bootstrap_distro: cloud.bootstrap_distro,
|
280
289
|
chef_client_script: cloud.chef_client_script,
|
281
290
|
default_availability_zone: cloud.default_availability_zone,
|
282
|
-
elastic_load_balancers: cloud.elastic_load_balancers,
|
291
|
+
elastic_load_balancers: cloud.respond_to?(:elastic_load_balancers) ? cloud.elastic_load_balancers : nil,
|
283
292
|
ebs_optimized: cloud.ebs_optimized,
|
284
293
|
flavor: cloud.flavor,
|
285
|
-
iam_server_certificates: cloud.iam_server_certificates,
|
294
|
+
iam_server_certificates: cloud.respond_to?(:iam_server_certificates) ? cloud.iam_server_certificates : nil,
|
286
295
|
image_id: cloud.image_id,
|
287
296
|
image_name: cloud.image_name,
|
288
297
|
keypair: cloud.keypair,
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Ironfan
|
4
|
+
class Dsl
|
5
|
+
|
6
|
+
class Compute < Ironfan::Dsl
|
7
|
+
def static(*attrs,&block) cloud(:static,*attrs,&block); end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Static < Cloud
|
11
|
+
|
12
|
+
magic :private_ip, String
|
13
|
+
magic :public_ip, String
|
14
|
+
magic :private_hostname, String
|
15
|
+
magic :public_hostname, String
|
16
|
+
magic :keypair, String
|
17
|
+
magic :provider, Whatever, :default => Ironfan::Provider::Static
|
18
|
+
|
19
|
+
magic :availability_zones, Array, :default => []
|
20
|
+
magic :backing, String, :default => nil
|
21
|
+
magic :bits, Integer, :default => 64
|
22
|
+
magic :bootstrap_distro, String, :default => "ubuntu12.04-ironfan"
|
23
|
+
magic :chef_client_script, String
|
24
|
+
magic :default_availability_zone, String, :default => "none"
|
25
|
+
magic :ebs_optimized, :boolean, :default => false
|
26
|
+
magic :flavor, String, :default => 'whatever'
|
27
|
+
magic :image_id, String
|
28
|
+
magic :image_name, String
|
29
|
+
magic :monitoring, String
|
30
|
+
magic :mount_ephemerals, Hash, :default => {}
|
31
|
+
magic :permanent, :boolean, :default => false
|
32
|
+
magic :placement_group, String
|
33
|
+
magic :elastic_ip, String
|
34
|
+
magic :auto_elastic_ip, String
|
35
|
+
magic :allocation_id, String
|
36
|
+
magic :region, String, :default => 'none'
|
37
|
+
collection :security_groups, Ironfan::Dsl::SecurityGroup, :key_method => :name
|
38
|
+
magic :ssh_user, String, :default => 'ubuntu'
|
39
|
+
magic :ssh_identity_dir, String, :default => ->{ Chef::Config.openstack_key_dir }
|
40
|
+
magic :subnet, String
|
41
|
+
magic :validation_key, String, :default => ->{ IO.read(Chef::Config.validation_key) rescue '' }
|
42
|
+
magic :vpc, String
|
43
|
+
magic :dns_search_domain, String, :default => 'static'
|
44
|
+
|
45
|
+
def to_display(style,values={})
|
46
|
+
return values if style == :minimal
|
47
|
+
|
48
|
+
values["Private IP"] = private_ip
|
49
|
+
values["Public IP"] = public_ip
|
50
|
+
values
|
51
|
+
end
|
52
|
+
|
53
|
+
def flavor_info
|
54
|
+
return nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def implied_volumes
|
58
|
+
[]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
data/lib/ironfan/dsl/vsphere.rb
CHANGED
@@ -32,6 +32,7 @@ module Ironfan
|
|
32
32
|
magic :virtual_disks, Array, :default => []
|
33
33
|
magic :vsphere_datacenters, Array, :default => ['New Datacenter']
|
34
34
|
magic :network, String, :default => "VM Network"
|
35
|
+
magic :dns_search_domain, String, :default => 'internal'
|
35
36
|
|
36
37
|
def image_info
|
37
38
|
bit_str = "#{self.bits.to_i}-bit" # correct for legacy image info.
|
data/lib/ironfan/dsl.rb
CHANGED
@@ -1,139 +1,6 @@
|
|
1
1
|
module Ironfan
|
2
|
-
|
3
2
|
class Dsl < Builder
|
4
|
-
include Gorillib::Resolution
|
5
|
-
|
6
|
-
def self.default_cookbook_reqs
|
7
|
-
@default_cookbook_reqs ||= []
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.cookbook_req name, constraint
|
11
|
-
default_cookbook_reqs << new_req(name, constraint)
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def join_req req1, req2
|
16
|
-
# order requirements by operation: =, >=, ~>
|
17
|
-
req1, req2 = (req1.constraint < req2.constraint) ? [req1, req2] : [req2, req1]
|
18
|
-
cn1, cn2 = [req1.constraint, req2.constraint]
|
19
|
-
vers1, vers2 = [cn1.split.last, cn2.split.last]
|
20
|
-
vers1_c, vers2_c = [vers1.split('.'), vers2.split('.')]
|
21
|
-
op1, op2 = [req1, req2].map{|x| x.constraint.split.first}
|
22
|
-
|
23
|
-
if op1 == '=' and op2 == '='
|
24
|
-
join_eq_eq(req1, req2)
|
25
|
-
elsif op1 == '>=' and op2 == '>='
|
26
|
-
join_geq_geq(req1, req2)
|
27
|
-
elsif op1 == '~>' and op2 == '~>'
|
28
|
-
join_agt_agt(req1, req2)
|
29
|
-
elsif op1 == '=' and op2 == '>='
|
30
|
-
join_eq_gte(req1, req2)
|
31
|
-
elsif op1 == '=' and op2 == '~>'
|
32
|
-
join_eq_agt(req1, req2)
|
33
|
-
elsif op1 == '>=' and op2 == '~>'
|
34
|
-
join_gte_agt(req1, req2)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def cookbook_req name, constraint
|
39
|
-
(@cookbook_reqs ||= []) << self.class.new_req(name, constraint)
|
40
|
-
end
|
41
|
-
|
42
|
-
def children() [] end
|
43
|
-
|
44
|
-
def cookbook_reqs
|
45
|
-
Hash[_cookbook_reqs.map{|x| [x.name, x.constraint]}]
|
46
|
-
end
|
47
|
-
|
48
|
-
def _cookbook_reqs
|
49
|
-
[
|
50
|
-
*shallow_cookbook_reqs,
|
51
|
-
*child_cookbook_reqs
|
52
|
-
].group_by(&:name).values.map do |group|
|
53
|
-
group.inject{|result, req| join_req(result, req)}
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
#-----------------------------------------------------------------------------------------------
|
60
|
-
|
61
|
-
def join_eq_eq(req1, req2)
|
62
|
-
(vers(req1) == vers(req2)) ? req1 : bad_reqs(req1, req2)
|
63
|
-
end
|
64
|
-
|
65
|
-
def join_geq_geq(req1, req2)
|
66
|
-
(vers(req1) >= vers(req2)) ? req1 : req2
|
67
|
-
end
|
68
|
-
|
69
|
-
def join_agt_agt(req1, req2)
|
70
|
-
if vers_a(req1).size == vers_a(req2).size and
|
71
|
-
vers_a_head(req1).zip(vers_a_head(req2)).all?{|v1,v2| v1 == v2}
|
72
|
-
(req1.constraint > req2.constraint) ? req1 : req2
|
73
|
-
else
|
74
|
-
bad_reqs(req1, req2)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def join_eq_gte(req1, req2)
|
79
|
-
vers(req1) >= vers(req2) ? req1 : bad_reqs(req1, req2)
|
80
|
-
end
|
81
|
-
|
82
|
-
def join_eq_agt(req1, req2)
|
83
|
-
if match_v_head(req1, req2) and
|
84
|
-
vers_a(req1)[vers_a(req2).size - 1] >= vers_a(req2).last
|
85
|
-
req1
|
86
|
-
else
|
87
|
-
bad_reqs(req1, req2)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def join_gte_agt(req1, req2)
|
92
|
-
if match_v_head(req1, req2) and vers(req1) <= vers(req2)
|
93
|
-
req2
|
94
|
-
else
|
95
|
-
bad_reqs(req1, req2)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def match_v_head(req1, req2)
|
100
|
-
vers_a_head(req1, vers_a(req2).size).zip(vers_a_head(req2)).all?{|v1,v2| v1 == v2}
|
101
|
-
end
|
102
|
-
|
103
|
-
def op(req)
|
104
|
-
req.constraint.split.first
|
105
|
-
end
|
106
|
-
|
107
|
-
def vers(req)
|
108
|
-
req.constraint.split.last
|
109
|
-
end
|
110
|
-
|
111
|
-
def vers_a(req)
|
112
|
-
vers(req).split('.')
|
113
|
-
end
|
114
|
-
|
115
|
-
def vers_a_head(req, last = 0)
|
116
|
-
vers_a(req)[0...last-1]
|
117
|
-
end
|
118
|
-
|
119
|
-
#-----------------------------------------------------------------------------------------------
|
120
|
-
|
121
|
-
def bad_reqs(req1, req2)
|
122
|
-
raise ArgumentError.new("#{req1.name}: cannot reconcile #{req1.constraint} with #{req2.constraint}")
|
123
|
-
end
|
124
|
-
|
125
|
-
def child_cookbook_reqs
|
126
|
-
children.map(&:_cookbook_reqs).flatten(1)
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.new_req(name, constraint)
|
130
|
-
raise StandardError.new("Please don't use >= constraints. They're too vague!") if
|
131
|
-
constraint.start_with?('>=') and not (@@testing ||= false)
|
132
|
-
Ironfan::Plugin::CookbookRequirement.new(name: name, constraint: constraint)
|
133
|
-
end
|
3
|
+
include Gorillib::Resolution, CookbookRequirements
|
134
4
|
|
135
|
-
def shallow_cookbook_reqs
|
136
|
-
@cookbook_reqs || self.class.default_cookbook_reqs
|
137
|
-
end
|
138
5
|
end
|
139
6
|
end
|
data/lib/ironfan/headers.rb
CHANGED
@@ -31,6 +31,14 @@ module Ironfan
|
|
31
31
|
class ElasticLoadBalancer < Ironfan::Dsl; end
|
32
32
|
class IamServerCertificate < Ironfan::Dsl; end
|
33
33
|
end
|
34
|
+
|
35
|
+
class OpenStack < Cloud
|
36
|
+
class SecurityGroup < Ironfan::Dsl; end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Static < Cloud
|
40
|
+
end
|
41
|
+
|
34
42
|
class VirtualBox < Cloud; end
|
35
43
|
class Vsphere < Cloud; end
|
36
44
|
class Rds < Cloud
|
@@ -65,6 +73,17 @@ module Ironfan
|
|
65
73
|
class ElasticLoadBalancer < Ironfan::Provider::Resource; end
|
66
74
|
class IamServerCertificate < Ironfan::Provider::Resource; end
|
67
75
|
end
|
76
|
+
|
77
|
+
class OpenStack < Ironfan::IaasProvider
|
78
|
+
class Machine < Ironfan::IaasProvider::Machine; end
|
79
|
+
class Keypair < Ironfan::Provider::Resource; end
|
80
|
+
class SecurityGroup < Ironfan::Provider::Resource; end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Static < Ironfan::IaasProvider
|
84
|
+
class Machine < Ironfan::IaasProvider::Machine; end
|
85
|
+
end
|
86
|
+
|
68
87
|
class VirtualBox < Ironfan::IaasProvider
|
69
88
|
class Machine < Ironfan::IaasProvider::Machine; end
|
70
89
|
end
|
@@ -67,6 +67,7 @@ module Ironfan
|
|
67
67
|
server = computer.server
|
68
68
|
chef_environment(server.environment.to_s)
|
69
69
|
run_list.instance_eval { @run_list_items = server.run_list }
|
70
|
+
normal[:realm_name] = server.realm_name
|
70
71
|
normal[:cluster_name] = server.cluster_name
|
71
72
|
normal[:facet_name] = server.facet_name
|
72
73
|
normal[:permanent] = computer.permanent?
|
@@ -86,8 +87,8 @@ module Ironfan
|
|
86
87
|
#
|
87
88
|
# Discovery
|
88
89
|
#
|
89
|
-
def self.load!(cluster=nil)
|
90
|
-
query = cluster && "name:#{cluster.
|
90
|
+
def self.load!(cluster = nil)
|
91
|
+
query = cluster && "name:#{cluster.realm_name}-*"
|
91
92
|
ChefServer.search(:node, query) do |raw|
|
92
93
|
next unless raw.present?
|
93
94
|
node = register(raw)
|
@@ -48,7 +48,7 @@ module Ironfan
|
|
48
48
|
def groups ; Array(adaptee.groups) ; end
|
49
49
|
def public_hostname ; dns_name ; end
|
50
50
|
def keypair ; key_pair ; end
|
51
|
-
|
51
|
+
|
52
52
|
def created?
|
53
53
|
not ['terminated', 'shutting-down'].include? state
|
54
54
|
end
|
@@ -141,7 +141,7 @@ module Ironfan
|
|
141
141
|
def self.validate_resources!(computers)
|
142
142
|
recall.each_value do |machine|
|
143
143
|
next unless machine.users.empty? and machine.name
|
144
|
-
if machine.name.match("^#{
|
144
|
+
if computers.clusters.any?{ |comp| machine.name.match("^#{comp.name}-") }
|
145
145
|
machine.bogus << :unexpected_machine
|
146
146
|
end
|
147
147
|
next unless machine.bogus?
|
@@ -230,15 +230,7 @@ module Ironfan
|
|
230
230
|
|
231
231
|
def self.launch_description(computer)
|
232
232
|
cloud = computer.server.cloud(:ec2)
|
233
|
-
|
234
|
-
:chef_server => Chef::Config[:chef_server_url],
|
235
|
-
:node_name => computer.name,
|
236
|
-
:organization => Chef::Config[:organization],
|
237
|
-
:cluster_name => computer.server.cluster_name,
|
238
|
-
:facet_name => computer.server.facet_name,
|
239
|
-
:facet_index => computer.server.index,
|
240
|
-
:client_key => computer.private_key
|
241
|
-
}
|
233
|
+
user_data = self.cloud_init_user_data(computer)
|
242
234
|
|
243
235
|
# main machine info
|
244
236
|
# note that Fog does not actually create tags when it creates a
|
@@ -249,16 +241,20 @@ module Ironfan
|
|
249
241
|
:vpc_id => cloud.vpc,
|
250
242
|
:subnet_id => cloud.subnet,
|
251
243
|
:key_name => cloud.ssh_key_name(computer),
|
252
|
-
:user_data =>
|
244
|
+
:user_data => user_data,
|
253
245
|
:block_device_mapping => block_device_mapping(computer),
|
254
246
|
:availability_zone => cloud.default_availability_zone,
|
255
247
|
:monitoring => cloud.monitoring,
|
256
248
|
}
|
257
249
|
|
258
250
|
# VPC security_groups can only be addressed by id (not name)
|
259
|
-
|
260
|
-
|
251
|
+
sec_group_ids = []
|
252
|
+
[computer.server.security_groups, cloud.security_groups].each do |container|
|
253
|
+
sec_group_ids += container.keys.map do |g|
|
254
|
+
SecurityGroup.recall( SecurityGroup.group_name_with_vpc(g,cloud.vpc) ).group_id
|
255
|
+
end
|
261
256
|
end
|
257
|
+
description[:security_group_ids] = sec_group_ids.uniq
|
262
258
|
|
263
259
|
description[:iam_server_certificates] = cloud.iam_server_certificates.values.map do |cert|
|
264
260
|
IamServerCertificate.recall(IamServerCertificate.full_name(computer, cert))
|