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
@@ -0,0 +1,133 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class ChefServer
|
4
|
+
|
5
|
+
class Node < Ironfan::Provider::Resource
|
6
|
+
delegate :[], :[]=, :add_to_index, :apply_expansion_attributes,
|
7
|
+
:attribute, :attribute=, :attribute?, :automatic_attrs,
|
8
|
+
:automatic_attrs=, :cdb_destroy, :cdb_save, :chef_environment,
|
9
|
+
:chef_environment=, :chef_server_rest, :class_from_file,
|
10
|
+
:construct_attributes, :consume_attributes,
|
11
|
+
:consume_external_attrs, :consume_run_list, :cookbook_collection,
|
12
|
+
:cookbook_collection=, :couchdb, :couchdb=, :couchdb_id,
|
13
|
+
:couchdb_id=, :couchdb_rev, :couchdb_rev=, :create, :default,
|
14
|
+
:default_attrs, :default_attrs=, :default_unless,
|
15
|
+
:delete_from_index, :destroy, :display_hash, :each,
|
16
|
+
:each_attribute, :each_key, :each_value, :expand!, :find_file,
|
17
|
+
:from_file, :has_key?, :include_attribute, :index_id, :index_id=,
|
18
|
+
:index_object_type, :key?, :keys,
|
19
|
+
:load_attribute_by_short_filename, :load_attributes, :name, :node,
|
20
|
+
:normal, :normal_attrs, :normal_attrs=, :normal_unless, :override,
|
21
|
+
:override_attrs, :override_attrs=, :override_unless, :recipe?,
|
22
|
+
:recipe_list, :recipe_list=, :reset_defaults_and_overrides, :role?,
|
23
|
+
:run_list, :run_list=, :run_list?, :run_state, :run_state=, :save,
|
24
|
+
:set, :set_if_args, :set_or_return, :set_unless, :drive, :tags,
|
25
|
+
:to_hash, :update_from!, :validate, :with_indexer_metadata,
|
26
|
+
:to => :adaptee
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super
|
30
|
+
self.adaptee ||= Chef::Node.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.shared?() false; end
|
34
|
+
def self.multiple?() false; end
|
35
|
+
# def self.resource_type() self; end
|
36
|
+
def self.resource_type() :node; end
|
37
|
+
def self.expected_ids(computer) [computer.server.fullname]; end
|
38
|
+
|
39
|
+
def to_display(style,values={})
|
40
|
+
values["Chef?"] = adaptee.nil? ? "no" : "yes"
|
41
|
+
values
|
42
|
+
end
|
43
|
+
|
44
|
+
def save!(computer)
|
45
|
+
prepare_from computer
|
46
|
+
save
|
47
|
+
end
|
48
|
+
|
49
|
+
def create!(computer)
|
50
|
+
prepare_from computer
|
51
|
+
|
52
|
+
client = computer[:client]
|
53
|
+
unless File.exists?(client.key_filename)
|
54
|
+
raise("Cannot create chef node #{name} -- client #{@chef_client} exists but no client key found in #{client.key_filename}.")
|
55
|
+
end
|
56
|
+
ChefServer.post_rest("nodes", adaptee, :client => client)
|
57
|
+
end
|
58
|
+
|
59
|
+
def prepare_from(computer)
|
60
|
+
organization = Chef::Config.organization
|
61
|
+
normal[:organization] = organization unless organization.nil?
|
62
|
+
|
63
|
+
server = computer.server
|
64
|
+
chef_environment = server.environment
|
65
|
+
run_list.instance_eval { @run_list_items = server.run_list }
|
66
|
+
normal[:cluster_name] = server.cluster_name
|
67
|
+
normal[:facet_name] = server.facet_name
|
68
|
+
normal[:permanent] = computer.permanent?
|
69
|
+
normal[:volumes] = {}
|
70
|
+
computer.drives.each {|v| normal[:volumes][v.name] = v.node}
|
71
|
+
end
|
72
|
+
|
73
|
+
def announce_state state
|
74
|
+
set[:state] = state
|
75
|
+
save
|
76
|
+
end
|
77
|
+
|
78
|
+
def conterminous_with_machine?
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Discovery
|
84
|
+
#
|
85
|
+
def self.load!(cluster=nil)
|
86
|
+
ChefServer.search(:node,"name:#{cluster.name}-*") do |raw|
|
87
|
+
next if raw.blank?
|
88
|
+
node = Node.new
|
89
|
+
node.adaptee = raw
|
90
|
+
remember node
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def on_correlate(computer)
|
95
|
+
self['volumes'].each do |name,volume|
|
96
|
+
computer.drive(name).node.merge! volume
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.validate_computer!(computer)
|
101
|
+
return unless computer.node and not computer[:client]
|
102
|
+
computer.node.bogus << :node_without_client
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Manipulation
|
107
|
+
#
|
108
|
+
def self.create!(computer)
|
109
|
+
return if computer.node?
|
110
|
+
node = Node.new
|
111
|
+
node.name computer.server.fullname
|
112
|
+
node.create! computer
|
113
|
+
computer.node = node
|
114
|
+
remember node
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.destroy!(computer)
|
118
|
+
return unless computer.node?
|
119
|
+
forget computer.node.name
|
120
|
+
computer.node.destroy
|
121
|
+
computer.delete(:node)
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.save!(computer)
|
125
|
+
return unless computer.node?
|
126
|
+
computer.node.save! computer
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class ChefServer
|
4
|
+
|
5
|
+
class Role < Ironfan::Provider::Resource
|
6
|
+
delegate :active_run_list_for, :add_to_index, :cdb_destroy, :cdb_save,
|
7
|
+
:chef_server_rest, :class_from_file, :couchdb, :couchdb=,
|
8
|
+
:couchdb_id, :couchdb_id=, :couchdb_rev, :couchdb_rev=, :create,
|
9
|
+
:default_attributes, :delete_from_index, :description, :destroy,
|
10
|
+
:env_run_list, :env_run_lists, :environment, :environments,
|
11
|
+
:from_file, :index_id, :index_id=, :index_object_type, :name,
|
12
|
+
:override_attributes, :recipes, :run_list, :run_list_for, :save,
|
13
|
+
:set_or_return, :to_hash, :update_from!, :validate,
|
14
|
+
:with_indexer_metadata,
|
15
|
+
:to => :adaptee
|
16
|
+
|
17
|
+
def self.shared?() true; end
|
18
|
+
def self.multiple?() true; end
|
19
|
+
# def self.resource_type() self; end
|
20
|
+
def self.resource_type() :role; end
|
21
|
+
def self.expected_ids(computer)
|
22
|
+
[ computer.server.cluster_role.name.to_s,
|
23
|
+
computer.server.facet_role.name.to_s ]
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(config={})
|
27
|
+
super
|
28
|
+
if self.adaptee.nil? and not config[:expected].nil?
|
29
|
+
expected = config[:expected]
|
30
|
+
desc = "Ironfan generated role for #{expected.name}"
|
31
|
+
self.adaptee = Chef::Role.new
|
32
|
+
self.name expected.name
|
33
|
+
self.override_attributes expected.override_attributes
|
34
|
+
self.default_attributes expected.default_attributes
|
35
|
+
self.description desc
|
36
|
+
end
|
37
|
+
raise "Missing adaptee" if self.adaptee.nil?
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Discovery
|
43
|
+
#
|
44
|
+
def self.load!(cluster)
|
45
|
+
ChefServer.search(:role,"name:#{cluster.name}_*") do |raw|
|
46
|
+
next if raw.blank?
|
47
|
+
remember Role.new(:adaptee => raw)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Manipulation
|
53
|
+
#
|
54
|
+
def self.save!(computer)
|
55
|
+
dsl_roles = []
|
56
|
+
dsl_roles << computer.server.cluster_role
|
57
|
+
dsl_roles << computer.server.facet_role
|
58
|
+
|
59
|
+
dsl_roles.each do |dsl_role|
|
60
|
+
next if recall? dsl_role.name # Handle each role only once
|
61
|
+
role = remember new(:expected => dsl_role)
|
62
|
+
role.save
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
|
4
|
+
class ChefServer < Ironfan::Provider
|
5
|
+
|
6
|
+
def self.resources
|
7
|
+
[ Client, Node, Role ]
|
8
|
+
end
|
9
|
+
|
10
|
+
#
|
11
|
+
# Utility functions
|
12
|
+
#
|
13
|
+
def self.post_rest(type, content, options={})
|
14
|
+
params = [ Chef::Config[:chef_server_url] ]
|
15
|
+
if options[:client]
|
16
|
+
params << options[:client].name
|
17
|
+
params << options[:client].key_filename
|
18
|
+
end
|
19
|
+
Chef::REST.new(*params).post_rest(type,content)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.search(*params,&block)
|
23
|
+
Chef::Search::Query.new.search(*params,&block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class Ec2
|
4
|
+
|
5
|
+
class EbsVolume < Ironfan::Provider::Resource
|
6
|
+
delegate :_dump, :attached_at, :attached_at=, :attributes,
|
7
|
+
:availability_zone, :availability_zone=, :collection, :collection=,
|
8
|
+
:connection, :connection=, :created_at, :created_at=,
|
9
|
+
:delete_on_termination, :delete_on_termination=, :destroy, :device,
|
10
|
+
:device=, :dup_attributes!, :force_detach, :id, :id=, :identity,
|
11
|
+
:identity=, :merge_attributes, :missing_attributes, :new_record?,
|
12
|
+
:ready?, :reload, :requires, :requires_one, :save, :server,
|
13
|
+
:server=, :server_id, :server_id=, :size, :size=, :snapshot,
|
14
|
+
:snapshot_id, :snapshot_id=, :snapshots, :state, :state=,
|
15
|
+
:symbolize_keys, :tags, :tags=, :wait_for,
|
16
|
+
:to => :adaptee
|
17
|
+
field :dsl_volume, Ironfan::Dsl::Volume
|
18
|
+
|
19
|
+
def self.shared?() false; end
|
20
|
+
def self.multiple?() true; end
|
21
|
+
def self.resource_type() :ebs_volume; end
|
22
|
+
def self.expected_ids(computer)
|
23
|
+
computer.server.volumes.values.map do |volume|
|
24
|
+
saved = computer.node[:volumes][volume.name][:volume_id] rescue nil
|
25
|
+
ebs_name = "#{computer.server.fullname}-#{volume.name}"
|
26
|
+
[ volume.volume_id, saved, ebs_name]
|
27
|
+
end.flatten.compact
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
tags["Name"] || tags["name"] || id
|
32
|
+
end
|
33
|
+
|
34
|
+
def ephemeral_device?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Discovery
|
40
|
+
#
|
41
|
+
def self.load!(cluster=nil)
|
42
|
+
Ec2.connection.volumes.each do |vol|
|
43
|
+
next if vol.blank?
|
44
|
+
ebs = EbsVolume.new(:adaptee => vol)
|
45
|
+
# Already have a volume by this name
|
46
|
+
if recall? ebs.name
|
47
|
+
ebs.bogus << :duplicate_volumes
|
48
|
+
recall(ebs.name).bogus << :duplicate_volumes
|
49
|
+
remember ebs, :append_id => "duplicate:#{ebs.id}"
|
50
|
+
else
|
51
|
+
remember ebs
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_correlate(computer)
|
57
|
+
Chef::Log.warn("ebs_volume::on_correlate is incomplete")
|
58
|
+
end
|
59
|
+
|
60
|
+
# def self.correlate!(computer)
|
61
|
+
# Chef::Log.warn("CODE SMELL: overly large method: #{caller}")
|
62
|
+
# return unless computer.server?
|
63
|
+
# computer.server.volumes.each do |volume|
|
64
|
+
# unless volume.attachable.to_s == 'ebs'
|
65
|
+
# Chef::Log.debug("Ignoring non-EBS volume = #{volume}")
|
66
|
+
# next
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# drive = computer.drive(volume.name)
|
70
|
+
# drive.node = computer.node[:volumes][volume.name].to_hash rescue {}
|
71
|
+
# if drive.node.has_key? :volume_id
|
72
|
+
# node_volume_id = drive.node[:volume_id]
|
73
|
+
# end
|
74
|
+
# ebs_name = "#{computer.server.fullname}-#{volume.name}"
|
75
|
+
#
|
76
|
+
# volume_id = volume.volume_id
|
77
|
+
# volume_id ||= node_volume_id
|
78
|
+
#
|
79
|
+
# # Volumes may match against name derived from the cluster definition,
|
80
|
+
# # or volume_id from the cluster definition or node
|
81
|
+
# case
|
82
|
+
# when (recall? ebs_name)
|
83
|
+
# ebs = recall ebs_name
|
84
|
+
# when (volume_id and recall? volume_id)
|
85
|
+
# ebs = recall volume_id
|
86
|
+
# else
|
87
|
+
# log_message = "Volume not found: name = #{ebs_name}"
|
88
|
+
# log_message += ", volume_id = #{volume_id}"
|
89
|
+
# Chef::Log.debug(log_message)
|
90
|
+
# next
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# # Make sure all the known volume_ids match
|
94
|
+
# [ ebs.id, volume.volume_id, node_volume_id ].compact.each do |id|
|
95
|
+
# id == volume_id or ebs.bogus << :volume_id_mismatch
|
96
|
+
# end if volume_id
|
97
|
+
#
|
98
|
+
# computer.bogus += ebs.bogus
|
99
|
+
# ebs.owner = computer.object_id
|
100
|
+
# drive.volume = volume
|
101
|
+
# drive.disk = ebs
|
102
|
+
# end
|
103
|
+
# end
|
104
|
+
def self.validate_computer!(computer)
|
105
|
+
Chef::Log.warn("ebs_volume::validate_computer! is incomplete")
|
106
|
+
# # Make sure all the known volume_ids match
|
107
|
+
# [ ebs.id, volume.volume_id, node_volume_id ].compact.each do |id|
|
108
|
+
# id == volume_id or ebs.bogus << :volume_id_mismatch
|
109
|
+
# end if volume_id
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Manipulation
|
114
|
+
#
|
115
|
+
|
116
|
+
def self.save!(computer)
|
117
|
+
Ironfan.step(computer.name,"syncing EBS volumes",:blue)
|
118
|
+
computer.drives.each do |drive|
|
119
|
+
# Only worry about computers with ebs volumes
|
120
|
+
ebs = drive.disk or next
|
121
|
+
# Only attach volumes if they aren't already attached
|
122
|
+
if ebs.server_id.nil?
|
123
|
+
Ironfan.step(computer.name, " - attaching #{ebs.name}", :blue)
|
124
|
+
Ironfan.safely do
|
125
|
+
ebs.device = drive.volume.device
|
126
|
+
ebs.server = computer.machine.adaptee
|
127
|
+
end
|
128
|
+
end
|
129
|
+
# Record the volume information in chef
|
130
|
+
drive.node['volume_id'] = ebs.id
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class Ec2
|
4
|
+
|
5
|
+
class KeyPair < Ironfan::Provider::Resource
|
6
|
+
delegate :_dump, :collection, :collection=, :connection,
|
7
|
+
:connection=, :destroy, :fingerprint, :fingerprint=, :identity,
|
8
|
+
:identity=, :name, :name=, :new_record?, :public_key,
|
9
|
+
:public_key=, :reload, :requires, :requires_one, :save,
|
10
|
+
:symbolize_keys, :wait_for, :writable?, :write,
|
11
|
+
:to => :adaptee
|
12
|
+
field :key_filename, String,
|
13
|
+
:default => ->{ "#{KeyPair.key_dir}/#{name}.pem" }
|
14
|
+
|
15
|
+
def self.shared?() true; end
|
16
|
+
def self.multiple?() false; end
|
17
|
+
def self.resource_type() :key_pair; end
|
18
|
+
def self.expected_ids(computer) [computer.server.cluster_name]; end
|
19
|
+
|
20
|
+
def private_key
|
21
|
+
File.open(key_filename, "rb").read
|
22
|
+
end
|
23
|
+
|
24
|
+
def private_key=(body=nil)
|
25
|
+
File.open(key_filename, "w", 0600){|f| f.print( body ) }
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Discovery
|
30
|
+
#
|
31
|
+
def self.load!(cluster=nil)
|
32
|
+
Ec2.connection.key_pairs.each do |keypair|
|
33
|
+
register keypair unless keypair.blank?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Manipulation
|
39
|
+
#
|
40
|
+
|
41
|
+
def self.create!(computer)
|
42
|
+
name = computer.server.cluster_name
|
43
|
+
return if recall? name
|
44
|
+
Ironfan.step(name, "creating key pair for #{name}", :blue)
|
45
|
+
result = Ec2.connection.create_key_pair(name)
|
46
|
+
private_key = result.body["keyMaterial"]
|
47
|
+
load! # Reload to get the native object
|
48
|
+
recall(name).private_key = private_key
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Utility
|
53
|
+
#
|
54
|
+
|
55
|
+
def self.key_dir
|
56
|
+
return Chef::Config.ec2_key_dir if Chef::Config.ec2_key_dir
|
57
|
+
dir = "#{ENV['HOME']}/.chef/credentials/ec2_keys"
|
58
|
+
warn "Please set 'ec2_key_dir' in your knife.rb. Will use #{dir} as a default"
|
59
|
+
dir
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|