poolparty 1.4.8 → 1.5.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/VERSION.yml +2 -2
- data/bin/cloud-show +8 -1
- data/lib/cloud_providers/connections.rb +42 -8
- data/lib/cloud_providers/ec2/ec2.rb +4 -0
- data/lib/cloud_providers/ec2/helpers/elastic_auto_scaler.rb +2 -2
- data/lib/cloud_providers/ec2/helpers/elastic_block_store_group.rb +1 -1
- data/lib/cloud_providers/ec2/helpers/rds_instance.rb +18 -6
- data/lib/cloud_providers/remote_instance.rb +10 -7
- data/lib/poolparty/cloud.rb +42 -5
- metadata +2 -2
data/VERSION.yml
CHANGED
data/bin/cloud-show
CHANGED
|
@@ -38,10 +38,17 @@ EOS
|
|
|
38
38
|
load_balancers = cld.cloud_provider.load_balancers.first.running_load_balancers.map {|a| a[:dns_name]}
|
|
39
39
|
msg << "Load balancers: #{load_balancers.join("\n\t\t\t")}"
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
if cld.rds_instances.size > 0
|
|
43
|
+
available = cld.cloud_provider.available_rds_instances.map{|r| "#{r.instance_id}\t#{r.current_status.Endpoint.Address}" }
|
|
44
|
+
available.unshift 'RDS Instances:'
|
|
45
|
+
|
|
46
|
+
msg << available.join("\n\t\t\t")
|
|
47
|
+
end
|
|
41
48
|
|
|
42
49
|
puts msg.flatten
|
|
43
50
|
|
|
44
51
|
end
|
|
45
52
|
|
|
46
53
|
end
|
|
47
|
-
end
|
|
54
|
+
end
|
|
@@ -27,15 +27,48 @@ module CloudProviders
|
|
|
27
27
|
def run(commands, o={})
|
|
28
28
|
ssh(commands)
|
|
29
29
|
end
|
|
30
|
-
|
|
30
|
+
|
|
31
|
+
def shell_escape(str)
|
|
32
|
+
String(str).gsub(/(?=["'\\$])/n, '\\').
|
|
33
|
+
gsub(/\n/, "'\n'").
|
|
34
|
+
sub(/^$/, "''")
|
|
35
|
+
end
|
|
36
|
+
|
|
31
37
|
def ssh( commands=[], extra_ssh_ops={})
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
# Get the environment hash out of
|
|
39
|
+
# the extra_ssh_ops and then delete
|
|
40
|
+
# the element
|
|
41
|
+
env = extra_ssh_ops[:env] || {}
|
|
42
|
+
extra_ssh_ops.delete :env
|
|
43
|
+
|
|
44
|
+
# Decide to use sudo or not
|
|
45
|
+
do_sudo = true
|
|
46
|
+
if extra_ssh_ops.has_key? :do_sudo
|
|
47
|
+
do_sudo = extra_ssh_ops[:do_sudo]
|
|
48
|
+
extra_ssh_ops.delete :do_sudo
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
envstring = env.collect {|k,v| "#{k}=#{v}"}.join ' && '
|
|
52
|
+
envstring += " && " unless envstring.size == 0
|
|
53
|
+
ssh_string = "ssh #{user}@#{host} #{ssh_options(extra_ssh_ops)}"
|
|
54
|
+
|
|
34
55
|
if commands.empty?
|
|
35
56
|
#TODO: replace this with a IO.popen call with read_nonblocking to show progress, and accept input
|
|
36
|
-
Kernel.system(
|
|
57
|
+
Kernel.system(ssh_string)
|
|
37
58
|
else
|
|
38
|
-
|
|
59
|
+
r = nil
|
|
60
|
+
commands.each do |command|
|
|
61
|
+
|
|
62
|
+
cmd = "#{envstring}#{command}"
|
|
63
|
+
if do_sudo
|
|
64
|
+
sudocmd = %Q% sudo sh -c "#{shell_escape cmd}" %
|
|
65
|
+
else
|
|
66
|
+
sudocmd = cmd
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
r = system_run ssh_string + %Q% "#{shell_escape sudocmd}"%
|
|
70
|
+
end
|
|
71
|
+
r
|
|
39
72
|
end
|
|
40
73
|
end
|
|
41
74
|
|
|
@@ -46,7 +79,7 @@ module CloudProviders
|
|
|
46
79
|
def ssh_options(opts={})
|
|
47
80
|
return @ssh_options if @ssh_options && opts.empty?
|
|
48
81
|
ssh_opts = {"-i" => keypair.full_filepath,
|
|
49
|
-
"-o" =>"StrictHostKeyChecking=no"
|
|
82
|
+
"-o" =>"StrictHostKeyChecking=no",
|
|
50
83
|
}.merge(opts)
|
|
51
84
|
@ssh_options = ssh_opts.collect{ |k,v| "#{k} #{v}"}.join(' ')
|
|
52
85
|
end
|
|
@@ -55,7 +88,8 @@ module CloudProviders
|
|
|
55
88
|
raise StandardError.new("You must pass a :source=>uri option to rsync") unless opts[:source]
|
|
56
89
|
destination_path = opts[:destination] || opts[:source]
|
|
57
90
|
rsync_opts = opts[:rsync_opts] || '-va'
|
|
58
|
-
|
|
91
|
+
rsync_opts += %q% --rsync-path="sudo rsync" --exclude=.svn --exclude=.git --exclude=.cvs %
|
|
92
|
+
cmd_string = "rsync -L -e 'ssh #{ssh_options}' #{rsync_opts} #{opts[:source]} #{user}@#{host}:#{destination_path}"
|
|
59
93
|
out = system_run(cmd_string)
|
|
60
94
|
out
|
|
61
95
|
end
|
|
@@ -106,4 +140,4 @@ module CloudProviders
|
|
|
106
140
|
end
|
|
107
141
|
|
|
108
142
|
end
|
|
109
|
-
end
|
|
143
|
+
end
|
|
@@ -326,6 +326,10 @@ module CloudProviders
|
|
|
326
326
|
rds_instances << RdsInstance.new(given_name, sub_opts.merge(o || {}), &block)
|
|
327
327
|
end
|
|
328
328
|
|
|
329
|
+
def available_rds_instances
|
|
330
|
+
rds_instances.select{|r| r.available? }
|
|
331
|
+
end
|
|
332
|
+
|
|
329
333
|
# Proxy to the raw Grempe amazon-aws @ec2 instance
|
|
330
334
|
def ec2
|
|
331
335
|
@ec2 ||= begin
|
|
@@ -145,7 +145,7 @@ module CloudProviders
|
|
|
145
145
|
:user_data => user_data,
|
|
146
146
|
:kernel_id => kernel_id,
|
|
147
147
|
:ramdisk_id => ramdisk_id,
|
|
148
|
-
:
|
|
148
|
+
:block_device_mapping => block_device_mapping
|
|
149
149
|
})
|
|
150
150
|
rescue Exception => e
|
|
151
151
|
puts <<-EOE
|
|
@@ -424,4 +424,4 @@ module CloudProviders
|
|
|
424
424
|
"#{(measure_names[measure] || measure)}-#{name}" || name
|
|
425
425
|
end
|
|
426
426
|
end
|
|
427
|
-
end
|
|
427
|
+
end
|
|
@@ -32,7 +32,7 @@ module CloudProviders
|
|
|
32
32
|
|
|
33
33
|
# get volumes that are not attached
|
|
34
34
|
def free_volumes(availability_zone)
|
|
35
|
-
@volumes.select{|vol| vol.available? and vol.availability_zone == availability_zone}
|
|
35
|
+
@volumes.flatten.select{|vol| vol.available? and vol.availability_zone == availability_zone}
|
|
36
36
|
end
|
|
37
37
|
# Get a free volume from existing volumes in group or create a new one
|
|
38
38
|
def get_free_volume(availability_zone)
|
|
@@ -33,6 +33,22 @@ module CloudProviders
|
|
|
33
33
|
delete_rds_instance!
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def current_status
|
|
37
|
+
rds_instances.detect{|i| i.DBInstanceIdentifier == instance_id }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def exists?
|
|
41
|
+
! current_status.nil?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def available?
|
|
45
|
+
exists? && current_status.DBInstanceStatus == 'available'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def instance_id
|
|
49
|
+
name.to_s
|
|
50
|
+
end
|
|
51
|
+
|
|
36
52
|
private
|
|
37
53
|
|
|
38
54
|
def authorizations
|
|
@@ -53,11 +69,7 @@ module CloudProviders
|
|
|
53
69
|
end
|
|
54
70
|
|
|
55
71
|
def should_create_rds_instance?
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def instance_id
|
|
60
|
-
name.to_s
|
|
72
|
+
! exists?
|
|
61
73
|
end
|
|
62
74
|
|
|
63
75
|
def create_rds_instance!
|
|
@@ -107,4 +119,4 @@ module CloudProviders
|
|
|
107
119
|
end
|
|
108
120
|
end
|
|
109
121
|
end
|
|
110
|
-
end
|
|
122
|
+
end
|
|
@@ -37,7 +37,8 @@ module CloudProviders
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def chef_bootstrapped?
|
|
40
|
-
|
|
40
|
+
# do_sudo is false cause we want to capture the return code of the call
|
|
41
|
+
@chef_bootstrapped ||= !ssh(["gem list | grep chef"], :do_sudo => false).empty?
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def bootstrap_chef!
|
|
@@ -45,19 +46,21 @@ module CloudProviders
|
|
|
45
46
|
ssh([
|
|
46
47
|
'apt-get update',
|
|
47
48
|
'apt-get autoremove -y',
|
|
48
|
-
'apt-get install -y ruby ruby-dev rubygems git-core',
|
|
49
|
+
'apt-get install -y ruby ruby-dev rubygems git-core libopenssl-ruby',
|
|
49
50
|
'gem sources -a http://gems.opscode.com',
|
|
50
|
-
'gem install chef ohai --no-rdoc --no-ri' ]
|
|
51
|
-
bootstrap_gems.collect { |gem| "gem install #{gem} --no-rdoc --no-ri" } )
|
|
51
|
+
'gem install chef ohai --no-rdoc --no-ri' ])
|
|
52
52
|
end
|
|
53
|
+
ssh(bootstrap_gems.collect { |gem| "gem install #{gem} --no-rdoc --no-ri" } )
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
def run_chef!
|
|
56
57
|
chef_solo_cmd = <<-CMD
|
|
57
|
-
GEM_BIN
|
|
58
|
-
&& $GEM_BIN/chef-solo -j /etc/chef/dna.json -c /etc/chef/solo.rb
|
|
58
|
+
$GEM_BIN/chef-solo -j /etc/chef/dna.json -c /etc/chef/solo.rb
|
|
59
59
|
CMD
|
|
60
|
-
|
|
60
|
+
envhash = {
|
|
61
|
+
:GEM_BIN => %q%$(gem env | grep "EXECUTABLE DIRECTORY" | awk "{print \\$4}")%
|
|
62
|
+
}
|
|
63
|
+
ssh([chef_solo_cmd.strip.squeeze(' ')], :env => envhash )
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
def run
|
data/lib/poolparty/cloud.rb
CHANGED
|
@@ -64,10 +64,34 @@ You did not specify a cloud provider in your clouds.rb. Make sure you have a blo
|
|
|
64
64
|
def chef_attributes(hsh={}, &block)
|
|
65
65
|
@chef_attributes ||= ChefAttribute.new(hsh, &block)
|
|
66
66
|
end
|
|
67
|
+
|
|
68
|
+
def chef_override_attributes(hsh={}, &block)
|
|
69
|
+
@chef_override_attributes ||= ChefAttribute.new(hsh, &block)
|
|
70
|
+
end
|
|
67
71
|
|
|
72
|
+
# Adds a chef recipe to the cloud
|
|
73
|
+
#
|
|
74
|
+
# The hsh parameter is inserted into the chef_override_attributes.
|
|
75
|
+
# The insertion is performed as follows. If
|
|
76
|
+
# the recipe name = "foo::bar" then effectively the call is
|
|
77
|
+
#
|
|
78
|
+
# chef_override_attributes.merge! { :foo => { :bar => hsh } }
|
|
68
79
|
def recipe(recipe_name, hsh={})
|
|
69
80
|
_recipes << recipe_name unless _recipes.include?(recipe_name)
|
|
70
|
-
|
|
81
|
+
|
|
82
|
+
head = {}
|
|
83
|
+
tail = head
|
|
84
|
+
recipe_name.split("::").each do |key|
|
|
85
|
+
unless key == "default"
|
|
86
|
+
n = {}
|
|
87
|
+
tail[key] = n
|
|
88
|
+
tail = n
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
tail.replace hsh
|
|
92
|
+
|
|
93
|
+
chef_override_attributes.merge!(head) unless hsh.empty?
|
|
94
|
+
|
|
71
95
|
end
|
|
72
96
|
|
|
73
97
|
def recipes(*recipes)
|
|
@@ -81,16 +105,18 @@ You did not specify a cloud provider in your clouds.rb. Make sure you have a blo
|
|
|
81
105
|
def _recipes
|
|
82
106
|
@_recipes ||= []
|
|
83
107
|
end
|
|
84
|
-
def _attributes
|
|
85
|
-
@_attributes ||= {}
|
|
86
|
-
end
|
|
87
108
|
|
|
88
109
|
# The NEW actual chef resolver.
|
|
89
110
|
def build_tmp_dir
|
|
90
111
|
base_directory = tmp_path/"etc"/"chef"
|
|
112
|
+
FileUtils.rm_rf base_directory
|
|
91
113
|
puts "Copying the chef-repo into the base directory from #{chef_repo}"
|
|
92
114
|
FileUtils.mkdir_p base_directory/"roles"
|
|
93
115
|
if File.directory?(chef_repo)
|
|
116
|
+
if File.exist?(base_directory)
|
|
117
|
+
# First remove the directory
|
|
118
|
+
FileUtils.remove_entry base_directory, :force => true
|
|
119
|
+
end
|
|
94
120
|
FileUtils.cp_r "#{chef_repo}/.", base_directory
|
|
95
121
|
else
|
|
96
122
|
raise "#{chef_repo} chef repo directory does not exist"
|
|
@@ -114,12 +140,23 @@ log_level :info
|
|
|
114
140
|
end
|
|
115
141
|
|
|
116
142
|
def write_chef_role_json(to=tmp_path/"etc"/"chef"/"dna.json")
|
|
143
|
+
|
|
144
|
+
# Add the parent name and the name of the cloud to
|
|
145
|
+
# the role for easy access in recipes.
|
|
146
|
+
pp = {
|
|
147
|
+
:poolparty => {
|
|
148
|
+
:parent_name => parent.name,
|
|
149
|
+
:name => name,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
chef_override_attributes.merge! pp
|
|
117
154
|
ca = ChefAttribute.new({
|
|
118
155
|
:name => name,
|
|
119
156
|
:json_class => "Chef::Role",
|
|
120
157
|
:chef_type => "role",
|
|
121
158
|
:default_attributes => chef_attributes.init_opts,
|
|
122
|
-
:override_attributes =>
|
|
159
|
+
:override_attributes => chef_override_attributes.init_opts,
|
|
123
160
|
:description => description
|
|
124
161
|
})
|
|
125
162
|
ca.to_dna _recipes.map {|a| File.basename(a) }, to
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: poolparty
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ari Lerner
|
|
@@ -11,7 +11,7 @@ autorequire:
|
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
13
|
|
|
14
|
-
date: 2010-
|
|
14
|
+
date: 2010-02-18 00:00:00 -08:00
|
|
15
15
|
default_executable:
|
|
16
16
|
dependencies: []
|
|
17
17
|
|