auser-poolparty 0.2.21 → 0.2.22

Sign up to get free protection for your applications and to get access to all the features.
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