auser-poolparty 0.2.78 → 0.2.79

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/Manifest.txt CHANGED
@@ -16,6 +16,7 @@ bin/cloud-maintain
16
16
  bin/cloud-osxcopy
17
17
  bin/cloud-provision
18
18
  bin/cloud-refresh
19
+ bin/cloud-rsync
19
20
  bin/cloud-run
20
21
  bin/cloud-ssh
21
22
  bin/cloud-start
@@ -81,6 +82,7 @@ lib/erlang/messenger/ebin/pm_node.beam
81
82
  lib/erlang/messenger/ebin/pm_node_rel-0.1.rel
82
83
  lib/erlang/messenger/ebin/pm_node_supervisor.beam
83
84
  lib/erlang/messenger/ebin/pm_packager.beam
85
+ lib/erlang/messenger/ebin/pm_spawner.beam
84
86
  lib/erlang/messenger/ebin/pm_strings.beam
85
87
  lib/erlang/messenger/ebin/utils.beam
86
88
  lib/erlang/messenger/include/defines.hrl
@@ -160,6 +162,7 @@ lib/erlang/messenger/src/pm_master_supervisor.erl
160
162
  lib/erlang/messenger/src/pm_node.erl
161
163
  lib/erlang/messenger/src/pm_node_supervisor.erl
162
164
  lib/erlang/messenger/src/pm_packager.erl
165
+ lib/erlang/messenger/src/pm_spawner.erl
163
166
  lib/erlang/messenger/src/pm_strings.erl
164
167
  lib/erlang/messenger/src/utils.erl
165
168
  lib/erlang/messenger/useful_snippets
@@ -391,7 +394,6 @@ test/test_generator_helper.rb
391
394
  test/test_helper.rb
392
395
  test/test_pool_spec_generator.rb
393
396
  test/test_poolparty.rb
394
- website/index.html
395
397
  website/index.txt
396
398
  website/javascripts/rounded_corners_lite.inc.js
397
399
  website/stylesheets/code.css
data/PostInstall.txt CHANGED
@@ -1,4 +1,4 @@
1
- Get ready to jump in the pool, you just installed PoolParty! (Updated at 09:44 12/05/08)
1
+ Get ready to jump in the pool, you just installed PoolParty! (Updated at 13:46 12/06/08)
2
2
 
3
3
  To get started, run the generator:
4
4
 
data/bin/cloud-maintain CHANGED
@@ -22,7 +22,7 @@ o.loaded_clouds.each do |cloud|
22
22
  elsif maximum_number_of_instances_are_running?
23
23
  vputs "#{list_of_running_instances.size} running instances of between #{minimum_instances} and #{maximum_instances}"
24
24
  vputs "Shutting down non-master instance"
25
- contract_cloud_if_necessary( !testing )
25
+ contract_cloud_if_necessary( testing ? true : false )
26
26
  end
27
27
  vputs "Cloud is maintained"
28
28
  end
data/bin/cloud-rsync ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+ require "poolparty"
4
+ require "poolpartycl"
5
+
6
+ o = PoolParty::Optioner.new(ARGV, {:extra_help => "\nUsage: cloud [options] rsync source target\n\n"}) do |opts, optioner|
7
+ opts.on('-n name', '--name name', 'Listing for cloud name') { |c| optioner.cloudname c }
8
+ opts.on('-i num', '--id num', 'Instance num to ssh (default: 0)') { |i| optioner.num i }
9
+ end
10
+
11
+ @instance_number = (o.num || 0 ).to_i
12
+
13
+ if o.unflagged_args.length > 1
14
+ @target = o.unflagged_args.pop
15
+ @source = o.unflagged_args.pop
16
+ else
17
+ @source = o.unflagged_args.pop
18
+ @target = ''
19
+ end
20
+
21
+ o.loaded_clouds.each do |cloud|
22
+
23
+ with_cloud(cloud, {:source=>@source, :target=>@target, :instance_number=>@instance_number }) do
24
+ puts header("rsyncing")
25
+ rsync_to source, target, instance_number
26
+ end
27
+
28
+ end
@@ -133,7 +133,7 @@ init(Args) ->
133
133
  %% Description: Handling call messages
134
134
  %%--------------------------------------------------------------------
135
135
  handle_call({run_command, Cmd}, _From, State) ->
136
- Reply = os:cmd(". /etc/profile && server-fire-cmd \""++Cmd++"\""),
136
+ Reply = os:cmd(Cmd),
137
137
  {reply, Reply, State};
138
138
  handle_call({update_load, Type, Load}, _From, State) ->
139
139
  {Type, NewState} = store_load_for_type(Type, Load, State),
@@ -197,5 +197,4 @@ code_change(_OldVsn, State, _Extra) ->
197
197
  {ok, State}.
198
198
 
199
199
  % Private
200
- server_location() ->
201
- global:whereis_name(node()).
200
+ server_location() -> global:whereis_name(node()).
@@ -0,0 +1,213 @@
1
+ %
2
+ % pm_spawner.erl
3
+ % Spawn a process in this gen_server remotely
4
+ % and hear back from it when it's got stuff to say
5
+ %
6
+ % Created by Ari Lerner on 2008-12-05.
7
+ % Copyright 2008 CitrusByte. All rights reserved.
8
+ %
9
+ -module (pm_spawner).
10
+ -behaviour(gen_server).
11
+
12
+ -include_lib("../include/defines.hrl").
13
+
14
+ %% API
15
+ -export([start_link/0]).
16
+ -export ([run_command/1, run_command/2, check_command/1]).
17
+
18
+ %% gen_server callbacks
19
+ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
20
+
21
+ -record(state, {
22
+ processes = ?DICT:new() % Array of the output
23
+ }).
24
+ -define(SERVER, ?MODULE).
25
+
26
+ %%--------------------------------------------------------------------
27
+ %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
28
+ %% Description: Starts the server
29
+ %%--------------------------------------------------------------------
30
+ start_link() -> gen_server:start_link({global, ?MODULE}, ?MODULE, [], []).
31
+
32
+ %%====================================================================
33
+ %% gen_server callbacks
34
+ %%====================================================================
35
+
36
+ %%--------------------------------------------------------------------
37
+ %% Function: init(Args) -> {ok, State} |
38
+ %% {ok, State, Timeout} |
39
+ %% ignore |
40
+ %% {stop, Reason}
41
+ %% Description: Initiates the server
42
+ %%--------------------------------------------------------------------
43
+ init([]) ->
44
+ % process_flag(trap_exit, true),
45
+ {ok, #state{
46
+ processes = ?DICT:new()
47
+ }}.
48
+
49
+ %%--------------------------------------------------------------------
50
+ %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
51
+ %% {reply, Reply, State, Timeout} |
52
+ %% {noreply, State} |
53
+ %% {noreply, State, Timeout} |
54
+ %% {stop, Reason, Reply, State} |
55
+ %% {stop, Reason, State}
56
+ %% Description: Handling call messages
57
+ %%--------------------------------------------------------------------
58
+ handle_call({run_command, Cmds}, _From, State) ->
59
+ {ok, NewState} = run_command(Cmds, State),
60
+ ?TRACE("storing into state from call", [Cmds, NewState]),
61
+ {reply, ok, NewState};
62
+ handle_call({check_command, Cmd}, _From, State) ->
63
+ AtomCommand = erlang:list_to_atom(Cmd),
64
+ ?TRACE("is_key for ", [AtomCommand, ?DICT:is_key(AtomCommand, State#state.processes)]),
65
+ case ?DICT:is_key(AtomCommand, State#state.processes) of
66
+ false ->
67
+ Reply = nil,
68
+ NewState = State;
69
+ true ->
70
+ Pid = ?DICT:fetch(AtomCommand, State#state.processes),
71
+ case erlang:is_pid(Pid) of
72
+ true ->
73
+ Pid ! {self(), collect},
74
+ receive
75
+ {command_response, OutFromCommand} ->
76
+ Reply = OutFromCommand,
77
+ NewState = State#state{processes = ?DICT:store(AtomCommand, OutFromCommand, State#state.processes)};
78
+ Msg ->
79
+ NewState = State,
80
+ Reply = Msg
81
+ after
82
+ 1000 ->
83
+ Pid ! {self(), collect},
84
+ NewState = State,
85
+ Reply = "no output"
86
+ end;
87
+ false ->
88
+ NewState = State,
89
+ Reply = Pid
90
+ end
91
+ end,
92
+ {reply, Reply, NewState};
93
+ handle_call(_Request, _From, State) ->
94
+ Reply = ok,
95
+ {reply, Reply, State}.
96
+ %%--------------------------------------------------------------------
97
+ %% Function: handle_cast(Msg, State) -> {noreply, State} |
98
+ %% {noreply, State, Timeout} |
99
+ %% {stop, Reason, State}
100
+ %% Description: Handling cast messages
101
+ %%--------------------------------------------------------------------
102
+ handle_cast({run_command, Cmd}, State) ->
103
+ {ok, NewState} = run_command(Cmd, State),
104
+ {noreply, NewState};
105
+ handle_cast(_Msg, State) ->
106
+ {noreply, State}.
107
+
108
+ %%--------------------------------------------------------------------
109
+ %% Function: handle_info(Info, State) -> {noreply, State} |
110
+ %% {noreply, State, Timeout} |
111
+ %% {stop, Reason, State}
112
+ %% Description: Handling all non call/cast messages
113
+ %%--------------------------------------------------------------------
114
+ handle_info(_Info, State) ->
115
+ {noreply, State}.
116
+
117
+ %%--------------------------------------------------------------------
118
+ %% Function: terminate(Reason, State) -> void()
119
+ %% Description: This function is called by a gen_server when it is about to
120
+ %% terminate. It should be the opposite of Module:init/1 and do any necessary
121
+ %% cleaning up. When it returns, the gen_server terminates with Reason.
122
+ %% The return value is ignored.
123
+ %%--------------------------------------------------------------------
124
+ terminate(_Reason, _State) ->
125
+ ok.
126
+
127
+ %%--------------------------------------------------------------------
128
+ %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
129
+ %% Description: Convert process state when code is changed
130
+ %%--------------------------------------------------------------------
131
+ code_change(_OldVsn, State, _Extra) ->
132
+ {ok, State}.
133
+
134
+ % Quick helper for running commands
135
+ run_command(Cmd) -> gen_server:call(server_location(), {run_command, Cmd}).
136
+ check_command(Cmd) ->
137
+ Command = lists:flatten(io_lib:format("~s", [Cmd])),
138
+ gen_server:call(server_location(), {check_command, Command}).
139
+
140
+ % Run the command, start up the
141
+ run_command(Cmd, State) ->
142
+ Command = lists:flatten(io_lib:format("~s", [Cmd])),
143
+ AtomCommand = erlang:list_to_atom(Command),
144
+ Pid = spawn(fun() -> spawn_command(Command) end),
145
+ Storage = Pid,
146
+ ?TRACE("storing into state", [AtomCommand]),
147
+ NewState = State#state{processes = ?DICT:store(AtomCommand, Storage, State#state.processes)},
148
+ {ok, NewState}.
149
+
150
+ spawn_command(Command) ->
151
+ Port = erlang:open_port({spawn, Command}, [stream, exit_status, stderr_to_stdout, use_stdio]),
152
+ ResponsePid = response_reader(Port),
153
+ spawn_command_loop(Command, Port, ResponsePid).
154
+
155
+ spawn_command_loop(Command, Port, Responses) ->
156
+ receive
157
+ {Pid, collect} ->
158
+ case erlang:is_pid(Responses) of
159
+ true ->
160
+ io:format("There is no output on your command yet, try again in a few seconds ~p~n", [Responses]),
161
+ spawn_command_loop(Command, Port, Responses);
162
+ false ->
163
+ Pid ! {command_response, Responses}
164
+ end;
165
+ {exit_status, _} ->
166
+ spawn_command_loop(Command, Port, Responses);
167
+ {done, Port, Response} ->
168
+ ?TRACE("Received done message", Response),
169
+ spawn_command_loop(Command, Port, Response);
170
+ {Port, {exit_status, 0}} ->
171
+ ?TRACE("Received exit_status", [Port]),
172
+ Responses ! {Port, {exit_status, 0, self()}},
173
+ receive
174
+ {ok, Resp} ->
175
+ ?TRACE("Received ok back", [Resp]),
176
+ spawn_command_loop(Command, Port, Resp)
177
+ end;
178
+ Mes ->
179
+ ?TRACE("received message", [Mes]),
180
+ Responses ! Mes,
181
+ spawn_command_loop(Command, Port, Responses)
182
+ end.
183
+
184
+ response_reader(Port) ->
185
+ ResponsePid = spawn(fun() -> response_reader_loop(Port, []) end),
186
+ ResponsePid.
187
+
188
+ response_reader_loop(Port, Acc) ->
189
+ receive
190
+ {Port, {data, Bin}} ->
191
+ ?TRACE("received data", [Bin]),
192
+ response_reader_loop(Port, [Bin|Acc]);
193
+ {Port, {exit_status, 0, Pid}} ->
194
+ catch erlang:port_close(Port),
195
+ Response = lists:flatten(lists:reverse(Acc)),
196
+ ?TRACE("received exit_status", [Response, Port]),
197
+ Pid ! {ok, Response};
198
+ {Port, {exit_status, _}} ->
199
+ catch erlang:port_close(Port),
200
+ Output = lists:flatten(lists:reverse(Acc)),
201
+ {error, Output};
202
+ {Pid, get_data} ->
203
+ ?TRACE("get_data for", [Pid, Acc]),
204
+ Pid ! {data, Port, Acc},
205
+ response_reader_loop(Port, Acc);
206
+ {_, collect} ->
207
+ response_reader_loop(Port, Acc);
208
+ Mes ->
209
+ io:format("Unexpected message in response_reader_loop ~p~n", [Mes]),
210
+ response_reader_loop(Port, Acc)
211
+ end.
212
+
213
+ server_location() -> global:whereis_name(?SERVER).
@@ -72,6 +72,7 @@ module PoolParty
72
72
  mode 744
73
73
  template File.join(File.dirname(__FILE__), "..", "templates/puppetrerun")
74
74
  end
75
+
75
76
  has_remotefile(:name => "/usr/bin/puppetcleaner") do
76
77
  mode 744
77
78
  template File.join(File.dirname(__FILE__), "..", "templates/puppetcleaner")
@@ -80,10 +81,10 @@ module PoolParty
80
81
  execute_on_master do
81
82
  has_exec(:name => "update_hosts", :command => ". /etc/profile && server-update-hosts -n #{cloud.name}")
82
83
 
83
- has_cron(:name => "master puppetd runner", :user => Base.user, :minute => "*/15") do
84
- requires get_gempackage("poolparty")
85
- command(PoolParty::Remote::RemoteInstance.puppet_runner_command)
86
- end
84
+ # has_cron(:name => "master puppetd runner", :user => Base.user, :minute => "*/15") do
85
+ # requires get_gempackage("poolparty")
86
+ # command(PoolParty::Remote::RemoteInstance.puppet_runner_command)
87
+ # end
87
88
  has_cron(:name => "Load handler", :user => Base.user, :minute => "*/4") do
88
89
  requires get_gempackage("poolparty")
89
90
  command(". /etc/profile && cloud-handle-load -n #{cloud.name}")
@@ -24,14 +24,21 @@ module Kernel
24
24
  ensure
25
25
  $-v = saved_verbosity
26
26
  end
27
+
28
+ #redirect stdout and stderr to /dev/null and reopen after block
27
29
  def hide_output
28
30
  begin
29
31
  old_stdout = STDOUT.dup
32
+ old_stderr = STDERR.dup
30
33
  STDOUT.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
34
+ STDERR.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
31
35
  yield if block_given?
32
36
  ensure
33
37
  STDOUT.flush
34
38
  STDOUT.reopen(old_stdout)
39
+ STDERR.flush
40
+ STDERR.reopen(old_stderr)
35
41
  end
36
42
  end
43
+
37
44
  end
@@ -9,9 +9,12 @@ module PoolParty
9
9
  class Optioner
10
10
  include Configurable
11
11
  include MethodMissingSugar
12
-
13
- def initialize(args=[], opts={}, &block)
14
- @arguments = parse_args(args)
12
+
13
+
14
+ def initialize(args=[], opts={}, &block)
15
+ boolean_args << opts[:boolean_args] if opts.has_key?(:boolean_args)
16
+
17
+ @arguments = parse_args(args)
15
18
  @extra_help = opts.has_key?(:extra_help) ? opts[:extra_help] : ""
16
19
  @abstract = opts.has_key?(:abstract) ? opts[:abstract] : false
17
20
  @load_pools = opts.has_key?(:load_pools) ? opts[:load_pools] : !@abstract
@@ -22,16 +25,43 @@ module PoolParty
22
25
  set_default_options
23
26
  self
24
27
  end
25
-
26
28
  def daemonizeable
27
29
  @opts.on('-d', '--daemonize', 'Daemonize starting the cloud') { self.daemon true }
28
30
  end
29
31
  def cloudnames
30
32
  @opts.on('-n cloudname', '--name name', 'Start cloud by this name') { |c| self.cloudname c }
33
+ end
34
+ def unflagged_args
35
+ @unflagged_args ||= []
36
+ end
37
+ def flagged_args
38
+ @flagged_args ||= []
39
+ end
40
+ def boolean_args
41
+ @boolean_args ||= ['-V', '-h', '-t', '-v']
31
42
  end
32
43
 
33
- def parse_args(argv, safe=[])
34
- argv
44
+ # Break ARGV into 2 arrays, one for flagged options one for unflagged
45
+ # For example the "command -v -i 1 five six -x"
46
+ # becomes ['-v', '-i', 1, '-x'] and ['five', 'six']
47
+ # Boolean options, such as -v, must be specified in the optioner definition
48
+ def parse_args(args=[])
49
+ i=0
50
+ while i < args.length
51
+ if boolean_args.include?(args[i])
52
+ flagged_args << args[i]
53
+ else
54
+ if args[i][0].chr == "-"
55
+ flagged_args << args[i]
56
+ flagged_args << args[i+1] if (args[i+1] and !args[i+1].nil?)
57
+ i+=1
58
+ else
59
+ unflagged_args << args[i]
60
+ end
61
+ end
62
+ i+=1
63
+ end
64
+ args
35
65
  end
36
66
 
37
67
  def parent
@@ -356,6 +356,9 @@ fi
356
356
 
357
357
  cp #{Base.remote_storage_path}/#{Base.template_directory}/puppetrerun /usr/bin/puppetrerun
358
358
  chmod +x /usr/bin/puppetrerun
359
+
360
+ cp #{Base.remote_storage_path}/#{Base.template_directory}/puppetcleaner /usr/bin/puppetcleaner
361
+ chmod +x /usr/bin/puppetcleaner
359
362
  EOS
360
363
  end
361
364
  end
@@ -24,7 +24,6 @@ module PoolParty
24
24
  setup_fileserver,
25
25
  setup_autosigning,
26
26
  install_poolparty,
27
- setup_poolparty,
28
27
  restart_puppetmaster,
29
28
  run_first_time,
30
29
  create_local_node,
@@ -35,6 +34,7 @@ module PoolParty
35
34
  [
36
35
  create_local_node,
37
36
  move_templates,
37
+ setup_poolparty,
38
38
  create_poolparty_manifest,
39
39
  restart_puppetd
40
40
  ]
@@ -91,7 +91,7 @@ echo "*" > /etc/puppet/autosign.conf
91
91
  <<-EOS
92
92
  echo "Setting the poolparty configuration"
93
93
  cp #{Base.remote_storage_path}/#{Base.key_file_locations.first} "#{Base.base_config_directory}/.ppkeys"
94
- cp #{Base.remote_storage_path}/#{Base.default_specfile_name} #{Base.base_config_directory}/#{Base.default_specfile_name}
94
+ mv #{Base.remote_storage_path}/#{Base.default_specfile_name} #{Base.base_config_directory}/
95
95
  EOS
96
96
  end
97
97
 
@@ -180,9 +180,11 @@ cp #{Base.remote_storage_path}/poolparty.pp /etc/puppet/manifests/classes/poolpa
180
180
  end
181
181
 
182
182
  def restart_puppetd
183
+ # /usr/bin/puppetrerun
183
184
  <<-EOS
184
185
  echo "Running puppet manifest"
185
- /usr/bin/puppetrerun
186
+ /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
187
+ /usr/bin/puppetcleaner master
186
188
  EOS
187
189
  end
188
190
  end
@@ -5,8 +5,8 @@ module PoolParty
5
5
  ebs_volume_id id
6
6
  ebs_volume_mount_point loc
7
7
  ebs_volume_device "/dev/#{id.sanitize}"
8
-
9
- has_mount(:name => loc, :device => ebs_volume_device, :requires => get_directory(loc))
8
+
9
+ has_mount(:name => loc, :device => ebs_volume_device, :onlyif => "test -d #{loc}")
10
10
  has_directory(:name => loc)
11
11
  end
12
12
 
@@ -23,11 +23,17 @@ module PoolParty
23
23
  self.run_in_context @stored_block if @stored_block
24
24
  end
25
25
 
26
- # Set instances with a range
27
- def instances(arg)
28
- if arg.is_a?(Range)
26
+ # Set instances with a range or a number
27
+ def instances(arg)
28
+ case arg
29
+ when Range
29
30
  minimum_instances arg.first
30
31
  maximum_instances arg.last
32
+ when Fixnum
33
+ minimum_instances arg
34
+ maximum_instances arg
35
+ else
36
+ raise SpecException.new("Don't know how to handle instances cloud input #{arg}")
31
37
  end
32
38
  end
33
39
 
@@ -8,8 +8,8 @@ module PoolParty
8
8
 
9
9
  def using(t)
10
10
  @cloud = self
11
- if available_bases.include?(t.to_sym)
12
- unless using_remoter? || t.nil?
11
+ if t && available_bases.include?(t.to_sym)
12
+ unless using_remoter?
13
13
  self.class.send :attr_reader, :remote_base
14
14
  self.class.send :attr_reader, :parent_cloud
15
15
  mod = "#{t}".preserved_module_constant
@@ -117,8 +117,8 @@ begin
117
117
 
118
118
  def before_configuration_tasks
119
119
  if has_cert_and_key?
120
- copy_file_to_storage_directory(pub_key)
121
- copy_file_to_storage_directory(private_key)
120
+ # copy_file_to_storage_directory(pub_key)
121
+ # copy_file_to_storage_directory(private_key)
122
122
  end
123
123
  end
124
124
  def has_cert_and_key?
@@ -140,8 +140,8 @@ begin
140
140
  def custom_install_tasks_for(o)
141
141
  arr = if has_cert_and_key?
142
142
  [
143
- "mv #{::File.basename(pub_key)} #{Base.base_config_directory}/ssl/public_keys/#{o.name}.pem",
144
- "mv #{::File.basename(private_key)} #{Base.base_config_directory}/ssl/private_keys/#{o.name}.pem"
143
+ # "mv #{::File.basename(pub_key)} #{Base.base_config_directory}/ssl/public_keys/#{o.name}.pem",
144
+ # "mv #{::File.basename(private_key)} #{Base.base_config_directory}/ssl/private_keys/#{o.name}.pem"
145
145
  ]
146
146
  else
147
147
  []
@@ -7,9 +7,14 @@ require File.dirname(__FILE__) + "/../helpers/provisioner_base"
7
7
  module PoolParty
8
8
  module Remote
9
9
  module Remoter
10
- def rsync_storage_files_to_command(remote_instance)
10
+ def rsync_storage_files_to_command(remote_instance)
11
+ #TODO: rsync_to_command("#{Base.storage_directory}/", Base.remote_storage_path, remote_storage_path) if remote_instance
11
12
  "#{rsync_command} #{Base.storage_directory}/ #{remote_instance.ip}:#{Base.remote_storage_path}" if remote_instance
12
13
  end
14
+ # rsync a file to a node. By default to the master node.
15
+ def rsync_to_command(source, target=source, remote_instance=master)
16
+ "#{rsync_command} #{source} #{remote_instance.ip}:#{target}"
17
+ end
13
18
  def run_command_on_command(cmd="ls -l", remote_instance=nil)
14
19
  vputs "Running #{cmd} on #{remote_instance.name == %x[hostname].chomp ? "self (master)" : "#{remote_instance.name}"}"
15
20
  remote_instance.name == %x[hostname].chomp ? %x[#{cmd}] : "#{ssh_command(remote_instance)} '#{cmd}'"
@@ -40,6 +45,13 @@ module PoolParty
40
45
  def remote_rsync_command
41
46
  "rsync -azP --exclude cache -e '#{remote_ssh_string}'"
42
47
  end
48
+
49
+
50
+ # def scp_command(source, dest=target, remote_instance=master)
51
+ # #TODO: check if source is Directory and add -r if it is
52
+ # "scp #{source} #{remote_instance.ip}:#{dest} #{ssh_array.join(' ')}"
53
+ # end
54
+
43
55
  # Get the names of the nodes. Mainly used for puppet templating
44
56
  def list_of_node_names(options={})
45
57
  list_of_running_instances.collect {|ri| ri.name }
@@ -71,10 +83,22 @@ module PoolParty
71
83
  def minimum_number_of_instances_are_running?
72
84
  list_of_running_instances.size >= minimum_instances.to_i
73
85
  end
86
+ # Are the minimum number of instances NOT running?
87
+ def minimum_number_of_instances_are_not_running?
88
+ !(minimum_number_of_instances_are_running?)
89
+ end
74
90
  # Can we shutdown an instance?
75
91
  def can_shutdown_an_instance?
76
92
  list_of_running_instances.size > minimum_instances.to_i
77
93
  end
94
+ # Are too few instances running?
95
+ def are_too_few_instances_running?
96
+ list_of_running_instances.size < minimum_instances.to_i
97
+ end
98
+ # Are there more instances than allowed?
99
+ def are_too_many_instances_running?
100
+ list_of_running_instances.size > maximum_instances.to_i
101
+ end
78
102
  # Request to launch a number of instances
79
103
  def request_launch_new_instances(num=1)
80
104
  out = []
@@ -204,11 +228,17 @@ module PoolParty
204
228
  end
205
229
  # Stub method for the time being to handle expansion of the cloud
206
230
  def should_expand_cloud?(force=false)
207
- valid_rules?(:expand_when) || force || false
231
+ (are_too_few_instances_running? || are_expansion_rules_valid? ) || force || false
232
+ end
233
+ def are_expansion_rules_valid?
234
+ valid_rules?(:expand_when)
208
235
  end
209
236
  # Stub method for the time being to handle the contraction of the cloud
210
237
  def should_contract_cloud?(force=false)
211
- valid_rules?(:contract_when) || force || false
238
+ (are_too_many_instances_running? || are_contraction_rules_valid?) || force || false
239
+ end
240
+ def are_contraction_rules_valid?
241
+ valid_rules?(:contract_when)
212
242
  end
213
243
  # Expand the cloud
214
244
  # If we can start a new instance and the load requires us to expand
@@ -233,12 +263,10 @@ module PoolParty
233
263
  # If we can shutdown an instnace and the load allows us to contract
234
264
  # the cloud, then we should request_termination_of_non_master_instance
235
265
  def contract_cloud_if_necessary(force=false)
236
- if can_shutdown_an_instance?
237
- if should_contract_cloud?(force)
238
- vputs "Shrinking the cloud by 1"
239
- before_shutdown
240
- request_termination_of_non_master_instance
241
- end
266
+ if can_shutdown_an_instance? && should_contract_cloud?(force)
267
+ vputs "Shrinking the cloud by 1"
268
+ before_shutdown
269
+ request_termination_of_non_master_instance
242
270
  end
243
271
  end
244
272
 
@@ -254,6 +282,13 @@ module PoolParty
254
282
  def before_shutdown
255
283
  end
256
284
 
285
+ # Rsync a file or directory to a node. Rsync to master by default
286
+ def rsync_to(source, target=source, num=0)
287
+ str = "#{rsync_to_command(source, target, get_instance_by_number( num ))}"
288
+ vputs "Running: #{str}"
289
+ verbose ? Kernel.system(str) : hide_output {Kernel.system str}
290
+ end
291
+
257
292
  # Rsync command to the instance
258
293
  def rsync_storage_files_to(instance=nil)
259
294
  hide_output {Kernel.system "#{rsync_storage_files_to_command(instance)}" if instance}
@@ -7,9 +7,15 @@ if [ $(/usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server mast
7
7
  echo "Clearing old certs"
8
8
  HN=`hostname`
9
9
  if [[ $HN == "master" ]]; then
10
- ps aux | grep puppetmaster | awk '{print $2}' | xargs kill;rm -rf /etc/poolparty/ssl;/etc/init.d/puppetmaster start
11
- /etc/init.d/puppetmaster start && /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
10
+ rm /etc/poolparty/ssl/ca/signed/$HN*
11
+ if [ $(/usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master) ]; then
12
+ echo "Run successfully" && exit 0
13
+ else
14
+ /etc/init.d/puppetmaster stop;rm -rf /etc/poolparty/ssl;/etc/init.d/puppetmaster start
15
+ /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
16
+ fi
12
17
  else
13
- rm -rf /etc/poolparty/ssl/*;/usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
18
+ rm /etc/poolparty/ssl/ca/signed/$HN*
19
+ /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
14
20
  fi
15
21
  fi
@@ -2,7 +2,7 @@ module PoolParty
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- TINY = 78
5
+ TINY = 79
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/poolparty.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poolparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.78
4
+ version: 0.2.79
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Lerner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-05 00:00:00 -08:00
12
+ date: 2008-12-06 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,6 +68,7 @@ executables:
68
68
  - cloud-osxcopy
69
69
  - cloud-provision
70
70
  - cloud-refresh
71
+ - cloud-rsync
71
72
  - cloud-run
72
73
  - cloud-ssh
73
74
  - cloud-start
@@ -127,6 +128,7 @@ files:
127
128
  - bin/cloud-osxcopy
128
129
  - bin/cloud-provision
129
130
  - bin/cloud-refresh
131
+ - bin/cloud-rsync
130
132
  - bin/cloud-run
131
133
  - bin/cloud-ssh
132
134
  - bin/cloud-start
@@ -192,6 +194,7 @@ files:
192
194
  - lib/erlang/messenger/ebin/pm_node_rel-0.1.rel
193
195
  - lib/erlang/messenger/ebin/pm_node_supervisor.beam
194
196
  - lib/erlang/messenger/ebin/pm_packager.beam
197
+ - lib/erlang/messenger/ebin/pm_spawner.beam
195
198
  - lib/erlang/messenger/ebin/pm_strings.beam
196
199
  - lib/erlang/messenger/ebin/utils.beam
197
200
  - lib/erlang/messenger/include/defines.hrl
@@ -271,6 +274,7 @@ files:
271
274
  - lib/erlang/messenger/src/pm_node.erl
272
275
  - lib/erlang/messenger/src/pm_node_supervisor.erl
273
276
  - lib/erlang/messenger/src/pm_packager.erl
277
+ - lib/erlang/messenger/src/pm_spawner.erl
274
278
  - lib/erlang/messenger/src/pm_strings.erl
275
279
  - lib/erlang/messenger/src/utils.erl
276
280
  - lib/erlang/messenger/useful_snippets
@@ -502,7 +506,6 @@ files:
502
506
  - test/test_helper.rb
503
507
  - test/test_pool_spec_generator.rb
504
508
  - test/test_poolparty.rb
505
- - website/index.html
506
509
  - website/index.txt
507
510
  - website/javascripts/rounded_corners_lite.inc.js
508
511
  - website/stylesheets/code.css
@@ -511,7 +514,7 @@ files:
511
514
  has_rdoc: true
512
515
  homepage: http://poolparty.rubyforge.org
513
516
  post_install_message: |-
514
- Get ready to jump in the pool, you just installed PoolParty! (Updated at 09:44 12/05/08)
517
+ Get ready to jump in the pool, you just installed PoolParty! (Updated at 13:46 12/06/08)
515
518
 
516
519
  To get started, run the generator:
517
520
 
@@ -114,9 +114,4 @@ describe "Rules" do
114
114
  @car.y = 5
115
115
  @car.valid_rules?(:names).should == true
116
116
  end
117
- it "should have the rules in an array of hashes" do
118
- @car.names.each do |n|
119
-
120
- end
121
- end
122
117
  end
@@ -1,5 +1,8 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
  require File.dirname(__FILE__) + '/../../../lib/poolparty/helpers/console'
3
+ require File.dirname(__FILE__) + '/../../../lib/poolparty/helpers/binary'
4
+
5
+ reset!
3
6
 
4
7
  describe "Console" do
5
8
  before(:each) do
@@ -27,6 +27,20 @@ describe "Option Parser" do
27
27
  end
28
28
  end
29
29
  end
30
+
31
+ describe "parse_args" do
32
+ before(:each) do
33
+ @op = PoolParty::Optioner.new(%w( -v -i 1 five six -x), {:abstract => true, :parse_options => false})
34
+ end
35
+ it "should have an array of default boolean args" do
36
+ @op.boolean_args.sort.should == ['-V', '-h', '-t', '-v']
37
+ end
38
+ it "should split ARGV into flagged and unflagged arg arrays" do
39
+ @op.unflagged_args.sort.sort.should == ["five", "six"]
40
+ @op.flagged_args.should == ["-v", "-i", "1", "-x"]
41
+ end
42
+ end
43
+
30
44
  it "should be able to take a block and set some options on the block" do
31
45
  PoolParty::Optioner.new(["-w"], {:abstract => false, :load_pools => false}) do |opts, optioner|
32
46
  opts.on('-w', '--wee') { optioner.wee "wee" }
@@ -35,6 +35,11 @@ describe "CloudResourcer" do
35
35
  @tc.instances 4..10
36
36
  @tc.minimum_instances.should == 4
37
37
  end
38
+ it "should be able to accept a Fixnum and set the minimum_instances and maximum_instances" do
39
+ @tc.instances 1
40
+ @tc.minimum_instances.should == 1
41
+ @tc.maximum_instances.should == 1
42
+ end
38
43
  it "should set the max to the maximum instances to the last" do
39
44
  @tc.instances 4..10
40
45
  @tc.maximum_instances.should == 10
@@ -10,17 +10,6 @@ module Hype
10
10
  end
11
11
  register_remote_base :Hype
12
12
  end
13
- class TestClass
14
- include Remote
15
- include RemoterBase
16
-
17
- def keypair
18
- "fake_keypair"
19
- end
20
- def verbose
21
- false
22
- end
23
- end
24
13
 
25
14
  describe "Remote" do
26
15
  before(:each) do
@@ -32,6 +21,9 @@ describe "Remote" do
32
21
  @tc.respond_to?(:using).should == true
33
22
  end
34
23
  it "should include the module with using" do
24
+ @tc.instance_eval do
25
+ @remote_base = nil
26
+ end
35
27
  @tc.should_receive(:extend).with("Hype".preserved_module_constant).once
36
28
  @tc.using :hype
37
29
  end
@@ -59,6 +51,9 @@ describe "Remote" do
59
51
  @tc.using :hype
60
52
  end
61
53
  it "should only include the remote class once" do
54
+ @tc.instance_eval do
55
+ @remote_base = nil
56
+ end
62
57
  @tc.should_receive(:extend).with(Hype).once
63
58
  @tc.using :hype
64
59
  @tc.using :hype
@@ -191,10 +186,6 @@ describe "Remote" do
191
186
  @tc.request_termination_of_non_master_instance
192
187
  end
193
188
  end
194
- describe "should_expand_cloud?" do
195
- end
196
- describe "should_contract_cloud?" do
197
- end
198
189
  describe "expansions" do
199
190
  before(:each) do
200
191
  setup
@@ -1,9 +1,12 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
- include Remote
3
+ class TestRemoteClass
4
+ include CloudResourcer
5
+ include PoolParty::Remote
4
6
 
5
- class TestRemoter
6
- include RemoterBase
7
+ def keypair
8
+ "fake_keypair"
9
+ end
7
10
  end
8
11
 
9
12
  describe "RemoterBase" do
@@ -12,7 +15,7 @@ describe "RemoterBase" do
12
15
  end
13
16
  describe "methods" do
14
17
  before(:each) do
15
- @tr = TestRemoter.new
18
+ @tr = TestRemoteClass.new
16
19
  end
17
20
  %w(launch_new_instance! terminate_instance describe_instance instances_list).each do |method|
18
21
  eval <<-EOE
@@ -22,7 +25,7 @@ describe "RemoterBase" do
22
25
  it "should not raise an exception if #{method} is defined as a method" do
23
26
  lambda {
24
27
  @tr.instance_eval do
25
- def #{method}
28
+ def #{method}
26
29
  end
27
30
  end
28
31
  @tr.#{method}
@@ -32,6 +35,7 @@ describe "RemoterBase" do
32
35
  end
33
36
  describe "lists" do
34
37
  before(:each) do
38
+ @tr = TestClass.new
35
39
  stub_list_of_instances_for(@tr)
36
40
  end
37
41
  it "should gather a list of the running instances" do
@@ -47,7 +51,7 @@ describe "RemoterBase" do
47
51
  @tr.list_of_nonterminated_instances.map {|a| a.name }.should == ["master", "node1", "node3"]
48
52
  end
49
53
  it "should return a list of remote instances" do
50
- @tr.remote_instances_list.first.class.should == RemoteInstance
54
+ @tr.remote_instances_list.first.class.should == PoolParty::Remote::RemoteInstance
51
55
  end
52
56
  describe "by keypairs" do
53
57
  it "should be able to grab all the alist keypairs" do
@@ -74,6 +78,7 @@ describe "RemoterBase" do
74
78
  before(:each) do
75
79
  @master = Object.new
76
80
  @master.stub!(:ip).and_return "192.68.0.1"
81
+ @tr = TestClass.new
77
82
  @tr.stub!(:master).and_return @master
78
83
  end
79
84
  it "should have the method custom_install_tasks" do;@tr.respond_to?(:custom_install_tasks_for).should == true;end
@@ -1,21 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
- include PoolParty::Remote
4
-
5
- def valid_rules?(*args)
6
- false
7
- end
8
-
9
- class TestClass
10
- include CloudResourcer
11
- include Remote
12
- using :ec2
13
- attr_accessor :parent
14
-
15
- def keypair
16
- "fake_keypair"
17
- end
18
- end
19
3
  describe "Remoter" do
20
4
  before(:each) do
21
5
  setup
@@ -92,5 +76,31 @@ describe "Remoter" do
92
76
  @tc.launch_and_configure_master!
93
77
  end
94
78
  end
79
+ describe "expansions and contractions" do
80
+ before(:each) do
81
+ @tc = TestClass.new
82
+ stub_list_from_remote_for @tc # sets the list of instances to 2
83
+ end
84
+ describe "are_too_few_instances_running?" do
85
+ it "should be false if the number of running instances is larger than the minimum instances" do
86
+ @tc.stub!(:minimum_instances).and_return 1
87
+ @tc.are_too_few_instances_running?.should == false
88
+ end
89
+ it "should be true if the number of running instances is smaller than the minimum instances" do
90
+ @tc.stub!(:minimum_instances).and_return 5
91
+ @tc.are_too_few_instances_running?.should == true
92
+ end
93
+ end
94
+ describe "are_too_many_instances_running?" do
95
+ it "should be true if the number of running instances is larger than the maximum instances" do
96
+ @tc.stub!(:maximum_instances).and_return 1
97
+ @tc.are_too_many_instances_running?.should == true
98
+ end
99
+ it "should be false if the number of running instances is smaller than the maximum instances" do
100
+ @tc.stub!(:maximum_instances).and_return 5
101
+ @tc.are_too_many_instances_running?.should == false
102
+ end
103
+ end
104
+ end
95
105
 
96
106
  end
@@ -25,7 +25,7 @@ describe "Pool" do
25
25
  @pool.respond_to?(:cloud).should == true
26
26
  end
27
27
  it "should evaluate the block when creating a new pool" do
28
- Proc.should_receive(:new).once
28
+ Proc.should_receive(:new).at_least(1)
29
29
  Pool.new(:test) do
30
30
  Proc.new {puts "hi"}
31
31
  end
@@ -16,6 +16,22 @@ ENV["POOL_SPEC"] = nil
16
16
  include PoolParty
17
17
  extend PoolParty
18
18
 
19
+ def are_too_many_instances_running?
20
+ end
21
+ def are_too_few_instances_running?
22
+ end
23
+
24
+ class TestClass < PoolParty::Cloud::Cloud
25
+ include CloudResourcer
26
+ attr_accessor :parent
27
+ def initialize(&block)
28
+ super :test_cloud, nil, &block
29
+ end
30
+ def keypair
31
+ "fake_keypair"
32
+ end
33
+ end
34
+
19
35
  def setup
20
36
  PoolParty::Messenger.stub!(:messenger_send!).and_return false
21
37
  end
data/tasks/spec.rake CHANGED
@@ -4,14 +4,13 @@ require 'spec/rake/spectask'
4
4
  task :default => :spec
5
5
 
6
6
  Spec::Rake::SpecTask.new(:spec) do |t|
7
- t.warning =
8
- t.rcov = false
7
+ t.warning = t.rcov = false
9
8
  t.spec_files = Dir["spec/**/*_spec.rb"]
10
9
  end
11
10
 
12
11
  Spec::Rake::SpecTask.new(:spec_v) do |t|
13
12
  t.rcov = true
14
- t.rcov_opts = ['--exclude', 'gems*,spec*']
13
+ t.rcov_opts = ['--exclude', 'gems*,spec*,website*,test*']
15
14
  t.ruby_opts = []
16
15
  t.spec_files = Dir["spec/**/*_spec.rb"]
17
16
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auser-poolparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.78
4
+ version: 0.2.79
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Lerner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-05 00:00:00 -08:00
12
+ date: 2008-12-06 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,6 +68,7 @@ executables:
68
68
  - cloud-osxcopy
69
69
  - cloud-provision
70
70
  - cloud-refresh
71
+ - cloud-rsync
71
72
  - cloud-run
72
73
  - cloud-ssh
73
74
  - cloud-start
@@ -127,6 +128,7 @@ files:
127
128
  - bin/cloud-osxcopy
128
129
  - bin/cloud-provision
129
130
  - bin/cloud-refresh
131
+ - bin/cloud-rsync
130
132
  - bin/cloud-run
131
133
  - bin/cloud-ssh
132
134
  - bin/cloud-start
@@ -192,6 +194,7 @@ files:
192
194
  - lib/erlang/messenger/ebin/pm_node_rel-0.1.rel
193
195
  - lib/erlang/messenger/ebin/pm_node_supervisor.beam
194
196
  - lib/erlang/messenger/ebin/pm_packager.beam
197
+ - lib/erlang/messenger/ebin/pm_spawner.beam
195
198
  - lib/erlang/messenger/ebin/pm_strings.beam
196
199
  - lib/erlang/messenger/ebin/utils.beam
197
200
  - lib/erlang/messenger/include/defines.hrl
@@ -271,6 +274,7 @@ files:
271
274
  - lib/erlang/messenger/src/pm_node.erl
272
275
  - lib/erlang/messenger/src/pm_node_supervisor.erl
273
276
  - lib/erlang/messenger/src/pm_packager.erl
277
+ - lib/erlang/messenger/src/pm_spawner.erl
274
278
  - lib/erlang/messenger/src/pm_strings.erl
275
279
  - lib/erlang/messenger/src/utils.erl
276
280
  - lib/erlang/messenger/useful_snippets
@@ -502,7 +506,6 @@ files:
502
506
  - test/test_helper.rb
503
507
  - test/test_pool_spec_generator.rb
504
508
  - test/test_poolparty.rb
505
- - website/index.html
506
509
  - website/index.txt
507
510
  - website/javascripts/rounded_corners_lite.inc.js
508
511
  - website/stylesheets/code.css
@@ -511,7 +514,7 @@ files:
511
514
  has_rdoc: true
512
515
  homepage: http://poolparty.rubyforge.org
513
516
  post_install_message: |-
514
- Get ready to jump in the pool, you just installed PoolParty! (Updated at 09:44 12/05/08)
517
+ Get ready to jump in the pool, you just installed PoolParty! (Updated at 13:46 12/06/08)
515
518
 
516
519
  To get started, run the generator:
517
520
 
data/website/index.html DELETED
@@ -1,107 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
- <head>
5
- <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
- <title>
8
- PoolParty
9
- </title>
10
- <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
- <link href="stylesheets/code.css" media="screen" rel="stylesheet" type="text/css" />
12
- <style>
13
-
14
- </style>
15
- <script type="text/javascript">
16
- window.onload = function() {
17
- settings = {
18
- tl: { radius: 10 },
19
- tr: { radius: 10 },
20
- bl: { radius: 10 },
21
- br: { radius: 10 },
22
- antiAlias: true,
23
- autoPad: true,
24
- validTags: ["div"]
25
- }
26
- var versionBox = new curvyCorners(settings, document.getElementById("version"));
27
- versionBox.applyCornersToAll();
28
- }
29
- </script>
30
- </head>
31
- <body>
32
- <div id="main">
33
-
34
- <h1>PoolParty</h1>
35
- <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/poolparty"; return false'>
36
- <p>Get Version</p>
37
- <a href="http://rubyforge.org/projects/poolparty" class="numbers">0.2.76</a>
38
- </div>
39
- <h1>&#8216;Easy cloud computing&#8217;</h1>
40
- <h2>What</h2>
41
- <p>A self-healing, load-balanced cloud computing solution. Combined with the power of <a href="http://reductivelabs.com/trac/puppet/">Puppet</a>, the <a href="http://www.linux-ha.org/">High Availability</a> project, ruby and erlang, PoolParty makes it easy and fun to set up your cloud! Currently, you can use it with ec2, but it&#8217;s not tied to any particular service. You can use PoolParty to manage and monitor your home network!</p>
42
- <h2>Installing</h2>
43
- <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="punct">--</span><span class="ident">source</span> <span class="ident">http</span><span class="punct">:/</span><span class="regex"></span><span class="punct">/</span><span class="ident">gems</span><span class="punct">.</span><span class="ident">github</span><span class="punct">.</span><span class="ident">com</span> <span class="ident">auser</span><span class="punct">-</span><span class="ident">poolparty</span></pre></p>
44
- <h2>The basics</h2>
45
- <h2>Demonstration of usage</h2>
46
- <pre>
47
- cloud spec [name]
48
- </pre>
49
- <p>This will create a basic spec for you in the spec directory. Then, write your spec file. There are examples in the repos as well as the one below:</p>
50
- <p><pre class='syntax'>
51
- <span class="comment"># Basic poolparty template with apache plugin</span>
52
- <span class="ident">require</span> <span class="punct">&quot;</span><span class="string">poolparty-apache2-plugin</span><span class="punct">&quot;</span>
53
-
54
- <span class="ident">pool</span> <span class="symbol">:app</span> <span class="keyword">do</span>
55
-
56
- <span class="ident">instances</span> <span class="number">2</span><span class="punct">..</span><span class="number">5</span>
57
- <span class="ident">port</span> <span class="number">80</span>
58
- <span class="ident">ami</span> <span class="punct">&quot;</span><span class="string">ami-1cd73375</span><span class="punct">&quot;</span> <span class="comment"># Alestic Ubuntu AMI</span>
59
-
60
- <span class="ident">cloud</span> <span class="symbol">:app</span> <span class="keyword">do</span>
61
-
62
- <span class="ident">apache</span> <span class="keyword">do</span>
63
- <span class="ident">installed_as_worker</span>
64
-
65
- <span class="ident">has_virtualhost</span> <span class="keyword">do</span>
66
-
67
- <span class="ident">name</span> <span class="punct">&quot;</span><span class="string">poolpartyrb.com</span><span class="punct">&quot;</span>
68
- <span class="ident">listen</span><span class="punct">(&quot;</span><span class="string">8080</span><span class="punct">&quot;)</span>
69
- <span class="ident">virtual_host_entry</span> <span class="punct">::</span><span class="constant">File</span><span class="punct">.</span><span class="ident">join</span><span class="punct">(</span><span class="constant">File</span><span class="punct">.</span><span class="ident">dirname</span><span class="punct">(</span><span class="constant">__FILE__</span><span class="punct">),</span> <span class="punct">&quot;</span><span class="string">templates</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">virtual_host.conf.erb</span><span class="punct">&quot;)</span>
70
-
71
- <span class="ident">has_git</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">poolpartyrepos</span><span class="punct">&quot;,</span> <span class="symbol">:source</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">git://github.com/auser/xnot.org.git</span><span class="punct">&quot;,</span> <span class="symbol">:path</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">/var/www/xnot.org/public</span><span class="punct">&quot;)</span>
72
-
73
- <span class="keyword">end</span>
74
- <span class="keyword">end</span>
75
-
76
- <span class="keyword">end</span>
77
-
78
- <span class="keyword">end</span>
79
- </pre></p>
80
- <h2>Forum</h2>
81
- <p><a href="http://groups.google.com/group/poolpartyrb">http://groups.google.com/group/PoolPartyRb</a></p>
82
- <h2>How to submit patches</h2>
83
- <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
84
- <p>The trunk repository is <code>http://github.com/auser/poolparty</code> for anonymous access.</p>
85
- <p>You can fetch the source from either:</p>
86
- <ul>
87
- <li>github: <a href="http://github.com/auser/PoolParty/tree/master">http://github.com/auser/PoolParty/tree/master</a></li>
88
- </ul>
89
- <pre>git clone git://github.com/auser/poolparty.git</pre>
90
- <h3>Build and test instructions</h3>
91
- <p><pre class='syntax'>cd PoolParty
92
- rake spec
93
- rake install_gem</pre></p>
94
- <h2>License</h2>
95
- <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
96
- <h2>Contact</h2>
97
- <p>Comments are welcome. Send an email to <a href="mailto:ari.lerner@citrusbyte.com">Ari Lerner</a> email via the <a href="http://groups.google.com/group/PoolParty">forum</a></p>
98
- <p class="coda">
99
- <a href="http://blog.citrusbyte.com">Ari Lerner</a> at <a href="http://citrusbyte.com">CitrusByte</a>, 15th October 2008<br>
100
- Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
101
- </p>
102
- </div>
103
-
104
- <!-- insert site tracking codes here, like Google Urchin -->
105
-
106
- </body>
107
- </html>