auser-poolparty 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. data/Manifest.txt +201 -0
  2. data/PostInstall.txt +17 -0
  3. data/Rakefile +22 -1
  4. data/bin/cloud-add-keypair +0 -0
  5. data/bin/cloud-osxcopy +22 -0
  6. data/bin/cloud-provision +1 -0
  7. data/bin/cloud-start +17 -15
  8. data/bin/cloud-terminate +23 -0
  9. data/bin/pool-start +14 -14
  10. data/bin/pool-start-monitor +1 -0
  11. data/config/hoe.rb +114 -0
  12. data/config/requirements.rb +15 -0
  13. data/lib/poolparty.rb +1 -0
  14. data/lib/poolparty/base_packages/haproxy.rb +32 -31
  15. data/lib/poolparty/base_packages/heartbeat.rb +2 -2
  16. data/lib/poolparty/base_packages/poolparty.rb +9 -3
  17. data/lib/poolparty/base_packages/ruby.rb +10 -0
  18. data/lib/poolparty/core/proc.rb +5 -0
  19. data/lib/poolparty/core/string.rb +1 -1
  20. data/lib/poolparty/helpers/binary.rb +6 -5
  21. data/lib/poolparty/helpers/display.rb +11 -2
  22. data/lib/poolparty/helpers/optioner.rb +6 -3
  23. data/lib/poolparty/helpers/provisioner_base.rb +9 -7
  24. data/lib/poolparty/helpers/provisioners/master.rb +38 -4
  25. data/lib/poolparty/helpers/provisioners/slave.rb +2 -2
  26. data/lib/poolparty/modules/cloud_resourcer.rb +20 -3
  27. data/lib/poolparty/modules/definable_resource.rb +1 -1
  28. data/lib/poolparty/modules/method_missing_sugar.rb +12 -4
  29. data/lib/poolparty/modules/pretty_printer.rb +2 -1
  30. data/lib/poolparty/net/remote.rb +1 -1
  31. data/lib/poolparty/net/remote_bases/ec2.rb +13 -10
  32. data/lib/poolparty/net/remote_instance.rb +3 -2
  33. data/lib/poolparty/net/remoter.rb +33 -18
  34. data/lib/poolparty/net/remoter_base.rb +3 -3
  35. data/lib/poolparty/plugins/gem_package.rb +6 -29
  36. data/lib/poolparty/plugins/git.rb +22 -0
  37. data/lib/poolparty/pool/base.rb +7 -6
  38. data/lib/poolparty/pool/cloud.rb +34 -5
  39. data/lib/poolparty/pool/custom_resource.rb +4 -4
  40. data/lib/poolparty/pool/plugin.rb +13 -14
  41. data/lib/poolparty/pool/resource.rb +19 -10
  42. data/lib/poolparty/pool/resources/class_package.rb +10 -6
  43. data/lib/poolparty/pool/resources/conditional.rb +41 -0
  44. data/lib/poolparty/pool/resources/gem.rb +2 -2
  45. data/lib/poolparty/pool/script.rb +25 -2
  46. data/lib/poolparty/templates/haproxy.conf +1 -1
  47. data/lib/poolparty/templates/puppet.conf +4 -2
  48. data/lib/poolparty/version.rb +1 -1
  49. data/poolparty.gemspec +60 -0
  50. data/setup.rb +1585 -0
  51. data/spec/poolparty/base_packages/haproxy_spec.rb +13 -0
  52. data/spec/poolparty/base_packages/heartbeat_spec.rb +30 -0
  53. data/spec/poolparty/bin/console_spec.rb +80 -0
  54. data/spec/poolparty/core/array_spec.rb +26 -0
  55. data/spec/poolparty/core/float.rb +13 -0
  56. data/spec/poolparty/core/hash_spec.rb +63 -0
  57. data/spec/poolparty/core/kernel_spec.rb +24 -0
  58. data/spec/poolparty/core/module_spec.rb +15 -0
  59. data/spec/poolparty/core/object_spec.rb +40 -0
  60. data/spec/poolparty/core/string_spec.rb +152 -0
  61. data/spec/poolparty/core/time_spec.rb +52 -0
  62. data/spec/poolparty/helpers/binary_spec.rb +26 -0
  63. data/spec/poolparty/helpers/display_spec.rb +13 -0
  64. data/spec/poolparty/helpers/optioner_spec.rb +39 -0
  65. data/spec/poolparty/helpers/provisioner_base_spec.rb +121 -0
  66. data/spec/poolparty/helpers/provisioners/master_spec.rb +54 -0
  67. data/spec/poolparty/helpers/provisioners/slave_spec.rb +28 -0
  68. data/spec/poolparty/modules/cloud_resourcer_spec.rb +135 -0
  69. data/spec/poolparty/modules/configurable_spec.rb +26 -0
  70. data/spec/poolparty/modules/definable_resource.rb +9 -0
  71. data/spec/poolparty/modules/file_writer_spec.rb +49 -0
  72. data/spec/poolparty/modules/s3_string_spec.rb +15 -0
  73. data/spec/poolparty/net/remote_bases/ec2_spec.rb +92 -0
  74. data/spec/poolparty/net/remote_instance_spec.rb +70 -0
  75. data/spec/poolparty/net/remote_spec.rb +286 -0
  76. data/spec/poolparty/net/remoter_base_spec.rb +80 -0
  77. data/spec/poolparty/net/remoter_spec.rb +191 -0
  78. data/spec/poolparty/plugins/git_spec.rb +19 -0
  79. data/spec/poolparty/plugins/line_spec.rb +16 -0
  80. data/spec/poolparty/plugins/svn_spec.rb +16 -0
  81. data/spec/poolparty/pool/base_spec.rb +108 -0
  82. data/spec/poolparty/pool/cloud_spec.rb +299 -0
  83. data/spec/poolparty/pool/configurers/files/ruby_basic.rb +17 -0
  84. data/spec/poolparty/pool/configurers/files/ruby_plugins.rb +16 -0
  85. data/spec/poolparty/pool/configurers/ruby_spec.rb +58 -0
  86. data/spec/poolparty/pool/custom_resource_spec.rb +115 -0
  87. data/spec/poolparty/pool/example_spec.rb +112 -0
  88. data/spec/poolparty/pool/plugin_model_spec.rb +63 -0
  89. data/spec/poolparty/pool/plugin_spec.rb +85 -0
  90. data/spec/poolparty/pool/pool_spec.rb +83 -0
  91. data/spec/poolparty/pool/resource_spec.rb +224 -0
  92. data/spec/poolparty/pool/resources/class_package_spec.rb +84 -0
  93. data/spec/poolparty/pool/resources/conditional_spec.rb +38 -0
  94. data/spec/poolparty/pool/resources/cron_spec.rb +49 -0
  95. data/spec/poolparty/pool/resources/directory_spec.rb +40 -0
  96. data/spec/poolparty/pool/resources/exec_spec.rb +37 -0
  97. data/spec/poolparty/pool/resources/file_spec.rb +40 -0
  98. data/spec/poolparty/pool/resources/gem_spec.rb +16 -0
  99. data/spec/poolparty/pool/resources/host_spec.rb +28 -0
  100. data/spec/poolparty/pool/resources/package_spec.rb +44 -0
  101. data/spec/poolparty/pool/resources/remote_file_spec.rb +40 -0
  102. data/spec/poolparty/pool/resources/service_spec.rb +45 -0
  103. data/spec/poolparty/pool/resources/sshkey_spec.rb +48 -0
  104. data/spec/poolparty/pool/resources/variable_spec.rb +20 -0
  105. data/spec/poolparty/pool/script_spec.rb +51 -0
  106. data/spec/poolparty/pool/test_plugins/sshkey_test +2 -0
  107. data/spec/poolparty/pool/test_plugins/virtual_host_template.erb +0 -0
  108. data/spec/poolparty/pool/test_plugins/webserver.rb +46 -0
  109. data/spec/poolparty/poolparty_spec.rb +33 -0
  110. data/spec/poolparty/spec_helper.rb +120 -0
  111. data/test/test_generator_helper.rb +29 -0
  112. data/test/test_helper.rb +2 -0
  113. data/test/test_pool_spec_generator.rb +47 -0
  114. data/test/test_poolparty.rb +11 -0
  115. data/website/index.html +81 -0
  116. data/website/index.txt +72 -0
  117. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  118. data/website/stylesheets/screen.css +138 -0
  119. data/website/template.html.erb +48 -0
  120. metadata +178 -60
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ include Remote
4
+
5
+ class TestRemoter
6
+ include RemoterBase
7
+ end
8
+
9
+ describe "RemoterBase" do
10
+ describe "methods" do
11
+ before(:each) do
12
+ @tr = TestRemoter.new
13
+ end
14
+ %w(launch_new_instance! terminate_instance describe_instance instances_list).each do |method|
15
+ eval <<-EOE
16
+ it "should raise an exception if #{method} is not defined as a method" do
17
+ lambda { @tr.#{method} }.should raise_error
18
+ end
19
+ it "should not raise an exception if #{method} is defined as a method" do
20
+ lambda {
21
+ @tr.instance_eval do
22
+ def #{method}
23
+ end
24
+ end
25
+ @tr.#{method}
26
+ }.should_not raise_error
27
+ end
28
+ EOE
29
+ end
30
+ describe "lists" do
31
+ before(:each) do
32
+ stub_list_of_instances_for(@tr)
33
+ end
34
+ it "should gather a list of the running instances" do
35
+ @tr.list_of_running_instances.map {|a| a.name }.should == ["master", "node1"]
36
+ end
37
+ it "should be able to gather a list of the pending instances" do
38
+ @tr.list_of_pending_instances.map {|a| a.name }.should == ["node3"]
39
+ end
40
+ it "should be able to gather a list of the terminating instances" do
41
+ @tr.list_of_terminating_instances.map {|a| a.name }.should == []
42
+ end
43
+ it "should be able to gather a list of the non-terminated instances" do
44
+ @tr.list_of_nonterminated_instances.map {|a| a.name }.should == ["master", "node1", "node3"]
45
+ end
46
+ it "should return a list of remote instances" do
47
+ @tr.remote_instances_list.first.class.should == RemoteInstance
48
+ end
49
+ describe "by keypairs" do
50
+ it "should be able to grab all the alist keypairs" do
51
+ @tr.list_of_instances("fake_keypair").map {|a| a[:name] }.should == ["master", "node1", "node2", "node3"]
52
+ end
53
+ it "should be able to grab all the blist keypairs" do
54
+ @tr.list_of_instances("blist").map {|a| a[:name] }.should == ["node4"]
55
+ end
56
+ end
57
+ describe "get by name" do
58
+ it "should fetch the instance by number " do
59
+ @tr.get_instance_by_number(1).name.should == "node1"
60
+ end
61
+ it "should fetch the master by number 0" do
62
+ @tr.get_instance_by_number(0).name.should == "master"
63
+ end
64
+ it "should not throw a fit if the node doesn't exist" do
65
+ lambda {@tr.get_instance_by_number(1000)}.should_not raise_error
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "adding custom install tasks (like set_hostname, for example)" do
71
+ before(:each) do
72
+ @master = Object.new
73
+ @master.stub!(:ip).and_return "192.68.0.1"
74
+ @tr.stub!(:master).and_return @master
75
+ end
76
+ it "should have the method custom_install_tasks" do;@tr.respond_to?(:custom_install_tasks_for).should == true;end
77
+ it "should have the method custom_configure_tasks" do;@tr.respond_to?(:custom_configure_tasks_for).should == true;end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,191 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ include PoolParty::Remote
4
+
5
+ class TestClass
6
+ include CloudResourcer
7
+ include Remote
8
+ using :ec2
9
+ attr_accessor :parent
10
+
11
+ def keypair
12
+ "fake_keypair"
13
+ end
14
+ end
15
+ describe "Remoter" do
16
+ before(:each) do
17
+ @cloud = cloud :app do;end
18
+ @tc = TestClass.new
19
+ @tc.parent = @cloud
20
+ ::File.stub!(:exists?).with("#{File.expand_path(Base.base_keypair_path)}/id_rsa-fake_keypair").and_return true
21
+ @sample_instances_list = [{:ip => "192.168.0.1", :name => "master"}, {:ip => "192.168.0.2", :name => "node1"}]
22
+ end
23
+ describe "ssh_string" do
24
+ it "should have the ssh command" do
25
+ @tc.ssh_string.should =~ /ssh -o StrictHostKeyChecking=no -l '#{Base.user}' -i/
26
+ end
27
+ it "should have the keypair in the ssh_string" do
28
+ @tc.ssh_string.should =~ /#{@tc.keypair}/
29
+ end
30
+ end
31
+ describe "ssh_array" do
32
+ it "should have StrictHostKeyChecking set to no" do
33
+ @tc.ssh_array.include?("-o StrictHostKeyChecking=no").should == true
34
+ end
35
+ it "should have the user set to the base user class" do
36
+ @tc.ssh_array.include?("-l '#{Base.user}'").should == true
37
+ end
38
+ it "should have the keypair path in the ssh_array" do
39
+ @tc.ssh_array.include?('-i "'+@tc.full_keypair_path+'"').should == true
40
+ end
41
+ end
42
+ describe "rsync_command" do
43
+ before(:each) do
44
+ @ri = Class.new
45
+ @ri.stub!(:ip).and_return "192.168.0.22"
46
+ end
47
+ it "should have rsync in the rsync_command" do
48
+ @tc.rsync_command.should == "rsync --delete -azP --exclude cache -e '#{@tc.ssh_string}'"
49
+ end
50
+ it "should be able to rsync storage commands" do
51
+ @tc.rsync_storage_files_to_command(@ri).should == "#{@tc.rsync_command} #{Dir.pwd}/tmp 192.168.0.22:/var/poolparty"
52
+ end
53
+ end
54
+ describe "launch_and_configure_master!" do
55
+ before(:each) do
56
+ @tc.stub!(:wait).and_return true
57
+ stub_list_from_remote_for(@tc)
58
+ @tc.stub!(:maximum_instances).and_return 5
59
+ @tc.stub!(:list_of_pending_instances).and_return []
60
+ @tc.stub!(:list_of_running_instances).and_return []
61
+ @tc.stub!(:master).and_return ris.first
62
+ Provisioner.stub!(:provision_master).and_return true
63
+ end
64
+ it "should have the method launch_master!" do
65
+ @tc.respond_to?(:launch_and_configure_master!).should == true
66
+ end
67
+ it "should test if it can start a new instance" do
68
+ @tc.should_receive(:can_start_a_new_instance?).once.and_return false
69
+ end
70
+ it "should test if the master is running" do
71
+ @tc.should_receive(:is_master_running?).and_return false
72
+ end
73
+ it "should ask to request_launch_new_instances when the master is not running and we can start a new instance" do
74
+ @tc.should_receive(:request_launch_new_instances).with(1)
75
+ @tc.stub!(:can_start_a_new_instance?).and_return true
76
+ @tc.stub!(:is_master_running?).and_return false
77
+ end
78
+ it "should tell the provisioner to provision_master" do
79
+ Provisioner.should_receive(:provision_master).once.and_return true
80
+ end
81
+ after(:each) do
82
+ @tc.launch_and_configure_master!
83
+ end
84
+ end
85
+ describe "listing" do
86
+ before(:each) do
87
+ @loc = Base.storage_directory + "/tc-instances.list"
88
+ @locations = [@loc]
89
+ @tc.stub!(:local_instances_list_file_locations).and_return @locations
90
+ end
91
+ it "should have the method list_from_local available" do
92
+ TestClass.respond_to?(:list_from_local).should == true
93
+ end
94
+ it "should have the method list_from_remote available" do
95
+ TestClass.respond_to?(:list_from_remote).should == true
96
+ end
97
+ describe "remote" do
98
+ before(:each) do
99
+ @tc.stub!(:list_of_instances).and_return @sample_instances_list
100
+ @tc.stub!(:local_instances_list_file_locations).and_return [
101
+ "#{Base.storage_directory}/tc-instances.list"
102
+ ]
103
+ end
104
+ it "should call list_of_instances when trying to list from remote" do
105
+ TestClass.should_receive(:list_of_instances).once.and_return @sample_instances_list
106
+ TestClass.list_from_remote
107
+ end
108
+ it "should create a new RemoteInstance for each hashed instance" do
109
+ PoolParty::Remote::RemoteInstance.should_receive(:new).exactly(2).and_return @ri
110
+ @tc.list_from_remote
111
+ end
112
+ it "should return a string" do
113
+ @tc.list_from_remote.class.should == Array
114
+ end
115
+ it "should contain the master in the listing" do
116
+ @tc.list_from_remote.first.name.should == "master"
117
+ @tc.list_from_remote.first.master?.should == true
118
+ end
119
+ it "should write to the first (preferred) local instances list file location for next time" do
120
+ @tc.list_from_remote(:cache => true)
121
+ ::File.file?(@tc.local_instances_list_file_locations.first).should == true
122
+ end
123
+ after(:all) do
124
+ # Cleanup after ourselves
125
+ # FileUtils.rm @loc if ::File.file?(@loc)
126
+ end
127
+ end
128
+ describe "local" do
129
+ describe "listing" do
130
+ before(:each) do
131
+ stub_list_from_remote_for(@tc)
132
+ @tc.stub!(:list_of_instances).and_return([@ri])
133
+ end
134
+ it "should call local_instances_list_file_locations" do
135
+ @tc.should_receive(:local_instances_list_file_locations).at_least(1).and_return [@loc]
136
+ end
137
+ it "should call File.file? on the local_instances_list_file_locations locations" do
138
+ File.should_receive(:file?).with(@loc).at_least(1).and_return false
139
+ end
140
+ it "should call get_working_listing_file to get the working local instance file" do
141
+ @tc.should_receive(:get_working_listing_file).at_least(1).and_return nil
142
+ end
143
+ after(:each) do
144
+ @tc.list_from_local
145
+ end
146
+ end
147
+ describe "with listing" do
148
+ before(:each) do
149
+ str = "master 192.168.0.1
150
+ node1 192.168.0.2"
151
+ @loc.stub!(:read).and_return str
152
+ TestClass.stub!(:open).and_return @loc
153
+ TestClass.stub!(:get_working_listing_file).and_return @loc
154
+ @ri = PoolParty::Remote::RemoteInstance.new({:ip => "192.168.0.1", :name => "master"})
155
+ PoolParty::Remote::RemoteInstance.stub!(:new).and_return @ri
156
+ stub_list_from_remote_for(@tc)
157
+ end
158
+ it "should call open on the get_working_listing_file" do
159
+ @tc.should_receive(:open).with(@loc).at_least(1).and_return @loc
160
+ @tc.list_from_local
161
+ end
162
+ it "should create a new RemoteInstance for each line in the file" do
163
+ PoolParty::Remote::RemoteInstance.should_receive(:new).at_least(2)
164
+ @tc.list_from_local
165
+ end
166
+ it "should return a string" do
167
+ @tc.list_from_local.class.should == Array
168
+ end
169
+ it "should have the name of the master and the ip in the list_from_local" do
170
+ @tc.list_from_local[0].name.should == "master"
171
+ end
172
+ it "should have name in the listing" do
173
+ @ri.should_receive(:name).at_least(1).and_return "node0"
174
+ @ri.to_s
175
+ end
176
+ it "should have the ip in the listing" do
177
+ @ri.should_receive(:ip).at_least(1).and_return "127.0.0.1"
178
+ @ri.to_s
179
+ end
180
+ it "should call to_s on the RemoteInstance instances" do
181
+ PoolParty::Remote::RemoteInstance.should_receive(:new).at_least(2).and_return @ri
182
+ @ri.should_receive(:to_s).at_least(1)
183
+ @ri.to_s
184
+ end
185
+ end
186
+ after(:each) do
187
+ @tc.list_from_local
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class TestClass
4
+ include PoolParty::Resources
5
+ end
6
+ describe "Remote Instance" do
7
+ before(:each) do
8
+ @tc = TestClass.new
9
+ end
10
+ it "should be a string" do
11
+ @tc.has_git({:name => "gitrepos.git", :source => "git://source.git"}).to_string.should =~ /file \{/
12
+ end
13
+ it "should included the flushed out options" do
14
+ @tc.has_git({:name => "git.git", :source => "git://source.git", :user => "finger"}).to_string.should =~ /finger@git:/
15
+ end
16
+ it "should not include the user if none is given" do
17
+ @tc.has_git({:name => "git.git", :source => "git://source.git"}).to_string.should =~ /git clone git:/
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class TestClass
4
+ include PoolParty::Resources
5
+ end
6
+ describe "Remote Instance" do
7
+ before(:each) do
8
+ @tc = TestClass.new
9
+ end
10
+ it "should be a string" do
11
+ @tc.has_line_in_file("hi", "ho").to_string.should =~ /line \{/
12
+ end
13
+ it "should included the flushed out options" do
14
+ @tc.has_line_in_file("hi", "who", {:name => "finger"}).to_string.should =~ /name => 'finger'/
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class TestClass
4
+ include PoolParty::Resources
5
+ end
6
+ describe "Remote Instance" do
7
+ before(:each) do
8
+ @tc = TestClass.new
9
+ end
10
+ it "should be a string" do
11
+ @tc.has_svnpath({:name => "name", :source => "svn://"}).to_string.should =~ /svnserve \{/
12
+ end
13
+ it "should included the flushed out options" do
14
+ @tc.has_svnpath({:user => "finger"}).to_string.should =~ /user => \"finger\"/
15
+ end
16
+ end
@@ -0,0 +1,108 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "Base" do
4
+ before(:each) do
5
+ ENV.stub!(:[]).with("AWS_ACCESS_KEY_ID").and_return "KEY"
6
+ ENV.stub!(:[]).with("AWS_SECRET_ACCESS_ID").and_return "SECRET"
7
+ end
8
+ it "should set the environment, if not set to production" do
9
+ Base.environment.should == "production"
10
+ end
11
+ it "should set the user to root" do
12
+ Base.user.should == "root"
13
+ end
14
+ it "should set the base keypair path to ~/.ec2" do
15
+ Base.base_keypair_path.should == "~/.ec2"
16
+ end
17
+ it "should set the storage_directory to the tmp directory of the current working directory" do
18
+ Base.storage_directory.should == "#{Dir.pwd}/tmp"
19
+ end
20
+ it "should set the tmp path to tmp" do
21
+ Base.tmp_path.should == "tmp"
22
+ end
23
+ it "should set the remote storage path to /var/poolparty" do
24
+ Base.remote_storage_path.should == "/var/poolparty"
25
+ end
26
+ it "should set the fileserver_base to puppet://" do
27
+ Base.fileserver_base.should =~ /puppet:\/\//
28
+ end
29
+ it "should have an access key" do
30
+ Base.access_key.should == "KEY"
31
+ end
32
+ it "should have a secret access key" do
33
+ Base.secret_access_key.should == "SECRET"
34
+ end
35
+ describe "keys" do
36
+ it "should have an array of key_file_locations" do
37
+ Base.key_file_locations.class.should == Array
38
+ end
39
+ it "should test if the files exist when looking for the file" do
40
+ ::File.stub!(:file?).and_return false
41
+ ::File.stub!(:file?).with("ppkeys").and_return true
42
+ Base.get_working_key_file_locations.should == "ppkeys"
43
+ end
44
+ describe "with keyfile" do
45
+ before(:each) do
46
+ @keyfile = "ppkeys"
47
+ @str = "---
48
+ :access_key: KEY
49
+ :secret_access_key: SECRET"
50
+ @keyfile.stub!(:read).and_return @str
51
+ Base.stub!(:get_working_key_file_locations).and_return @keyfile
52
+ Base.stub!(:open).with(@keyfile).and_return @keyfile
53
+ end
54
+ it "should call YAML::load on the working key file" do
55
+ YAML.should_receive(:load).with(@str)
56
+ Base.load_keys_from_file
57
+ end
58
+ it "should return a hash" do
59
+ Base.load_keys_from_file.class.should == Hash
60
+ end
61
+ it "should be able to fetch the access key from the loaded keys" do
62
+ Base.load_keys_from_file[:access_key].should == "KEY"
63
+ end
64
+ it "should be able to fetch the secret_access_key from the loaded key file" do
65
+ Base.load_keys_from_file[:secret_access_key].should == "SECRET"
66
+ end
67
+ describe "without keyfile" do
68
+ before(:each) do
69
+ Base.stub!(:get_working_key_file_locations).and_return nil
70
+ ENV.stub!(:[]).with("AWS_ACCESS_KEY_ID").and_return nil
71
+ ENV.stub!(:[]).with("AWS_SECRET_ACCESS_ID").and_return nil
72
+ Base.reset!
73
+ end
74
+ it "should render the access_key nil" do
75
+ Base.access_key.should == nil
76
+ end
77
+ it "should render the secret_access_key as nil" do
78
+ Base.secret_access_key.should == nil
79
+ end
80
+ end
81
+ end
82
+ describe "storing keyfile" do
83
+ before(:each) do
84
+ @ak = "KEY"
85
+ @pk = "SECRET"
86
+ @str = "weee"
87
+ @hash = {:access_key => @ak, :secret_access_key => @pk}
88
+ Base.stub!(:access_key).and_return @ak
89
+ Base.stub!(:secret_access_key).and_return @pk
90
+ Base.stub!(:write_to_file).and_return true
91
+ Base.stub!(:key_file_locations).and_return ["ppkey"]
92
+ end
93
+ it "should call access_key.nil?" do
94
+ @ak.should_receive(:nil?).and_return false
95
+ @pk.should_receive(:nil?).and_return true
96
+ end
97
+ it "should call YAML::dump" do
98
+ YAML.should_receive(:dump).and_return @str
99
+ end
100
+ it "should call write_to_file with the key file location" do
101
+ Base.should_receive(:write_to_file).with("ppkey", YAML::dump(@hash)).and_return true
102
+ end
103
+ after(:each) do
104
+ Base.store_keys_in_file
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,299 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ include PoolParty::Cloud
4
+ class TestServiceClass
5
+ plugin :test_service do
6
+ def enable
7
+ has_file(:name => "/etc/poolparty/lobos")
8
+ end
9
+ end
10
+ end
11
+
12
+ describe "Cloud" do
13
+ before(:each) do
14
+ @obj = Object.new
15
+ @pool = pool :just_pool do; end
16
+ end
17
+ it "should respond to the pool method outside the block" do
18
+ @obj.respond_to?(:cloud).should == true
19
+ end
20
+ describe "global" do
21
+ before(:each) do
22
+ @cloud1 = cloud :pop do;end
23
+ end
24
+ it "should store the cloud in the global list of clouds" do
25
+ @obj.clouds.has_key?(:pop).should == true
26
+ end
27
+ it "should store the cloud" do
28
+ @obj.cloud(:pop).should == @cloud1
29
+ end
30
+ it "should have set the using base on intantiation to ec2" do
31
+ @cloud1.using_remoter?.should_not == nil
32
+ end
33
+ it "should say the remoter_base is ec2 (by default)" do
34
+ @cloud1.remote_base.should == PoolParty::Ec2
35
+ end
36
+ end
37
+ it "should return the cloud if the cloud key is already in the clouds list" do
38
+ @cld = cloud :pop do;end
39
+ @pool.cloud(:pop).should == @cld
40
+ end
41
+ describe "options" do
42
+ before(:each) do
43
+ reset!
44
+ @p = pool :options do
45
+ minimum_instances 100
46
+ access_key "access_key"
47
+ cloud :apple do
48
+ access_key "cloud_access_key"
49
+ end
50
+ end
51
+ @c = @p.cloud(:apple)
52
+ end
53
+ it "should be able to grab the cloud from the pool" do
54
+ @c.should == @p.cloud(:apple)
55
+ end
56
+ it "should take the options set on the pool" do
57
+ @p.minimum_instances.should == 100
58
+ end
59
+ it "should take the access_key option set from the cloud" do
60
+ @c.access_key.should == "cloud_access_key"
61
+ end
62
+ end
63
+ describe "block" do
64
+ before(:each) do
65
+ reset!
66
+ @cloud = Cloud.new(:test, @pool) do
67
+ # Inside cloud block
68
+ keypair "fake_keypair"
69
+ end
70
+ end
71
+
72
+ it "should be able to pull the pool from the cloud" do
73
+ @cloud.parent == @pool
74
+ end
75
+ it "should have services in an array" do
76
+ @cloud.services.class.should == Array
77
+ end
78
+ it "should have no services in the array when there are no services defined" do
79
+ @cloud.services.size.should == 0
80
+ end
81
+ it "should respond to a configure method" do
82
+ @cloud.respond_to?(:configure).should == true
83
+ end
84
+ describe "configuration" do
85
+ before(:each) do
86
+ reset!
87
+ @cloud2 = Cloud.new(:test, @pool) do
88
+ minimum_instances 1
89
+ maximum_instances 2
90
+ end
91
+ end
92
+ it "should be able to se the minimum_instances without the var" do
93
+ @cloud2.minimum_instances.should == 1
94
+ end
95
+ it "should be able to se the maximum_instances with the =" do
96
+ @cloud2.maximum_instances.should == 2
97
+ end
98
+ end
99
+ describe "options" do
100
+ it "should set the minimum_instances to 2" do
101
+ @cloud.minimum_instances.should == 2
102
+ end
103
+ it "should set the maximum_instances to 4" do
104
+ @cloud.maximum_instances.should == 4
105
+ end
106
+ it "should be able to set the minimum instances" do
107
+ @cloud.minimum_instances 3
108
+ @cloud.minimum_instances.should == 3
109
+ end
110
+ it "should be able to take a hash from configure and convert it to the options" do
111
+ @cloud.configure( {:minimum_instances => 1, :maximum_instances => 10, :keypair => "friend"} )
112
+ @cloud.keypair.should == "friend"
113
+ end
114
+ describe "minimum_instances/maximum_instances as a range" do
115
+ before(:each) do
116
+ reset!
117
+ @pool = pool :just_pool do
118
+ cloud :app do
119
+ instances 8..15
120
+ end
121
+ end
122
+ @cloud = @pool.cloud(:app)
123
+ end
124
+ it "should set the minimum based on the range" do
125
+ @cloud.minimum_instances.should == 8
126
+ end
127
+ it "should set the maximum based on the range set by instances" do
128
+ @cloud.maximum_instances.should == 15
129
+ end
130
+ end
131
+ describe "keypair" do
132
+ before(:each) do
133
+ reset!
134
+ end
135
+ it "should be able to define a keypair in the cloud" do
136
+ @c = cloud :app do
137
+ keypair "hotdog"
138
+ end
139
+ @c.keypair.should == "hotdog"
140
+ end
141
+ it "should take the pool parent's keypair if it's defined on the pool" do
142
+ pool :pool do
143
+ keypair "ney"
144
+ cloud :app do
145
+ end
146
+ cloud :group do
147
+ end
148
+ end
149
+ pool(:pool).cloud(:app).keypair.should == "ney"
150
+ pool(:pool).cloud(:group).keypair.should == "ney"
151
+ end
152
+ it "should generate a keypair based on the cloud name if none is defined" do
153
+ pool :pool do
154
+ cloud :app do
155
+ end
156
+ cloud :nickes do
157
+ end
158
+ end
159
+ pool(:pool).cloud(:app).keypair.should == "pool_app"
160
+ pool(:pool).cloud(:nickes).keypair.should == "pool_nickes"
161
+ end
162
+ end
163
+ describe "Manifest" do
164
+ before(:each) do
165
+ reset!
166
+ stub_list_from_remote_for(@cloud)
167
+ @cloud.instance_eval do
168
+ has_file(:name => "/etc/httpd/http.conf") do
169
+ content <<-EOE
170
+ hello my lady
171
+ EOE
172
+ end
173
+ has_gem(:name => "poolparty")
174
+ has_package(:name => "dummy")
175
+ end
176
+ end
177
+ it "should it should have the method build_manifest" do
178
+ @cloud.respond_to?(:build_manifest).should == true
179
+ end
180
+ it "should have 3 resources" do
181
+ @cloud.add_poolparty_base_requirements
182
+ @cloud.number_of_resources.should == 4
183
+ end
184
+ it "should receive add_poolparty_base_requirements before building the manifest" do
185
+ @cloud.should_receive(:add_poolparty_base_requirements).once
186
+ @cloud.build_manifest
187
+ end
188
+ describe "add_poolparty_base_requirements" do
189
+ before(:each) do
190
+ reset!
191
+ @cloud.instance_eval do
192
+ @heartbeat = nil
193
+ end
194
+ @hb = "heartbeat".class_constant.new(@cloud)
195
+ end
196
+ it "should call initialize on heartbeat (in add_poolparty_base_requirements)" do
197
+ @hb.class.should_receive(:new).and_return true
198
+ @cloud.add_poolparty_base_requirements
199
+ end
200
+ it "should call heartbeat on the cloud" do
201
+ @cloud.should_receive(:heartbeat).and_return true
202
+ @cloud.add_poolparty_base_requirements
203
+ end
204
+ it "should call Hearbeat.new" do
205
+ "heartbeat".class_constant.should_receive(:new).and_return @hb
206
+ @cloud.add_poolparty_base_requirements
207
+ end
208
+ it "should call enable on the plugin call" do
209
+ @hb = "heartbeat".class_constant
210
+ "heartbeat".class_constant.stub!(:new).and_return @hb
211
+
212
+ @cloud.add_poolparty_base_requirements
213
+ @cloud.heartbeat.should == @hb
214
+ end
215
+ describe "after adding" do
216
+ before(:each) do
217
+ stub_list_from_remote_for(@cloud)
218
+ @cloud.add_poolparty_base_requirements
219
+ end
220
+ it "should add resources onto the heartbeat class inside the cloud" do
221
+ @cloud.services.size.should > 0
222
+ end
223
+ it "should store the class heartbeat" do
224
+ @cloud.services.map {|a| a.class}.include?("heartbeat".class_constant).should == true
225
+ end
226
+ it "should have an array of resources on the heartbeat" do
227
+ @cloud.services.first.resources.class.should == Hash
228
+ end
229
+ describe "resources" do
230
+ before(:each) do
231
+ @cloud8 = Cloud.new(:tester, @pool) do
232
+ test_service
233
+ end
234
+ @service = @cloud8.services.first
235
+ @files = @service.resource(:file)
236
+ end
237
+ it "should have a file resource" do
238
+ @files.first.nil?.should == false
239
+ end
240
+ it "should have an array of lines" do
241
+ @files.class.should == Array
242
+ end
243
+ it "should not be empty" do
244
+ @files.should_not be_empty
245
+ end
246
+ end
247
+ end
248
+ end
249
+ describe "building" do
250
+ before(:each) do
251
+ str = "master 192.168.0.1
252
+ node1 192.168.0.2"
253
+ @sample_instances_list = [{:ip => "192.168.0.1", :name => "master"}, {:ip => "192.168.0.2", :name => "node1"}]
254
+ @ris = @sample_instances_list.map {|h| PoolParty::Remote::RemoteInstance.new(h, @cloud) }
255
+
256
+ @manifest = @cloud.build_manifest
257
+ end
258
+ it "should return a string when calling build_manifest" do
259
+ @manifest.class.should == String
260
+ end
261
+ it "should have a comment of # file in the manifest as described by the has_file" do
262
+ @manifest.should =~ /file \{/
263
+ end
264
+ it "should have the comment of a package in the manifest" do
265
+ @manifest.should =~ /package \{/
266
+ end
267
+ it "should have the comment for heartbeat in the manifest" do
268
+ @manifest.should =~ /class heartbeat/
269
+ end
270
+ it "should include the poolparty gem" do
271
+ @manifest.should =~ /package \{/
272
+ end
273
+ it "should include custom functions" do
274
+ @manifest.should =~ /define line\(\$file/
275
+
276
+ File.open("test_manifest.pp", "w+") {|f| f << @manifest}
277
+ end
278
+ it "should include the hosts for all the listed local instances" do
279
+ @manifest.should =~ /host \{\n\t\t"master":/
280
+ end
281
+ end
282
+ end
283
+ end
284
+
285
+ describe "instances" do
286
+ before(:each) do
287
+ @cloud3 = cloud :pop do;keypair "fake_keypair";end
288
+ stub_list_from_remote_for(@cloud3)
289
+ end
290
+ it "should respond to the method master" do
291
+ @cloud3.respond_to?(:master).should == true
292
+ end
293
+ it "should return a master that is not nil" do
294
+ @cloud3.master.should_not be_nil
295
+ end
296
+ end
297
+
298
+ end
299
+ end