auser-poolparty 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CHANGELOG +12 -0
  2. data/Manifest +115 -0
  3. data/README.txt +140 -0
  4. data/Rakefile +27 -0
  5. data/bin/instance +61 -0
  6. data/bin/pool +62 -0
  7. data/config/cloud_master_takeover +17 -0
  8. data/config/create_proxy_ami.sh +582 -0
  9. data/config/haproxy.conf +29 -0
  10. data/config/heartbeat.conf +8 -0
  11. data/config/heartbeat_authkeys.conf +2 -0
  12. data/config/installers/ubuntu_install.sh +77 -0
  13. data/config/monit/haproxy.monit.conf +7 -0
  14. data/config/monit/nginx.monit.conf +0 -0
  15. data/config/monit.conf +9 -0
  16. data/config/nginx.conf +24 -0
  17. data/config/reconfigure_instances_script.sh +18 -0
  18. data/config/sample-config.yml +23 -0
  19. data/config/scp_instances_script.sh +12 -0
  20. data/lib/core/array.rb +13 -0
  21. data/lib/core/exception.rb +9 -0
  22. data/lib/core/float.rb +13 -0
  23. data/lib/core/hash.rb +11 -0
  24. data/lib/core/kernel.rb +12 -0
  25. data/lib/core/module.rb +22 -0
  26. data/lib/core/object.rb +18 -0
  27. data/lib/core/proc.rb +15 -0
  28. data/lib/core/string.rb +49 -0
  29. data/lib/core/time.rb +41 -0
  30. data/lib/modules/callback.rb +133 -0
  31. data/lib/modules/ec2_wrapper.rb +82 -0
  32. data/lib/modules/safe_instance.rb +31 -0
  33. data/lib/modules/vlad_override.rb +82 -0
  34. data/lib/poolparty/application.rb +170 -0
  35. data/lib/poolparty/init.rb +6 -0
  36. data/lib/poolparty/master.rb +329 -0
  37. data/lib/poolparty/monitors/cpu.rb +19 -0
  38. data/lib/poolparty/monitors/memory.rb +26 -0
  39. data/lib/poolparty/monitors/web.rb +23 -0
  40. data/lib/poolparty/monitors.rb +13 -0
  41. data/lib/poolparty/optioner.rb +16 -0
  42. data/lib/poolparty/plugin.rb +43 -0
  43. data/lib/poolparty/plugin_manager.rb +67 -0
  44. data/lib/poolparty/provider/packages/essential.rb +6 -0
  45. data/lib/poolparty/provider/packages/git.rb +4 -0
  46. data/lib/poolparty/provider/packages/haproxy.rb +20 -0
  47. data/lib/poolparty/provider/packages/heartbeat.rb +4 -0
  48. data/lib/poolparty/provider/packages/monit.rb +6 -0
  49. data/lib/poolparty/provider/packages/rsync.rb +4 -0
  50. data/lib/poolparty/provider/packages/ruby.rb +37 -0
  51. data/lib/poolparty/provider/packages/s3fuse.rb +11 -0
  52. data/lib/poolparty/provider/provider.rb +60 -0
  53. data/lib/poolparty/provider.rb +2 -0
  54. data/lib/poolparty/remote_instance.rb +216 -0
  55. data/lib/poolparty/remoter.rb +106 -0
  56. data/lib/poolparty/remoting.rb +112 -0
  57. data/lib/poolparty/scheduler.rb +103 -0
  58. data/lib/poolparty/tasks/cloud.rake +57 -0
  59. data/lib/poolparty/tasks/development.rake +38 -0
  60. data/lib/poolparty/tasks/ec2.rake +20 -0
  61. data/lib/poolparty/tasks/instance.rake +63 -0
  62. data/lib/poolparty/tasks/plugins.rake +30 -0
  63. data/lib/poolparty/tasks/server.rake +42 -0
  64. data/lib/poolparty/tasks.rb +29 -0
  65. data/lib/poolparty/tmp.rb +46 -0
  66. data/lib/poolparty.rb +105 -0
  67. data/lib/s3/s3_object_store_folders.rb +44 -0
  68. data/misc/basics_tutorial.txt +142 -0
  69. data/poolparty.gemspec +72 -0
  70. data/spec/application_spec.rb +39 -0
  71. data/spec/callback_spec.rb +194 -0
  72. data/spec/core_spec.rb +15 -0
  73. data/spec/helpers/ec2_mock.rb +44 -0
  74. data/spec/kernel_spec.rb +11 -0
  75. data/spec/master_spec.rb +203 -0
  76. data/spec/monitors/cpu_monitor_spec.rb +38 -0
  77. data/spec/monitors/memory_spec.rb +50 -0
  78. data/spec/monitors/misc_monitor_spec.rb +50 -0
  79. data/spec/monitors/web_spec.rb +39 -0
  80. data/spec/optioner_spec.rb +22 -0
  81. data/spec/plugin_manager_spec.rb +31 -0
  82. data/spec/plugin_spec.rb +101 -0
  83. data/spec/pool_binary_spec.rb +10 -0
  84. data/spec/poolparty_spec.rb +15 -0
  85. data/spec/provider_spec.rb +17 -0
  86. data/spec/remote_instance_spec.rb +149 -0
  87. data/spec/remoter_spec.rb +65 -0
  88. data/spec/remoting_spec.rb +84 -0
  89. data/spec/scheduler_spec.rb +75 -0
  90. data/spec/spec_helper.rb +39 -0
  91. data/spec/string_spec.rb +28 -0
  92. data/web/static/conf/nginx.conf +22 -0
  93. data/web/static/site/images/balloon.png +0 -0
  94. data/web/static/site/images/cb.png +0 -0
  95. data/web/static/site/images/clouds.png +0 -0
  96. data/web/static/site/images/railsconf_preso_img.png +0 -0
  97. data/web/static/site/index.html +71 -0
  98. data/web/static/site/javascripts/application.js +3 -0
  99. data/web/static/site/javascripts/corner.js +178 -0
  100. data/web/static/site/javascripts/jquery-1.2.6.pack.js +11 -0
  101. data/web/static/site/misc.html +42 -0
  102. data/web/static/site/storage/pool_party_presentation.pdf +0 -0
  103. data/web/static/site/stylesheets/application.css +100 -0
  104. data/web/static/site/stylesheets/reset.css +17 -0
  105. data/web/static/src/layouts/application.haml +25 -0
  106. data/web/static/src/pages/index.haml +25 -0
  107. data/web/static/src/pages/misc.haml +5 -0
  108. data/web/static/src/stylesheets/application.sass +100 -0
  109. metadata +260 -0
@@ -0,0 +1,142 @@
1
+ PoolParty, a tutorial.
2
+
3
+ To get PoolParty up and running on your very own ec2 instances, you have to do a few things in preparation first.
4
+
5
+ First, install the gem with:
6
+
7
+ sudo gem install auser-poolparty -s http://gems.github.com
8
+
9
+ First, head on over to http://aws.amazon.com and sign up for an account. Make sure you make note of the access key and the secret access key on the access identifiers page. Also, scroll down to the bottom of that page and download your x.509 certificate and the private one as well. You only can generate that once, so make sure you download it immediately. Finally, take note of your account id.
10
+
11
+ Now, let's get to some PoolParty setup. PoolParty only requires one file, a configuration file. Once you get this setup, PoolParty will do the rest for you, so let's get started editing the config file.
12
+
13
+ There is a generator in progress, so if by the time you read this and you have the gem installed, type
14
+
15
+ which poolparty
16
+
17
+ If you get a response, then the generator has been built and you can skip this section and go right to the next 'using it' section, however, if not or you just want to understand the innerworkings, read on.
18
+
19
+ config/config.yml
20
+ PoolParty makes the guess that your config is in a file and is in config/config.yml in your base project directory. However, this is not necessary if you do not want a configuration file, since all options can be added at runtime using switches on the command-line. That being said, the easiest way is to write a config file.
21
+
22
+ The minimal config file looks like this:
23
+
24
+ :access_key: "1XCTNEK1CC5BQXXXXXXX"
25
+ :secret_access_key: "Q2qJHP0S2iOKikn9glB+XXXX/XXXXXXXX/XXXXXXX"
26
+ :ami: "ami-3057b259"
27
+
28
+ That's it. However,a more complete one would look more like this:
29
+
30
+ :app_name: "test_app"
31
+ :user_id: "1619-6456-1111"
32
+ :access_key: "1XCTNEK1CC5BQXXXXXXX"
33
+ :secret_access_key: "Q2qJHP0S2iOKikn9glB+XXXX/XXXXXXXX/XXXXXXX"
34
+ :ami: "ami-3057b259"
35
+ :size: small
36
+ :polling_time: "5.minutes"
37
+ :minimum_instances: 2
38
+ :maximum_instances: 10
39
+ :ec2_dir: "/Users/user/.ec2"
40
+ :keypair: user
41
+ :os: ubuntu
42
+ :host_port: 80
43
+ :shared_bucket: "pool-party-app-data"
44
+ :environment: production
45
+ :contract_when:
46
+ web > 10
47
+ cpu < 0.2
48
+ :expand_when:
49
+ cpu > 0.45
50
+ web < 10
51
+
52
+ Most of it should be self-explanatory, but a few points are necessary to describe. ec2_dir and keypair are for your location development machine. If you didn't create a keypair, not to worry, put in anything here. If you did, it's the name of the keypair you added. This is important for working with the instances after you get them up.
53
+
54
+ If you put in a bucket in the shared_bucket key, the instances will automount that bucket to the /data drive. If you leave it out or don't include it, then it won't.
55
+
56
+ The master instance takes care of monitoring the cloud for you. If the the parameters you set in the contract_when and expand_when are met, then the cloud will respond accordingly. Those are based on monitors that are included in PoolParty.
57
+
58
+ The installation of the required software for PoolParty is taken care of by PoolParty. That being said, PoolParty makes no assumptions of what the cloud's responsibilities will be. See 'Using' later on.
59
+
60
+ Monitors
61
+ The monitors are flexible and extensible. Currently included in PoolParty are monitors that monitor web requests and cpu and memory percentages. Writing a monitor or a plugin are out of the scope of this tutorial, but will be included in future tutorials.
62
+
63
+ Configuring
64
+ It can be tedious setting up just your development machine. This is why PoolParty makes it super easy for you in just one rake task.
65
+
66
+ If you are not familiar with ruby, I suggest you look into it, it's a beautiful language. However, PoolParty is language-agnostic, so not to worry.
67
+
68
+ Create a file in your development directory called Rakefile and add this to it.
69
+
70
+ require 'rubygems'
71
+ require 'poolparty'
72
+
73
+ PoolParty.include_tasks
74
+
75
+ That's it, pretty simple and a bunch of tasks are available to you directly!
76
+ Your development directory should look like this:
77
+
78
+ ./
79
+ config/
80
+ config.yml
81
+ Rakefile
82
+
83
+ Now, once you have this setup and your config file setup, you can type
84
+
85
+ rake dev:setup
86
+
87
+ That's it and you should be able to type ec2-describe-images (provided you have installed the ec2-api-tools, available here: http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351&categoryID=88) at this point and you are set.
88
+
89
+ You will find yourself with a .<keypair_name>_pool_keys file in your home directory. Anytime you want to setup a new cloud or simply check on this one, all you have to do is type:
90
+
91
+ source ~/.<keypair_name>_pool_keys
92
+
93
+ and your'll be ready to switch over to editing the new cloud.
94
+
95
+ Using:
96
+ When it's easy to maintain a cloud, it's even easier to use.
97
+
98
+ There are two binaries included with PoolParty when you install them. Working with the cloud, you can use the binary: pool. Working with the instance, you can use the binary: instance.
99
+
100
+ Start your pool by typing:
101
+
102
+ pool start
103
+
104
+ It may take a minute. PoolParty is starting your cloud and configuring the master at this point. You may be asked to confirm an ssh connection. This only happens the first time so other pool commands won't ask you again.
105
+
106
+ To check on your cloud, simply type:
107
+
108
+ pool list
109
+
110
+ and you will be presented with the list of your cloud and their roles
111
+
112
+ If you want to stop the pool, it's as straightforward as:
113
+
114
+ pool stop
115
+
116
+ There are a other commands you have available to you on the pool site. If you are hosting your master off-site, rather than on EC2, you can type on the master machine:
117
+
118
+ pool maintain
119
+
120
+ and it will bootup as the master, watching the other instances in the cloud.
121
+
122
+ If you want to log into a specific instance, you can do so with the command:
123
+
124
+ instance ssh -i num
125
+
126
+ The num is the number in the list from: pool list. It defaults to logging into the master if the number is not supplied.
127
+
128
+ You have some more options when working with instances. You can
129
+
130
+ instance ssh
131
+ instance scp src='' dest=''
132
+ instance cmd cmd='ls -la'
133
+ instance start|stop|install|restart
134
+ instance start_maintain
135
+
136
+ The last command will force the instance to become the new master.
137
+
138
+ Those are the basics of PoolParty.
139
+
140
+ You can check it out at http://poolpartyrb.com/.
141
+
142
+ If you are interested in active development, check out the source at github at http://github.com/auser/pool-party/tree/master. Active discussion is held here: http://groups.google.com/group/poolpartyrb. Of course, the latest and greatest information will always be released first at http://blog.citrusbyte.com.
data/poolparty.gemspec ADDED
@@ -0,0 +1,72 @@
1
+
2
+ # Gem::Specification for Poolparty-0.0.8
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{poolparty}
7
+ s.version = "0.0.8"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Ari Lerner"]
13
+ s.date = %q{2008-06-20}
14
+ s.description = %q{Run your entire application off EC2, managed and auto-scaling}
15
+ s.email = %q{ari.lerner@citrusbyte.com}
16
+ s.executables = ["instance", "pool"]
17
+ s.extra_rdoc_files = ["bin/instance", "bin/pool", "CHANGELOG", "lib/core/array.rb", "lib/core/exception.rb", "lib/core/float.rb", "lib/core/hash.rb", "lib/core/kernel.rb", "lib/core/module.rb", "lib/core/object.rb", "lib/core/proc.rb", "lib/core/string.rb", "lib/core/time.rb", "lib/modules/callback.rb", "lib/modules/ec2_wrapper.rb", "lib/modules/safe_instance.rb", "lib/modules/vlad_override.rb", "lib/poolparty/application.rb", "lib/poolparty/init.rb", "lib/poolparty/master.rb", "lib/poolparty/monitors/cpu.rb", "lib/poolparty/monitors/memory.rb", "lib/poolparty/monitors/web.rb", "lib/poolparty/monitors.rb", "lib/poolparty/optioner.rb", "lib/poolparty/plugin.rb", "lib/poolparty/plugin_manager.rb", "lib/poolparty/provider/packages/essential.rb", "lib/poolparty/provider/packages/git.rb", "lib/poolparty/provider/packages/haproxy.rb", "lib/poolparty/provider/packages/heartbeat.rb", "lib/poolparty/provider/packages/monit.rb", "lib/poolparty/provider/packages/rsync.rb", "lib/poolparty/provider/packages/ruby.rb", "lib/poolparty/provider/packages/s3fuse.rb", "lib/poolparty/provider/provider.rb", "lib/poolparty/provider.rb", "lib/poolparty/remote_instance.rb", "lib/poolparty/remoter.rb", "lib/poolparty/remoting.rb", "lib/poolparty/scheduler.rb", "lib/poolparty/tasks/cloud.rake", "lib/poolparty/tasks/development.rake", "lib/poolparty/tasks/ec2.rake", "lib/poolparty/tasks/instance.rake", "lib/poolparty/tasks/plugins.rake", "lib/poolparty/tasks/server.rake", "lib/poolparty/tasks.rb", "lib/poolparty/tmp.rb", "lib/poolparty.rb", "lib/s3/s3_object_store_folders.rb", "README.txt"]
18
+ s.files = ["archives/ruby-1.8.6-p111.tar.gz", "bin/instance", "bin/pool", "CHANGELOG", "config/cloud_master_takeover", "config/create_proxy_ami.sh", "config/haproxy.conf", "config/heartbeat.conf", "config/heartbeat_authkeys.conf", "config/installers/ubuntu_install.sh", "config/monit/haproxy.monit.conf", "config/monit/nginx.monit.conf", "config/monit.conf", "config/nginx.conf", "config/reconfigure_instances_script.sh", "config/sample-config.yml", "config/scp_instances_script.sh", "lib/core/array.rb", "lib/core/exception.rb", "lib/core/float.rb", "lib/core/hash.rb", "lib/core/kernel.rb", "lib/core/module.rb", "lib/core/object.rb", "lib/core/proc.rb", "lib/core/string.rb", "lib/core/time.rb", "lib/modules/callback.rb", "lib/modules/ec2_wrapper.rb", "lib/modules/safe_instance.rb", "lib/modules/vlad_override.rb", "lib/poolparty/application.rb", "lib/poolparty/init.rb", "lib/poolparty/master.rb", "lib/poolparty/monitors/cpu.rb", "lib/poolparty/monitors/memory.rb", "lib/poolparty/monitors/web.rb", "lib/poolparty/monitors.rb", "lib/poolparty/optioner.rb", "lib/poolparty/plugin.rb", "lib/poolparty/plugin_manager.rb", "lib/poolparty/provider/packages/essential.rb", "lib/poolparty/provider/packages/git.rb", "lib/poolparty/provider/packages/haproxy.rb", "lib/poolparty/provider/packages/heartbeat.rb", "lib/poolparty/provider/packages/monit.rb", "lib/poolparty/provider/packages/rsync.rb", "lib/poolparty/provider/packages/ruby.rb", "lib/poolparty/provider/packages/s3fuse.rb", "lib/poolparty/provider/provider.rb", "lib/poolparty/provider.rb", "lib/poolparty/remote_instance.rb", "lib/poolparty/remoter.rb", "lib/poolparty/remoting.rb", "lib/poolparty/scheduler.rb", "lib/poolparty/tasks/cloud.rake", "lib/poolparty/tasks/development.rake", "lib/poolparty/tasks/ec2.rake", "lib/poolparty/tasks/instance.rake", "lib/poolparty/tasks/plugins.rake", "lib/poolparty/tasks/server.rake", "lib/poolparty/tasks.rb", "lib/poolparty/tmp.rb", "lib/poolparty.rb", "lib/s3/s3_object_store_folders.rb", "Manifest", "misc/basics_tutorial.txt", "Rakefile", "README.txt", "spec/application_spec.rb", "spec/callback_spec.rb", "spec/core_spec.rb", "spec/helpers/ec2_mock.rb", "spec/kernel_spec.rb", "spec/master_spec.rb", "spec/monitors/cpu_monitor_spec.rb", "spec/monitors/memory_spec.rb", "spec/monitors/misc_monitor_spec.rb", "spec/monitors/web_spec.rb", "spec/optioner_spec.rb", "spec/plugin_manager_spec.rb", "spec/plugin_spec.rb", "spec/pool_binary_spec.rb", "spec/poolparty_spec.rb", "spec/provider_spec.rb", "spec/remote_instance_spec.rb", "spec/remoter_spec.rb", "spec/remoting_spec.rb", "spec/scheduler_spec.rb", "spec/spec_helper.rb", "spec/string_spec.rb", "tmp/node0-pool-party-ha.cf", "tmp/node0-pool-party-haresources", "tmp/node0-pool-party-hosts", "tmp/node1-pool-party-ha.cf", "tmp/node1-pool-party-haresources", "tmp/node1-pool-party-hosts", "tmp/pool-party-haproxy.cfg", "web/static/conf/nginx.conf", "web/static/site/images/balloon.png", "web/static/site/images/cb.png", "web/static/site/images/clouds.png", "web/static/site/images/railsconf_preso_img.png", "web/static/site/index.html", "web/static/site/javascripts/application.js", "web/static/site/javascripts/corner.js", "web/static/site/javascripts/jquery-1.2.6.pack.js", "web/static/site/misc.html", "web/static/site/storage/pool_party_presentation.pdf", "web/static/site/stylesheets/application.css", "web/static/site/stylesheets/reset.css", "web/static/src/layouts/application.haml", "web/static/src/pages/index.haml", "web/static/src/pages/misc.haml", "web/static/src/stylesheets/application.sass", "poolparty.gemspec"]
19
+ s.has_rdoc = true
20
+ s.homepage = %q{http://blog.citrusbyte.com}
21
+ s.post_install_message = %q{ Thanks for installing PoolParty!
22
+
23
+ Please check out the documentation for any questions or check out the google groups at
24
+ http://groups.google.com/group/poolpartyrb
25
+
26
+ Don't forget to check out the plugins for extending PoolParty!
27
+
28
+ For more information, check http://poolpartyrb.com
29
+ *** Ari Lerner @ <ari.lerner@citrusbyte.com> ***
30
+ }
31
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Poolparty", "--main", "README.txt"]
32
+ s.require_paths = ["lib"]
33
+ s.rubyforge_project = %q{poolparty}
34
+ s.rubygems_version = %q{1.1.1}
35
+ s.summary = %q{Run your entire application off EC2, managed and auto-scaling}
36
+
37
+ s.add_dependency(%q<aws-s3>, [">= 0"])
38
+ s.add_dependency(%q<amazon-ec2>, [">= 0"])
39
+ s.add_dependency(%q<aska>, [">= 0"])
40
+ s.add_dependency(%q<git>, [">= 0"])
41
+ end
42
+
43
+
44
+ # # Original Rakefile source (requires the Echoe gem):
45
+ #
46
+ # require 'rubygems'
47
+ # require 'echoe'
48
+ # require 'lib/poolparty'
49
+ #
50
+ # task :default => :test
51
+ #
52
+ # Echoe.new("poolparty") do |p|
53
+ # p.author = "Ari Lerner"
54
+ # p.email = "ari.lerner@citrusbyte.com"
55
+ # p.summary = "Run your entire application off EC2, managed and auto-scaling"
56
+ # p.url = "http://blog.citrusbyte.com"
57
+ # p.dependencies = %w(aws-s3 amazon-ec2 aska git)
58
+ # p.install_message =<<-EOM
59
+ # Thanks for installing PoolParty!
60
+ #
61
+ # Please check out the documentation for any questions or check out the google groups at
62
+ # http://groups.google.com/group/poolpartyrb
63
+ #
64
+ # Don't forget to check out the plugins for extending PoolParty!
65
+ #
66
+ # For more information, check http://poolpartyrb.com
67
+ # *** Ari Lerner @ <ari.lerner@citrusbyte.com> ***
68
+ # EOM
69
+ # p.include_rakefile = true
70
+ # end
71
+ #
72
+ # PoolParty.include_tasks
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Application" do
4
+ it "should be able to send options in the Application.options" do
5
+ options({:optparse => {:banner => "hi"}})
6
+ end
7
+ it "should have the root_dir defined" do
8
+ PoolParty.root_dir.should_not be_nil
9
+ end
10
+ it "should be able to call on the haproxy_config_file" do
11
+ Application.haproxy_config_file.should_not be_nil
12
+ end
13
+ it "should be able to find the client_port" do
14
+ Application.options.should_receive(:client_port).and_return(7788)
15
+ Application.client_port.should == 7788
16
+ end
17
+ it "should always have cloud_master_takeover in the managed services list" do
18
+ Application.master_managed_services.should =~ /cloud_master_takeover/
19
+ end
20
+ it "should be able to say it is in development mode if it is in dev mode" do
21
+ Application.stub!(:environment).and_return("development")
22
+ Application.development?.should == true
23
+ end
24
+ it "should be able to say it is in production if it is in production" do
25
+ Application.stub!(:environment).and_return("production")
26
+ Application.production?.should == true
27
+ end
28
+ it "should be able to say it's keypair path is in the $HOME/ directory" do
29
+ Application.stub!(:ec2_dir).and_return("~/.ec2")
30
+ Application.stub!(:keypair).and_return("poolparty")
31
+ Application.keypair_path.should == "~/.ec2/id_rsa-poolparty"
32
+ end
33
+ it "should be able to show the version of the gem" do
34
+ Application.version.should_not be_nil
35
+ end
36
+ it "should show the version as a string" do
37
+ Application.version.class.should == String
38
+ end
39
+ end
@@ -0,0 +1,194 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class TestCallbacks
4
+ include Callbacks
5
+ attr_reader :str
6
+
7
+ before :world, :hello
8
+ after :world, :thanks
9
+
10
+ def hello(caller)
11
+ string << "hello "
12
+ end
13
+ def world
14
+ string << "world"
15
+ end
16
+ def thanks(caller)
17
+ string << ", thank you"
18
+ end
19
+ after :pop, :boom
20
+ def pop
21
+ string << "pop"
22
+ end
23
+ def boom(caller)
24
+ string << " goes boom"
25
+ end
26
+ def string
27
+ @str ||= String.new
28
+ end
29
+ end
30
+ describe "Callbacks" do
31
+ before(:each) do
32
+ @klass = TestCallbacks.new
33
+ end
34
+ it "should retain it's class identifier" do
35
+ @klass.class.should == TestCallbacks
36
+ end
37
+ it "should callback the method before the method runs" do
38
+ @klass.world.should == "hello world, thank you"
39
+ end
40
+ it "should callback the method before the method runs" do
41
+ @klass.pop.should == "pop goes boom"
42
+ end
43
+ end
44
+ class TestMultipleCallbacks
45
+ include Callbacks
46
+ attr_reader :str
47
+ def hi(caller)
48
+ string << "hi, "
49
+ end
50
+ def hello(caller)
51
+ string << "hello "
52
+ end
53
+ def world
54
+ string << "world"
55
+ end
56
+ def string
57
+ @str ||= String.new
58
+ end
59
+ before :world, :hi, :hello
60
+ end
61
+ describe "Multiple callbacks" do
62
+ before(:each) do
63
+ @klass = TestMultipleCallbacks.new
64
+ end
65
+ it "should be able to have multiple callbacks on the same call" do
66
+ @klass.world.should == "hi, hello world"
67
+ end
68
+ end
69
+ class OutsideClass
70
+ def self.hello(caller)
71
+ puts "hello"
72
+ end
73
+ end
74
+ class TestOutsideClass
75
+ include Callbacks
76
+ before :world, {:hello => OutsideClass}
77
+ def world
78
+ "world"
79
+ end
80
+ end
81
+ describe "Options" do
82
+ before(:each) do
83
+ @c = TestOutsideClass.new
84
+ end
85
+ it "should be able to pass external class options to the callback" do
86
+ OutsideClass.should_receive(:hello).and_return "hello"
87
+ @c.world
88
+ end
89
+ end
90
+ class BlockClass
91
+ include Callbacks
92
+ before :world do
93
+ string << "hello "
94
+ end
95
+ def world
96
+ string << "world"
97
+ end
98
+ def string
99
+ @string ||= ""
100
+ end
101
+ end
102
+ describe "Block callbacks" do
103
+ it "should call the block on the callback" do
104
+ BlockClass.new.world.should == "hello world"
105
+ end
106
+ end
107
+ class BlockAndMethodClass
108
+ include Callbacks
109
+ before :world, :hi do
110
+ string << "hello "
111
+ end
112
+ def world
113
+ string << "world"
114
+ end
115
+ def hi(caller)
116
+ string << "hi, "
117
+ end
118
+ def string
119
+ @string ||= ""
120
+ end
121
+ end
122
+ describe "Block and method callbacks" do
123
+ it "should call the block on the callback and add the block" do
124
+ BlockAndMethodClass.new.world.should == "hi, hello world"
125
+ end
126
+ end
127
+ class ExternalMethodCallClass
128
+ include Callbacks
129
+ before :world, :hello
130
+ after :hello, :peter
131
+
132
+ def world
133
+ string << "world"
134
+ end
135
+ def hello(caller)
136
+ string << "hello "
137
+ end
138
+ def peter(caller)
139
+ string << "peter "
140
+ end
141
+ def string
142
+ @string ||= ""
143
+ end
144
+ end
145
+ describe "External method callbacks inside a method" do
146
+ it "should call the block on the callback and add the " do
147
+ ExternalMethodCallClass.new.world.should == "hello peter world"
148
+ end
149
+ end
150
+ class OutsideBindingClass
151
+ def hello(caller)
152
+ caller.string << "hello"
153
+ end
154
+ end
155
+ class BindingClass
156
+ include Callbacks
157
+ before :world, :hello => "OutsideBindingClass"
158
+ def world
159
+ string << "#{@hello} world"
160
+ end
161
+ def string
162
+ @string ||= ""
163
+ end
164
+ end
165
+ describe "Methods" do
166
+ it "should have access to the local variables of the call" do
167
+ BindingClass.new.world.should == "hello world"
168
+ end
169
+ end
170
+ class EvilOutsideClass
171
+ attr_reader :name
172
+ def get_name(caller)
173
+ @name = caller.hello
174
+ end
175
+ def show_name(caller)
176
+ @name
177
+ end
178
+ end
179
+ class BindingClass
180
+ include Callbacks
181
+ before :print, :get_name => "EvilOutsideClass"
182
+ def print
183
+ "hello"
184
+ end
185
+ def hello
186
+ "franke"
187
+ end
188
+ end
189
+ describe "Variables on the plugin callbacker class" do
190
+ it "should have a new method of the class" do
191
+ BindingClass.new.print
192
+ BindingClass.new.methods.include?("eviloutsideclass").should == true
193
+ end
194
+ end
data/spec/core_spec.rb ADDED
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Hash" do
4
+ it "should preserve the contents of the original hash when safe_merge'ing" do
5
+ a = {:a => "10", :b => "20"}
6
+ b = {:b => "30", :c => "40"}
7
+ a.safe_merge(b).should == {:a => "10", :b => "20", :c => "40"}
8
+ end
9
+ it "should preserve the contents of the original hash when safe_merge!'ing" do
10
+ a = {:a => "10", :b => "20"}
11
+ b = {:b => "30", :c => "40"}
12
+ a.safe_merge!(b)
13
+ a.should == {:a => "10", :b => "20", :c => "40"}
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ module PoolParty
2
+ class Master
3
+ def launch_new_instance!
4
+ letter = ("a".."z").to_a[instances.size] # For unique instance_ids
5
+ h = {:instance_id => "i-58ba56#{letter}", :ip => "ip-127-0-0-1.aws.amazonaws.com", :status => "pending", :launching_time => Time.now }
6
+ instances << h
7
+ Thread.new {wait 0.1;h[:status] = "running"} # Simulate the startup time
8
+ return h
9
+ end
10
+ # Shutdown the instance by instance_id
11
+ def terminate_instance!(instance_id)
12
+ instances.select {|a| a[:instance_id] == instance_id}[0][:status] = "terminating"
13
+ end
14
+ # Instance description
15
+ def describe_instance(id)
16
+ item = instances.select {|a| a[:instance_id] == id}[0]
17
+ EC2ResponseObject.get_hash_from_response(item)
18
+ end
19
+ # Get instance by id
20
+ def get_instance_by_id(id)
21
+ get_instances_description.select {|a| a.instance_id == id}[0] rescue nil
22
+ end
23
+ # Get the s3 description for the response in a hash format
24
+ def get_instances_description
25
+ instances
26
+ end
27
+ # Fake the ec2 connection
28
+ def ec2
29
+ @ec2 ||= EC2::Base.new(:access_key_id => "not a key", :secret_access_key => "not a key")
30
+ end
31
+ # Some basic instances, not totally necessary
32
+ def instances
33
+ @instances ||= []
34
+ end
35
+ end
36
+ class RemoteInstance
37
+ def ssh(l="")
38
+ "true"
39
+ end
40
+ def scp(s,d,o={})
41
+ "true"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Kernel extensions" do
4
+ before(:each) do
5
+ @host = Master.new
6
+ end
7
+ it "should eval the string into time" do
8
+ @host.should_receive(:sleep).once.and_return true
9
+ @host.wait "10.seconds"
10
+ end
11
+ end