webbynode 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of webbynode might be problematic. Click here for more details.

Files changed (98) hide show
  1. data/Manifest +88 -4
  2. data/PostInstall.txt +42 -9
  3. data/README.rdoc +6 -0
  4. data/Rakefile +16 -19
  5. data/assets/webbynode.png +0 -0
  6. data/bin/webbynode +3 -3
  7. data/bin/wn +7 -0
  8. data/cucumber.yml +1 -0
  9. data/devver.rake +174 -0
  10. data/features/bootstrap.feature +17 -0
  11. data/features/step_definitions/command_steps.rb +14 -0
  12. data/features/support/env.rb +22 -0
  13. data/features/support/hooks.rb +8 -0
  14. data/{test/test_webbynode.rb → features/support/io_features.rb} +0 -0
  15. data/features/support/mocha.rb +15 -0
  16. data/lib/templates/api_token +14 -0
  17. data/lib/templates/backup +15 -0
  18. data/lib/templates/gitignore +4 -0
  19. data/lib/templates/help +53 -0
  20. data/lib/webbynode/api_client.rb +121 -0
  21. data/lib/webbynode/application.rb +21 -0
  22. data/lib/webbynode/command.rb +332 -0
  23. data/lib/webbynode/commands/add_backup.rb +33 -0
  24. data/lib/webbynode/commands/add_key.rb +24 -0
  25. data/lib/webbynode/commands/alias.rb +153 -0
  26. data/lib/webbynode/commands/change_dns.rb +29 -0
  27. data/lib/webbynode/commands/config.rb +15 -0
  28. data/lib/webbynode/commands/delete.rb +25 -0
  29. data/lib/webbynode/commands/help.rb +25 -0
  30. data/lib/webbynode/commands/init.rb +77 -0
  31. data/lib/webbynode/commands/push.rb +70 -0
  32. data/lib/webbynode/commands/remote.rb +28 -0
  33. data/lib/webbynode/commands/restart.rb +25 -0
  34. data/lib/webbynode/commands/start.rb +23 -0
  35. data/lib/webbynode/commands/stop.rb +23 -0
  36. data/lib/webbynode/commands/tasks.rb +149 -0
  37. data/lib/webbynode/commands/version.rb +8 -0
  38. data/lib/webbynode/commands/webbies.rb +30 -0
  39. data/lib/webbynode/git.rb +112 -0
  40. data/lib/webbynode/io.rb +175 -0
  41. data/lib/webbynode/notify.rb +19 -0
  42. data/lib/webbynode/option.rb +84 -0
  43. data/lib/webbynode/parameter.rb +27 -0
  44. data/lib/webbynode/properties.rb +43 -0
  45. data/lib/webbynode/push_and.rb +16 -0
  46. data/lib/webbynode/remote_executor.rb +21 -0
  47. data/lib/webbynode/server.rb +39 -0
  48. data/lib/webbynode/ssh.rb +65 -0
  49. data/lib/webbynode/ssh_keys.rb +36 -0
  50. data/lib/webbynode.rb +56 -0
  51. data/spec/fixtures/aliases +0 -0
  52. data/spec/fixtures/api/credentials +3 -0
  53. data/spec/fixtures/api/dns +30 -0
  54. data/spec/fixtures/api/dns_a_record +20 -0
  55. data/spec/fixtures/api/dns_a_record_already_exists +15 -0
  56. data/spec/fixtures/api/dns_a_record_error +13 -0
  57. data/spec/fixtures/api/dns_new_zone +17 -0
  58. data/spec/fixtures/api/webbies +26 -0
  59. data/spec/fixtures/api/webbies_unauthorized +12 -0
  60. data/spec/fixtures/api/webby +6 -0
  61. data/spec/fixtures/commands/tasks/after_push +3 -0
  62. data/spec/fixtures/fixture_helpers +2 -0
  63. data/spec/fixtures/git/config/210.11.13.12 +9 -0
  64. data/spec/fixtures/git/config/67.23.79.31 +9 -0
  65. data/spec/fixtures/git/config/67.23.79.32 +9 -0
  66. data/spec/fixtures/git/config/config +9 -0
  67. data/spec/fixtures/git/status/clean +2 -0
  68. data/spec/fixtures/git/status/dirty +9 -0
  69. data/spec/fixtures/pushand +2 -0
  70. data/spec/spec_helper.rb +58 -0
  71. data/spec/webbynode/api_client_spec.rb +227 -0
  72. data/spec/webbynode/application_spec.rb +50 -0
  73. data/spec/webbynode/command_spec.rb +285 -0
  74. data/spec/webbynode/commands/add_backup_spec.rb +66 -0
  75. data/spec/webbynode/commands/add_key_spec.rb +58 -0
  76. data/spec/webbynode/commands/alias_spec.rb +213 -0
  77. data/spec/webbynode/commands/change_dns_spec.rb +51 -0
  78. data/spec/webbynode/commands/config_spec.rb +22 -0
  79. data/spec/webbynode/commands/delete_spec.rb +78 -0
  80. data/spec/webbynode/commands/help_spec.rb +43 -0
  81. data/spec/webbynode/commands/init_spec.rb +326 -0
  82. data/spec/webbynode/commands/push_spec.rb +175 -0
  83. data/spec/webbynode/commands/remote_spec.rb +76 -0
  84. data/spec/webbynode/commands/tasks_spec.rb +288 -0
  85. data/spec/webbynode/commands/version_spec.rb +18 -0
  86. data/spec/webbynode/commands/webbies_spec.rb +27 -0
  87. data/spec/webbynode/git_spec.rb +310 -0
  88. data/spec/webbynode/io_spec.rb +198 -0
  89. data/spec/webbynode/option_spec.rb +48 -0
  90. data/spec/webbynode/parameter_spec.rb +70 -0
  91. data/spec/webbynode/push_and_spec.rb +28 -0
  92. data/spec/webbynode/remote_executor_spec.rb +25 -0
  93. data/spec/webbynode/server_spec.rb +101 -0
  94. data/webbynode.gemspec +25 -16
  95. metadata +182 -14
  96. data/lib/wn.rb +0 -106
  97. data/test/test_helper.rb +0 -9
  98. data/test/test_wn.rb +0 -220
@@ -0,0 +1,76 @@
1
+ # Load Spec Helper
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
3
+
4
+ describe Webbynode::Commands::Remote do
5
+
6
+ def load_all_mocks(rem=remote)
7
+ rem.should_receive(:remote_executor).any_number_of_times.and_return(re)
8
+ rem.should_receive(:git).any_number_of_times.and_return(git)
9
+ rem.should_receive(:io).any_number_of_times.and_return(io)
10
+ rem.should_receive(:pushand).any_number_of_times.and_return(pushand)
11
+ rem.should_receive(:server).any_number_of_times.and_return(server)
12
+ end
13
+
14
+ let(:re) { double("RemoteExecutor").as_null_object }
15
+ let(:git) { double("Git").as_null_object }
16
+ let(:pushand) { double("Pushand").as_null_object }
17
+ let(:server) { double("Server").as_null_object }
18
+ let(:ssh) { double("SSh").as_null_object }
19
+ let(:io) { double("Io").as_null_object }
20
+ let(:remote) { Webbynode::Commands::Remote.new('ls -la') }
21
+
22
+ before do
23
+ load_all_mocks
24
+ end
25
+
26
+ it "should notify the user" do
27
+ io.should_receive(:log).with("Performing the requested remote command..", true)
28
+ remote.run
29
+ end
30
+
31
+ context "when successful" do
32
+ it "should receive at least one option when passing in the remote command" do
33
+ remote = Webbynode::Commands::Remote.new('ls')
34
+ remote.params.first.value.should eql(['ls'])
35
+ end
36
+
37
+ it "multiple options will be joined together if multiple options are provided" do
38
+ remote = Webbynode::Commands::Remote.new('ls -la')
39
+ remote.params.first.value.should eql(['ls -la'])
40
+ end
41
+
42
+ it "should establish a connection with the server" do
43
+ remote = Webbynode::Commands::Remote.new('ls -la')
44
+ remote.stub(:validate_initialization)
45
+ load_all_mocks(remote)
46
+ pushand.should_receive(:parse_remote_app_name).and_return('test.webbynode.com')
47
+ re.should_receive(:exec).with("cd test.webbynode.com; ls -la", true)
48
+ remote.run
49
+ end
50
+
51
+ it "should consider all parameters a single command" do
52
+ remote = Webbynode::Commands::Remote.new('these', 'are', 'the', 'params')
53
+ pushand.should_receive(:parse_remote_app_name).and_return('webbynode')
54
+ load_all_mocks(remote)
55
+ remote.stub(:validate_initialization)
56
+ remote.stub(:validate_remote_application_availability)
57
+
58
+ re.should_receive(:exec).with("cd webbynode; these are the params", true)
59
+ remote.run
60
+ end
61
+
62
+ it "should parse the pushand file for the application folder name on the remote server" do
63
+ remote.stub(:validate_initialization)
64
+ pushand.should_receive(:parse_remote_app_name).and_return("dummy_app")
65
+ remote.run
66
+ end
67
+
68
+ end
69
+
70
+ context "when unsuccesful" do
71
+ it "should raise an error if no options are provided" do
72
+ Webbynode::Commands::Remote.new.run
73
+ stdout.should =~ /Missing 'command' parameter/
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,288 @@
1
+ # Load Spec Helper
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
3
+
4
+ describe Webbynode::Commands::Tasks do
5
+
6
+ it "should have constants defining the paths to the task files" do
7
+ tasks_class = Webbynode::Commands::Tasks
8
+ tasks_class::TasksPath.should eql(".webbynode/tasks")
9
+ tasks_class::BeforePushTasksFile.should eql(".webbynode/tasks/before_push")
10
+ tasks_class::AfterPushTasksFile.should eql(".webbynode/tasks/after_push")
11
+ end
12
+
13
+ let(:io) { double('io').as_null_object }
14
+ let(:task) { Webbynode::Commands::Tasks.new('add', 'after_push', 'rake', 'db:migrate', 'RAILS_ENV=production') }
15
+
16
+ before(:each) do
17
+ task.should_receive(:io).any_number_of_times.and_return(io)
18
+ end
19
+
20
+ describe "invalid parameters" do
21
+ before(:each) do
22
+ io.stub!(:directory?).with('.webbynode').and_return(true)
23
+ io.stub!(:directory?).with('.webbynode/tasks').and_return(true)
24
+ end
25
+
26
+ it "should should report an invalid action" do
27
+ task = Webbynode::Commands::Tasks.new('undefined_op', 'after', 'abc')
28
+ task.should_receive(:io).any_number_of_times.and_return(io)
29
+ task.run
30
+ stdout.should =~ /Invalid value 'undefined_op' for parameter 'action'. It should be one of 'add', 'remove' or 'show'./
31
+ end
32
+
33
+ it "should should report an invalid type" do
34
+ task = Webbynode::Commands::Tasks.new('add', 'nah_way', 'abc')
35
+ task.should_receive(:io).any_number_of_times.and_return(io)
36
+ task.run
37
+ stdout.should =~ /Invalid value 'nah_way' for parameter 'type'. It should be one of 'before_push' or 'after_push'./
38
+ end
39
+ end
40
+
41
+ describe "webbynode tasks folder and files" do
42
+ context "when not available" do
43
+ before(:each) do
44
+ io.stub!(:directory?).with('.webbynode').and_return(false)
45
+ io.stub!(:directory?).with('.webbynode/tasks').and_return(false)
46
+ end
47
+
48
+ it "should ensure the availability of the required webbynode files" do
49
+ task.should_receive(:ensure_tasks_folder)
50
+ task.execute
51
+ end
52
+
53
+ it "should create the webbynode tasks folder" do
54
+ io.should_receive(:exec).with('mkdir .webbynode/tasks')
55
+ task.execute
56
+ end
57
+
58
+ it "should create the 2 files required by the tasks command" do
59
+ %w[before_push after_push].each do |file|
60
+ io.should_receive(:file_exists?).with(".webbynode/tasks/#{file}").and_return(false)
61
+ io.should_receive(:exec).with("touch .webbynode/tasks/#{file}")
62
+ end
63
+ task.execute
64
+ end
65
+ end
66
+
67
+ context "when available" do
68
+ before(:each) do
69
+ io.stub!(:directory?).with('.webbynode').and_return(true)
70
+ io.stub!(:directory?).with('.webbynode/tasks').and_return(true)
71
+ end
72
+
73
+ it "should ensure the availability of the required webbynode files" do
74
+ task.should_receive(:ensure_tasks_folder)
75
+ task.execute
76
+ end
77
+
78
+ it "should create the webbynode folder" do
79
+ io.should_not_receive(:exec).with('mkdir .webbynode')
80
+ task.execute
81
+ end
82
+
83
+ it "should create the webbynode folder" do
84
+ io.should_not_receive(:exec).with('mkdir .webbynode/tasks')
85
+ task.execute
86
+ end
87
+
88
+ it "should create the 4 files required by the tasks command" do
89
+ %w[before_push after_push].each do |file|
90
+ io.should_receive(:file_exists?).with(".webbynode/tasks/#{file}").and_return(true)
91
+ io.should_not_receive(:exec).with("touch .webbynode/tasks/#{file}")
92
+ end
93
+ task.execute
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "#has_tasks?" do
99
+ it "should not have any tasks" do
100
+ task.session_tasks = []
101
+ task.has_tasks?.should be_false
102
+ end
103
+
104
+ it "should have 2 tasks" do
105
+ 2.times { task.session_tasks << "foo" }
106
+ task.has_tasks?.should be_true
107
+ end
108
+ end
109
+
110
+ it "should parse the params provided by the user" do
111
+ task.should_receive(:parse_parameters)
112
+ task.stub!(:send)
113
+ task.execute
114
+ end
115
+
116
+ it "should have correctly parsed and stored the user input" do
117
+ task.execute
118
+ task.action.should eql("add")
119
+ task.type.should eql("after_push")
120
+ task.command.should eql("rake db:migrate RAILS_ENV=production")
121
+ end
122
+
123
+ it "should set the current path for the specified task interaction type" do
124
+ task.should_receive(:set_session_file)
125
+ task.execute
126
+ end
127
+
128
+ describe "selectable paths" do
129
+ def selectable_helper(type)
130
+ @task = @tasks_class.new("add", type)
131
+ @task.stub!(:validate_parameters)
132
+ @task.stub!(:send)
133
+ @task.should_receive(:io).any_number_of_times.and_return(io)
134
+ @task.execute
135
+ end
136
+
137
+ before(:each) do
138
+ @tasks_class = Webbynode::Commands::Tasks
139
+ end
140
+
141
+ it "should be the before_create path" do
142
+ selectable_helper('before_push')
143
+ @task.session_file.should eql(@tasks_class::BeforePushTasksFile)
144
+ end
145
+
146
+ it "should be the before_create path" do
147
+ selectable_helper('after_push')
148
+ @task.session_file.should eql(@tasks_class::AfterPushTasksFile)
149
+ end
150
+ end
151
+
152
+ context "should initialize the [add] or [remove] action, depending on user input" do
153
+ it "should have a [add] and [remove] method availble" do
154
+ task.private_methods.should include('add')
155
+ task.private_methods.should include('remove')
156
+ end
157
+
158
+ it "should initialize the [add] method" do
159
+ task.should_receive(:send).with('add')
160
+ task.execute
161
+ end
162
+
163
+ it "should initialize the [remove] method" do
164
+ task = Webbynode::Commands::Tasks.new('remove', 'after_push', 'rake', 'db:migrate', 'RAILS_ENV=production')
165
+ task.should_receive(:send).with('remove')
166
+ task.stub!(:read_tasks)
167
+ task.execute
168
+ end
169
+ end
170
+
171
+ describe "displaying tasks from a file" do
172
+ let(:stask) { Webbynode::Commands::Tasks.new('show', 'after_push') }
173
+
174
+ before(:each) do
175
+ stask.should_receive(:io).any_number_of_times.and_return(io)
176
+ end
177
+
178
+ it "should invoke the [show] method" do
179
+ stask.should_receive(:send).with('show')
180
+ stask.execute
181
+ end
182
+
183
+ it "should read out the specified file" do
184
+ stask.should_receive(:show_tasks)
185
+ stask.execute
186
+ end
187
+
188
+ it "should display no tasks, since there are none initially" do
189
+ io.should_receive(:log).with("These are the current tasks for \"After push\":")
190
+ io.should_not_receive(:log)
191
+ stask.execute
192
+ stask.should have(0).session_tasks
193
+ end
194
+
195
+ it "should display 3 tasks: task0 task1 task2" do
196
+ 3.times {|num| stask.session_tasks << "task#{num}"}
197
+ io.should_receive(:log).with("These are the current tasks for \"After push\":")
198
+ stask.stub!(:read_tasks)
199
+ io.should_not_receive(:log_and_exit)
200
+ io.should_receive(:log).with("[0] task0")
201
+ io.should_receive(:log).with("[1] task1")
202
+ io.should_receive(:log).with("[2] task2")
203
+ stask.execute
204
+ stask.should have(3).session_tasks
205
+ end
206
+
207
+ it "should tell the user that there are no tasks if there aren't any" do
208
+ stask.stub!(:read_tasks)
209
+ io.should_receive(:log_and_exit).with("You haven't set up any tasks for \"After push\".")
210
+ io.should_not_receive(:log).with("These are the current tasks for \"After push\".")
211
+ stask.execute
212
+ end
213
+ end
214
+
215
+ describe "adding tasks to a file" do
216
+ before(:each) do
217
+ task.should_receive(:io).any_number_of_times.and_return(io)
218
+ end
219
+
220
+ context "when successful" do
221
+ it "should read the specified file" do
222
+ task.should_receive(:read_tasks).with('.webbynode/tasks/after_push')
223
+ task.stub!(:send)
224
+ task.execute
225
+ task.session_file.should eql('.webbynode/tasks/after_push')
226
+ end
227
+
228
+ it "should append the new task to the array" do
229
+ task.should_receive(:append_task).with('rake db:migrate RAILS_ENV=production')
230
+ task.execute
231
+ end
232
+
233
+ it "should have appended the new task to the array" do
234
+ task.execute
235
+ task.session_tasks.should include('rake db:migrate RAILS_ENV=production')
236
+ end
237
+
238
+ it "should write a new file with the updated task list" do
239
+ task.should_receive(:write_tasks)
240
+ task.execute
241
+ end
242
+
243
+ it "should display the updated list of tasks" do
244
+ io.should_receive(:log).with("These are the current tasks for \"After push\":")
245
+ io.should_receive(:log).with("[0] rake db:migrate RAILS_ENV=production")
246
+ task.execute
247
+ end
248
+ end
249
+ end
250
+
251
+ describe "removing tasks from a file" do
252
+ let(:rtask) { Webbynode::Commands::Tasks.new('remove', 'after_push', 1) }
253
+
254
+ before(:each) do
255
+ rtask.should_receive(:io).any_number_of_times.and_return(io)
256
+ end
257
+
258
+ context "when successful" do
259
+ it "should initialize the [remove] method" do
260
+ rtask.should_receive(:send).with('remove')
261
+ rtask.execute
262
+ end
263
+
264
+ it "should remove the task from the list of available tasks" do
265
+ rtask.should_receive(:delete_task).with(1)
266
+ rtask.execute
267
+ end
268
+
269
+ it "should write the new tasks" do
270
+ rtask.should_receive(:write_tasks)
271
+ rtask.execute
272
+ end
273
+
274
+ it "should display the updated list of tasks" do
275
+ 3.times {|num| rtask.session_tasks << "task#{num}" }
276
+ rtask.stub(:read_tasks)
277
+ io.should_receive(:log).with("These are the current tasks for \"After push\":")
278
+ io.should_receive(:log).with("[0] task0")
279
+ io.should_not_receive(:log).with("[1] task1")
280
+ io.should_receive(:log).with("[1] task2")
281
+ rtask.execute
282
+ rtask.session_tasks.should include("task0")
283
+ rtask.session_tasks.should_not include("task1")
284
+ rtask.session_tasks.should include("task2")
285
+ end
286
+ end
287
+ end
288
+ end
@@ -0,0 +1,18 @@
1
+ # Load Spec Helper
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
3
+
4
+ describe Webbynode::Commands::Version do
5
+
6
+ let(:version) { Webbynode::Commands::Version.new }
7
+ let(:io) { double('io').as_null_object }
8
+
9
+ before(:each) do
10
+ version.should_receive(:io).any_number_of_times.and_return(io)
11
+ end
12
+
13
+ it "should return the version of the gem" do
14
+ io.should_receive(:log).with("Rapid Deployment Gem v#{Webbynode::VERSION}", true)
15
+ version.execute
16
+ end
17
+
18
+ end
@@ -0,0 +1,27 @@
1
+ # Load Spec Helper
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
3
+
4
+ describe Webbynode::Commands::Webbies do
5
+ before(:each) do
6
+ FakeWeb.clean_registry
7
+ end
8
+
9
+ it "should provide a list with all the Webbies and its status" do
10
+ FakeWeb.register_uri(:post, "#{Webbynode::ApiClient.base_uri}/webbies",
11
+ :email => "fcoury@me.com", :response => read_fixture("api/webbies"))
12
+
13
+ api = Webbynode::ApiClient.new
14
+ api.stub("properties")
15
+
16
+ cmd = Webbynode::Commands::Webbies.new
17
+ cmd.should_receive(:api).and_return(api)
18
+ cmd.execute
19
+
20
+ stdout.should =~ /sandbox/
21
+ stdout.should =~ /201\.81\.121\.201/
22
+ stdout.should =~ /miami-b15/
23
+ stdout.should =~ /webby3067/
24
+ stdout.should =~ /61\.21\.71\.31/
25
+ stdout.should =~ /miami-b02/
26
+ end
27
+ end