ironfan 3.1.7 → 3.2.2

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.
Files changed (63) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +15 -12
  3. data/Rakefile +1 -1
  4. data/VERSION +1 -1
  5. data/config/ubuntu10.04-ironfan.erb +10 -0
  6. data/config/ubuntu11.10-ironfan.erb +10 -0
  7. data/ironfan.gemspec +29 -54
  8. data/lib/chef/knife/bootstrap/centos6.2-ironfan.erb +10 -0
  9. data/lib/chef/knife/bootstrap/ubuntu10.04-ironfan.erb +10 -0
  10. data/lib/chef/knife/bootstrap/ubuntu11.10-ironfan.erb +10 -0
  11. data/lib/chef/knife/cluster_kick.rb +7 -2
  12. data/lib/chef/knife/cluster_launch.rb +3 -0
  13. data/lib/chef/knife/cluster_ssh.rb +3 -3
  14. data/lib/chef/knife/ironfan_knife_common.rb +21 -0
  15. data/lib/chef/knife/ironfan_script.rb +2 -0
  16. data/lib/ironfan/chef_layer.rb +9 -9
  17. data/lib/ironfan/cloud.rb +232 -360
  18. data/lib/ironfan/cluster.rb +3 -3
  19. data/lib/ironfan/compute.rb +26 -40
  20. data/lib/ironfan/deprecated.rb +45 -10
  21. data/lib/ironfan/discovery.rb +1 -1
  22. data/lib/ironfan/dsl_builder.rb +99 -0
  23. data/lib/ironfan/facet.rb +2 -3
  24. data/lib/ironfan/fog_layer.rb +14 -10
  25. data/lib/ironfan/private_key.rb +1 -1
  26. data/lib/ironfan/security_group.rb +46 -44
  27. data/lib/ironfan/server.rb +26 -52
  28. data/lib/ironfan/server_slice.rb +13 -19
  29. data/lib/ironfan/volume.rb +47 -59
  30. data/lib/ironfan.rb +5 -4
  31. metadata +116 -122
  32. data/lib/ironfan/dsl_object.rb +0 -124
  33. data/notes/Backup of ec2-pricing_and_capacity.numbers +0 -0
  34. data/notes/Home.md +0 -45
  35. data/notes/INSTALL-cloud_setup.md +0 -103
  36. data/notes/INSTALL.md +0 -134
  37. data/notes/Ironfan-Roadmap.md +0 -70
  38. data/notes/advanced-superpowers.md +0 -16
  39. data/notes/aws_servers.jpg +0 -0
  40. data/notes/aws_user_key.png +0 -0
  41. data/notes/cookbook-versioning.md +0 -11
  42. data/notes/core_concepts.md +0 -200
  43. data/notes/declaring_volumes.md +0 -3
  44. data/notes/design_notes-aspect_oriented_devops.md +0 -36
  45. data/notes/design_notes-ci_testing.md +0 -169
  46. data/notes/design_notes-cookbook_event_ordering.md +0 -249
  47. data/notes/design_notes-meta_discovery.md +0 -59
  48. data/notes/ec2-pricing_and_capacity.md +0 -69
  49. data/notes/ec2-pricing_and_capacity.numbers +0 -0
  50. data/notes/homebase-layout.txt +0 -102
  51. data/notes/knife-cluster-commands.md +0 -18
  52. data/notes/named-cloud-objects.md +0 -11
  53. data/notes/opscode_org_key.png +0 -0
  54. data/notes/opscode_user_key.png +0 -0
  55. data/notes/philosophy.md +0 -13
  56. data/notes/rake_tasks.md +0 -24
  57. data/notes/renamed-recipes.txt +0 -142
  58. data/notes/silverware.md +0 -85
  59. data/notes/style_guide.md +0 -300
  60. data/notes/tips_and_troubleshooting.md +0 -92
  61. data/notes/version-3_2.md +0 -273
  62. data/notes/walkthrough-hadoop.md +0 -168
  63. data/notes/walkthrough-web.md +0 -166
@@ -51,7 +51,7 @@ module Ironfan
51
51
  def facet(facet_name, attrs={}, &block)
52
52
  facet_name = facet_name.to_sym
53
53
  @facets[facet_name] ||= Ironfan::Facet.new(self, facet_name)
54
- @facets[facet_name].configure(attrs, &block)
54
+ @facets[facet_name].receive!(attrs, &block)
55
55
  @facets[facet_name]
56
56
  end
57
57
 
@@ -83,7 +83,7 @@ module Ironfan
83
83
  #
84
84
  # @return [Ironfan::ServerSlice] the requested slice
85
85
  def slice facet_name=nil, slice_indexes=nil
86
- return Ironfan::ServerSlice.new(self, self.servers) if facet_name.nil?
86
+ return servers if facet_name.nil?
87
87
  find_facet(facet_name).slice(slice_indexes)
88
88
  end
89
89
 
@@ -103,7 +103,7 @@ module Ironfan
103
103
  # Create a security group named for the cluster
104
104
  # that is friends with everything in the cluster
105
105
  def create_cluster_security_group
106
- clname = self.name # put it in scope
106
+ clname = self.name.to_s # put it in scope
107
107
  cloud.security_group(clname){ authorize_group(clname) }
108
108
  end
109
109
 
@@ -1,18 +1,23 @@
1
+ require 'ironfan/volume' # configure external and internal volumes
1
2
  module Ironfan
2
3
  #
3
4
  # Base class allowing us to layer settings for facet over cluster
4
5
  #
5
- class ComputeBuilder < Ironfan::DslObject
6
- attr_reader :cloud, :volumes, :chef_roles
7
- has_keys :name, :bogosity, :environment
6
+ class ComputeBuilder < Ironfan::DslBuilder
7
+ magic :name, String
8
+ magic :bogosity, String, :default => false
9
+ magic :environment, String
10
+ collection :volumes, Ironfan::Volume, :resolution => ->(f) { merge_resolve(f) }
11
+
12
+ attr_reader :cloud, :chef_roles
8
13
  @@role_implications ||= Mash.new
9
14
  @@run_list_rank ||= 0
10
15
 
11
16
  def initialize(builder_name, attrs={})
12
17
  super(attrs)
13
- set :name, builder_name
18
+ name builder_name
14
19
  @run_list_info = attrs[:run_list] || Mash.new
15
- @volumes = Mash.new
20
+ @clouds = Mash.new
16
21
  end
17
22
 
18
23
  # set the bogosity to a descriptive reason. Anything truthy implies bogusness
@@ -36,11 +41,18 @@ module Ironfan
36
41
  # region 'us-east-1d'
37
42
  # end
38
43
  #
39
- def cloud(cloud_provider=nil, attrs={}, &block)
40
- raise "Only have ec2 so far" if cloud_provider && (cloud_provider != :ec2)
41
- @cloud ||= Ironfan::Cloud::Ec2.new(self)
42
- @cloud.configure(attrs, &block)
43
- @cloud
44
+ def cloud(cloud_provider=:ec2, attrs={}, &block)
45
+ case cloud_provider
46
+ when :ec2
47
+ klass = Ironfan::CloudDsl::Ec2
48
+ when :virtualbox
49
+ klass = Ironfan::CloudDsl::VirtualBox
50
+ else
51
+ raise "Only have EC2 and VirtualBox so far"
52
+ end
53
+ @clouds[cloud_provider] ||= klass.new(self)
54
+ @clouds[cloud_provider].receive!(attrs, &block)
55
+ @clouds[cloud_provider]
44
56
  end
45
57
 
46
58
  # sugar for cloud(:ec2)
@@ -48,39 +60,13 @@ module Ironfan
48
60
  cloud(:ec2, attrs, &block)
49
61
  end
50
62
 
51
- # Magic method to describe a volume
52
- # * returns the named volume, creating it if necessary.
53
- # * executes the block (if any) in the volume's context
54
- #
55
- # @example
56
- # # a 1 GB volume at '/data' from the given snapshot
57
- # volume(:data) do
58
- # size 1
59
- # mount_point '/data'
60
- # snapshot_id 'snap-12345'
61
- # end
62
- #
63
- # @param volume_name [String] an arbitrary handle -- you can use the device
64
- # name, or a descriptive symbol.
65
- # @param attrs [Hash] a hash of attributes to pass down.
66
- #
67
- def volume(volume_name, attrs={}, &block)
68
- volumes[volume_name] ||= Ironfan::Volume.new(:parent => self, :name => volume_name)
69
- volumes[volume_name].configure(attrs, &block)
70
- volumes[volume_name]
71
- end
72
-
73
63
  def raid_group(rg_name, attrs={}, &block)
74
- volumes[rg_name] ||= Ironfan::RaidGroup.new(:parent => self, :name => rg_name)
75
- volumes[rg_name].configure(attrs, &block)
76
- volumes[rg_name].sub_volumes.each do |sv_name|
64
+ raid = volumes[rg_name] || Ironfan::RaidGroup.new(:parent => self, :name => rg_name)
65
+ raid.receive!(attrs, &block)
66
+ raid.sub_volumes.each do |sv_name|
77
67
  volume(sv_name){ in_raid(rg_name) ; mountable(false) ; tags({}) }
78
68
  end
79
- volumes[rg_name]
80
- end
81
-
82
- def root_volume(attrs={}, &block)
83
- volume(:root, attrs, &block)
69
+ volumes[rg_name] = raid
84
70
  end
85
71
 
86
72
  #
@@ -1,33 +1,68 @@
1
1
  module Ironfan
2
+ def self.deprecated call, replacement=nil
3
+ correction = ", use #{replacement} instead" if replacement
4
+ ui.warn "The '#{call}' statement is deprecated #{caller(2).first.inspect}#{correction}"
5
+ end
6
+
7
+ class DslBuilder
8
+ def to_hash
9
+ Ironfan.deprecated 'to_hash', 'attributes'
10
+ attributes
11
+ end
12
+ def to_mash
13
+ Ironfan.deprecated 'to_mash', 'attributes'
14
+ attributes
15
+ end
16
+ def reverse_merge!(attrs={})
17
+ Ironfan.deprecated 'reverse_merge!', 'receive!'
18
+ receive!(attrs)
19
+ end
20
+ def configure(attrs={},&block)
21
+ Ironfan.deprecated 'configure', 'receive!'
22
+ receive!(attrs, &block)
23
+ end
24
+ end
25
+
26
+ class ComputeBuilder
27
+ def root_volume(attrs={}, &block)
28
+ Ironfan.deprecated 'root_volume', 'volume(:root)'
29
+ volume(:root, attrs, &block)
30
+ end
31
+ end
2
32
 
3
33
  class Cluster
4
- #
5
- # **DEPRECATED**: This doesn't really work -- use +reverse_merge!+ instead
6
- #
7
34
  def use(*clusters)
8
- ui.warn "The 'use' statement is deprecated #{caller.inspect}"
35
+ Ironfan.deprecated 'use', 'underlay'
9
36
  clusters.each do |c|
10
37
  other_cluster = Ironfan.load_cluster(c)
11
- reverse_merge! other_cluster
38
+ cluster.underlay other_cluster
12
39
  end
13
40
  self
14
41
  end
15
-
16
42
  end
17
43
 
18
44
  class Server
19
- # **DEPRECATED**: Please use +fullname+ instead.
20
45
  def chef_node_name name
21
- ui.warn "[DEPRECATION] `chef_node_name` is deprecated. Please use `fullname` instead."
46
+ Ironfan.deprecated 'chef_node_name', 'fullname'
22
47
  fullname name
23
48
  end
49
+
50
+ def composite_volumes
51
+ Ironfan.deprecated 'composite_volumes', 'volumes'
52
+ volumes
53
+ end
24
54
  end
25
55
 
26
- class Cloud::Ec2
27
- # **DEPRECATED**: Please use +public_ip+ instead.
56
+ class CloudDsl::Ec2
28
57
  def elastic_ip(*args, &block)
58
+ Ironfan.deprecated 'elastic_ip', 'public_ip'
29
59
  public_ip(*args, &block)
30
60
  end
31
61
  end
32
62
 
63
+ class Volume
64
+ def defaults
65
+ Ironfan.deprecated 'defaults'
66
+ end
67
+ end
33
68
  end
@@ -76,7 +76,7 @@ module Ironfan
76
76
  next
77
77
  end
78
78
  svr = Ironfan::Server.get(cluster_name, facet_name, facet_index)
79
- svr.chef_node = chef_node
79
+ svr.chef_node chef_node
80
80
  @aws_instance_hash[ chef_node.ec2.instance_id ] = svr if chef_node[:ec2] && chef_node.ec2.instance_id
81
81
  end
82
82
  end
@@ -0,0 +1,99 @@
1
+ module Gorillib
2
+ module Model
3
+ Field.class_eval do
4
+ field :resolution, Whatever
5
+ end
6
+ end
7
+ module Underlies
8
+ include Gorillib::FancyBuilder
9
+ attr_accessor :underlay
10
+
11
+ def read_attribute(field_name)
12
+ field = self.class.fields[field_name] or return
13
+ return override_resolve(field_name) unless field.resolution.is_a? Proc
14
+ return self.instance_exec(field_name, &field.resolution)
15
+ end
16
+
17
+ def override_resolve(field_name)
18
+ result = read_set_or_underlay(field_name)
19
+ return result unless result.nil?
20
+ read_unset_attribute(field_name)
21
+ end
22
+
23
+ def merge_resolve(field_name)
24
+ attr = {}
25
+ if self.class.fields[field_name].respond_to? :item_type
26
+ attr[:item_type] = self.class.fields[field_name].item_type
27
+ end
28
+ result = self.class.fields[field_name].type.new(attr)
29
+ result.receive! read_underlay_attribute(field_name) || {}
30
+ result.receive! read_set_attribute(field_name) || {}
31
+ return result unless result.empty?
32
+ read_unset_attribute(field_name)
33
+ end
34
+
35
+ def read_set_attribute(field_name)
36
+ attr_name = "@#{field_name}"
37
+ instance_variable_get(attr_name) if instance_variable_defined?(attr_name)
38
+ end
39
+
40
+ def read_underlay_attribute(field_name)
41
+ return if @underlay.nil?
42
+ underlay.read_set_or_underlay(field_name)
43
+ end
44
+
45
+ def read_set_or_underlay(field_name)
46
+ result = read_set_attribute(field_name)
47
+ return result unless result.nil?
48
+ read_underlay_attribute(field_name)
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ module Ironfan
55
+ #
56
+ # This class is intended as a drop-in replacement for DslObject, using
57
+ # Gorillib::Builder setup, instead its half-baked predecessor.
58
+ #
59
+ # The magic attribute :underlay provides an object (preferably another
60
+ # Gorillib::Model or the like) that will respond with defaults. If
61
+ # fields are declared with a resolution lambda, it will apply that
62
+ # lambda in preference to the normal resolution rules (self.field
63
+ # -> underlay.magic -> self.field.default )
64
+ #
65
+ module DslHooks
66
+ def self.ui() Ironfan.ui ; end
67
+ def ui() Ironfan.ui ; end
68
+
69
+ # helper method for turning exceptions into warnings
70
+ def safely(*args, &block) Ironfan.safely(*args, &block) ; end
71
+
72
+ def step(desc, *style)
73
+ ui.info(" #{"%-15s" % (name.to_s+":")}\t#{ui.color(desc.to_s, *style)}")
74
+ end
75
+ end
76
+
77
+ class DslBuilder
78
+ include Gorillib::FancyBuilder
79
+ include Gorillib::Underlies
80
+ include Ironfan::DslHooks
81
+ end
82
+
83
+ class DslBuilderCollection < Gorillib::ModelCollection
84
+ include Ironfan::DslHooks
85
+ include Enumerable
86
+ # #
87
+ # # Enumerable
88
+ # #
89
+ # def each(&block)
90
+ # @servers.each(&block)
91
+ # end
92
+ # def length
93
+ # @servers.length
94
+ # end
95
+ # def empty?
96
+ # length == 0
97
+ # end
98
+ end
99
+ end
data/lib/ironfan/facet.rb CHANGED
@@ -1,14 +1,13 @@
1
1
  module Ironfan
2
2
  class Facet < Ironfan::ComputeBuilder
3
3
  attr_reader :cluster
4
- has_keys :instances
4
+ magic :instances, Integer, :default => 1
5
5
 
6
6
  def initialize cluster, facet_name, attrs={}
7
7
  super(facet_name.to_sym, attrs)
8
8
  @cluster = cluster
9
9
  @servers = Mash.new
10
10
  @chef_roles = []
11
- @settings[:instances] ||= 1
12
11
  create_facet_role
13
12
  create_facet_security_group unless attrs[:no_security_group]
14
13
  end
@@ -55,7 +54,7 @@ module Ironfan
55
54
  def server(idx, attrs={}, &block)
56
55
  idx = idx.to_i
57
56
  @servers[idx] ||= Ironfan::Server.new(self, idx)
58
- @servers[idx].configure(attrs, &block)
57
+ @servers[idx].receive!(attrs, &block)
59
58
  @servers[idx]
60
59
  end
61
60
 
@@ -33,6 +33,7 @@ module Ironfan
33
33
  :key_name => cloud.keypair.to_s,
34
34
  # Fog does not actually create tags when it creates a server.
35
35
  :tags => {
36
+ :name => self.fullname,
36
37
  :cluster => cluster_name,
37
38
  :facet => facet_name,
38
39
  :index => facet_index, },
@@ -72,11 +73,12 @@ module Ironfan
72
73
  end
73
74
 
74
75
  def discover_volumes!
75
- composite_volumes.each do |vol_name, vol|
76
- my_vol = volumes[vol_name]
77
- next if my_vol.fog_volume
76
+ result = self.class.fields[:volumes].type.new
77
+ volumes.each_pair do |vol_name, definition|
78
+ next if definition.fog_volume
78
79
  next if Ironfan.chef_config[:cloud] == false
79
- my_vol.fog_volume = Ironfan.fog_volumes.find do |fv|
80
+ vol = definition.dup
81
+ vol.fog_volume = Ironfan.fog_volumes.find do |fv|
80
82
  ( # matches the explicit volume id
81
83
  (vol.volume_id && (fv.id == vol.volume_id) ) ||
82
84
  # OR this server's machine exists, and this volume is attached to
@@ -90,19 +92,21 @@ module Ironfan
90
92
  (fv.tags['device'] == vol.device.to_s) )
91
93
  )
92
94
  end
93
- next unless my_vol.fog_volume
94
- my_vol.volume_id(my_vol.fog_volume.id) unless my_vol.volume_id.present?
95
- my_vol.availability_zone(my_vol.fog_volume.availability_zone) unless my_vol.availability_zone.present?
96
- check_server_id_pairing(my_vol.fog_volume, my_vol.desc)
95
+ next unless vol.fog_volume
96
+ vol.volume_id(vol.fog_volume.id) unless vol.volume_id.present?
97
+ vol.availability_zone(vol.fog_volume.availability_zone) unless vol.availability_zone.present?
98
+ check_server_id_pairing(vol.fog_volume, vol.desc)
99
+ result[vol.name] = vol
97
100
  end
101
+ write_attribute(:volumes,result)
98
102
  end
99
103
 
100
104
  def attach_volumes
101
105
  return unless in_cloud?
102
106
  discover_volumes!
103
- return if composite_volumes.empty?
107
+ return if volumes.empty?
104
108
  step(" attaching volumes")
105
- composite_volumes.each do |vol_name, vol|
109
+ volumes.each_pair do |vol_name, vol|
106
110
  next if vol.volume_id.blank? || (vol.attachable != :ebs)
107
111
  if (not vol.in_cloud?) then Chef::Log.debug("Volume not found: #{vol.desc}") ; next ; end
108
112
  if (vol.has_server?) then check_server_id_pairing(vol.fog_volume, vol.desc) ; next ; end
@@ -5,7 +5,7 @@ module Ironfan
5
5
  # A private key -- chef client key, ssh key, etc.
6
6
  #
7
7
  # The key is a pro
8
- class PrivateKey < Ironfan::DslObject
8
+ class PrivateKey < Ironfan::DslBuilder
9
9
  attr_reader :name
10
10
  attr_reader :proxy
11
11
  attr_reader :on_update
@@ -1,20 +1,22 @@
1
1
  module Ironfan
2
- module Cloud
2
+ module CloudDsl
3
+ class SecurityGroup < Ironfan::DslBuilder
4
+ magic :name, String
5
+ magic :description, String
6
+ magic :group_authorizations, Array
7
+ magic :group_authorized_by, Array
8
+ magic :range_authorizations, Array
3
9
 
4
- class SecurityGroup < DslObject
5
- has_keys :name, :description, :owner_id
6
- attr_reader :group_authorizations
7
- attr_reader :range_authorizations
10
+ def initialize params
11
+ name params[:name].to_s
12
+ description "ironfan generated group #{name}"
13
+ group_authorizations []
14
+ group_authorized_by []
15
+ range_authorizations []
16
+ end
8
17
 
9
- def initialize cloud, group_name, group_description=nil, group_owner_id=nil
10
- super()
11
- set :name, group_name.to_s
12
- description group_description || "ironfan generated group #{group_name}"
13
- @cloud = cloud
14
- @group_authorizations = []
15
- @group_authorized_by = []
16
- @range_authorizations = []
17
- owner_id(group_owner_id || Chef::Config[:knife][:aws_account_id])
18
+ def to_key
19
+ name
18
20
  end
19
21
 
20
22
  @@all = nil
@@ -52,34 +54,34 @@ module Ironfan
52
54
  end
53
55
 
54
56
  def authorize_group(group_name, owner_id=nil)
55
- @group_authorizations << [group_name.to_s, owner_id]
57
+ group_authorizations << [group_name.to_s, owner_id]
56
58
  end
57
59
 
58
60
  def authorized_by_group(other_name)
59
- @group_authorized_by << other_name.to_s
61
+ group_authorized_by << other_name.to_s
60
62
  end
61
63
 
62
64
  def authorize_port_range(range, cidr_ip = '0.0.0.0/0', ip_protocol = 'tcp')
63
65
  range = (range .. range) if range.is_a?(Integer)
64
- @range_authorizations << [range, cidr_ip, ip_protocol]
65
- end
66
-
67
- def group_permission_already_set?(fog_group, other_name, authed_owner)
68
- return false if fog_group.ip_permissions.nil?
69
- fog_group.ip_permissions.any? do |existing_permission|
70
- existing_permission["groups"].include?({"userId" => authed_owner, "groupName" => other_name}) &&
71
- existing_permission["fromPort"] == 1 &&
72
- existing_permission["toPort"] == 65535
73
- end
66
+ range_authorizations << [range, cidr_ip, ip_protocol]
74
67
  end
75
-
76
- def range_permission_already_set?(fog_group, range, cidr_ip, ip_protocol)
77
- return false if fog_group.ip_permissions.nil?
78
- fog_group.ip_permissions.include?(
79
- { "groups"=>[], "ipRanges"=>[{"cidrIp"=>cidr_ip}],
80
- "ipProtocol"=>ip_protocol, "fromPort"=>range.first, "toPort"=>range.last})
81
- end
82
-
68
+ #
69
+ # def group_permission_already_set?(fog_group, other_name, authed_owner)
70
+ # return false if fog_group.ip_permissions.nil?
71
+ # fog_group.ip_permissions.any? do |existing_permission|
72
+ # existing_permission["groups"].include?({"userId" => authed_owner, "groupName" => other_name}) &&
73
+ # existing_permission["fromPort"] == 1 &&
74
+ # existing_permission["toPort"] == 65535
75
+ # end
76
+ # end
77
+ #
78
+ # def range_permission_already_set?(fog_group, range, cidr_ip, ip_protocol)
79
+ # return false if fog_group.ip_permissions.nil?
80
+ # fog_group.ip_permissions.include?(
81
+ # { "groups"=>[], "ipRanges"=>[{"cidrIp"=>cidr_ip}],
82
+ # "ipProtocol"=>ip_protocol, "fromPort"=>range.first, "toPort"=>range.last})
83
+ # end
84
+ #
83
85
  # FIXME: so if you're saying to yourself, "self, this is some soupy gooey
84
86
  # code right here" then you and your self are correct. Much of this is to
85
87
  # work around old limitations in the EC2 api. You can now treat range and
@@ -110,22 +112,22 @@ module Ironfan
110
112
  rescue StandardError => err ; handle_security_group_error(err) ; end
111
113
  end
112
114
  end
113
-
114
- def handle_security_group_error(err)
115
- if (/has already been authorized/ =~ err.to_s)
116
- Chef::Log.debug err
117
- else
118
- ui.warn(err)
119
- end
120
- end
121
-
115
+ #
116
+ # def handle_security_group_error(err)
117
+ # if (/has already been authorized/ =~ err.to_s)
118
+ # Chef::Log.debug err
119
+ # else
120
+ # ui.warn(err)
121
+ # end
122
+ # end
123
+ #
122
124
  def self.step(group_name, desc, *style)
123
125
  ui.info(" group #{"%-15s" % (group_name+":")}\t#{ui.color(desc.to_s, *style)}")
124
126
  end
125
127
  def step(desc, *style)
126
128
  self.class.step(self.name, desc, *style)
127
129
  end
128
-
129
130
  end
131
+
130
132
  end
131
133
  end
@@ -7,15 +7,20 @@ module Ironfan
7
7
  # or if it exists in the real world (as revealed by Fog)
8
8
  #
9
9
  class Server < Ironfan::ComputeBuilder
10
- attr_reader :cluster, :facet, :facet_index, :tags
11
- attr_accessor :chef_node, :fog_server
10
+ magic :cluster, Cluster
11
+ magic :facet, Facet
12
+ magic :facet_index, Integer
13
+ attr_reader :tags
14
+
15
+ magic :chef_node, Whatever, :default => -> owner,name { owner.cluster.find_node(name) || false }
16
+ attr_accessor :fog_server
12
17
 
13
18
  @@all ||= Mash.new
14
19
 
15
20
  def initialize facet, idx
16
- @cluster = facet.cluster
17
- @facet = facet
18
- @facet_index = idx
21
+ cluster facet.cluster
22
+ facet facet
23
+ facet_index idx
19
24
  @fullname = [cluster_name, facet_name, facet_index].join('-')
20
25
  super(@fullname)
21
26
  @tags = { "name" => name, "cluster" => cluster_name, "facet" => facet_name, "index" => facet_index, }
@@ -40,13 +45,13 @@ module Ironfan
40
45
  Ironfan::ServerSlice.new(cluster, [self])
41
46
  end
42
47
 
43
- def bogosity val=nil
44
- @settings[:bogosity] = val if not val.nil?
45
- return @settings[:bogosity] if not @settings[:bogosity].nil?
46
- return :bogus_facet if facet.bogus?
47
- # return :out_of_range if (self.facet_index.to_i >= facet.instances)
48
- false
49
- end
48
+ # def bogosity val=nil
49
+ # @settings[:bogosity] = val if not val.nil?
50
+ # return @settings[:bogosity] if not @settings[:bogosity].nil?
51
+ # return :bogus_facet if facet.bogus?
52
+ # # return :out_of_range if (self.facet_index.to_i >= facet.instances)
53
+ # false
54
+ # end
50
55
 
51
56
  def in_cloud?
52
57
  !! fog_server
@@ -85,7 +90,7 @@ module Ironfan
85
90
  end
86
91
 
87
92
  def permanent?
88
- !! self.cloud.permanent
93
+ [true, :true, 'true'].include?(self.cloud.permanent)
89
94
  end
90
95
 
91
96
  def killable?
@@ -118,13 +123,12 @@ module Ironfan
118
123
  # Resolve:
119
124
  #
120
125
  def resolve!
121
- reverse_merge!(facet)
122
- reverse_merge!(cluster)
123
- @settings[:run_list] = combined_run_list
124
- #
125
- cloud.reverse_merge!(facet.cloud)
126
- cloud.reverse_merge!(cluster.cloud)
127
- #
126
+ facet.underlay = cluster
127
+ self.underlay = facet
128
+
129
+ facet.cloud.underlay = cluster.cloud
130
+ cloud.underlay = facet.cloud
131
+
128
132
  cloud.user_data({
129
133
  :chef_server => chef_server_url,
130
134
  :validation_client_name => validation_client_name,
@@ -185,36 +189,6 @@ module Ironfan
185
189
  cg[:last], fg[:last], sg[:last], ].flatten.compact.uniq
186
190
  end
187
191
 
188
- #
189
- # This prepares a composited view of the volumes -- it shows the cluster
190
- # definition overlaid by the facet definition overlaid by the server
191
- # definition.
192
- #
193
- # This method *does* auto-vivify an empty volume declaration on the server,
194
- # but doesn't modify it.
195
- #
196
- # This code is pretty smelly, but so is the resolve! behavior. advice welcome.
197
- #
198
- def composite_volumes
199
- vols = {}
200
- self.volumes.each do |vol_name, vol|
201
- vols[vol_name] ||= self.volumes[vol_name].dup
202
- vols[vol_name].reverse_merge!(vol)
203
- end
204
- facet.volumes.each do |vol_name, vol|
205
- self.volumes[vol_name] ||= Ironfan::Volume.new(:parent => self, :name => vol_name)
206
- vols[vol_name] ||= self.volumes[vol_name].dup
207
- vols[vol_name].reverse_merge!(vol)
208
- end
209
- cluster.volumes.each do |vol_name, vol|
210
- self.volumes[vol_name] ||= Ironfan::Volume.new(:parent => self, :name => vol_name)
211
- vols[vol_name] ||= self.volumes[vol_name].dup
212
- vols[vol_name].reverse_merge!(vol)
213
- end
214
- vols.each{|vol_name, vol| vol.availability_zone self.default_availability_zone }
215
- vols
216
- end
217
-
218
192
  # FIXME -- this will break on some edge case wehre a bogus node is
219
193
  # discovered after everything is resolve!d
220
194
  def default_availability_zone
@@ -269,7 +243,7 @@ module Ironfan
269
243
  return unless created?
270
244
  step(" labeling servers and volumes")
271
245
  fog_create_tags(fog_server, self.fullname, tags)
272
- composite_volumes.each do |vol_name, vol|
246
+ volumes.each_pair do |vol_name, vol|
273
247
  if vol.fog_volume
274
248
  fog_create_tags(vol.fog_volume, vol.desc,
275
249
  { "server" => self.fullname, "name" => "#{name}-#{vol.name}", "device" => vol.device, "mount_point" => vol.mount_point, "cluster" => cluster_name, "facet" => facet_name, "index" => facet_index, })
@@ -278,7 +252,7 @@ module Ironfan
278
252
  end
279
253
 
280
254
  def block_device_mapping
281
- composite_volumes.values.map(&:block_device_mapping).compact
255
+ volumes.values.map(&:block_device_mapping).compact
282
256
  end
283
257
 
284
258
  # ugh. non-dry below.