ironfan 3.2.2 → 4.0.0
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 +5 -0
- data/VERSION +1 -1
- data/ironfan.gemspec +33 -20
- data/lib/chef/knife/cluster_kick.rb +17 -17
- data/lib/chef/knife/cluster_kill.rb +13 -7
- data/lib/chef/knife/cluster_launch.rb +60 -66
- data/lib/chef/knife/cluster_pry.rb +2 -2
- data/lib/chef/knife/cluster_show.rb +3 -6
- data/lib/chef/knife/cluster_ssh.rb +5 -11
- data/lib/chef/knife/cluster_start.rb +2 -4
- data/lib/chef/knife/cluster_stop.rb +1 -3
- data/lib/chef/knife/cluster_sync.rb +13 -21
- data/lib/chef/knife/ironfan_knife_common.rb +11 -9
- data/lib/chef/knife/ironfan_script.rb +2 -1
- data/lib/gorillib/resolution.rb +119 -0
- data/lib/ironfan/broker/computer.rb +316 -0
- data/lib/ironfan/broker/drive.rb +21 -0
- data/lib/ironfan/broker.rb +37 -0
- data/lib/ironfan/builder.rb +14 -0
- data/lib/ironfan/deprecated.rb +16 -58
- data/lib/ironfan/dsl/cloud.rb +21 -0
- data/lib/ironfan/dsl/cluster.rb +27 -0
- data/lib/ironfan/dsl/compute.rb +84 -0
- data/lib/ironfan/dsl/ec2.rb +260 -0
- data/lib/ironfan/dsl/facet.rb +25 -0
- data/lib/ironfan/dsl/role.rb +19 -0
- data/lib/ironfan/dsl/server.rb +31 -0
- data/lib/ironfan/dsl/virtualbox.rb +8 -0
- data/lib/ironfan/dsl/volume.rb +45 -0
- data/lib/ironfan/dsl.rb +7 -0
- data/lib/ironfan/headers.rb +58 -0
- data/lib/ironfan/provider/chef/client.rb +77 -0
- data/lib/ironfan/provider/chef/node.rb +133 -0
- data/lib/ironfan/provider/chef/role.rb +69 -0
- data/lib/ironfan/provider/chef.rb +28 -0
- data/lib/ironfan/provider/ec2/ebs_volume.rb +137 -0
- data/lib/ironfan/provider/ec2/elastic_ip.rb +10 -0
- data/lib/ironfan/provider/ec2/key_pair.rb +65 -0
- data/lib/ironfan/provider/ec2/machine.rb +258 -0
- data/lib/ironfan/provider/ec2/placement_group.rb +24 -0
- data/lib/ironfan/provider/ec2/security_group.rb +118 -0
- data/lib/ironfan/provider/ec2.rb +47 -0
- data/lib/ironfan/provider/virtualbox/machine.rb +10 -0
- data/lib/ironfan/provider/virtualbox.rb +8 -0
- data/lib/ironfan/provider.rb +139 -0
- data/lib/ironfan/requirements.rb +52 -0
- data/lib/ironfan.rb +44 -33
- metadata +34 -21
- data/lib/chef/knife/cluster_vagrant.rb +0 -144
- data/lib/chef/knife/vagrant/ironfan_environment.rb +0 -18
- data/lib/chef/knife/vagrant/ironfan_provisioners.rb +0 -27
- data/lib/chef/knife/vagrant/skeleton_vagrantfile.rb +0 -119
- data/lib/ironfan/chef_layer.rb +0 -300
- data/lib/ironfan/cloud.rb +0 -323
- data/lib/ironfan/cluster.rb +0 -118
- data/lib/ironfan/compute.rb +0 -139
- data/lib/ironfan/discovery.rb +0 -190
- data/lib/ironfan/dsl_builder.rb +0 -99
- data/lib/ironfan/facet.rb +0 -143
- data/lib/ironfan/fog_layer.rb +0 -196
- data/lib/ironfan/private_key.rb +0 -130
- data/lib/ironfan/role_implications.rb +0 -58
- data/lib/ironfan/security_group.rb +0 -133
- data/lib/ironfan/server.rb +0 -291
- data/lib/ironfan/server_slice.rb +0 -265
- data/lib/ironfan/volume.rb +0 -146
data/lib/ironfan/cluster.rb
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
module Ironfan
|
2
|
-
#
|
3
|
-
# A cluster has many facets. Any setting applied here is merged with the facet
|
4
|
-
# at resolve time; if the facet explicitly sets any attributes they will win out.
|
5
|
-
#
|
6
|
-
class Cluster < Ironfan::ComputeBuilder
|
7
|
-
attr_reader :facets, :undefined_servers
|
8
|
-
|
9
|
-
def initialize(name, attrs={})
|
10
|
-
super(name.to_sym, attrs)
|
11
|
-
@facets = Mash.new
|
12
|
-
@chef_roles = []
|
13
|
-
environment :_default if environment.blank?
|
14
|
-
create_cluster_role
|
15
|
-
create_cluster_security_group unless attrs[:no_security_group]
|
16
|
-
end
|
17
|
-
|
18
|
-
def cluster
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
def cluster_name
|
23
|
-
name
|
24
|
-
end
|
25
|
-
|
26
|
-
# The auto-generated role for this cluster.
|
27
|
-
# Instance-evals the given block in the context of that role
|
28
|
-
#
|
29
|
-
# @example
|
30
|
-
# cluster_role do
|
31
|
-
# override_attributes({
|
32
|
-
# :time_machine => { :transition_speed => 88 },
|
33
|
-
# })
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
# @return [Chef::Role] The auto-generated role for this facet.
|
37
|
-
def cluster_role(&block)
|
38
|
-
@cluster_role.instance_eval( &block ) if block_given?
|
39
|
-
@cluster_role
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# Retrieve or define the given facet
|
44
|
-
#
|
45
|
-
# @param [String] facet_name -- name of the desired facet
|
46
|
-
# @param [Hash] attrs -- attributes to configure on the object
|
47
|
-
# @yield a block to execute in the context of the object
|
48
|
-
#
|
49
|
-
# @return [Ironfan::Facet]
|
50
|
-
#
|
51
|
-
def facet(facet_name, attrs={}, &block)
|
52
|
-
facet_name = facet_name.to_sym
|
53
|
-
@facets[facet_name] ||= Ironfan::Facet.new(self, facet_name)
|
54
|
-
@facets[facet_name].receive!(attrs, &block)
|
55
|
-
@facets[facet_name]
|
56
|
-
end
|
57
|
-
|
58
|
-
def has_facet? facet_name
|
59
|
-
@facets.include?(facet_name)
|
60
|
-
end
|
61
|
-
|
62
|
-
def find_facet(facet_name)
|
63
|
-
@facets[facet_name] or raise("Facet '#{facet_name}' is not defined in cluster '#{cluster_name}'")
|
64
|
-
end
|
65
|
-
|
66
|
-
# All servers in this facet, sorted by facet name and index
|
67
|
-
#
|
68
|
-
# @return [Ironfan::ServerSlice] slice containing all servers
|
69
|
-
def servers
|
70
|
-
svrs = @facets.sort.map{|name, facet| facet.servers.to_a }
|
71
|
-
Ironfan::ServerSlice.new(self, svrs.flatten)
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
# A slice of a cluster:
|
76
|
-
#
|
77
|
-
# If +facet_name+ is nil, returns all servers.
|
78
|
-
# Otherwise, takes slice (given by +*args+) from the requested facet.
|
79
|
-
#
|
80
|
-
# @param [String] facet_name -- facet to slice (or nil for all in cluster)
|
81
|
-
# @param [Array, String] slice_indexes -- servers in that facet (or nil for all in facet).
|
82
|
-
# You must specify a facet if you use slice_indexes.
|
83
|
-
#
|
84
|
-
# @return [Ironfan::ServerSlice] the requested slice
|
85
|
-
def slice facet_name=nil, slice_indexes=nil
|
86
|
-
return servers if facet_name.nil?
|
87
|
-
find_facet(facet_name).slice(slice_indexes)
|
88
|
-
end
|
89
|
-
|
90
|
-
def to_s
|
91
|
-
"#{super[0..-3]} @facets=>#{@facets.keys.inspect}}>"
|
92
|
-
end
|
93
|
-
|
94
|
-
#
|
95
|
-
# Resolve:
|
96
|
-
#
|
97
|
-
def resolve!
|
98
|
-
facets.values.each(&:resolve!)
|
99
|
-
end
|
100
|
-
|
101
|
-
protected
|
102
|
-
|
103
|
-
# Create a security group named for the cluster
|
104
|
-
# that is friends with everything in the cluster
|
105
|
-
def create_cluster_security_group
|
106
|
-
clname = self.name.to_s # put it in scope
|
107
|
-
cloud.security_group(clname){ authorize_group(clname) }
|
108
|
-
end
|
109
|
-
|
110
|
-
# Creates a chef role named for the cluster
|
111
|
-
def create_cluster_role
|
112
|
-
@cluster_role_name = "#{name}_cluster"
|
113
|
-
@cluster_role = new_chef_role(@cluster_role_name, cluster)
|
114
|
-
role(@cluster_role_name, :own)
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
end
|
data/lib/ironfan/compute.rb
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
require 'ironfan/volume' # configure external and internal volumes
|
2
|
-
module Ironfan
|
3
|
-
#
|
4
|
-
# Base class allowing us to layer settings for facet over cluster
|
5
|
-
#
|
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
|
13
|
-
@@role_implications ||= Mash.new
|
14
|
-
@@run_list_rank ||= 0
|
15
|
-
|
16
|
-
def initialize(builder_name, attrs={})
|
17
|
-
super(attrs)
|
18
|
-
name builder_name
|
19
|
-
@run_list_info = attrs[:run_list] || Mash.new
|
20
|
-
@clouds = Mash.new
|
21
|
-
end
|
22
|
-
|
23
|
-
# set the bogosity to a descriptive reason. Anything truthy implies bogusness
|
24
|
-
def bogus?
|
25
|
-
!! self.bogosity
|
26
|
-
end
|
27
|
-
|
28
|
-
# Magic method to produce cloud instance:
|
29
|
-
# * returns the cloud instance, creating it if necessary.
|
30
|
-
# * executes the block in the cloud's object context
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# cloud do
|
34
|
-
# image_name 'maverick'
|
35
|
-
# security_group :nagios
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# # defines ec2-specific behavior
|
39
|
-
# cloud(:ec2) do
|
40
|
-
# public_ip '1.2.3.4'
|
41
|
-
# region 'us-east-1d'
|
42
|
-
# end
|
43
|
-
#
|
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]
|
56
|
-
end
|
57
|
-
|
58
|
-
# sugar for cloud(:ec2)
|
59
|
-
def ec2(attrs={}, &block)
|
60
|
-
cloud(:ec2, attrs, &block)
|
61
|
-
end
|
62
|
-
|
63
|
-
def raid_group(rg_name, attrs={}, &block)
|
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|
|
67
|
-
volume(sv_name){ in_raid(rg_name) ; mountable(false) ; tags({}) }
|
68
|
-
end
|
69
|
-
volumes[rg_name] = raid
|
70
|
-
end
|
71
|
-
|
72
|
-
#
|
73
|
-
# Adds the given role to the run list, and invokes any role_implications it
|
74
|
-
# implies (for instance, defining and applying the 'ssh' security group if
|
75
|
-
# the 'ssh' role is applied.)
|
76
|
-
#
|
77
|
-
# You can specify placement of `:first`, `:normal` (or nil) or `:last`; the
|
78
|
-
# final runlist is assembled as
|
79
|
-
#
|
80
|
-
# * run_list :first items -- cluster, then facet, then server
|
81
|
-
# * run_list :normal items -- cluster, then facet, then server
|
82
|
-
# * run_list :last items -- cluster, then facet, then server
|
83
|
-
#
|
84
|
-
# (see Ironfan::Server#combined_run_list for full details though)
|
85
|
-
#
|
86
|
-
def role(role_name, placement=nil)
|
87
|
-
add_to_run_list("role[#{role_name}]", placement)
|
88
|
-
self.instance_eval(&@@role_implications[role_name]) if @@role_implications[role_name]
|
89
|
-
end
|
90
|
-
|
91
|
-
# Add the given recipe to the run list. You can specify placement of
|
92
|
-
# `:first`, `:normal` (or nil) or `:last`; the final runlist is assembled as
|
93
|
-
#
|
94
|
-
# * run_list :first items -- cluster, then facet, then server
|
95
|
-
# * run_list :normal items -- cluster, then facet, then server
|
96
|
-
# * run_list :last items -- cluster, then facet, then server
|
97
|
-
#
|
98
|
-
# (see Ironfan::Server#combined_run_list for full details though)
|
99
|
-
#
|
100
|
-
def recipe(name, placement=nil)
|
101
|
-
add_to_run_list(name, placement)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Roles and recipes for this element only.
|
105
|
-
#
|
106
|
-
# See Ironfan::Server#combined_run_list for run_list order resolution
|
107
|
-
def run_list
|
108
|
-
groups = run_list_groups
|
109
|
-
[ groups[:first], groups[:normal], groups[:last] ].flatten.compact.uniq
|
110
|
-
end
|
111
|
-
|
112
|
-
# run list elements grouped into :first, :normal and :last
|
113
|
-
def run_list_groups
|
114
|
-
@run_list_info.keys.sort_by{|item| @run_list_info[item][:rank] }.group_by{|item| @run_list_info[item][:placement] }
|
115
|
-
end
|
116
|
-
|
117
|
-
#
|
118
|
-
# Some roles imply aspects of the machine that have to exist at creation.
|
119
|
-
# For instance, on an ec2 machine you may wish the 'ssh' role to imply a
|
120
|
-
# security group explicity opening port 22.
|
121
|
-
#
|
122
|
-
# @param [String] role_name -- the role that triggers the block
|
123
|
-
# @yield block will be instance_eval'd in the object that calls 'role'
|
124
|
-
#
|
125
|
-
def self.role_implication(name, &block)
|
126
|
-
@@role_implications[name] = block
|
127
|
-
end
|
128
|
-
|
129
|
-
protected
|
130
|
-
|
131
|
-
def add_to_run_list(item, placement)
|
132
|
-
raise "run_list placement must be one of :first, :normal, :last or nil (also means :normal)" unless [:first, :last, :own, nil].include?(placement)
|
133
|
-
@@run_list_rank += 1
|
134
|
-
placement ||= :normal
|
135
|
-
@run_list_info[item] ||= { :rank => @@run_list_rank, :placement => placement }
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
end
|
data/lib/ironfan/discovery.rb
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
module Ironfan
|
2
|
-
class Cluster
|
3
|
-
|
4
|
-
def discover!
|
5
|
-
@aws_instance_hash = {}
|
6
|
-
discover_ironfan!
|
7
|
-
discover_chef_nodes!
|
8
|
-
discover_fog_servers! unless Ironfan.chef_config[:cloud] == false
|
9
|
-
discover_chef_clients!
|
10
|
-
discover_volumes!
|
11
|
-
end
|
12
|
-
|
13
|
-
def chef_clients
|
14
|
-
return @chef_clients if @chef_clients
|
15
|
-
@chef_clients = []
|
16
|
-
|
17
|
-
# Oh for fuck's sake -- the key used to index clients changed from
|
18
|
-
# 'clientname' in 0.10.4-and-prev to 'name' in 0.10.8. Rather than index
|
19
|
-
# both 'clientname' and 'name', they switched it -- so we have to fall
|
20
|
-
# back. FIXME: While the Opscode platform is 0.10.4 I have clientname
|
21
|
-
# first (sorry, people of the future). When it switches to 0.10.8 we'll
|
22
|
-
# reverse them (suck it people of the past).
|
23
|
-
# Also sometimes the server returns results that are nil on
|
24
|
-
# recently-expired clients, so that's annoying too.
|
25
|
-
clients, wtf, num = Chef::Search::Query.new.search(:client, "clientname:#{cluster_name}-*") ; clients.compact!
|
26
|
-
clients, wtf, num = Chef::Search::Query.new.search(:client, "name:#{cluster_name}-*") if clients.blank?
|
27
|
-
clients.each do |client_hsh|
|
28
|
-
next if client_hsh.nil?
|
29
|
-
# Return values from Chef::Search seem to be inconsistent across chef
|
30
|
-
# versions (sometimes a hash, sometimes an object). Fix if necessary.
|
31
|
-
client_hsh = Chef::ApiClient.json_create(client_hsh) unless client_hsh.is_a?(Chef::ApiClient)
|
32
|
-
@chef_clients.push( client_hsh )
|
33
|
-
end
|
34
|
-
@chef_clients
|
35
|
-
end
|
36
|
-
|
37
|
-
# returns client with the given name if in catalog, nil otherwise
|
38
|
-
def find_client(cl_name)
|
39
|
-
chef_clients.find{|ccl| ccl.name == cl_name }
|
40
|
-
end
|
41
|
-
|
42
|
-
def chef_nodes
|
43
|
-
return @chef_nodes if @chef_nodes
|
44
|
-
@chef_nodes = []
|
45
|
-
Chef::Search::Query.new.search(:node,"cluster_name:#{cluster_name}") do |n|
|
46
|
-
@chef_nodes.push(n) unless n.blank? || (n.cluster_name != cluster_name.to_s)
|
47
|
-
end
|
48
|
-
@chef_nodes
|
49
|
-
end
|
50
|
-
|
51
|
-
# returns node with the given name if in catalog, nil otherwise
|
52
|
-
def find_node(nd_name)
|
53
|
-
chef_nodes.find{|nd| nd.name == nd_name }
|
54
|
-
end
|
55
|
-
|
56
|
-
protected
|
57
|
-
|
58
|
-
def fog_servers
|
59
|
-
@fog_servers ||= Ironfan.fog_servers.select{|fs| fs.key_name == cluster_name.to_s && (fs.state != "terminated") }
|
60
|
-
end
|
61
|
-
|
62
|
-
# Walk the list of chef nodes and
|
63
|
-
# * vivify the server,
|
64
|
-
# * associate the chef node
|
65
|
-
# * if the chef node knows about its instance id, memorize that for lookup
|
66
|
-
# when we discover cloud instances.
|
67
|
-
def discover_chef_nodes!
|
68
|
-
chef_nodes.each do |chef_node|
|
69
|
-
if chef_node["cluster_name"] && chef_node["facet_name"] && chef_node["facet_index"]
|
70
|
-
cluster_name = chef_node["cluster_name"]
|
71
|
-
facet_name = chef_node["facet_name"]
|
72
|
-
facet_index = chef_node["facet_index"]
|
73
|
-
elsif chef_node.name
|
74
|
-
( cluster_name, facet_name, facet_index ) = chef_node.name.split(/-/)
|
75
|
-
else
|
76
|
-
next
|
77
|
-
end
|
78
|
-
svr = Ironfan::Server.get(cluster_name, facet_name, facet_index)
|
79
|
-
svr.chef_node chef_node
|
80
|
-
@aws_instance_hash[ chef_node.ec2.instance_id ] = svr if chef_node[:ec2] && chef_node.ec2.instance_id
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Walk the list of servers, asking each to discover its chef client.
|
85
|
-
def discover_chef_clients!
|
86
|
-
servers.each(&:chef_client)
|
87
|
-
end
|
88
|
-
|
89
|
-
# calling #servers vivifies each facet's Ironfan::Server instances
|
90
|
-
def discover_ironfan!
|
91
|
-
self.servers
|
92
|
-
end
|
93
|
-
|
94
|
-
def discover_fog_servers!
|
95
|
-
# If the fog server is tagged with cluster/facet/index, then try to
|
96
|
-
# locate the corresponding machine in the cluster def
|
97
|
-
# Otherwise, try to get to it through mapping the aws instance id
|
98
|
-
# to the chef node name found in the chef node
|
99
|
-
fog_servers.each do |fs|
|
100
|
-
if fs.tags["cluster"] && fs.tags["facet"] && fs.tags["index"] && fs.tags["cluster"] == cluster_name.to_s
|
101
|
-
svr = Ironfan::Server.get(fs.tags["cluster"], fs.tags["facet"], fs.tags["index"])
|
102
|
-
elsif @aws_instance_hash[fs.id]
|
103
|
-
svr = @aws_instance_hash[fs.id]
|
104
|
-
else
|
105
|
-
next
|
106
|
-
end
|
107
|
-
|
108
|
-
# If there already is a fog server there, then issue a warning and slap
|
109
|
-
# the just-discovered one onto a server with an arbitrary index, and
|
110
|
-
# mark both bogus
|
111
|
-
if existing_fs = svr.fog_server
|
112
|
-
if existing_fs.id != fs.id
|
113
|
-
ui.warn "Duplicate fog instance found for #{svr.fullname}: #{fs.id} and #{existing_fs.id}!!"
|
114
|
-
old_svr = svr
|
115
|
-
svr = old_svr.facet.server(1_000 + svr.facet_index.to_i)
|
116
|
-
old_svr.bogosity :duplicate
|
117
|
-
svr.bogosity :duplicate
|
118
|
-
end
|
119
|
-
end
|
120
|
-
svr.fog_server = fs
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def discover_volumes!
|
125
|
-
servers.each(&:discover_volumes!)
|
126
|
-
end
|
127
|
-
|
128
|
-
def discover_addresses!
|
129
|
-
servers.each(&:discover_addresses!)
|
130
|
-
end
|
131
|
-
|
132
|
-
end # Ironfan::Cluster
|
133
|
-
end
|
134
|
-
|
135
|
-
module Ironfan
|
136
|
-
|
137
|
-
def self.fog_connection
|
138
|
-
@fog_connection ||= Fog::Compute.new({
|
139
|
-
:provider => 'AWS',
|
140
|
-
:aws_access_key_id => Chef::Config[:knife][:aws_access_key_id],
|
141
|
-
:aws_secret_access_key => Chef::Config[:knife][:aws_secret_access_key],
|
142
|
-
:region => Chef::Config[:knife][:region]
|
143
|
-
})
|
144
|
-
end
|
145
|
-
|
146
|
-
def self.fog_servers
|
147
|
-
return @fog_servers if @fog_servers
|
148
|
-
Chef::Log.debug("Using fog to catalog all servers")
|
149
|
-
@fog_servers = Ironfan.fog_connection.servers.all
|
150
|
-
end
|
151
|
-
|
152
|
-
def self.fog_addresses
|
153
|
-
return @fog_addresses if @fog_addresses
|
154
|
-
Chef::Log.debug("Using fog to catalog all addresses")
|
155
|
-
@fog_addresses = {}.tap{|hsh| Ironfan.fog_connection.addresses.each{|fa| hsh[fa.public_ip] = fa } }
|
156
|
-
end
|
157
|
-
|
158
|
-
def self.fog_volumes
|
159
|
-
@fog_volumes || fetch_fog_volumes
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.fetch_fog_volumes
|
163
|
-
Chef::Log.debug("Using fog to catalog all volumes")
|
164
|
-
@fog_volumes = Ironfan.fog_connection.volumes
|
165
|
-
end
|
166
|
-
|
167
|
-
def self.fog_keypairs
|
168
|
-
return @fog_keypairs if @fog_keypairs
|
169
|
-
Chef::Log.debug("Using fog to catalog all keypairs")
|
170
|
-
@fog_keypairs = {}.tap{|hsh| Ironfan.fog_connection.key_pairs.each{|kp| hsh[kp.name] = kp } }
|
171
|
-
end
|
172
|
-
|
173
|
-
def self.dry_run?
|
174
|
-
Ironfan.chef_config[:dry_run]
|
175
|
-
end
|
176
|
-
|
177
|
-
def self.placement_groups
|
178
|
-
return @placement_groups if @placement_groups
|
179
|
-
Chef::Log.debug("Using fog to catalog all placement_groups")
|
180
|
-
resp = self.fog_connection.describe_placement_groups unless dry_run?
|
181
|
-
return {} unless resp.respond_to?(:body) && resp.body.present?
|
182
|
-
arr = resp.body['placementGroupSet']
|
183
|
-
@placement_groups = arr.inject({}){|acc, pg| acc[pg['groupName']] = pg ; acc }
|
184
|
-
end
|
185
|
-
|
186
|
-
def safely *args, &block
|
187
|
-
Ironfan.safely(*args, &block)
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
data/lib/ironfan/dsl_builder.rb
DELETED
@@ -1,99 +0,0 @@
|
|
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
DELETED
@@ -1,143 +0,0 @@
|
|
1
|
-
module Ironfan
|
2
|
-
class Facet < Ironfan::ComputeBuilder
|
3
|
-
attr_reader :cluster
|
4
|
-
magic :instances, Integer, :default => 1
|
5
|
-
|
6
|
-
def initialize cluster, facet_name, attrs={}
|
7
|
-
super(facet_name.to_sym, attrs)
|
8
|
-
@cluster = cluster
|
9
|
-
@servers = Mash.new
|
10
|
-
@chef_roles = []
|
11
|
-
create_facet_role
|
12
|
-
create_facet_security_group unless attrs[:no_security_group]
|
13
|
-
end
|
14
|
-
|
15
|
-
def cluster_name
|
16
|
-
cluster.name
|
17
|
-
end
|
18
|
-
|
19
|
-
def facet_name
|
20
|
-
name
|
21
|
-
end
|
22
|
-
|
23
|
-
# The auto-generated role for this facet.
|
24
|
-
# Instance-evals the given block in the context of that role,
|
25
|
-
#
|
26
|
-
# @example
|
27
|
-
# facet_role do
|
28
|
-
# override_attributes({
|
29
|
-
# :time_machine => { :transition_speed => 88 },
|
30
|
-
# })
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# @return [Chef::Role] The auto-generated role for this facet.
|
34
|
-
def facet_role(&block)
|
35
|
-
@facet_role.instance_eval( &block ) if block_given?
|
36
|
-
@facet_role
|
37
|
-
end
|
38
|
-
|
39
|
-
def assign_volume_ids(volume_name, *volume_ids)
|
40
|
-
volume_ids.flatten.zip(servers).each do |volume_id, server|
|
41
|
-
server.volume(volume_name){ volume_id(volume_id) } if server
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
#
|
46
|
-
# Retrieve or define the given server
|
47
|
-
#
|
48
|
-
# @param [Integer] idx -- the index of the desired server
|
49
|
-
# @param [Hash] attrs -- attributes to configure on the object
|
50
|
-
# @yield a block to execute in the context of the object
|
51
|
-
#
|
52
|
-
# @return [Ironfan::Facet]
|
53
|
-
#
|
54
|
-
def server(idx, attrs={}, &block)
|
55
|
-
idx = idx.to_i
|
56
|
-
@servers[idx] ||= Ironfan::Server.new(self, idx)
|
57
|
-
@servers[idx].receive!(attrs, &block)
|
58
|
-
@servers[idx]
|
59
|
-
end
|
60
|
-
|
61
|
-
# if the server has been added to this facet or is in range
|
62
|
-
def has_server? idx
|
63
|
-
(idx.to_i < instances) || @servers.include?(idx.to_i)
|
64
|
-
end
|
65
|
-
|
66
|
-
#
|
67
|
-
# Slicing
|
68
|
-
#
|
69
|
-
|
70
|
-
# All servers in this facet
|
71
|
-
#
|
72
|
-
# @return [Ironfan::ServerSlice] slice containing all servers
|
73
|
-
def servers
|
74
|
-
slice(indexes)
|
75
|
-
end
|
76
|
-
|
77
|
-
#
|
78
|
-
# A slice of servers from this facet, in index order
|
79
|
-
#
|
80
|
-
# If +slice_indexes+ is nil, returns all servers.
|
81
|
-
# Otherwise, takes slice (given by +*args+) from the requested facet.
|
82
|
-
#
|
83
|
-
# @param [Array, String] slice_indexes -- servers in that facet (or nil for all in facet).
|
84
|
-
#
|
85
|
-
# @return [Ironfan::ServerSlice] the requested slice
|
86
|
-
def slice(slice_indexes=nil)
|
87
|
-
slice_indexes = self.indexes if slice_indexes.blank?
|
88
|
-
slice_indexes = indexes_from_intervals(slice_indexes) if slice_indexes.is_a?(String)
|
89
|
-
svrs = Array(slice_indexes).map(&:to_i).sort!.select{|idx| has_server?(idx) }.map{|idx| server(idx) }
|
90
|
-
Ironfan::ServerSlice.new(self.cluster, svrs)
|
91
|
-
end
|
92
|
-
|
93
|
-
# all valid server indexes
|
94
|
-
def valid_indexes
|
95
|
-
(0 ... instances).to_a # note the '...'
|
96
|
-
end
|
97
|
-
|
98
|
-
# indexes in the 0...instances range plus bogus ones that showed up
|
99
|
-
# (probably from chef or fog)
|
100
|
-
def indexes
|
101
|
-
[@servers.keys, valid_indexes].flatten.compact.uniq.sort
|
102
|
-
end
|
103
|
-
|
104
|
-
#
|
105
|
-
# Resolve:
|
106
|
-
#
|
107
|
-
def resolve!
|
108
|
-
servers.each(&:resolve!)
|
109
|
-
end
|
110
|
-
|
111
|
-
protected
|
112
|
-
|
113
|
-
def create_facet_security_group
|
114
|
-
cloud.security_group("#{cluster_name}-#{facet_name}")
|
115
|
-
end
|
116
|
-
|
117
|
-
# Creates a chef role named for the facet
|
118
|
-
def create_facet_role
|
119
|
-
@facet_role_name = "#{cluster_name}_#{facet_name}"
|
120
|
-
@facet_role = new_chef_role(@facet_role_name, cluster, self)
|
121
|
-
role(@facet_role_name, :own)
|
122
|
-
end
|
123
|
-
|
124
|
-
#
|
125
|
-
# Given a string enumerating indexes to select returns a flat array of
|
126
|
-
# indexes. The indexes will be unique but in an arbitrary order.
|
127
|
-
#
|
128
|
-
# @example
|
129
|
-
# facet = Ironfan::Facet.new('foo', 'bar')
|
130
|
-
# facet.indexes_from_intervals('1,2-3,8-9,7') # [1, 2, 3, 8, 9, 7]
|
131
|
-
# facet.indexes_from_intervals('1,3-5,4,7') # [1, 3, 4, 5, 7]
|
132
|
-
#
|
133
|
-
def indexes_from_intervals intervals
|
134
|
-
intervals.split(",").map do |term|
|
135
|
-
if term =~ /^(\d+)-(\d+)$/ then ($1.to_i .. $2.to_i).to_a
|
136
|
-
elsif term =~ /^(\d+)$/ then $1.to_i
|
137
|
-
else ui.warn("Bad interval: #{term}") ; nil
|
138
|
-
end
|
139
|
-
end.flatten.compact.uniq
|
140
|
-
end
|
141
|
-
|
142
|
-
end
|
143
|
-
end
|