auser-poolparty 1.2.8 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. data/VERSION.yml +1 -1
  2. data/bin/cloud-list +4 -4
  3. data/bin/cloud-provision +2 -0
  4. data/bin/cloud-ssh +1 -1
  5. data/bin/install-poolparty +1 -1
  6. data/examples/fairchild.rb +26 -17
  7. data/examples/metavirt_cloud.rb +2 -4
  8. data/lib/poolparty.rb +2 -7
  9. data/lib/poolparty/core/array.rb +1 -1
  10. data/lib/poolparty/core/exception.rb +1 -1
  11. data/lib/poolparty/core/hash.rb +12 -5
  12. data/lib/poolparty/core/integer.rb +11 -0
  13. data/lib/poolparty/core/object.rb +14 -0
  14. data/lib/poolparty/core/string.rb +6 -1
  15. data/lib/poolparty/core/time.rb +6 -0
  16. data/lib/poolparty/extra/duration.rb +96 -0
  17. data/lib/poolparty/helpers/binary.rb +1 -1
  18. data/lib/poolparty/modules/cloud_resourcer.rb +1 -1
  19. data/lib/poolparty/modules/definable_resource.rb +5 -7
  20. data/lib/poolparty/modules/output.rb +2 -2
  21. data/lib/poolparty/monitors/base_monitor.rb +17 -0
  22. data/lib/poolparty/net/init.rb +4 -11
  23. data/lib/poolparty/net/remote_instance.rb +5 -0
  24. data/lib/poolparty/net/remoter/connections.rb +14 -11
  25. data/lib/poolparty/net/remoter/interactive.rb +13 -2
  26. data/lib/poolparty/net/remoter_base.rb +9 -4
  27. data/lib/poolparty/net/remoter_bases/ec2/ec2.rb +50 -35
  28. data/lib/poolparty/net/remoter_bases/ec2/ec2_remote_instance.rb +46 -5
  29. data/lib/poolparty/net/remoter_bases/ec2/ec2_response_object.rb +57 -1
  30. data/lib/poolparty/plugins/apache2/apache.rb +13 -160
  31. data/lib/poolparty/plugins/apache2/passenger_site.rb +86 -0
  32. data/lib/poolparty/plugins/apache2/php5.rb +40 -0
  33. data/lib/poolparty/plugins/apache2/virtual_host.rb +53 -0
  34. data/lib/poolparty/plugins/authorized_key.rb +2 -2
  35. data/lib/poolparty/plugins/bind.rb +5 -6
  36. data/lib/poolparty/plugins/{chef.rb → chef/chef.rb} +22 -18
  37. data/lib/poolparty/plugins/{chef_deploy.rb → chef/chef_deploy.rb} +20 -19
  38. data/lib/poolparty/plugins/deploy_directory.rb +2 -3
  39. data/lib/poolparty/plugins/gem_package.rb +6 -12
  40. data/lib/poolparty/plugins/git.rb +22 -7
  41. data/lib/poolparty/{base_packages → plugins}/haproxy.rb +2 -2
  42. data/lib/poolparty/{base_packages → plugins}/heartbeat.rb +7 -7
  43. data/lib/poolparty/plugins/line_in_file.rb +4 -2
  44. data/lib/poolparty/plugins/plugin_template.rb +13 -0
  45. data/lib/poolparty/{base_packages/poolparty.rb → plugins/poolparty_base_packages.rb} +2 -2
  46. data/lib/poolparty/plugins/rails_deploy.rb +2 -3
  47. data/lib/poolparty/{base_packages → plugins}/ruby.rb +3 -3
  48. data/lib/poolparty/{base_packages → plugins}/runit.rb +3 -3
  49. data/lib/poolparty/plugins/svn.rb +8 -6
  50. data/lib/poolparty/poolparty/cloud.rb +5 -8
  51. data/lib/poolparty/poolparty/default.rb +1 -1
  52. data/lib/poolparty/poolparty/plugin.rb +36 -15
  53. data/lib/poolparty/poolparty/pool.rb +6 -2
  54. data/lib/poolparty/poolparty/poolparty_base_class.rb +5 -11
  55. data/lib/poolparty/poolparty/resource.rb +2 -1
  56. data/lib/poolparty/poolparty/service.rb +6 -8
  57. data/lib/poolparty/provision/dr_configure.rb +3 -3
  58. data/lib/poolparty/verification/verifier_base.rb +10 -0
  59. data/spec/bin/server-list-active_spec.rb +1 -3
  60. data/spec/poolparty/core/string_spec.rb +1 -1
  61. data/spec/poolparty/dependency_resolver/chef_resolver_spec.rb +0 -2
  62. data/spec/poolparty/dependency_resolver/dependency_resolver_cloud_extensions_spec.rb +16 -13
  63. data/spec/poolparty/extra/deployments_spec.rb +68 -68
  64. data/spec/poolparty/net/remoter_bases/ec2_spec.rb +1 -0
  65. data/spec/poolparty/plugins/deploydirectory_spec.rb +64 -51
  66. data/spec/poolparty/poolparty/cloud_spec.rb +21 -19
  67. data/spec/poolparty/poolparty/configurers/files/ruby_basic.rb +1 -1
  68. data/spec/poolparty/poolparty/configurers/files/ruby_plugins.rb +1 -1
  69. data/spec/poolparty/{base_packages → poolparty}/haproxy_spec.rb +1 -1
  70. data/spec/poolparty/{base_packages → poolparty}/heartbeat_spec.rb +1 -1
  71. data/spec/poolparty/poolparty/plugin_model_spec.rb +6 -13
  72. data/spec/poolparty/poolparty/plugin_spec.rb +7 -7
  73. data/spec/poolparty/poolparty/resource_spec.rb +15 -5
  74. data/spec/poolparty/poolparty/test_plugins/webserver.rb +27 -23
  75. data/test/fixtures/metavirt_cloud.json +1 -0
  76. data/test/poolparty/dependency_resolver/puppet_resolver_test.rb +0 -5
  77. data/test/poolparty/modules/cloud_dsl_test.rb +1 -1
  78. data/test/poolparty/monitors/test_base_monitor.rb +17 -0
  79. data/test/poolparty/monitors/test_monitor_rack.rb +39 -0
  80. data/test/poolparty/net/remoter_base_test.rb +18 -0
  81. data/test/poolparty/plugins/chef_deploy_test.rb +1 -1
  82. data/test/poolparty/plugins/rails_deploy_test.rb +3 -3
  83. data/test/poolparty/poolparty/cloud_test.rb +27 -2
  84. data/test/poolparty/poolparty/isolated_cloud_test.rb +25 -0
  85. data/test/poolparty/poolparty/plugin_test.rb +9 -8
  86. data/test/poolparty/poolparty/schema_test.rb +13 -0
  87. data/test/poolparty/verification/verify_test.rb +4 -0
  88. data/test/test_helper.rb +10 -3
  89. data/test/test_methods.rb +11 -0
  90. data/vendor/gems/dslify/test/dslify_test.rb +28 -0
  91. metadata +29 -15
  92. data/lib/poolparty/extra/deployments.rb +0 -31
  93. data/lib/poolparty/poolparty/plugin_model.rb +0 -46
@@ -5,17 +5,10 @@ class Object
5
5
  end
6
6
  end
7
7
 
8
- # Load the core net libraries. These are neccessary for any of the remoter_bases to function.
9
- %w(remote_instance remoter_base).each do |file|
10
- require File.join(::File.dirname(__FILE__),file+'.rb')
11
- end
12
- #
13
- # # Register available remoter_bases
14
- # Dir["#{::File.dirname(__FILE__)}/remoter_bases/*/*.rb"].each do |base|
15
- # name = File.join(::File.basename(base, ::File.extname(base)))
16
- # require base
17
- # end
18
-
8
+ # Load the core net libraries.
9
+ # These are neccessary for any of the remoter_bases to function.
10
+ require ::File.join(::File.dirname(__FILE__),'remoter_base.rb')
11
+ require ::File.join(::File.dirname(__FILE__),'remote_instance.rb')
19
12
 
20
13
  Dir["#{::File.dirname(__FILE__)}/remoter_bases/*/*.rb"].each do |base|
21
14
  name = ::File.basename(base, ::File.extname(base))
@@ -7,6 +7,7 @@ module PoolParty
7
7
  dsl_methods :name, # Name of the remote instance (internal usage)
8
8
  :ip, # Ip of the remote instance
9
9
  :internal_ip, # Internal ip of the remote instance
10
+ :public_ip,
10
11
  :status # Status of the remote instance
11
12
 
12
13
  def initialize(opts={})
@@ -64,6 +65,10 @@ module PoolParty
64
65
  "#{name}\t#{ip}\t#{instance_id rescue ""}"
65
66
  end
66
67
 
68
+ def has_key?(key)
69
+ dsl_options.has_key?(key)
70
+ end
71
+
67
72
  # Class method to disect a neighborhood line
68
73
  def self.hash_from_s(s)
69
74
  arr = s.split("\t")
@@ -9,7 +9,7 @@ module PoolParty
9
9
  def target_host(dns_or_ip=nil)
10
10
  dns_or_ip ? @target_host=dns_or_ip : @target_host
11
11
  end
12
-
12
+
13
13
  # Simply shell out and call ssh, simple, reliable and fewest dependencies, but slow
14
14
  def simplest_run_remote(host=target_host, command=[], extra_ssh_ops={})
15
15
  command = command.compact.join(' && ') if command.is_a? Array
@@ -34,19 +34,20 @@ module PoolParty
34
34
  }.merge(opts)
35
35
  o.collect{ |k,v| "#{k} #{v}"}.join(' ')
36
36
  end
37
-
37
+
38
38
  def rsync( source_path, destination_path, rsync_opts=['-v -a'] )
39
39
  dputs "rsync -e 'ssh #{ssh_options}' #{rsync_opts.join(' ')} #{source_path} root@#{target_host}:#{destination_path}"
40
40
  out = %x{ rsync -e 'ssh #{ssh_options}' #{rsync_opts.join(' ')} #{source_path} root@#{target_host}:#{destination_path} }
41
41
  puts out if debugging?
42
42
  end
43
-
43
+
44
+ # Run commands on the local machine, i.e. your laptop, not the server
44
45
  def run_local(commands)
45
46
  commands.each do |cmd|
46
47
  puts `#{cmd}`
47
48
  end
48
49
  end
49
-
50
+
50
51
  def commands
51
52
  @commands ||= Array.new
52
53
  end
@@ -60,15 +61,17 @@ module PoolParty
60
61
  end
61
62
 
62
63
  def netssh(cmds=[], opts={})
63
- user = opts.delete(:user) || user #rescue 'root'
64
+ user = opts.delete(:user) || 'root' #user rescue 'root'
64
65
  host = opts.delete(:host) || target_host
65
- ssh_options_hash = {:keys => [keypair.full_filepath],
66
+ ssh_options_hash = {:keys => [keypair.full_filepath],
66
67
  :auth_methods => 'publickey',
67
- :paranoid => false
68
+ :paranoid => false,
69
+ :timeout => 3.minutes,
70
+ :user => user
68
71
  }.merge(opts)
69
-
70
- # Start the connection
71
- Net::SSH.start(host, user, ssh_options_hash) do |ssh|
72
+ ssh_options_hash[:verbose]=:debug if debugging?
73
+ puts "connecting to ssh with options = #{ssh_options_hash.inspect}"
74
+ Net::SSH.start(host, user, ssh_options_hash) do |ssh|
72
75
  cmds.each do |command|
73
76
  ssh.exec!(command) do |ch, stream, data|
74
77
  if stream == :stdout
@@ -82,7 +85,7 @@ module PoolParty
82
85
  end
83
86
 
84
87
 
85
- ##########################################################################################################
88
+ ##########################################################################################
86
89
  # TODO: Delete deprecated commands below here
87
90
 
88
91
  def rsync_storage_files_to_command(remote_instance)
@@ -2,8 +2,19 @@ module PoolParty
2
2
  module Remote
3
3
 
4
4
  # Select a list of instances based on their status
5
- def nodes(hsh={}, with_neighborhood_default=true)
6
- list_of_instances(with_neighborhood_default).select_with_hash(hsh)
5
+ def nodes(hsh={}, with_neighborhood_default=false)
6
+ if with_neighborhood_default
7
+ list_of_instances(with_neighborhood_default).select_with_hash(hsh)
8
+ else
9
+ key_condition = {:key_name => (hsh[:key_name] ||self.key_name || keypair.basename) }
10
+ # if hsh.delete(:uncached)
11
+ # @nodes = describe_instances.select_with_hash(conditions)
12
+ # else
13
+ # @nodes ||= describe_instances.select_with_hash(conditions)
14
+ # end
15
+ results = describe_instances.select_with_hash(key_condition)
16
+ results.select_with_hash(hsh)
17
+ end
7
18
  end
8
19
 
9
20
  # Select the list of instances, either based on the neighborhoods
@@ -33,7 +33,7 @@ module PoolParty
33
33
  def initialize(opts={}, &block)
34
34
  opts.each {|k,v| opts[k] = v.call if v.respond_to?(:call) }
35
35
  set_vars_from_options opts
36
- instance_eval &block if block
36
+ instance_eval(&block) if block
37
37
  end
38
38
 
39
39
  def cloud(n=nil)
@@ -58,14 +58,13 @@ module PoolParty
58
58
  # end
59
59
 
60
60
  def self.available_bases
61
- @available_bases ||= []
61
+ @available_bases ||= []
62
62
  end
63
63
  def self.inherited(arg)
64
64
  base_name = "#{arg}".downcase.top_level_class.to_sym
65
65
  (available_bases << base_name) unless available_bases.include?(base_name)
66
- (remote_bases << base_name) unless remote_bases.include?(base_name)
66
+ (remote_bases << base_name) unless remote_bases.include?(base_name) #TODO: Deprecate
67
67
  end
68
-
69
68
 
70
69
  # def method_missing(meth, *args, &block)
71
70
  # if @cloud
@@ -115,8 +114,14 @@ module PoolParty
115
114
 
116
115
  # TODO: Rename and modularize the @inst.status =~ /pending/ so that it works on all
117
116
  # remoter_bases
117
+ # 1.) Launches a new instance,
118
+ # 2.) Waits for the instance to get an ip address
119
+ # 3.) Waits for port 22 to be open
120
+ # 4.) Calls call_after_launch_instance callbacks
121
+ # 5.) Executes passes block, if any
118
122
  def launch_instance!(o={}, &block)
119
123
  @cloud = clouds[o[:cloud_name] || o[:name]]
124
+ o[:keypair_name] = @cloud.keypair.basename
120
125
  @inst = launch_new_instance!( dsl_options.merge(o) )
121
126
  sleep(2)
122
127
 
@@ -35,30 +35,33 @@ end
35
35
  module PoolParty
36
36
  module Remote
37
37
  class Ec2 < Remote::RemoterBase
38
+ require "#{::File.dirname(__FILE__)}/ec2_remote_instance"
38
39
 
39
40
  dsl_methods :elastic_ips, # An array of the elastic ips
40
41
  :ebs_volume_id # The volume id of an ebs volume
41
42
 
42
43
  default_options({
43
- :image_id => 'ami-bf5eb9d6',
44
+ :image_id => 'ami-bf5eb9d6',
45
+ :ami => 'ami-bf5eb9d6', #Deprecated, but here for backwards compatability
44
46
  # :key_name => ::File.basename(keypair.is_a?(String) ? keypair : keypair.full_filepath),
45
- :instance_type => 'm1.small', # or 'm1.large', 'm1.xlarge', 'c1.medium', or 'c1.xlarge'
46
- :addressing_type => "public",
47
- :availability_zone => "us-east-1a",
48
- :access_key => ENV['AWS_ACCESS_KEY'],
49
- :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
50
- :security_group => ["default"],
51
- :keypair_name =>nil
47
+ :instance_type => 'm1.small', # or 'm1.large', 'm1.xlarge', 'c1.medium', or 'c1.xlarge'
48
+ :addressing_type => "public",
49
+ :availability_zone => "us-east-1a",
50
+ :access_key => ENV['AWS_ACCESS_KEY'],
51
+ :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
52
+ :security_group => ["default"],
53
+ :keypair_name => nil,
54
+ :key_name => nil
52
55
  })
53
56
 
54
57
  # alias to image_id
55
- def ami(n=nil)
56
- if n.nil?
57
- image_id
58
- else
59
- image_id n
60
- end
61
- end
58
+ # def ami(n=nil)
59
+ # if n.nil?
60
+ # image_id
61
+ # else
62
+ # image_id n
63
+ # end
64
+ # end
62
65
 
63
66
  # Requires a hash of options
64
67
  def self.launch_new_instance!(o)
@@ -69,7 +72,8 @@ module PoolParty
69
72
  # Start a new instance with the given options
70
73
  def launch_new_instance!(o={})
71
74
  set_vars_from_options o
72
- raise "You must pass a keypair to launch an instance, or else you will not be able to login. options = #{o.inspect}" if !keypair
75
+ keypair_name ||= o[:keypair_name] || keypair || (clouds[o[:cloud_name]].keypair.basename if o[:cloud_name])
76
+ raise "You must pass a keypair to launch an instance, or else you will not be able to login. options = #{o.inspect}" if !keypair_name
73
77
  o.merge!( dsl_options.merge(:key_name=>keypair_name) )
74
78
  instance = ec2(o).run_instances(o)
75
79
  begin
@@ -81,36 +85,47 @@ module PoolParty
81
85
  end
82
86
  h
83
87
  end
88
+
84
89
  # Terminate an instance by id
85
90
  def terminate_instance!(o={})
86
91
  ec2(o).terminate_instances(:instance_id => o[:instance_id])
87
92
  end
93
+
88
94
  # Describe an instance's status
89
95
  def describe_instance(o={})
90
- return describe_instances.first if o[:instance_id].nil?
96
+ return describe_instances.first if o.empty? || o[:instance_id].nil?
91
97
  describe_instances.detect {|a| a[:name] == o[:instance_id] || a[:ip] == o[:instance_id] || a[:instance_id] == o[:instance_id] }
92
98
  end
93
- # TODO: Clean up this method and remove hostnames
99
+
94
100
  def describe_instances(o={})
95
- id = 0
96
- set_vars_from_options(dsl_options.merge(o))
97
- get_instances_description(dsl_options).each_with_index do |h,i|
98
- if h[:status] == "running"
99
- inst_name = id == 0 ? "master" : "node#{id}"
100
- id += 1
101
- else
102
- inst_name = "#{h[:status]}_node#{i}"
103
- end
104
- h.merge!({
105
- :name => inst_name,
106
- :hostname => h[:ip],
107
- :ip => h[:ip].convert_from_ec2_to_ip,
108
- :index => i, #TODO get the instance id from the aws result instead
109
- :launching_time => (h[:launching_time])
110
- })
111
- end.compact.sort {|a,b| a[:index] <=> b[:index] }
101
+ ec2_instants = EC2ResponseObject.describe_instances(ec2.describe_instances)
102
+ insts = ec2_instants.select_with_hash(o) if !o.empty?
103
+ ec2_remote_instances = ec2_instants.collect{|i| Ec2RemoteInstance.new(i)}
104
+ ec2_remote_instances.sort {|a,b| a[:ami_launch_index] <=> b[:ami_launch_index] }
112
105
  end
113
106
 
107
+ # TODO: Clean up this method and remove hostnames
108
+ # def describe_instances(o={})
109
+ # id = 0
110
+ # set_vars_from_options(dsl_options.merge(o))
111
+ # get_instances_description(dsl_options).each_with_index do |h,i|
112
+ # if h[:status] == "running"
113
+ # inst_name = id == 0 ? "master" : "node#{id}"
114
+ # id += 1
115
+ # else
116
+ # inst_name = "#{h[:status]}_node#{i}"
117
+ # end
118
+ # h.merge!({
119
+ # :name => inst_name,
120
+ # :hostname => h[:ip],
121
+ # :ip => h[:ip].convert_from_ec2_to_ip,
122
+ # # :internal_ip => h.ip
123
+ # :index => i, #TODO get the instance id from the aws result instead
124
+ # :launching_time => (h[:launching_time])
125
+ # })
126
+ # end.compact.sort {|a,b| a[:index] <=> b[:index] }
127
+ # end
128
+
114
129
  # ===================================
115
130
  # = Ec2 Specific methods below here =
116
131
  # ===================================
@@ -3,10 +3,24 @@ module PoolParty
3
3
  module Remote
4
4
  class Ec2RemoteInstance < RemoteInstance
5
5
  include Dslify
6
+ include Remote
6
7
 
7
- attr_reader :uniquely_identifiable_by, :found_at
8
+ default_options({
9
+ # :launching_time => Time.now,
10
+ :dns_name => nil,
11
+ :private_dns_name => nil,
12
+ :key_name => nil,
13
+ :kernel_id => nil,
14
+ :ramdisk_id => nil,
15
+ :launch_time => nil,
16
+ :instance_id => nil,
17
+ :ami_launch_index => nil,
18
+ :ip => nil,
19
+ :public_ip => nil,
20
+ :internal_ip => nil
21
+ }.merge(Remote::Ec2.default_options) )
8
22
 
9
- default_options( {:launching_time => Time.now}.merge(Remote::Ec2.default_options) )
23
+ @uniquely_identifiable_by = [:ip, :name, :dns_name, :instance_id]
10
24
 
11
25
  # A new instance will be created from the passed in hash.
12
26
  # This hash of passed in values will be converted to methods on this instance.
@@ -14,11 +28,38 @@ module PoolParty
14
28
  # If an instance is found, this instance's properties will be set to the properties provided
15
29
  # If the found instance has properties of the same key as the provided options, the found instance's values will override the passed in options
16
30
  def initialize(opts={})
17
- @uniquely_identifiable_by = [:ip, :name, :dns_name, :instance_id]
18
- @original_options = opts
19
- super(opts)
31
+ set_vars_from_options(opts) if opts.is_a?(Hash)
32
+ @target_host = public_ip || internal_ip || ip #set this for the netssh commands
33
+ # super(opts)
34
+ end
35
+
36
+ def keypair(*n)
37
+ @keypair ||= Key.new(key_name)
38
+ end
39
+
40
+ ## hash like methods
41
+ # TODO: move these into a module, or into dslify
42
+ # include Enumerable
43
+ def each
44
+ dsl_options.each{ |k,v| yield k,v }
45
+ end
46
+ def [](k)
47
+ dsl_options[k]
48
+ end
49
+
50
+ def []=(k,v)
51
+ dsl_options[k] = v
52
+ end
53
+
54
+ def keys
55
+ dsl_options.keys
20
56
  end
21
57
 
58
+ def values
59
+ dsl_options.values
60
+ end
61
+ ##end of hash like methods
62
+
22
63
  # Is this instance running?
23
64
  def running?
24
65
  !(status =~ /running/).nil?
@@ -50,6 +50,7 @@ class EC2ResponseObject
50
50
  group
51
51
  end
52
52
  def self.get_hash_from_response(resp, group = 'default')
53
+ symbolize_and_snakecase
53
54
  {
54
55
  :instance_id => resp.instanceId,
55
56
  :name => resp.instanceId,
@@ -60,6 +61,61 @@ class EC2ResponseObject
60
61
  :launching_time => resp.launchTime.parse_datetime,
61
62
  :keypair => (resp.keyName rescue ""),
62
63
  :security_group => group
63
- }
64
+ }
64
65
  end
66
+
67
+ #####
68
+
69
+ # Convert the standard reponse into output similar to this example
70
+ # {:dns_name=>"ec2-75-101-175-49.compute-1.amazonaws.com",
71
+ # :private_dns_name=>"domU-11-31-39-00-DC-78.compute-1.internal",
72
+ # :reason=>nil,
73
+ # :instance_state=>{"name"=>"running", "code"=>"16"},
74
+ # :kernel_id=>"aki-a71cf9ce",
75
+ # :ramdisk_id=>"ari-a51cf9cc",
76
+ # :placement=>{"availabilityZone"=>"us-east-1a"},
77
+ # :product_codes=>nil,
78
+ # :image_id=>"ami-bf5eb9d6",
79
+ # :launch_time=>"2009-05-29T05:07:09.000Z",
80
+ # :key_name=>"poolname_cloudname",
81
+ # :instance_id=>"i-1b7b2942",
82
+ # :ami_launch_index=>"0",
83
+ # :instance_type=>"m1.small"}
84
+ #
85
+ # Selects the first instance if an index is not given.
86
+ def self.describe_instance(response, index=0)
87
+ inst=response['reservationSet']['item'].first['instancesSet']['item'][index]
88
+ Ec2RemoteInstance.new(symbolize_and_snakecase(inst))
89
+ end
90
+
91
+ def self.describe_instances(response)
92
+ return [] if response['reservationSet'].nil?
93
+ ec2_insts = response['reservationSet']['item'].collect do |ri|
94
+ ri['instancesSet']['item'].collect{|i| i}
95
+ end
96
+ ec2_insts.flatten.collect {|i| symbolize_and_snakecase(i) }
97
+ end
98
+
99
+ # Convert the standard response hash to format used throughout the rest of PoolParty code.
100
+ # And add in some more values we rely on
101
+ def self.symbolize_and_snakecase(inst)
102
+ n = inst.symbolize_keys(:snake_case)
103
+ n[:internal_ip] = convert_from_ec2_dns_to_ip(n[:private_dns_name])
104
+ n[:public_ip] = convert_from_ec2_dns_to_ip(n[:dns_name])
105
+ n[:ip] = n[:public_ip]
106
+ n[:launch_time] = parse_datetime(n[:launch_time])
107
+ n[:status] = n[:instance_state][:name]
108
+ n[:availability_zone] = n[:placement][:availability_zone]
109
+ n
110
+ end
111
+
112
+ def self.convert_from_ec2_dns_to_ip(str)
113
+ return nil if str.nil?
114
+ str.scan(/-(\d{1,3})-(\d{1,3})-(\d{1,3})-(\d{1,3})/).flatten.join('.')
115
+ end
116
+
117
+ def self.parse_datetime(str)
118
+ DateTime.parse( str.chomp ) rescue self
119
+ end
120
+
65
121
  end
@@ -1,5 +1,5 @@
1
1
  module PoolParty
2
- class Base
2
+ module Plugin
3
3
 
4
4
  =begin rdoc
5
5
 
@@ -10,10 +10,12 @@ host. This means apache will not start up unless you specify at least the
10
10
  default host.
11
11
 
12
12
  =end
13
-
14
- plugin :apache do
13
+ class Apache < Plugin
15
14
  dsl_methods :passenger_version
16
15
 
16
+ default_options :port => 80,
17
+ :www_user => 'www-data'
18
+
17
19
  def loaded(opts={}, &block)
18
20
  configs
19
21
  has_service("apache2", :requires => get_package("apache2"))
@@ -27,29 +29,25 @@ default host.
27
29
  install
28
30
  end
29
31
 
30
- def www_user(www_user_name='www-data')
31
- www_user_name
32
- end
33
-
34
32
  def install
35
33
  installed_as_worker
36
34
  end
37
35
 
38
- def installed_as_worker
36
+ def installed_as_worker
39
37
  unless @installed_as_worker
40
38
  has_package("apache2")
41
39
  has_package("apache2-mpm-worker")
42
40
 
43
41
  base_install
44
42
  @installed_as_worker = true
45
- end
43
+ end
46
44
  end
47
45
 
48
- def base_install
46
+ def base_install
49
47
  unless @base_install
50
48
  has_exec({:name => "restart-apache2", :command => "/etc/init.d/apache2 restart", :action => :nothing})
51
49
  has_exec({:name => "reload-apache2", :command => "/etc/init.d/apache2 reload", :action => :nothing})
52
- has_exec({:name => "force-reload-apache2", :command => "/etc/init.d/apache2 force-reload", :action => :nothing})
50
+ has_exec({:name => "force-reload-apache2", :command => "/etc/init.d/apache2 force-reload", :action => :nothing})
53
51
  @base_install = true
54
52
  end
55
53
  end
@@ -125,7 +123,7 @@ default host.
125
123
 
126
124
  def configs
127
125
  unless @configs
128
- listen unless @listen
126
+ listen(port) unless @listen
129
127
  has_directory("/etc/apache2")
130
128
  has_directory("/etc/apache2/conf.d")
131
129
  has_directory("/etc/apache2/site-includes")
@@ -168,6 +166,7 @@ default host.
168
166
 
169
167
  def listen(p="80")
170
168
  has_variable(:name => "port", :value => p)
169
+ self.port = p
171
170
  @listen = true
172
171
  end
173
172
 
@@ -212,126 +211,14 @@ default host.
212
211
  has_exec({:name => "no-mod-#{name}"}, :command => "/usr/sbin/a2dismod #{name}") do
213
212
  requires get_package("apache2")
214
213
  if_not "/bin/sh -c \'[ -L /etc/apache2/mods-enabled/#{name}.load ] && [ /etc/apache2/mods-enabled/#{name}.load -ef /etc/apache2/mods-available/#{name}.load ]\'"
215
- calls get_exec("force-reload-apache2")
214
+ calls get_exec("force-reload-apache2")
216
215
  end
217
216
  end
218
217
  end
219
218
 
220
219
  end
221
220
 
222
- virtual_resource(:virtualhost) do
223
- def listen(port="80")
224
- has_variable(:name => "port", :value => port)
225
- port port
226
- end
227
-
228
- def virtual_host_entry(file)
229
- @virtual_host_entry = true
230
- if ::File.file?(file)
231
- has_file(dsl_options.merge({:name => "/etc/apache2/sites-available/#{name}",
232
- :template => file,
233
- :requires => get_package("apache2")}))
234
- else
235
- has_file(dsl_options.merge({:content => file,
236
- :name => "/etc/apache2/sites-available/#{name}",
237
- :requires => get_package("apache2")}))
238
- end
239
- end
240
-
241
-
242
- def loaded(opts={}, parent=self)
243
- has_directory(:name => "/var/www", :owner => www_user, :mode=>'0744')
244
- has_directory(:name => "/var/www/#{name}", :owner => www_user, :mode=>'0744')
245
- has_directory(:name => "/var/www/#{name}/logs", :owner => www_user, :mode=>'0744')
246
-
247
- has_variable(:name => "sitename", :value => "#{name}")
248
-
249
- unless @virtual_host_entry
250
- virtual_host_entry <<-eof
251
- <VirtualHost *:#{port}>
252
- ServerName #{name}
253
- DocumentRoot /var/www/#{name}
254
- </VirtualHost>
255
- eof
256
- end
257
-
258
- has_exec(:name => "insert-site-#{name}",
259
- :command => "/usr/sbin/a2ensite #{name}",
260
- :calls => get_exec("reload-apache2"),
261
- :requires => get_file("/etc/apache2/sites-available/#{name}")) do
262
- requires get_package("apache2")
263
- if_not "/bin/sh -c '[ -L /etc/apache2/sites-enabled/#{parent.name} ] && [ /etc/apache2/sites-enabled/#{parent.name} -ef /etc/apache2/sites-available/#{parent.name} ]'"
264
- end
265
- end
266
-
267
- end
268
-
269
- virtual_resource(:passengersite) do # {{{
270
-
271
- default_options(
272
- :dir => "/var/www",
273
- :appended_path => nil,
274
- :owner => 'www-data',
275
- :mode =>'0744',
276
- :enviornment => 'production'
277
- )
278
-
279
- def loaded(opts={}, prnt=nil)
280
- enable_passenger
281
- port "80" unless self.port
282
-
283
- has_directory(:name => dir, :owner => www_user, :mode => '0744')
284
- has_directory(:name => "#{site_directory}", :owner => www_user, :mode => '0744')
285
- has_directory(:name => "#{site_directory}/logs", :owner => www_user, :mode => '0744')
286
- if opts[:with_deployment_directories]
287
- has_directory(:name => "#{site_directory}/shared", :owner => www_user, :mode=>'0744')
288
- has_directory(:name => "#{site_directory}/shared/public", :owner => www_user, :mode=>'0744')
289
- has_directory(:name => "#{site_directory}/shared/config", :owner => www_user, :mode=>'0744')
290
- has_directory(:name => "#{site_directory}/shared/log", :owner => www_user, :mode=>'0744')
291
- has_directory(:name => "#{site_directory}/releases", :owner => www_user, :mode=>'0744')
292
- do_once do |variable|
293
- # setup an initial symlink so apache will start even if there have not been any deploys yet
294
- has_directory(:name => "#{site_directory}/releases/initial/public", :owner => www_user, :mode=>'0744')
295
- #FIXME the following line is chef specific. It will fail with puppet
296
-
297
- # has_symlink(:target_file => "#{dir}/#{name}/current", :to => "#{dir}/#{name}/releases/initial")
298
- end
299
- log_dir = "#{site_directory}/shared/log"
300
- appended_path "current"
301
- else
302
- log_dir = "#{site_directory}/log"
303
- end
304
-
305
- passenger_entry <<-EOE
306
- <VirtualHost *:#{port}>
307
- ServerName #{name}
308
- DocumentRoot #{site_directory}/public
309
- RailsEnv #{enviornment}
310
- ErrorLog #{log_dir}/error_log
311
- CustomLog #{log_dir}/access_log common
312
- </VirtualHost>
313
- EOE
314
-
315
- # has_directory(:name => "/var/www")
316
- # has_directory(:name => "/var/www/#{name}")
317
- # has_directory(:name => "/var/www/#{name}/log")
318
- parent.install_site(name, :no_file => true) # we already created the file with #passenger_entry
319
- end
320
-
321
- def passenger_entry(file)
322
- if ::File.file?(file)
323
- has_file({:name => "/etc/apache2/sites-available/#{name}", :template => file})
324
- else
325
- has_file({:content => file, :name => "/etc/apache2/sites-available/#{name}" })
326
- end
327
- end
328
-
329
- def site_directory
330
- "#{dir}/#{name}%s" % [appended_path ? "/" + appended_path : ""]
331
- end
332
- end
333
-
334
- # virtual_resource(:passengersite_with_ssl) do# {{{
221
+ # plugin(:passengersite_with_ssl) do# {{{
335
222
  # def loaded(opts={}, parent=self)
336
223
  # enable_passenger
337
224
 
@@ -374,40 +261,6 @@ eof
374
261
  # end
375
262
  # }}}
376
263
 
377
- # Usage:
378
- #
379
- # enable_php5 do
380
- # extras :cli, :pspell, :mysql
381
- # end
382
- virtual_resource(:enable_php5) do
383
- def loaded(opts={}, parent=self)
384
- has_package(:name => "php5")
385
- has_package(:name => "libapache2-mod-php5")
386
- present_apache_module("php5")
387
- has_file({:name => "/etc/php5/apache2/php.ini",
388
- :template => "apache2/php.ini.erb",
389
- :mode => 755,
390
- :requires => get_package("libapache2-mod-php5"),
391
- :calls => get_exec("reload-apache2")})
392
-
393
- has_file(:name => "/etc/apache2/conf.d/enable-php.conf",
394
- :mode => 755,
395
- :calls => get_exec("reload-apache2"),
396
- :content => <<-eos
397
- AddHandler php5-script php
398
- AddType text/html php
399
- eos
400
- )
401
- end
402
-
403
- def extras(*names)
404
- names.each do |name|
405
- has_package(:name => "php5-#{name}", :requires => get_package("php5"))
406
- end
407
- end
408
-
409
- end
410
-
411
264
  end
412
265
 
413
266
  end