poolparty 1.3.8 → 1.3.13
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 +1 -1
- data/bin/cloud-thrift +32 -18
- data/config/jeweler.rb +3 -2
- data/examples/thrift/thrift_example.rb +3 -1
- data/lib/cloud_providers/cloud_provider.rb +9 -0
- data/lib/cloud_providers/cloud_provider_instance.rb +7 -2
- data/lib/cloud_providers/ec2/ec2.rb +22 -7
- data/lib/cloud_providers/ec2/ec2_helpers.rb +60 -5
- data/lib/dependency_resolvers/base.rb +2 -9
- data/lib/poolparty/base.rb +2 -2
- data/lib/poolparty/cloud.rb +12 -2
- data/lib/poolparty/monitor.rb +25 -3
- data/lib/poolparty/plugins/hermes.rb +24 -11
- data/lib/poolparty/pool.rb +9 -10
- data/lib/poolparty/resource.rb +16 -13
- data/lib/poolparty/resources/file.rb +2 -2
- data/lib/poolparty/resources/link.rb +2 -1
- data/lib/proto/command_interface_handler.rb +27 -8
- data/lib/proto/command_query_handler.rb +19 -0
- data/lib/proto/poolparty.thrift +1 -0
- data/lib/provision/bootstrap_scripts/build_centos.sh +2 -0
- data/lib/provision/bootstrap_scripts/build_ubuntu.sh +1 -0
- data/tasks/poolparty.rake +24 -0
- data/test/lib/dependency_resolvers/base_test.rb +1 -1
- data/test/lib/dependency_resolvers/chef/resources/remote_directory_test.rb +2 -2
- data/test/lib/dependency_resolvers/chef/resources/remote_file_test.rb +1 -1
- data/test/lib/dependency_resolvers/chef_test.rb +3 -3
- data/test/lib/poolparty/cloud_test.rb +19 -3
- data/test/lib/poolparty/monitor_test.rb +28 -1
- data/test/lib/poolparty/resource_test.rb +14 -2
- data/test/lib/poolparty/resources/conditional_test.rb +1 -0
- data/test/lib/poolparty/resources/directory_test.rb +1 -1
- data/test/lib/poolparty/resources/file_test.rb +1 -1
- data/test/lib/poolparty/resources/user_test.rb +1 -1
- data/test/lib/proto/command_query_handler_test.rb +11 -0
- metadata +5 -3
data/VERSION.yml
CHANGED
data/bin/cloud-thrift
CHANGED
|
@@ -22,9 +22,11 @@ Usage: #{$0} #{all_options_string}
|
|
|
22
22
|
EOS
|
|
23
23
|
|
|
24
24
|
short_desc "Start the cloud thrift interface"
|
|
25
|
-
opt :port, "Start
|
|
25
|
+
opt :port, "Start on port", :type => :integer, :default => 11223
|
|
26
26
|
opt :dir, "Pid directory", :type => :string, :default => "/tmp"
|
|
27
27
|
opt :daemon, "Daemonize", :type => :bool, :default => true
|
|
28
|
+
# Query params
|
|
29
|
+
opt :host, "Query on host", :type => :string, :default => "localhost"
|
|
28
30
|
|
|
29
31
|
run do |command|
|
|
30
32
|
|
|
@@ -33,12 +35,12 @@ EOS
|
|
|
33
35
|
cmd = ARGV.shift
|
|
34
36
|
cmd = ARGV.shift if cmd == "thrift"
|
|
35
37
|
|
|
36
|
-
if %w(run start restart stop).include?(cmd)
|
|
38
|
+
if %w(run start restart stop query).include?(cmd)
|
|
37
39
|
args = [cmd]
|
|
38
40
|
args << ["--", command.argv] unless command.argv.empty?
|
|
39
41
|
args.flatten!
|
|
40
42
|
else
|
|
41
|
-
puts "You must pass one of the following: #{%w(run start restart stop).join(", ")}"
|
|
43
|
+
puts "You must pass one of the following: #{%w(run start restart stop query).join(", ")}"
|
|
42
44
|
args = ["--help"]
|
|
43
45
|
end
|
|
44
46
|
|
|
@@ -55,22 +57,34 @@ EOS
|
|
|
55
57
|
:monitor => true
|
|
56
58
|
}.merge(command.opts)
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
processor = CloudThrift::CommandInterface::Processor.new(handler)
|
|
61
|
-
transport = Thrift::ServerSocket.new( options[:port] )
|
|
62
|
-
transportFactory = Thrift::BufferedTransportFactory.new()
|
|
63
|
-
server = Thrift::SimpleServer.new(processor, transport, transportFactory)
|
|
60
|
+
if cmd == "query"
|
|
61
|
+
require "command_query_handler"
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
@loaded_clouds.each do |cld|
|
|
64
|
+
puts CommandQueryHandler.run_query(cld, ARGV.shift, ARGV, options)
|
|
65
|
+
end
|
|
66
|
+
else
|
|
67
|
+
block = Proc.new do
|
|
68
|
+
handler = CommandInterfaceHandler.new
|
|
69
|
+
processor = CloudThrift::CommandInterface::Processor.new(handler)
|
|
70
|
+
transport = Thrift::ServerSocket.new( options[:port] )
|
|
71
|
+
transportFactory = Thrift::BufferedTransportFactory.new()
|
|
72
|
+
server = Thrift::SimpleServer.new(processor, transport, transportFactory)
|
|
73
|
+
|
|
74
|
+
puts "Starting the cloud server..."
|
|
75
|
+
begin
|
|
76
|
+
server.serve()
|
|
77
|
+
rescue
|
|
78
|
+
exit 10
|
|
79
|
+
end
|
|
80
|
+
puts "done."
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
if command[:daemon]
|
|
84
|
+
Daemons.run_proc("cloud-thrift", options, &block)
|
|
85
|
+
else
|
|
86
|
+
block.call
|
|
87
|
+
end
|
|
74
88
|
end
|
|
75
89
|
|
|
76
90
|
end
|
data/config/jeweler.rb
CHANGED
|
@@ -15,7 +15,7 @@ end
|
|
|
15
15
|
s.description = "PoolParty: The easy, open-source, cross-cloud management solution"
|
|
16
16
|
s.summary = <<-EOM
|
|
17
17
|
Self-healing, auto-scaling system administration, provisioning
|
|
18
|
-
and maintaining tool that makes cloud computing
|
|
18
|
+
and maintaining tool that makes cloud computing easier.
|
|
19
19
|
EOM
|
|
20
20
|
|
|
21
21
|
s.homepage = "http://poolpartyrb.com"
|
|
@@ -25,8 +25,9 @@ end
|
|
|
25
25
|
s.test_files = Dir["test/**/test_*.rb"]
|
|
26
26
|
|
|
27
27
|
s.files = (%w(Rakefile README.rdoc License.txt VERSION.yml) + Dir["{config,examples,lib,test,tasks,script,generators,bin,vendor}/**/*"])
|
|
28
|
+
s.files += ["vendor/erlang/hermes/ebin/*.tar.gz"]
|
|
28
29
|
|
|
29
|
-
s.files.exclude 'vendor/erlang
|
|
30
|
+
s.files.exclude 'vendor/erlang/hermes'
|
|
30
31
|
s.files.exclude 'examples/thrift/**/*.beam'
|
|
31
32
|
# s.files.exclude "**/*/erl_crash.dump"
|
|
32
33
|
|
|
@@ -15,6 +15,7 @@ require "poolparty_types"
|
|
|
15
15
|
port = ARGV.pop || 11223
|
|
16
16
|
|
|
17
17
|
transport = Thrift::BufferedTransport.new(Thrift::Socket.new('localhost', port))
|
|
18
|
+
# transport = Thrift::BufferedTransport.new(Thrift::Socket.new('192.168.2.31', port))
|
|
18
19
|
# transport = Thrift::BufferedTransport.new(Thrift::Socket.new('vm', port))
|
|
19
20
|
protocol = Thrift::BinaryProtocol.new(transport)
|
|
20
21
|
|
|
@@ -22,7 +23,8 @@ client = CloudThrift::CommandInterface::Client.new(protocol)
|
|
|
22
23
|
transport.open()
|
|
23
24
|
|
|
24
25
|
cld = CloudThrift::CloudQuery.new
|
|
25
|
-
cld.name = '
|
|
26
|
+
cld.name = 'pp2'
|
|
27
|
+
# cld.name = 'monitored_app'
|
|
26
28
|
# cld.name = 'vmware'
|
|
27
29
|
|
|
28
30
|
resp = client.run_command(cld, "name", [])
|
|
@@ -68,10 +68,15 @@ module CloudProviders
|
|
|
68
68
|
raise StandardError.new("You must pass in a cloud to configure an instance") unless cloud
|
|
69
69
|
cloud.compile(self)
|
|
70
70
|
|
|
71
|
-
scp(:source => keypair.full_filepath,
|
|
72
|
-
|
|
71
|
+
# scp(:source => keypair.full_filepath,
|
|
72
|
+
# :destination => "/etc/poolparty/keys/#{keypair.basename}")
|
|
73
73
|
|
|
74
74
|
FileUtils.mkdir_p cloud.tmp_path/"etc"/"poolparty" unless File.directory?(cloud.tmp_path/"etc"/"poolparty")
|
|
75
|
+
FileUtils.mkdir_p cloud.tmp_path/"etc"/"poolparty"/"keys" unless File.directory?(cloud.tmp_path/"etc"/"poolparty"/"keys")
|
|
76
|
+
|
|
77
|
+
FileUtils.cp keypair.full_filepath, cloud.tmp_path/"etc"/"poolparty"/"keys"/keypair.basename
|
|
78
|
+
File.open(cloud.tmp_path/"etc"/"poolparty"/"cloud_name", "w") {|f| f << cloud.name }
|
|
79
|
+
|
|
75
80
|
pack_clouds_dot_rb_and_expected_directories
|
|
76
81
|
|
|
77
82
|
dputs("Rsyncing #{cloud.tmp_path/"*"}")
|
|
@@ -19,12 +19,15 @@ using :provider_name
|
|
|
19
19
|
EOM
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
require "#{File.dirname(__FILE__)}/ec2_helpers"
|
|
22
23
|
require "#{File.dirname(__FILE__)}/ec2_response"
|
|
23
24
|
require "#{File.dirname(__FILE__)}/ec2_instance"
|
|
24
25
|
|
|
25
26
|
module CloudProviders
|
|
26
27
|
class Ec2 < CloudProvider
|
|
27
28
|
|
|
29
|
+
include CloudProviders::Ec2Helpers
|
|
30
|
+
|
|
28
31
|
# Set the aws keys from the environment, or load from /etc/poolparty/env.yml if the environment variable is not set
|
|
29
32
|
def self.default_access_key
|
|
30
33
|
ENV['EC2_ACCESS_KEY'] || load_keys_from_file[:access_key]
|
|
@@ -63,7 +66,7 @@ module CloudProviders
|
|
|
63
66
|
return @aws_yml if @aws_yml && caching==true
|
|
64
67
|
return {} unless File.exists?(filename)
|
|
65
68
|
ddputs("Reading keys from file: #{filename}")
|
|
66
|
-
@aws_yml = YAML::load( open(filename).read )
|
|
69
|
+
@aws_yml = YAML::load( open(filename).read ) || {}
|
|
67
70
|
end
|
|
68
71
|
|
|
69
72
|
default_options({
|
|
@@ -88,13 +91,13 @@ module CloudProviders
|
|
|
88
91
|
:ramdisk_id => nil,
|
|
89
92
|
:availability_zone => nil,
|
|
90
93
|
:block_device_mappings => nil,
|
|
91
|
-
:elastic_ips =>
|
|
92
|
-
:
|
|
94
|
+
:elastic_ips => [], # An array of the elastic ips
|
|
95
|
+
:ebs_volumes => [] # The volume id of an ebs volume # TODO: ensure this is consistent with :block_device_mappings
|
|
93
96
|
})
|
|
94
97
|
|
|
95
98
|
|
|
96
99
|
def ec2(o={})
|
|
97
|
-
@ec2 ||= Rightscale::Ec2.new(access_key, secret_access_key, o.merge(:logger => PoolParty::PoolPartyLog, :
|
|
100
|
+
@ec2 ||= Rightscale::Ec2.new(access_key, secret_access_key, o.merge(:logger => PoolParty::PoolPartyLog, :endpoint_url => ec2_url))
|
|
98
101
|
end
|
|
99
102
|
|
|
100
103
|
# Start a new instance with the given options
|
|
@@ -114,9 +117,12 @@ module CloudProviders
|
|
|
114
117
|
availability_zone,
|
|
115
118
|
block_device_mappings
|
|
116
119
|
)
|
|
117
|
-
instances = response_array
|
|
120
|
+
instances = response_array.collect do |aws_response_hash|
|
|
118
121
|
Ec2Instance.new( Ec2Response.pp_format(aws_response_hash).merge(o) )
|
|
119
122
|
end
|
|
123
|
+
|
|
124
|
+
after_run_instance(instances)
|
|
125
|
+
|
|
120
126
|
#FIXME: This needs to deal with the case when an array is returned if max_instances > 1
|
|
121
127
|
instances.first
|
|
122
128
|
end
|
|
@@ -159,7 +165,15 @@ module CloudProviders
|
|
|
159
165
|
end
|
|
160
166
|
|
|
161
167
|
def after_compile(cld)
|
|
162
|
-
save_aws_env_to_yml(cld.tmp_path/"etc"/"poolparty"/"env.yml")
|
|
168
|
+
save_aws_env_to_yml(cld.tmp_path/"etc"/"poolparty"/"env.yml") rescue nil
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Run after all the instances are run
|
|
172
|
+
def after_run_instance(instances_list)
|
|
173
|
+
instances_list.each do |inst|
|
|
174
|
+
associate_address(inst.instance_id) if next_unused_elastic_ip
|
|
175
|
+
attach_volume(inst.instance_id) if next_unused_volume
|
|
176
|
+
end
|
|
163
177
|
end
|
|
164
178
|
|
|
165
179
|
# Read yaml file and use it to set environment variables and local variables.
|
|
@@ -171,7 +185,8 @@ module CloudProviders
|
|
|
171
185
|
|
|
172
186
|
# Save aws keys and env variables to a yaml file
|
|
173
187
|
def save_aws_env_to_yml(filename='/etc/poolparty/env.yml')
|
|
174
|
-
|
|
188
|
+
hsh = aws_hash(default_options, "/etc/poolparty/ec2")
|
|
189
|
+
File.open(filename, 'w') {|f| f<<YAML::dump(hsh) }
|
|
175
190
|
end
|
|
176
191
|
|
|
177
192
|
# Return a hash of the aws keys and environment variables
|
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
module CloudProviders
|
|
2
2
|
module Ec2Helpers
|
|
3
3
|
|
|
4
|
+
# VOLUMES
|
|
5
|
+
def attach_volume(instance_id, volume_id=next_unused_volume, device="/dev/sdh")
|
|
6
|
+
ec2.attach_volume(volume_id, instance_id, device)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def next_unused_volume
|
|
10
|
+
if all_volumes.empty?
|
|
11
|
+
nil
|
|
12
|
+
else
|
|
13
|
+
available_volumes.first
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def all_volumes
|
|
20
|
+
ebs_volumes.empty? ? [] : ec2.describe_volumes.select {|v| ebs_volumes.include?(v[:aws_id]) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def available_volumes
|
|
24
|
+
all_volumes.select {|v| v[:aws_status] == 'available' }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def unavailable_volumes
|
|
28
|
+
all_volumes.reject {|v| available_volumes.include?(v) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
public
|
|
32
|
+
|
|
33
|
+
# SECURITY GROUPS
|
|
34
|
+
def security_groups(list=[])
|
|
35
|
+
ec2.describe_security_groups(list)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
public
|
|
39
|
+
|
|
40
|
+
# ELASTIC IPS
|
|
41
|
+
|
|
4
42
|
# Associate an address with the instance using ec2
|
|
5
43
|
# Get the next_unused_elastic_ip
|
|
6
44
|
# and if there is one, associate the instance to the
|
|
7
45
|
# public ip
|
|
8
|
-
def associate_address()
|
|
9
|
-
|
|
46
|
+
def associate_address(instance_id)
|
|
47
|
+
new_ip = next_unused_elastic_ip
|
|
48
|
+
ec2.associate_address(instance_id, new_ip)
|
|
49
|
+
loop do
|
|
50
|
+
if describe_instance(:instance_id => instance_id).public_ip == new_ip
|
|
51
|
+
return new_ip
|
|
52
|
+
end
|
|
53
|
+
sleep 1
|
|
54
|
+
end
|
|
10
55
|
end
|
|
11
56
|
|
|
12
57
|
# Get the next usable elastic ip
|
|
@@ -17,13 +62,23 @@ module CloudProviders
|
|
|
17
62
|
# intersection of the unused ips and those, find the first one available
|
|
18
63
|
# and return that.
|
|
19
64
|
def next_unused_elastic_ip
|
|
20
|
-
|
|
21
|
-
if elastic_ips.empty?
|
|
65
|
+
if unusued_elastic_ips.empty?
|
|
22
66
|
nil
|
|
23
67
|
else
|
|
68
|
+
unusued_elastic_ips.first
|
|
24
69
|
end
|
|
25
70
|
end
|
|
26
|
-
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def all_elastic_ips
|
|
75
|
+
elastic_ips.empty? ? [] : ec2.describe_addresses & elastic_ips
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def unusued_elastic_ips
|
|
79
|
+
all_elastic_ips.select {|i| i[:instance_id] == nil }
|
|
80
|
+
end
|
|
81
|
+
|
|
27
82
|
# Help create a keypair for the cloud
|
|
28
83
|
# This is a helper to create the keypair and add them to the cloud for you
|
|
29
84
|
# def create_keypair
|
|
@@ -89,14 +89,7 @@ module DependencyResolvers
|
|
|
89
89
|
"#{obj.to_i}"
|
|
90
90
|
end
|
|
91
91
|
when String
|
|
92
|
-
|
|
93
|
-
when /^\d{4}$/
|
|
94
|
-
"#{obj}"
|
|
95
|
-
when /^\d{3}$/
|
|
96
|
-
"0#{obj}"
|
|
97
|
-
else
|
|
98
|
-
"\"#{obj}\""
|
|
99
|
-
end
|
|
92
|
+
"\"#{obj}\""
|
|
100
93
|
when Proc
|
|
101
94
|
obj.call # eh
|
|
102
95
|
when Array
|
|
@@ -119,4 +112,4 @@ module DependencyResolvers
|
|
|
119
112
|
|
|
120
113
|
end
|
|
121
114
|
|
|
122
|
-
end
|
|
115
|
+
end
|
data/lib/poolparty/base.rb
CHANGED
|
@@ -157,12 +157,12 @@ module PoolParty
|
|
|
157
157
|
deps_array.each do |dep_name|
|
|
158
158
|
dep = get_resource(dep_type, dep_name)
|
|
159
159
|
raise PoolPartyError.create("ResourceNotFound", "A resource required for #{resource.has_method_name}(#{resource.name}) was not found: #{dep_type}(#{dep_name}). Please make sure you've specified this in your configuration.") unless dep
|
|
160
|
-
result.add_edge!(dep, resource, dep.name) unless result.edge?(dep, resource)
|
|
160
|
+
result.add_edge!(dep, resource, dep.name) unless result.edge?(dep, resource) or result.edge?(resource, dep)
|
|
161
161
|
end
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
if on
|
|
165
|
-
result.add_edge!(resource, on, resource.name) unless result.edge?(resource, on)
|
|
165
|
+
result.add_edge!(resource, on, resource.name) unless result.edge?(resource, on) or result.edge?(on, resource)
|
|
166
166
|
else
|
|
167
167
|
result.add_vertex!(resource)
|
|
168
168
|
end
|
data/lib/poolparty/cloud.rb
CHANGED
|
@@ -196,12 +196,14 @@ module PoolParty
|
|
|
196
196
|
# the defined (or the default dependency_resolver, chef)
|
|
197
197
|
def compile(caller=nil)
|
|
198
198
|
callback :before_compile
|
|
199
|
+
cloud_provider.before_compile(self)
|
|
199
200
|
FileUtils.mkdir_p tmp_path unless File.directory?(tmp_path)
|
|
200
201
|
ddputs <<-EOE
|
|
201
202
|
Compiling cloud #{self.name} to #{tmp_path/"etc"/"#{dependency_resolver_name}"}
|
|
202
203
|
number of resources: #{ordered_resources.size}
|
|
203
204
|
EOE
|
|
204
205
|
out = dependency_resolver.compile_to(ordered_resources, tmp_path/"etc"/"#{dependency_resolver_name}", caller)
|
|
206
|
+
cloud_provider.after_compile(self)
|
|
205
207
|
callback :after_compile
|
|
206
208
|
out
|
|
207
209
|
end
|
|
@@ -230,14 +232,14 @@ Compiling cloud #{self.name} to #{tmp_path/"etc"/"#{dependency_resolver_name}"}
|
|
|
230
232
|
# vote_for(:expand) if v > 0.8
|
|
231
233
|
# end
|
|
232
234
|
def monitor(monitor_symbol, &block)
|
|
233
|
-
monitors[monitor_symbol] ||= PoolParty::Monitor.new(monitor_symbol, &block)
|
|
235
|
+
monitors[monitor_symbol.to_sym] ||= PoolParty::Monitor.new(monitor_symbol, &block)
|
|
234
236
|
end
|
|
235
237
|
|
|
236
238
|
# Run the monitor logic
|
|
237
239
|
def run_monitor(monitor_name, value)
|
|
238
240
|
mon = monitors[monitor_name.to_sym]
|
|
239
241
|
if mon
|
|
240
|
-
mon.run(value
|
|
242
|
+
mon.run(value)
|
|
241
243
|
else
|
|
242
244
|
"unhandled monitor"
|
|
243
245
|
end
|
|
@@ -248,6 +250,14 @@ Compiling cloud #{self.name} to #{tmp_path/"etc"/"#{dependency_resolver_name}"}
|
|
|
248
250
|
@monitors ||= {}
|
|
249
251
|
end
|
|
250
252
|
|
|
253
|
+
def monitor_format(mon_name, meth=nil, &block)
|
|
254
|
+
if monitors.has_key?(mon_name.to_sym)
|
|
255
|
+
monitors[mon_name.to_sym].format(meth, &block)
|
|
256
|
+
else
|
|
257
|
+
raise PoolPartyError.create("MonitorsFormattingError", "You created a monitor format for an unknown monitor. Please check and try again!")
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
251
261
|
##### Internal methods #####
|
|
252
262
|
# Methods that only the cloud itself will use
|
|
253
263
|
# and thus are private
|
data/lib/poolparty/monitor.rb
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
module PoolParty
|
|
16
16
|
class Monitor
|
|
17
17
|
|
|
18
|
-
attr_reader :name, :monitor_block
|
|
18
|
+
attr_reader :name, :monitor_block, :value_format
|
|
19
19
|
|
|
20
20
|
def initialize(monitor_name, &block)
|
|
21
21
|
msg =<<-EOE
|
|
@@ -27,7 +27,7 @@ You must pass a block with your monitor
|
|
|
27
27
|
end
|
|
28
28
|
EOE
|
|
29
29
|
raise PoolPartyError.create("MonitorDefinitionError", msg) unless block
|
|
30
|
-
@name = monitor_name
|
|
30
|
+
@name = monitor_name.to_sym
|
|
31
31
|
@monitor_block = block
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -37,11 +37,33 @@ You must pass a block with your monitor
|
|
|
37
37
|
# retrieved and return the methods available.
|
|
38
38
|
def run(val)
|
|
39
39
|
@methods = nil
|
|
40
|
-
instance_exec val, &monitor_block
|
|
40
|
+
instance_exec format_value(val), &monitor_block
|
|
41
41
|
methods
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
# Format the monitor values
|
|
45
|
+
# Set the monitor format here.
|
|
46
|
+
# The default will be to turn the value into a float
|
|
47
|
+
# but to allow other formats, call the value here, for instance:
|
|
48
|
+
# mon.format :to_s
|
|
49
|
+
# Blocks are also permitted
|
|
50
|
+
def format(meth=nil, &block)
|
|
51
|
+
@value_format ||= (meth ? meth : block)
|
|
52
|
+
end
|
|
53
|
+
|
|
44
54
|
private
|
|
55
|
+
|
|
56
|
+
# Format the value of the monitor
|
|
57
|
+
def format_value(value)
|
|
58
|
+
case value_format
|
|
59
|
+
when Proc
|
|
60
|
+
value_format.call(value)
|
|
61
|
+
when nil
|
|
62
|
+
value.to_f
|
|
63
|
+
else
|
|
64
|
+
value.send value_format
|
|
65
|
+
end
|
|
66
|
+
end
|
|
45
67
|
|
|
46
68
|
# We don't want the methods actually executing since we are executing the methods
|
|
47
69
|
# in a cloud, we just want to store the output values of the
|
|
@@ -11,22 +11,28 @@ module PoolParty
|
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
def after_loaded
|
|
14
|
+
run_dependencies
|
|
15
|
+
build_rsync_directory
|
|
14
16
|
add_unpack
|
|
17
|
+
run_dependencies
|
|
15
18
|
run_if_needed
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
def after_compile
|
|
19
|
-
run_dependencies
|
|
20
|
-
build_rsync_directory
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def run_dependencies
|
|
24
|
-
case cloud.platform
|
|
25
|
+
install_packages = case cloud.platform
|
|
25
26
|
when false
|
|
26
27
|
else
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
["erlang-nox", "erlang-dev"]
|
|
29
|
+
end
|
|
30
|
+
has_package "rrdtool"
|
|
31
|
+
has_exec "install_erlang" do
|
|
32
|
+
command "echo ''"
|
|
33
|
+
install_packages.each do |pkg|
|
|
34
|
+
has_package pkg
|
|
35
|
+
end
|
|
30
36
|
end
|
|
31
37
|
end
|
|
32
38
|
|
|
@@ -43,18 +49,25 @@ module PoolParty
|
|
|
43
49
|
etc_poolparty = cloud.tmp_path + "/etc/poolparty"
|
|
44
50
|
FileUtils.mkdir_p(etc_poolparty)
|
|
45
51
|
node_names = cloud.nodes.collect{|n| n.internal_ip || n.dns_name}.compact.collect{|n| "hermes@#{n}"}
|
|
46
|
-
contents = node_names.collect{|n| %Q{
|
|
52
|
+
contents = node_names.collect{|n| %Q{'#{n}'.}}.join("\n")
|
|
47
53
|
File.open(etc_poolparty + "/seeds.conf", "w") {|f| f.puts contents}
|
|
48
54
|
end
|
|
49
55
|
|
|
50
56
|
def add_unpack
|
|
51
|
-
has_exec "
|
|
52
|
-
:
|
|
57
|
+
has_exec "install_hermes",
|
|
58
|
+
:command => "cd /tmp/hermes && escript target_system install hermes-#{hermes_release_version} #{remote_hermes_deployed_dir}",
|
|
59
|
+
:creates => "#{remote_hermes_deployed_dir}/releases/#{hermes_release_version}",
|
|
60
|
+
:requires => get_package("erlang-dev")
|
|
61
|
+
|
|
62
|
+
has_link :name => "collectd_dir",
|
|
63
|
+
:to => "/var/lib/collectd/rrd/\#{`hostname -f`.chomp}", :source => "/var/lib/collectd/localhost",
|
|
64
|
+
:requires => [get_package("collectd")]
|
|
53
65
|
end
|
|
54
66
|
|
|
55
67
|
def run_if_needed
|
|
56
|
-
has_exec "env GEN_CLUSTER_SEED_CONFIG=/etc/poolparty/seeds.conf #{remote_hermes_deployed_dir}/bin/erl -boot #{remote_hermes_deployed_dir}/releases/#{hermes_release_version}/start -noshell -detached",
|
|
57
|
-
:not_if => "ps aux | grep -v grep | grep hermes | grep beam"
|
|
68
|
+
has_exec "env GEN_CLUSTER_SEED_CONFIG=/etc/poolparty/seeds.conf HERMES_RRD_DIRECTORY=/var/lib/collectd/localhost #{remote_hermes_deployed_dir}/bin/erl -boot #{remote_hermes_deployed_dir}/releases/#{hermes_release_version}/start -noshell -detached",
|
|
69
|
+
:not_if => "ps aux | grep -v grep | grep hermes | grep beam",
|
|
70
|
+
:requires => [get_exec("install_hermes"), get_link("collectd_dir")]
|
|
58
71
|
end
|
|
59
72
|
|
|
60
73
|
private
|
data/lib/poolparty/pool.rb
CHANGED
|
@@ -97,7 +97,7 @@ module PoolParty
|
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
def self.clouds_dot_rb_dir(n=nil)
|
|
100
|
-
File.dirname(self.clouds_dot_rb_file)
|
|
100
|
+
self.clouds_dot_rb_file ? File.dirname(self.clouds_dot_rb_file) : "./"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
# Load the default clouds.rb file
|
|
@@ -151,17 +151,16 @@ module PoolParty
|
|
|
151
151
|
# + calls the resource define_resource_methods to define the resource methods
|
|
152
152
|
# + sets up the log
|
|
153
153
|
def self.before_file_load(filepath)
|
|
154
|
-
$:.unshift(
|
|
155
|
-
|
|
154
|
+
$:.unshift(File.dirname(filepath))
|
|
155
|
+
$:.unshift("#{File.dirname(filepath)}/lib")
|
|
156
|
+
$:.unshift("#{File.dirname(filepath)}/plugins")
|
|
157
|
+
|
|
158
|
+
Dir["#{File.dirname(filepath)}/lib/*"].each {|lib_path| require lib_path }
|
|
159
|
+
Dir["#{File.dirname(filepath)}/plugins/*"].each do |plugin_path|
|
|
156
160
|
if File.directory?(plugin_path)
|
|
157
161
|
$:.unshift(plugin_path)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
require potential if File.exists?(potential)
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
elsif File.file?(plugin_path) && plugin_path.match(/.rb$/)
|
|
164
|
-
require plugin_path
|
|
162
|
+
else
|
|
163
|
+
require plugin_path if File.file?(plugin_path) && plugin_path.match(/.rb$/)
|
|
165
164
|
end
|
|
166
165
|
end
|
|
167
166
|
end
|
data/lib/poolparty/resource.rb
CHANGED
|
@@ -15,6 +15,7 @@ module PoolParty
|
|
|
15
15
|
def initialize(opts={}, extra_opts={}, exists=true, &block)
|
|
16
16
|
@exists ||= exists
|
|
17
17
|
super(opts, extra_opts, &block)
|
|
18
|
+
after_loaded_requires_parent
|
|
18
19
|
valid?
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -69,6 +70,11 @@ module PoolParty
|
|
|
69
70
|
other_resources_obj.each do |obj|
|
|
70
71
|
requires(obj)
|
|
71
72
|
end
|
|
73
|
+
else
|
|
74
|
+
# When is an object
|
|
75
|
+
# k = other_resources_obj.has_method_name
|
|
76
|
+
# dependencies[k] ||= []
|
|
77
|
+
# dependencies[k] << other_resources_obj.name
|
|
72
78
|
end
|
|
73
79
|
end
|
|
74
80
|
|
|
@@ -114,7 +120,7 @@ module PoolParty
|
|
|
114
120
|
def after_compile
|
|
115
121
|
end
|
|
116
122
|
|
|
117
|
-
def
|
|
123
|
+
def after_loaded_requires_parent
|
|
118
124
|
requires parent if parent && !parent.is_a?(PoolParty::Cloud) && !parent.is_a?(PoolParty::Pool)
|
|
119
125
|
end
|
|
120
126
|
|
|
@@ -162,8 +168,8 @@ module PoolParty
|
|
|
162
168
|
def self.define_resource_methods
|
|
163
169
|
defined_resources.each do |res|
|
|
164
170
|
next if res.method_defined?
|
|
165
|
-
ddputs "Defining resource: #{res} as #{res.has_method_name}"
|
|
166
|
-
define_resource(res)
|
|
171
|
+
ddputs "Defining resource: #{res} as #{res.has_method_name} on #{self}"
|
|
172
|
+
define_resource(res, is_base_resource_class? ? Base : self)
|
|
167
173
|
res.method_defined!
|
|
168
174
|
unless res.defined_resources.empty?
|
|
169
175
|
res.define_resource_methods
|
|
@@ -171,10 +177,14 @@ module PoolParty
|
|
|
171
177
|
end
|
|
172
178
|
end
|
|
173
179
|
|
|
180
|
+
def self.is_base_resource_class?
|
|
181
|
+
self.to_s == PoolParty::Resource.to_s
|
|
182
|
+
end
|
|
183
|
+
|
|
174
184
|
# Define the resource on the base class so it's available across all
|
|
175
185
|
# PoolParty classes that use Base
|
|
176
|
-
def self.define_resource(res)
|
|
177
|
-
|
|
186
|
+
def self.define_resource(res, base_klass=Base)
|
|
187
|
+
base_klass.class_eval <<-EOE
|
|
178
188
|
def has_#{res.has_method_name}(a={},b={},e=true, &block)
|
|
179
189
|
obj = #{res}.new(a,b,e,&block)
|
|
180
190
|
resources << obj
|
|
@@ -252,14 +262,7 @@ module PoolParty
|
|
|
252
262
|
"#{obj.to_i}"
|
|
253
263
|
end
|
|
254
264
|
when String
|
|
255
|
-
|
|
256
|
-
when /^\d{4}$/
|
|
257
|
-
"#{obj}"
|
|
258
|
-
when /^\d{3}$/
|
|
259
|
-
"0#{obj}"
|
|
260
|
-
else
|
|
261
|
-
"\"#{obj}\""
|
|
262
|
-
end
|
|
265
|
+
"\"#{obj}\""
|
|
263
266
|
when Proc
|
|
264
267
|
obj.call # eh
|
|
265
268
|
when Array
|
|
@@ -66,8 +66,8 @@ end
|
|
|
66
66
|
file = arg.first
|
|
67
67
|
@template = if File.file?(b = File.expand_path(file))
|
|
68
68
|
b
|
|
69
|
-
elsif File.file?(
|
|
70
|
-
|
|
69
|
+
elsif File.file?(d = File.expand_path(File.join(clouds_dot_rb_dir, file)))
|
|
70
|
+
d
|
|
71
71
|
elsif f = search_in_known_locations(file)
|
|
72
72
|
f
|
|
73
73
|
else
|
|
@@ -30,12 +30,13 @@ module PoolParty
|
|
|
30
30
|
|
|
31
31
|
default_options(
|
|
32
32
|
:link_type => :symbolic,
|
|
33
|
+
:source => nil,
|
|
33
34
|
:to => nil
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
def print_to_chef
|
|
37
38
|
<<-EOE
|
|
38
|
-
link "<%= name %>" do
|
|
39
|
+
link "<%= source || name %>" do
|
|
39
40
|
link_type <%= print_variable(link_type) %>
|
|
40
41
|
action :<%= exists? ? :create : :delete %>
|
|
41
42
|
to <%= print_variable(to) %>
|
|
@@ -4,7 +4,31 @@ class CommandInterfaceHandler
|
|
|
4
4
|
cr = CloudThrift::CloudResponse.new
|
|
5
5
|
cr.name = cld.name
|
|
6
6
|
cr.command = command
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
cr.response = format_response(get_response(cld, command, args))
|
|
9
|
+
|
|
10
|
+
return cr
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def cast_command(cld, command, args)
|
|
14
|
+
|
|
15
|
+
cr = CloudThrift::CloudResponse.new
|
|
16
|
+
cr.name = cld.name
|
|
17
|
+
cr.command = command
|
|
18
|
+
cr.response = format_response("Running command: #{command}(#{args})")
|
|
19
|
+
|
|
20
|
+
fork do
|
|
21
|
+
get_response(cld, command, args)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
return cr
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def get_response(cld, command, args)
|
|
31
|
+
begin
|
|
8
32
|
the_cloud = clouds[cld.name]
|
|
9
33
|
if the_cloud
|
|
10
34
|
if command.include?(".")
|
|
@@ -25,15 +49,9 @@ class CommandInterfaceHandler
|
|
|
25
49
|
end
|
|
26
50
|
rescue Exception => e
|
|
27
51
|
cr.response = "Error: #{e.inspect}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
cr.response = format_response(resp)
|
|
31
|
-
|
|
32
|
-
return cr
|
|
52
|
+
end
|
|
33
53
|
end
|
|
34
54
|
|
|
35
|
-
private
|
|
36
|
-
|
|
37
55
|
def format_response(resp)
|
|
38
56
|
case resp
|
|
39
57
|
when Array
|
|
@@ -44,4 +62,5 @@ class CommandInterfaceHandler
|
|
|
44
62
|
[resp]
|
|
45
63
|
end.map {|ele| ele.to_s }
|
|
46
64
|
end
|
|
65
|
+
|
|
47
66
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class CommandQueryHandler
|
|
2
|
+
def self.run_query(on_cloud, command, args, opts={})
|
|
3
|
+
port = opts[:port] || 11223
|
|
4
|
+
host = opts[:host] || "localhost"
|
|
5
|
+
|
|
6
|
+
transport = Thrift::BufferedTransport.new(Thrift::Socket.new(host, port))
|
|
7
|
+
protocol = Thrift::BinaryProtocol.new(transport)
|
|
8
|
+
|
|
9
|
+
client = CloudThrift::CommandInterface::Client.new(protocol)
|
|
10
|
+
transport.open()
|
|
11
|
+
|
|
12
|
+
cld = CloudThrift::CloudQuery.new
|
|
13
|
+
cld.name = on_cloud.name
|
|
14
|
+
|
|
15
|
+
ddputs("Running command: #{command} on #{cld.name} at #{host}:#{port}")
|
|
16
|
+
resp = client.run_command(cld, command, args)
|
|
17
|
+
resp.response
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/proto/poolparty.thrift
CHANGED
data/tasks/poolparty.rake
CHANGED
|
@@ -22,6 +22,30 @@ task :thrift do
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
namespace(:hermes) do
|
|
26
|
+
|
|
27
|
+
desc "Pack for distribution"
|
|
28
|
+
task :target_system do
|
|
29
|
+
erl_dir = File.dirname(__FILE__) + "/../vendor/erlang"
|
|
30
|
+
hermes_dir = File.join(erl_dir, "hermes")
|
|
31
|
+
|
|
32
|
+
puts `cd #{hermes_dir} && make target_system`
|
|
33
|
+
end
|
|
34
|
+
desc "Update hermes code"
|
|
35
|
+
task :update do
|
|
36
|
+
erl_dir = File.dirname(__FILE__) + "/../vendor/erlang"
|
|
37
|
+
hermes_dir = File.join(erl_dir, "hermes")
|
|
38
|
+
|
|
39
|
+
if File.directory?(hermes_dir)
|
|
40
|
+
`cd #{hermes_dir} && git pull origin master`
|
|
41
|
+
else
|
|
42
|
+
FileUtils.mkdir_p erl_dir
|
|
43
|
+
r = "git clone git://github.com/auser/hermes.git #{hermes_dir}"
|
|
44
|
+
Kernel.system r
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
25
49
|
namespace(:pp) do
|
|
26
50
|
task :build_gem => ["poolparty:vendor:setup", "poolparty:vendor:update", :gemspec, :build]
|
|
27
51
|
|
|
@@ -26,10 +26,10 @@ class RemoteDirectoryResourceTest < Test::Unit::TestCase
|
|
|
26
26
|
remote_directory "/tmp/remote_something" do
|
|
27
27
|
source "something"
|
|
28
28
|
files_backup 10
|
|
29
|
-
files_mode 0644
|
|
29
|
+
files_mode "0644"
|
|
30
30
|
action :create
|
|
31
31
|
recursive false
|
|
32
|
-
mode 0755
|
|
32
|
+
mode "0755"
|
|
33
33
|
owner "nobody"
|
|
34
34
|
group "nobody"
|
|
35
35
|
files_owner "root"
|
|
@@ -54,7 +54,7 @@ class ChefTest < Test::Unit::TestCase
|
|
|
54
54
|
|
|
55
55
|
def test_compile_to_the_recipes
|
|
56
56
|
@base.compile_to(@resources[:files], test_dir)
|
|
57
|
-
assert_equal "template \"/etc/motd\" do\n source \"/etc/motd.erb\"\n action :create\n backup 5\n mode 0644\n owner \"root\"\nend\n", open(@cookboox_directory/"recipes"/"default.rb").read
|
|
57
|
+
assert_equal "template \"/etc/motd\" do\n source \"/etc/motd.erb\"\n action :create\n backup 5\n mode \"0644\"\n owner \"root\"\nend\n", open(@cookboox_directory/"recipes"/"default.rb").read
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def test_compile_the_recipes
|
|
@@ -78,14 +78,14 @@ template "/etc/motd" do
|
|
|
78
78
|
source "/etc/motd.erb"
|
|
79
79
|
action :create
|
|
80
80
|
backup 5
|
|
81
|
-
mode 0644
|
|
81
|
+
mode "0644"
|
|
82
82
|
owner "root"
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
directory "/etc/poolparty" do
|
|
86
86
|
action :create
|
|
87
87
|
recursive true
|
|
88
|
-
mode 0644
|
|
88
|
+
mode "0644"
|
|
89
89
|
owner "root"
|
|
90
90
|
group "root"
|
|
91
91
|
end
|
|
@@ -134,7 +134,6 @@ class CloudTest < Test::Unit::TestCase
|
|
|
134
134
|
assert_equal 22, clouds["noneity"].ssh_port
|
|
135
135
|
end
|
|
136
136
|
|
|
137
|
-
|
|
138
137
|
def test_children_getting_parent_options
|
|
139
138
|
clear!
|
|
140
139
|
pool "outside" do
|
|
@@ -159,13 +158,24 @@ class CloudTest < Test::Unit::TestCase
|
|
|
159
158
|
configure if v < 0.2
|
|
160
159
|
vote_for(:expand) if v > 1.1
|
|
161
160
|
end
|
|
161
|
+
|
|
162
|
+
monitor :load do |a|
|
|
163
|
+
# [0.42 0.43 0.37]
|
|
164
|
+
vote_for(:expand) if a[0] > 0.8
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
monitor_format :load do |d|
|
|
168
|
+
d.split(",").map {|ele| ele.to_f }
|
|
169
|
+
end
|
|
170
|
+
|
|
162
171
|
end
|
|
163
172
|
end
|
|
164
173
|
|
|
165
|
-
assert_equal
|
|
166
|
-
assert_equal [:cpu], clouds["monitor_app"].monitors.map {|m,v| v.name }
|
|
174
|
+
assert_equal 2, clouds["monitor_app"].monitors.size
|
|
175
|
+
assert_equal [:cpu, :load], clouds["monitor_app"].monitors.map {|m,v| v.name }
|
|
167
176
|
assert_equal({:configure => []}, clouds["monitor_app"].run_monitor("cpu", "0.1"))
|
|
168
177
|
assert_equal({:vote_for => [:expand]}, clouds["monitor_app"].run_monitor("cpu", "1.4"))
|
|
178
|
+
assert_equal({:vote_for => [:expand]}, clouds["monitor_app"].run_monitor("load", "0.98, 0.23, 0.1"))
|
|
169
179
|
end
|
|
170
180
|
|
|
171
181
|
def test_add_monitoring_stack_if_needed
|
|
@@ -183,5 +193,11 @@ class CloudTest < Test::Unit::TestCase
|
|
|
183
193
|
assert_equal 1, clouds["app_cloud"].monitors.size
|
|
184
194
|
|
|
185
195
|
clouds["app_cloud"].compile
|
|
196
|
+
|
|
197
|
+
compile_dir = clouds["app_cloud"].tmp_path/"etc"/"chef"/"cookbooks"/"poolparty"
|
|
198
|
+
recipe_file = compile_dir/"recipes"/"default.rb"
|
|
199
|
+
recipe_contents = open(recipe_file).read
|
|
200
|
+
|
|
201
|
+
assert_match /install hermes/, recipe_contents
|
|
186
202
|
end
|
|
187
203
|
end
|
|
@@ -3,7 +3,7 @@ require "#{File.dirname(__FILE__)}/../../test_helper"
|
|
|
3
3
|
class MonitorTest < Test::Unit::TestCase
|
|
4
4
|
|
|
5
5
|
def setup
|
|
6
|
-
@mon = PoolParty::Monitor.new(
|
|
6
|
+
@mon = PoolParty::Monitor.new("cpu-idle") do |c|
|
|
7
7
|
vote_for(:expand) if c > 0.8
|
|
8
8
|
configure if c < 0.1
|
|
9
9
|
end
|
|
@@ -27,4 +27,31 @@ class MonitorTest < Test::Unit::TestCase
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def test_formatting_input
|
|
31
|
+
mon = PoolParty::Monitor.new("memory-used") {|c| long if c.length > 2}
|
|
32
|
+
mon.format(:to_s)
|
|
33
|
+
assert_equal({:long => []}, mon.run("hellllllllooooo world"))
|
|
34
|
+
|
|
35
|
+
mon = PoolParty::Monitor.new("memory-used") do |c|
|
|
36
|
+
long if c.length > 2
|
|
37
|
+
short if c.length < 2
|
|
38
|
+
end
|
|
39
|
+
mon.format(:to_a)
|
|
40
|
+
assert_equal({:long => []}, mon.run(%w(1 2 3 4)))
|
|
41
|
+
assert_equal({:short => []}, mon.run(%w(1)))
|
|
42
|
+
|
|
43
|
+
mon = PoolParty::Monitor.new("memory-used") do |saying, to|
|
|
44
|
+
if saying == "hello"
|
|
45
|
+
hello
|
|
46
|
+
else
|
|
47
|
+
goodbye
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
mon.format {|d|return *d.split(",")}
|
|
52
|
+
|
|
53
|
+
assert_equal({:hello => []}, mon.run("hello, world"))
|
|
54
|
+
assert_equal({:short => []}, mon.run("good day"))
|
|
55
|
+
end
|
|
56
|
+
|
|
30
57
|
end
|
|
@@ -73,8 +73,6 @@ class ResourceTest < Test::Unit::TestCase
|
|
|
73
73
|
assert_equal @inst.print_variable(:a), ":a"
|
|
74
74
|
assert_equal @inst.print_variable({:a => "a"}), ":a => \"a\""
|
|
75
75
|
assert_equal @inst.print_variable(644), "644"
|
|
76
|
-
assert_equal @inst.print_variable("0755"), "0755"
|
|
77
|
-
assert_equal @inst.print_variable("755"), "0755"
|
|
78
76
|
assert_equal @inst.print_variable(@inst), @inst.to_s
|
|
79
77
|
assert_equal @inst.print_variable(nil), nil
|
|
80
78
|
end
|
|
@@ -147,4 +145,18 @@ class ResourceTest < Test::Unit::TestCase
|
|
|
147
145
|
end
|
|
148
146
|
end
|
|
149
147
|
|
|
148
|
+
def test_a_subclassed_resource_has_the_method_of_the_subclassed_resource
|
|
149
|
+
pool "oblong" do
|
|
150
|
+
cloud "piece" do
|
|
151
|
+
fake_plugin do
|
|
152
|
+
has_subclassed "box"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
assert_equal PoolParty::Resources::FakePlugin, clouds["piece"].resources.first.class
|
|
158
|
+
assert_equal PoolParty::Resources::FakeSubclassedPlugin, clouds["piece"].resources.first.resources[0].class
|
|
159
|
+
assert_equal 1, clouds["piece"].resources.first.resources[0].resources.size
|
|
160
|
+
end
|
|
161
|
+
|
|
150
162
|
end
|
|
@@ -12,7 +12,7 @@ class DirectoryResourceTest < Test::Unit::TestCase
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
should "have the directory method denoted by has_method_name" do
|
|
15
|
-
str = "directory \"/etc/poolparty\" do\n action :create\n recursive true\n mode 0644\n owner \"root\"\n group \"root\"\nend\n"
|
|
15
|
+
str = "directory \"/etc/poolparty\" do\n action :create\n recursive true\n mode \"0644\"\n owner \"root\"\n group \"root\"\nend\n"
|
|
16
16
|
assert_equal str, @base.compile(@res)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -13,7 +13,7 @@ class DirectoryResourceTest < Test::Unit::TestCase
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
should "have the template method denoted by has_method_name" do
|
|
16
|
-
str = "template \"/etc/poolparty/lyrics\" do\n source \"/etc/poolparty/lyrics.erb\"\n action :create\n backup 5\n mode 0644\n owner \"root\"\nend\n"
|
|
16
|
+
str = "template \"/etc/poolparty/lyrics\" do\n source \"/etc/poolparty/lyrics.erb\"\n action :create\n backup 5\n mode \"0644\"\n owner \"root\"\nend\n"
|
|
17
17
|
|
|
18
18
|
assert_equal str, @base.compile(@res)
|
|
19
19
|
assert_equal "I'm just a file, a lonely little file in the world", open(@cookboox_directory/"templates"/"default"/"etc"/"poolparty"/"lyrics.erb").read
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../test_helper"
|
|
2
|
+
$:.unshift("#{File.dirname(__FILE__)}/../../../lib/proto")
|
|
3
|
+
require "command_query_handler"
|
|
4
|
+
|
|
5
|
+
class CommandQueryHandlerTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
def test_has_run_query_command
|
|
8
|
+
assert CommandQueryHandler.respond_to?(:run_query)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
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.3.
|
|
4
|
+
version: 1.3.13
|
|
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: 2009-09-
|
|
14
|
+
date: 2009-09-04 00:00:00 -07:00
|
|
15
15
|
default_executable:
|
|
16
16
|
dependencies: []
|
|
17
17
|
|
|
@@ -208,6 +208,7 @@ files:
|
|
|
208
208
|
- lib/poolparty/resources/user.rb
|
|
209
209
|
- lib/poolparty/resources/variable.rb
|
|
210
210
|
- lib/proto/command_interface_handler.rb
|
|
211
|
+
- lib/proto/command_query_handler.rb
|
|
211
212
|
- lib/proto/gen-erl/commandInterface_thrift.erl
|
|
212
213
|
- lib/proto/gen-erl/commandInterface_thrift.hrl
|
|
213
214
|
- lib/proto/gen-erl/poolparty_constants.hrl
|
|
@@ -335,6 +336,7 @@ files:
|
|
|
335
336
|
- test/lib/poolparty/resources/service_test.rb
|
|
336
337
|
- test/lib/poolparty/resources/user_test.rb
|
|
337
338
|
- test/lib/poolparty/resources/variable_test.rb
|
|
339
|
+
- test/lib/proto/command_query_handler_test.rb
|
|
338
340
|
- test/lib/provision/base_test.rb
|
|
339
341
|
- test/lib/provision/bootstrapper_test.rb
|
|
340
342
|
- test/test_helper.rb
|
|
@@ -1142,7 +1144,7 @@ rubyforge_project:
|
|
|
1142
1144
|
rubygems_version: 1.3.4
|
|
1143
1145
|
signing_key:
|
|
1144
1146
|
specification_version: 3
|
|
1145
|
-
summary: Self-healing, auto-scaling system administration, provisioning and maintaining tool that makes cloud computing
|
|
1147
|
+
summary: Self-healing, auto-scaling system administration, provisioning and maintaining tool that makes cloud computing easier.
|
|
1146
1148
|
test_files:
|
|
1147
1149
|
- test/test_helper.rb
|
|
1148
1150
|
- test/test_methods.rb
|