ironfan 5.0.11 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/.gitignore +4 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +8 -26
  4. data/Gemfile.lock +38 -41
  5. data/NOTES-REALM.md +172 -0
  6. data/Rakefile +19 -77
  7. data/config/ubuntu12.04-ironfan.erb +7 -0
  8. data/ironfan.gemspec +28 -225
  9. data/lib/chef/cluster_knife.rb +26 -0
  10. data/lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb +7 -0
  11. data/lib/chef/knife/cluster_bootstrap.rb +1 -3
  12. data/lib/chef/knife/cluster_diff.rb +2 -8
  13. data/lib/chef/knife/cluster_kick.rb +1 -3
  14. data/lib/chef/knife/cluster_kill.rb +1 -2
  15. data/lib/chef/knife/cluster_launch.rb +17 -34
  16. data/lib/chef/knife/cluster_list.rb +6 -5
  17. data/lib/chef/knife/cluster_proxy.rb +1 -3
  18. data/lib/chef/knife/cluster_pry.rb +1 -2
  19. data/lib/chef/knife/cluster_show.rb +6 -7
  20. data/lib/chef/knife/cluster_ssh.rb +10 -8
  21. data/lib/chef/knife/cluster_start.rb +1 -2
  22. data/lib/chef/knife/cluster_stop.rb +1 -2
  23. data/lib/chef/knife/cluster_sync.rb +2 -3
  24. data/lib/chef/knife/ironfan_knife_common.rb +58 -18
  25. data/lib/chef/knife/ironfan_script.rb +0 -3
  26. data/lib/ironfan/broker/computer.rb +14 -11
  27. data/lib/ironfan/broker.rb +17 -12
  28. data/lib/ironfan/cookbook_requirements.rb +155 -0
  29. data/lib/ironfan/dsl/cloud.rb +2 -0
  30. data/lib/ironfan/dsl/cluster.rb +25 -15
  31. data/lib/ironfan/dsl/component.rb +12 -15
  32. data/lib/ironfan/dsl/compute.rb +10 -8
  33. data/lib/ironfan/dsl/ec2.rb +2 -26
  34. data/lib/ironfan/dsl/facet.rb +16 -14
  35. data/lib/ironfan/dsl/openstack.rb +147 -0
  36. data/lib/ironfan/dsl/realm.rb +23 -16
  37. data/lib/ironfan/dsl/security_group.rb +29 -0
  38. data/lib/ironfan/dsl/server.rb +14 -5
  39. data/lib/ironfan/dsl/static.rb +63 -0
  40. data/lib/ironfan/dsl/vsphere.rb +1 -0
  41. data/lib/ironfan/dsl.rb +1 -134
  42. data/lib/ironfan/headers.rb +19 -0
  43. data/lib/ironfan/provider/chef/node.rb +3 -2
  44. data/lib/ironfan/provider/ec2/machine.rb +10 -14
  45. data/lib/ironfan/provider/ec2/security_group.rb +58 -43
  46. data/lib/ironfan/provider/openstack/elastic_ip.rb +96 -0
  47. data/lib/ironfan/provider/openstack/keypair.rb +78 -0
  48. data/lib/ironfan/provider/openstack/machine.rb +371 -0
  49. data/lib/ironfan/provider/openstack/security_group.rb +224 -0
  50. data/lib/ironfan/provider/openstack.rb +69 -0
  51. data/lib/ironfan/provider/static/machine.rb +192 -0
  52. data/lib/ironfan/provider/static.rb +23 -0
  53. data/lib/ironfan/provider.rb +58 -1
  54. data/lib/ironfan/requirements.rb +17 -1
  55. data/lib/ironfan/version.rb +3 -0
  56. data/lib/ironfan.rb +107 -172
  57. data/spec/chef/cluster_bootstrap_spec.rb +2 -7
  58. data/spec/chef/cluster_launch_spec.rb +1 -2
  59. data/spec/fixtures/realms/samurai.rb +26 -0
  60. data/spec/integration/minimal-chef-repo/clusters/.gitkeep +0 -0
  61. data/spec/integration/minimal-chef-repo/config/.gitkeep +0 -0
  62. data/spec/integration/minimal-chef-repo/knife/credentials/.gitignore +1 -0
  63. data/spec/integration/minimal-chef-repo/knife/credentials/certificates/.gitkeep +0 -0
  64. data/spec/integration/minimal-chef-repo/knife/credentials/client_keys/.gitkeep +0 -0
  65. data/spec/integration/minimal-chef-repo/knife/credentials/data_bag_keys/.gitkeep +0 -0
  66. data/spec/integration/minimal-chef-repo/knife/credentials/ec2_certs/.gitkeep +0 -0
  67. data/spec/integration/minimal-chef-repo/knife/credentials/ec2_keys/.gitkeep +0 -0
  68. data/spec/integration/minimal-chef-repo/knife/credentials/ironfantest-validator.pem +27 -0
  69. data/spec/integration/minimal-chef-repo/knife/credentials/ironfantester.pem +27 -0
  70. data/spec/integration/minimal-chef-repo/tasks/.gitkeep +0 -0
  71. data/spec/ironfan/cluster_spec.rb +1 -2
  72. data/spec/ironfan/diff_spec.rb +0 -2
  73. data/spec/ironfan/dsl_spec.rb +6 -3
  74. data/spec/ironfan/ec2/cloud_provider_spec.rb +17 -18
  75. data/spec/ironfan/ec2/elb_spec.rb +44 -41
  76. data/spec/ironfan/ec2/security_group_spec.rb +45 -47
  77. data/spec/ironfan/manifest_spec.rb +0 -1
  78. data/spec/ironfan/plugin_spec.rb +55 -40
  79. data/spec/ironfan/realm_spec.rb +42 -30
  80. data/spec/spec_helper.rb +17 -31
  81. data/spec/{spec_helper → support}/dummy_chef.rb +0 -0
  82. data/spec/{spec_helper → support}/dummy_diff_drawer.rb +0 -0
  83. metadata +78 -155
  84. data/.rspec +0 -2
  85. data/.yardopts +0 -19
  86. data/VERSION +0 -2
  87. data/chefignore +0 -41
  88. data/notes/Future-development-proposals.md +0 -266
  89. data/notes/Home.md +0 -55
  90. data/notes/INSTALL-cloud_setup.md +0 -103
  91. data/notes/INSTALL.md +0 -134
  92. data/notes/Ironfan-Roadmap.md +0 -70
  93. data/notes/Upgrading-to-v4.md +0 -66
  94. data/notes/advanced-superpowers.md +0 -16
  95. data/notes/aws_servers.jpg +0 -0
  96. data/notes/aws_user_key.png +0 -0
  97. data/notes/cookbook-versioning.md +0 -11
  98. data/notes/core_concepts.md +0 -200
  99. data/notes/declaring_volumes.md +0 -3
  100. data/notes/design_notes-aspect_oriented_devops.md +0 -36
  101. data/notes/design_notes-ci_testing.md +0 -169
  102. data/notes/design_notes-cookbook_event_ordering.md +0 -249
  103. data/notes/design_notes-meta_discovery.md +0 -59
  104. data/notes/ec2-pricing_and_capacity.md +0 -75
  105. data/notes/ec2-pricing_and_capacity.numbers +0 -0
  106. data/notes/homebase-layout.txt +0 -102
  107. data/notes/knife-cluster-commands.md +0 -21
  108. data/notes/named-cloud-objects.md +0 -11
  109. data/notes/opscode_org_key.png +0 -0
  110. data/notes/opscode_user_key.png +0 -0
  111. data/notes/philosophy.md +0 -13
  112. data/notes/rake_tasks.md +0 -24
  113. data/notes/renamed-recipes.txt +0 -142
  114. data/notes/silverware.md +0 -85
  115. data/notes/style_guide.md +0 -300
  116. data/notes/tips_and_troubleshooting.md +0 -92
  117. data/notes/walkthrough-hadoop.md +0 -168
  118. data/notes/walkthrough-web.md +0 -166
  119. data/spec/fixtures/gunbai.rb +0 -24
  120. data/spec/test_config.rb +0 -20
  121. 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
+
@@ -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
- def children
8
- clusters.to_a
6
+ magic :cluster_suffixes, Whatever
7
+
8
+ def self.definitions
9
+ @realms ||= {}
9
10
  end
10
11
 
11
- magic :cluster_suffixes, Whatever
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={},&block)
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, &block)
22
+ super(attrs, &blk)
18
23
  end
19
24
 
20
- def cluster(label, attrs={},&blk)
21
- new_name = [realm_name, label].join('_').to_sym
22
-
23
- if clusters.keys.include? new_name
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.new(name: new_name, owner: self, cluster_names: cluster_names)
30
- cluster_names[label] = new_name
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(new_name, cluster)
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
@@ -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() "#{cluster_name}-#{facet_name}-#{name}"; end
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() selected_cloud.implied_volumes; end
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"] = environment
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
+
@@ -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
@@ -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.name}-*"
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("^#{computers.cluster.name}-")
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
- user_data_hsh = {
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 => JSON.pretty_generate(user_data_hsh),
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
- description[:security_group_ids] = cloud.security_groups.keys.map do |g|
260
- SecurityGroup.recall( SecurityGroup.group_name_with_vpc(g,cloud.vpc) ).group_id
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))