auser-poolparty 0.2.21 → 0.2.22

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
@@ -140,10 +140,12 @@ lib/poolparty/base_packages/poolparty.rb
140
140
  lib/poolparty/base_packages/ruby.rb
141
141
  lib/poolparty/config/allowed_commands.yml
142
142
  lib/poolparty/core/array.rb
143
+ lib/poolparty/core/class.rb
143
144
  lib/poolparty/core/exception.rb
144
145
  lib/poolparty/core/float.rb
145
146
  lib/poolparty/core/hash.rb
146
147
  lib/poolparty/core/kernel.rb
148
+ lib/poolparty/core/metaid.rb
147
149
  lib/poolparty/core/module.rb
148
150
  lib/poolparty/core/my_open_struct.rb
149
151
  lib/poolparty/core/object.rb
@@ -153,6 +155,7 @@ lib/poolparty/core/symbol.rb
153
155
  lib/poolparty/core/time.rb
154
156
  lib/poolparty/dependency_resolutions/base.rb
155
157
  lib/poolparty/dependency_resolutions/puppet.rb
158
+ lib/poolparty/exceptions/MasterException.rb
156
159
  lib/poolparty/exceptions/RemoteException.rb
157
160
  lib/poolparty/exceptions/ResourceException.rb
158
161
  lib/poolparty/exceptions/RuntimeException.rb
data/PostInstall.txt CHANGED
@@ -11,8 +11,7 @@ Tutorials are at http://poolpartyrb.com
11
11
 
12
12
  Don't forget to check out the plugin tutorial @ http://poolpartyrb.com to extend PoolParty for your needs!
13
13
 
14
- For more information, check http://PoolPartyrb.com
15
- On IRC:
14
+ For more information, check http://PoolPartyrb.com or visit us on IRC at:
16
15
  irc.freenode.net
17
16
  #poolpartyrb
18
17
 
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ task :gemspec => [:spec, :clean_tmp, :"manifest:refresh", :local_deploy, :clean
25
25
  end
26
26
 
27
27
  desc "Generate gemspec for github"
28
- task :githubspec => [:gemspec] do
28
+ task :gh => [:gemspec] do
29
29
  filepath = ::File.join(::File.dirname(__FILE__), "poolparty.gemspec")
30
30
  data = open(filepath).read
31
31
  spec = eval("$SAFE = 3\n#{data}")
data/bin/cloud-start CHANGED
@@ -17,7 +17,7 @@ load_pool(o.spec || Binary.get_existing_spec_location)
17
17
  with_cloud(cloud, {:testing => @testing}) do
18
18
  puts header("Starting cloud")
19
19
  puts "#{list_of_running_instances.size} running instances (#{minimum_instances} - #{maximum_instances})"
20
- if (minimum_instances - list_of_running_instances.size) > 0
20
+ if list_of_running_instances.size != 1
21
21
  puts "Starting the master instance"
22
22
  if testing
23
23
  puts("\tNot launching while in testing mode")
data/config/hoe.rb CHANGED
@@ -12,7 +12,6 @@ HOMEPATH = "http://#{GEM_NAME}.rubyforge.org"
12
12
  DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
13
13
  EXTRA_DEPENDENCIES = [
14
14
  ['activesupport'],
15
- ['open4'],
16
15
  ['logging'],
17
16
  ["ruby2ruby"]
18
17
  ] # An array of rubygem dependencies [name, version]
data/lib/poolparty.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
 
3
3
  # Load required gems
4
- %w(activesupport open4 ftools logging ruby2ruby).each do |lib|
4
+ %w(activesupport ftools logging ruby2ruby).each do |lib|
5
5
  begin
6
6
  require lib
7
7
  rescue Exception => e
@@ -7,22 +7,20 @@ module PoolParty
7
7
  has_package(:name => "erlang-dev")
8
8
  has_package(:name => "erlang-src")
9
9
 
10
- has_package(:name => "rubygems") do
10
+ has_package(:name => "rubygems") do |g|
11
11
  # These should be installed automagically by poolparty, but just in case
12
12
  # TODO: Fix the requires method with a helper
13
- has_gempackage(:name => "logging")
14
- has_gempackage(:name => "xml-simple", :source => "/var/poolparty/xml-simple.gem") do
15
- has_gempackage(:name => "grempe-amazon-ec2", :source => "http://gems.github.com")
13
+ g.has_gempackage(:name => "logging")
14
+ g.has_gempackage(:name => "xml-simple") do |x|
15
+ x.has_gempackage(:name => "grempe-amazon-ec2", :source => "http://gems.github.com")
16
16
  end
17
17
 
18
- has_gempackage(:name => "open4")
19
-
20
- has_gempackage(:name => "ParseTree", :version => "2.2.0") do
21
- has_gempackage(:name => "ruby2ruby")
22
- has_gempackage(:name => "activesupport") do
23
- has_gempackage(:name => "auser-poolparty", :source => "http://gems.github.com") do
24
- has_exec(:name => "build_messenger", :command => ". /etc/profile && server-build-messenger") do
25
- has_exec(:name => "start_node", :command => ". /etc/profile && server-start-node")
18
+ has_gempackage(:name => "ParseTree", :version => "3.0.1") do |pt|
19
+ pt.has_gempackage(:name => "ruby2ruby")
20
+ pt.has_gempackage(:name => "activesupport") do |a|
21
+ a.has_gempackage(:name => "auser-poolparty", :source => "http://gems.github.com") do |pool|
22
+ pool.has_exec(:name => "build_messenger", :command => ". /etc/profile && server-build-messenger") do |mess|
23
+ mess.has_exec(:name => "start_node", :command => ". /etc/profile && server-start-node")
26
24
  end
27
25
  end
28
26
  end
@@ -0,0 +1,2 @@
1
+ class Class
2
+ end
@@ -2,8 +2,9 @@
2
2
  Exception overloads
3
3
  =end
4
4
  class Exception
5
+ alias nice_message to_str
5
6
  # Gives us a nice_message for exceptions
6
7
  def nice_message(padding="")
7
- "#{padding}#{message}\n#{padding}" + backtrace.join("\n#{padding}")
8
+ "#{padding}#{message}\n#{padding}"# + backtrace.join("\n#{padding}")
8
9
  end
9
10
  end
@@ -33,5 +33,5 @@ module Kernel
33
33
  STDOUT.flush
34
34
  STDOUT.reopen(old_stdout)
35
35
  end
36
- end
36
+ end
37
37
  end
@@ -0,0 +1,15 @@
1
+ class Object
2
+ # The hidden singleton lurks behind everyone
3
+ def metaclass; class << self; self; end; end
4
+ def meta_eval &blk; metaclass.instance_eval &blk; end
5
+
6
+ # Adds methods to a metaclass
7
+ def meta_def name, &blk
8
+ meta_eval { define_method name, &blk }
9
+ end
10
+
11
+ # Defines an instance method within a class
12
+ def class_def name, &blk
13
+ class_eval { define_method name, &blk }
14
+ end
15
+ end
@@ -57,6 +57,16 @@ class Object
57
57
  block_method.bind(self).call(*args)
58
58
  end
59
59
  def meta_def name, &blk
60
- (class << self; self; end).instance_eval { define_method name, &blk }
60
+ meta_eval { define_method name, &blk }
61
+ end
62
+ def meta_undef name
63
+ meta_eval { remove_method name }
64
+ end
65
+ def run_in_context(&block)
66
+ name="temp_#{self.class}_#{parent.to_s}".to_sym
67
+ meta_def name, &block
68
+ self.send name, self
69
+ # self.instance_eval &block if block
70
+ meta_undef name
61
71
  end
62
72
  end
@@ -0,0 +1,10 @@
1
+ class MasterException < Exception
2
+ EXCEPTION_MESSAGES = {
3
+ :no_ip => "Master does not have an ip or has not been launched"
4
+ }
5
+ attr_reader :message
6
+
7
+ def initialize(type=:no_ip, note="")
8
+ @message = "Master Exception: #{EXCEPTION_MESSAGES[type]} #{note}"
9
+ end
10
+ end
@@ -15,6 +15,10 @@ module PoolParty
15
15
  def self.configure_master(cloud, testing=false)
16
16
  Provisioner::Master.new(cloud).process_configure!(testing)
17
17
  end
18
+
19
+ def self.reconfigure_master(cloud, testing=false)
20
+ Provisioner::Master.new(cloud).process_reconfigure!(testing)
21
+ end
18
22
 
19
23
  def self.provision_slaves(cloud, testing=false)
20
24
  cloud.nonmaster_nonterminated_instances.each do |sl|
@@ -46,7 +50,7 @@ module PoolParty
46
50
  @cloud = cloud
47
51
 
48
52
  options(cloud.options) if cloud && cloud.respond_to?(:options)
49
- set_vars_from_options(instance.options) unless instance.nil? || instance.options.empty?
53
+ set_vars_from_options(instance.options) unless instance.nil? || !instance.options.empty?
50
54
  options(instance.options) if instance.respond_to?(:options)
51
55
 
52
56
  @os = os.to_s.downcase.to_sym
@@ -65,6 +69,9 @@ module PoolParty
65
69
  provisioner_file = ::File.join(Base.storage_directory, "install_#{name}.sh")
66
70
  ::File.open(provisioner_file, "w+") {|f| f << install }
67
71
  end
72
+ def name
73
+ @instance.name
74
+ end
68
75
  def process_install!(testing=false)
69
76
  error unless valid?
70
77
  write_install_file
@@ -102,6 +109,9 @@ module PoolParty
102
109
  @cloud.run_command_on(cmd, @instance)
103
110
  end
104
111
  end
112
+ def process_reconfigure!(testing=false)
113
+ @cloud.run_command_on("puppetd --test 2>&1 &", @instance) unless testing
114
+ end
105
115
  def setup_runner(cloud)
106
116
  cloud.prepare_to_configuration
107
117
  cloud.build_and_store_new_config_file
@@ -231,8 +241,8 @@ module PoolParty
231
241
  "
232
242
  touch /etc/apt/sources.list
233
243
  echo 'deb http://mirrors.kernel.org/ubuntu hardy main universe' >> /etc/apt/sources.list
234
- # aptitude update -y 2>&1
235
- # aptitude autoclean 2>&1 &
244
+ aptitude update -y 2>&1
245
+ aptitude autoclean 2>&1
236
246
  "
237
247
  else
238
248
  "# No system upgrade needed"
@@ -3,6 +3,7 @@ module PoolParty
3
3
  class Master < ProvisionerBase
4
4
 
5
5
  def initialize(cloud=self, os=:ubuntu)
6
+ raise MasterException.new(:no_ip) unless cloud.master && cloud.master.ip
6
7
  super(cloud.master, cloud, os)
7
8
  @master_ip = cloud.master.ip
8
9
  end
@@ -4,13 +4,13 @@ module PoolParty
4
4
 
5
5
  def install_tasks
6
6
  [
7
- setup_puppet
7
+ setup_puppet,
8
+ setup_configs
8
9
  ] << configure_tasks
9
10
  end
10
11
 
11
12
  def configure_tasks
12
- [
13
- setup_configs,
13
+ [
14
14
  start_puppet
15
15
  ]
16
16
  end
@@ -20,8 +20,9 @@ module PoolParty
20
20
  begin
21
21
  item = instance#.instancesSet.item
22
22
  EC2ResponseObject.get_hash_from_response(item)
23
- rescue Exception => e
23
+ rescue Exception => e
24
24
  end
25
+ instance
25
26
  end
26
27
  # Terminate an instance by id
27
28
  def terminate_instance!(instance_id=nil)
@@ -181,8 +181,9 @@ module PoolParty
181
181
  reset!
182
182
  when_no_pending_instances do
183
183
  wait "20.seconds" # Give some time for ssh to startup
184
- PoolParty::Provisioner.provision_slaves(self)
185
- PoolParty::Provisioner.configure_master(self, testing)
184
+ last_instance = nonmaster_nonterminated_instances.last
185
+ PoolParty::Provisioner.provision_slave(last_instance, self)
186
+ PoolParty::Provisioner.reconfigure_master(self, force)
186
187
  # prepare_reconfiguration
187
188
  end
188
189
  end
@@ -9,6 +9,8 @@ module PoolParty
9
9
 
10
10
  def has_git_repos
11
11
  has_package(:name => "git-core")
12
+ has_directory(:name => "#{cwd}")
13
+
12
14
  exec({:name => "git-#{name}", :requires => package(:name => "git-core")}) do
13
15
  command parent.user ? "git clone #{parent.user}@#{parent.source} #{parent.path}" : "git clone #{parent.source} #{parent.to ? parent.to : ""}"
14
16
  cwd "#{parent.cwd if parent.cwd}"
@@ -115,25 +115,29 @@ module PoolParty
115
115
  reset_resources!
116
116
  add_poolparty_base_requirements
117
117
 
118
- @build_manifest = returning Array.new do |str|
119
-
120
- # Refactor this into the resources method
121
- # TODO
122
- services.each do |service|
123
- @cp = classpackage_with_self(service)
124
- str << @cp.to_string
125
- str << @cp.include_string
126
- end
127
-
128
- str << resources_string_from_resources(resources)
129
-
130
- str << "# Custom functions"
131
- str << Resources::CustomResource.custom_functions_to_string
132
- end.join("\n")
118
+ @build_manifest = build_short_manifest
133
119
  end
134
120
  @build_manifest
135
121
  end
136
122
 
123
+ def build_short_manifest
124
+ returning Array.new do |str|
125
+
126
+ # Refactor this into the resources method
127
+ # TODO
128
+ services.each do |service|
129
+ @cp = classpackage_with_self(service)
130
+ str << @cp.to_string
131
+ str << @cp.include_string
132
+ end
133
+
134
+ str << resources_string_from_resources(resources)
135
+
136
+ str << "# Custom functions"
137
+ str << Resources::CustomResource.custom_functions_to_string
138
+ end.join("\n")
139
+ end
140
+
137
141
  def build_from_existing_file
138
142
  if ::FileTest.file?("/etc/puppet/manifests/classes/poolparty.pp")
139
143
  open("/etc/puppet/manifests/classes/poolparty.pp").read
@@ -108,7 +108,7 @@ module PoolParty
108
108
  # Take the options of the parents
109
109
  set_resource_parent(parent)
110
110
  set_vars_from_options(opts) unless opts.empty?
111
- self.instance_eval &block if block
111
+ self.run_in_context &block if block
112
112
  loaded(opts, @parent)
113
113
  end
114
114
 
@@ -6,10 +6,19 @@ module PoolParty
6
6
  # When we call gempackage, we want the exec to run on the directory we suggest
7
7
  # we also only want it to run if there is NOT a local gem already installed with
8
8
  # the package details (version and name)
9
+ #
10
+ # TODO: Add it so that it tries to pull the gem off the master fileserver first...
9
11
  def loaded(opts={}, parent=self)
12
+ # has_exec(:name => "unpack-#{name}-into-fileserver", :command => "gem unpack #{name} && mv #{name}* #{name}.gem", :cwd => Base.remote_storage_path) do
13
+ # ifnot "test -d #{Base.remote_storage_path}/#{name}.gem"
14
+ # end
15
+
10
16
  has_exec(opts.merge({:name => name, :cwd => "/tmp", :path => "/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/var/lib/gems/1.8/bin"}), parent) do
11
- command "gem install -y --no-ri --no-rdoc #{"--version #{version}" if version} #{"--source #{source}" if source} #{name}"
17
+ command "gem install -y --no-ri --no-rdoc #{"--version #{version}" if version} #{"--source #{source}" if source} #{name} <<heredoc
18
+ 1
19
+ heredoc"
12
20
  ifnot "gem list --local #{name} | grep #{name} #{"| grep #{version}" if version}"
21
+ # notify get_exec("unpack-#{name}-into-fileserver")
13
22
  end
14
23
  end
15
24
  def virtual_resource?
@@ -2,7 +2,7 @@ module PoolParty
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- TINY = 21
5
+ TINY = 22
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.21
4
+ version: 0.2.22
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-10-25 00:00:00 -07:00
12
+ date: 2008-10-27 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,16 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: open4
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: logging
37
27
  type: :runtime
@@ -248,10 +238,12 @@ files:
248
238
  - lib/poolparty/base_packages/ruby.rb
249
239
  - lib/poolparty/config/allowed_commands.yml
250
240
  - lib/poolparty/core/array.rb
241
+ - lib/poolparty/core/class.rb
251
242
  - lib/poolparty/core/exception.rb
252
243
  - lib/poolparty/core/float.rb
253
244
  - lib/poolparty/core/hash.rb
254
245
  - lib/poolparty/core/kernel.rb
246
+ - lib/poolparty/core/metaid.rb
255
247
  - lib/poolparty/core/module.rb
256
248
  - lib/poolparty/core/my_open_struct.rb
257
249
  - lib/poolparty/core/object.rb
@@ -261,6 +253,7 @@ files:
261
253
  - lib/poolparty/core/time.rb
262
254
  - lib/poolparty/dependency_resolutions/base.rb
263
255
  - lib/poolparty/dependency_resolutions/puppet.rb
256
+ - lib/poolparty/exceptions/MasterException.rb
264
257
  - lib/poolparty/exceptions/RemoteException.rb
265
258
  - lib/poolparty/exceptions/ResourceException.rb
266
259
  - lib/poolparty/exceptions/RuntimeException.rb
@@ -443,8 +436,7 @@ post_install_message: |-
443
436
 
444
437
  Don't forget to check out the plugin tutorial @ http://poolpartyrb.com to extend PoolParty for your needs!
445
438
 
446
- For more information, check http://PoolPartyrb.com
447
- On IRC:
439
+ For more information, check http://PoolPartyrb.com or visit us on IRC at:
448
440
  irc.freenode.net
449
441
  #poolpartyrb
450
442
 
@@ -56,5 +56,14 @@ describe "Object" do
56
56
  @b.dude.should == "totally"
57
57
  end
58
58
  end
59
+ describe "contextual running" do
60
+ before(:each) do
61
+ @obj.stub!(:default_options).and_return {}
62
+ @a = @obj.run_in_context { @a = "hello world" }
63
+ end
64
+ it "should have the method meta_eval" do
65
+ @obj.respond_to?(:meta_eval).should == true
66
+ end
67
+ end
59
68
  end
60
69
  end
@@ -194,8 +194,15 @@ describe "Remote" do
194
194
  before(:each) do
195
195
  @tc.stub!(:copy_ssh_app).and_return true
196
196
  @tc.stub!(:prepare_reconfiguration).and_return "full"
197
- PoolParty::Provisioner.stub!(:configure_master).and_return true
197
+ PoolParty::Provisioner.stub!(:reconfigure_master).and_return true
198
198
  @tc.stub!(:wait).and_return true
199
+ @tc.stub!(:nonmaster_nonterminated_instances).and_return true
200
+ @inst = stub_instance(9, "running")
201
+ @tc.nonmaster_nonterminated_instances.stub!(:last).and_return @inst
202
+ @inst.stub!(:options).and_return({:name => "red"})
203
+ @tc.stub!(:rsync_storage_files_to).and_return true
204
+ @tc.stub!(:run_command_on).and_return true
205
+ @tc.stub!(:full_keypair_path).and_return "true"
199
206
  end
200
207
  describe "expand_cloud_if_necessary" do
201
208
  before(:each) do
@@ -219,7 +226,11 @@ describe "Remote" do
219
226
  end
220
227
  it "should call a new slave provisioner" do
221
228
  @tc.stub!(:should_expand_cloud?).once.and_return true
222
- PoolParty::Provisioner.should_receive(:provision_slaves).and_return true
229
+ PoolParty::Provisioner.should_receive(:provision_slave).and_return true
230
+ end
231
+ it "should call reconfigure on the master to pick up the new slave" do
232
+ @tc.stub!(:should_expand_cloud?).once.and_return true
233
+ PoolParty::Provisioner.should_receive(:reconfigure_master).once
223
234
  end
224
235
  after(:each) do
225
236
  @tc.expand_cloud_if_necessary
data/website/index.html CHANGED
@@ -34,7 +34,7 @@
34
34
  <h1>PoolParty</h1>
35
35
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/poolparty"; return false'>
36
36
  <p>Get Version</p>
37
- <a href="http://rubyforge.org/projects/poolparty" class="numbers">0.2.21</a>
37
+ <a href="http://rubyforge.org/projects/poolparty" class="numbers">0.2.22</a>
38
38
  </div>
39
39
  <h1>&#8216;Easy cloud computing&#8217;</h1>
40
40
  <h2>What</h2>
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.21
4
+ version: 0.2.22
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-10-25 00:00:00 -07:00
12
+ date: 2008-10-27 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,16 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: open4
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: logging
37
27
  type: :runtime
@@ -248,10 +238,12 @@ files:
248
238
  - lib/poolparty/base_packages/ruby.rb
249
239
  - lib/poolparty/config/allowed_commands.yml
250
240
  - lib/poolparty/core/array.rb
241
+ - lib/poolparty/core/class.rb
251
242
  - lib/poolparty/core/exception.rb
252
243
  - lib/poolparty/core/float.rb
253
244
  - lib/poolparty/core/hash.rb
254
245
  - lib/poolparty/core/kernel.rb
246
+ - lib/poolparty/core/metaid.rb
255
247
  - lib/poolparty/core/module.rb
256
248
  - lib/poolparty/core/my_open_struct.rb
257
249
  - lib/poolparty/core/object.rb
@@ -261,6 +253,7 @@ files:
261
253
  - lib/poolparty/core/time.rb
262
254
  - lib/poolparty/dependency_resolutions/base.rb
263
255
  - lib/poolparty/dependency_resolutions/puppet.rb
256
+ - lib/poolparty/exceptions/MasterException.rb
264
257
  - lib/poolparty/exceptions/RemoteException.rb
265
258
  - lib/poolparty/exceptions/ResourceException.rb
266
259
  - lib/poolparty/exceptions/RuntimeException.rb
@@ -443,8 +436,7 @@ post_install_message: |-
443
436
 
444
437
  Don't forget to check out the plugin tutorial @ http://poolpartyrb.com to extend PoolParty for your needs!
445
438
 
446
- For more information, check http://PoolPartyrb.com
447
- On IRC:
439
+ For more information, check http://PoolPartyrb.com or visit us on IRC at:
448
440
  irc.freenode.net
449
441
  #poolpartyrb
450
442