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.
- data/Manifest +88 -4
- data/PostInstall.txt +42 -9
- data/README.rdoc +6 -0
- data/Rakefile +16 -19
- data/assets/webbynode.png +0 -0
- data/bin/webbynode +3 -3
- data/bin/wn +7 -0
- data/cucumber.yml +1 -0
- data/devver.rake +174 -0
- data/features/bootstrap.feature +17 -0
- data/features/step_definitions/command_steps.rb +14 -0
- data/features/support/env.rb +22 -0
- data/features/support/hooks.rb +8 -0
- data/{test/test_webbynode.rb → features/support/io_features.rb} +0 -0
- data/features/support/mocha.rb +15 -0
- data/lib/templates/api_token +14 -0
- data/lib/templates/backup +15 -0
- data/lib/templates/gitignore +4 -0
- data/lib/templates/help +53 -0
- data/lib/webbynode/api_client.rb +121 -0
- data/lib/webbynode/application.rb +21 -0
- data/lib/webbynode/command.rb +332 -0
- data/lib/webbynode/commands/add_backup.rb +33 -0
- data/lib/webbynode/commands/add_key.rb +24 -0
- data/lib/webbynode/commands/alias.rb +153 -0
- data/lib/webbynode/commands/change_dns.rb +29 -0
- data/lib/webbynode/commands/config.rb +15 -0
- data/lib/webbynode/commands/delete.rb +25 -0
- data/lib/webbynode/commands/help.rb +25 -0
- data/lib/webbynode/commands/init.rb +77 -0
- data/lib/webbynode/commands/push.rb +70 -0
- data/lib/webbynode/commands/remote.rb +28 -0
- data/lib/webbynode/commands/restart.rb +25 -0
- data/lib/webbynode/commands/start.rb +23 -0
- data/lib/webbynode/commands/stop.rb +23 -0
- data/lib/webbynode/commands/tasks.rb +149 -0
- data/lib/webbynode/commands/version.rb +8 -0
- data/lib/webbynode/commands/webbies.rb +30 -0
- data/lib/webbynode/git.rb +112 -0
- data/lib/webbynode/io.rb +175 -0
- data/lib/webbynode/notify.rb +19 -0
- data/lib/webbynode/option.rb +84 -0
- data/lib/webbynode/parameter.rb +27 -0
- data/lib/webbynode/properties.rb +43 -0
- data/lib/webbynode/push_and.rb +16 -0
- data/lib/webbynode/remote_executor.rb +21 -0
- data/lib/webbynode/server.rb +39 -0
- data/lib/webbynode/ssh.rb +65 -0
- data/lib/webbynode/ssh_keys.rb +36 -0
- data/lib/webbynode.rb +56 -0
- data/spec/fixtures/aliases +0 -0
- data/spec/fixtures/api/credentials +3 -0
- data/spec/fixtures/api/dns +30 -0
- data/spec/fixtures/api/dns_a_record +20 -0
- data/spec/fixtures/api/dns_a_record_already_exists +15 -0
- data/spec/fixtures/api/dns_a_record_error +13 -0
- data/spec/fixtures/api/dns_new_zone +17 -0
- data/spec/fixtures/api/webbies +26 -0
- data/spec/fixtures/api/webbies_unauthorized +12 -0
- data/spec/fixtures/api/webby +6 -0
- data/spec/fixtures/commands/tasks/after_push +3 -0
- data/spec/fixtures/fixture_helpers +2 -0
- data/spec/fixtures/git/config/210.11.13.12 +9 -0
- data/spec/fixtures/git/config/67.23.79.31 +9 -0
- data/spec/fixtures/git/config/67.23.79.32 +9 -0
- data/spec/fixtures/git/config/config +9 -0
- data/spec/fixtures/git/status/clean +2 -0
- data/spec/fixtures/git/status/dirty +9 -0
- data/spec/fixtures/pushand +2 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/webbynode/api_client_spec.rb +227 -0
- data/spec/webbynode/application_spec.rb +50 -0
- data/spec/webbynode/command_spec.rb +285 -0
- data/spec/webbynode/commands/add_backup_spec.rb +66 -0
- data/spec/webbynode/commands/add_key_spec.rb +58 -0
- data/spec/webbynode/commands/alias_spec.rb +213 -0
- data/spec/webbynode/commands/change_dns_spec.rb +51 -0
- data/spec/webbynode/commands/config_spec.rb +22 -0
- data/spec/webbynode/commands/delete_spec.rb +78 -0
- data/spec/webbynode/commands/help_spec.rb +43 -0
- data/spec/webbynode/commands/init_spec.rb +326 -0
- data/spec/webbynode/commands/push_spec.rb +175 -0
- data/spec/webbynode/commands/remote_spec.rb +76 -0
- data/spec/webbynode/commands/tasks_spec.rb +288 -0
- data/spec/webbynode/commands/version_spec.rb +18 -0
- data/spec/webbynode/commands/webbies_spec.rb +27 -0
- data/spec/webbynode/git_spec.rb +310 -0
- data/spec/webbynode/io_spec.rb +198 -0
- data/spec/webbynode/option_spec.rb +48 -0
- data/spec/webbynode/parameter_spec.rb +70 -0
- data/spec/webbynode/push_and_spec.rb +28 -0
- data/spec/webbynode/remote_executor_spec.rb +25 -0
- data/spec/webbynode/server_spec.rb +101 -0
- data/webbynode.gemspec +25 -16
- metadata +182 -14
- data/lib/wn.rb +0 -106
- data/test/test_helper.rb +0 -9
- data/test/test_wn.rb +0 -220
@@ -0,0 +1,285 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Command do
|
5
|
+
let(:re) { double("RemoteExecutor").as_null_object }
|
6
|
+
let(:git) { double("Git").as_null_object }
|
7
|
+
let(:pushand) { double("Pushand").as_null_object }
|
8
|
+
let(:server) { double("Server").as_null_object }
|
9
|
+
let(:ssh) { double("SSh").as_null_object }
|
10
|
+
let(:io) { double("Io").as_null_object }
|
11
|
+
|
12
|
+
describe "resolving commands" do
|
13
|
+
it "should allow adding aliases to child classes" do
|
14
|
+
class Zap < Webbynode::Command
|
15
|
+
add_alias "zip"
|
16
|
+
end
|
17
|
+
|
18
|
+
Webbynode::Commands.should_receive(:const_get).with("Zap")
|
19
|
+
Webbynode::Command.for("zip")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should look for a class with the name of the command" do
|
23
|
+
Webbynode::Commands.should_receive(:const_get).with("Zap")
|
24
|
+
Webbynode::Command.for("zap")
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when class exists" do
|
28
|
+
it "should translate words separated by underscore into capitalized parts" do
|
29
|
+
Webbynode::Commands.should_receive(:const_get).with("RandomThoughtsIHad")
|
30
|
+
Webbynode::Command.for("random_thoughts_i_had")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#command" do
|
36
|
+
it "should return the string representation of the command" do
|
37
|
+
AwfulCommand = Class.new(Webbynode::Command)
|
38
|
+
AwfulCommand.command.should == "awful_command"
|
39
|
+
Amazing = Class.new(Webbynode::Command)
|
40
|
+
Amazing.command.should == "amazing"
|
41
|
+
SomeStrangeStuff = Class.new(Webbynode::Command)
|
42
|
+
SomeStrangeStuff.command.should == "some_strange_stuff"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#run" do
|
47
|
+
class RequireInitialize < Webbynode::Command
|
48
|
+
requires_initialization!
|
49
|
+
|
50
|
+
def execute
|
51
|
+
puts "command was executed"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when git is missing" do
|
56
|
+
it "should provide a friendly error" do
|
57
|
+
git.should_receive(:present?).and_return(false)
|
58
|
+
|
59
|
+
command = RequireInitialize.new
|
60
|
+
command.should_receive(:remote_executor).any_number_of_times.and_return(re)
|
61
|
+
command.should_receive(:git).any_number_of_times.and_return(git)
|
62
|
+
command.should_receive(:io).any_number_of_times.and_return(io)
|
63
|
+
command.should_receive(:pushand).any_number_of_times.and_return(pushand)
|
64
|
+
command.should_receive(:server).any_number_of_times.and_return(server)
|
65
|
+
command.run
|
66
|
+
|
67
|
+
stdout.should =~ /Hello, McFly, anybody home?/
|
68
|
+
stdout.should_not =~ /command was executed/
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "array of parameters" do
|
74
|
+
class ArrayCommand < Webbynode::Command
|
75
|
+
description "Initializes the current folder as a deployable application"
|
76
|
+
parameter :params, Array, "Name or IP of the Webby to deploy to"
|
77
|
+
option :passphrase, String, "If present, passphrase will be used when creating a new SSH key", :take => :words
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return an array of parameters" do
|
81
|
+
cmd = ArrayCommand.new("a", "b", "--passphrase=abc", "c", "d")
|
82
|
+
cmd.params.first.value.should == ["a", "b", "c", "d"]
|
83
|
+
cmd.option(:passphrase).should == "abc"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "with no params" do
|
88
|
+
class Brief < Webbynode::Command
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should refuse any param" do
|
92
|
+
cmd = Brief.new("test")
|
93
|
+
cmd.run
|
94
|
+
stdout.should =~ /command 'brief' takes no parameters/
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "help for commands" do
|
99
|
+
class NewCommand < Webbynode::Command
|
100
|
+
description "Initializes the current folder as a deployable application"
|
101
|
+
parameter :webby, String, "Name or IP of the Webby to deploy to"
|
102
|
+
parameter :dns, String, "The DNS used for this application", :required => false
|
103
|
+
|
104
|
+
option :passphrase, String, "If present, passphrase will be used when creating a new SSH key", :take => :words
|
105
|
+
end
|
106
|
+
|
107
|
+
before(:each) do
|
108
|
+
@cmd = NewCommand.new("what!")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should provide help for parameters" do
|
112
|
+
NewCommand.help.should =~ /Usage: webbynode new_command webby \[dns\] \[options\]/
|
113
|
+
NewCommand.help.should =~ /Parameters:/
|
114
|
+
NewCommand.help.should =~ / webby Name or IP of the Webby to deploy to/
|
115
|
+
NewCommand.help.should =~ / dns The DNS used for this application, optional/
|
116
|
+
NewCommand.help.should =~ /Options:/
|
117
|
+
NewCommand.help.should =~ / --passphrase=words If present, passphrase will be used when creating a new SSH key/
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should show the help if --help option is passed" do
|
121
|
+
cmd = NewCommand.new("--help")
|
122
|
+
cmd.run
|
123
|
+
stdout.should =~ /Usage: webbynode new_command webby \[dns\] \[options\]/
|
124
|
+
stdout.should =~ /Parameters:/
|
125
|
+
stdout.should =~ / webby Name or IP of the Webby to deploy to/
|
126
|
+
stdout.should =~ / dns The DNS used for this application, optional/
|
127
|
+
stdout.should =~ /Options:/
|
128
|
+
stdout.should =~ / --passphrase=words If present, passphrase will be used when creating a new SSH key/
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "parsing options" do
|
133
|
+
it "should complain about missing params and show usage" do
|
134
|
+
Sample = Class.new(Webbynode::Command)
|
135
|
+
Sample.parameter :param1, "Teste"
|
136
|
+
|
137
|
+
cmd = Sample.new
|
138
|
+
cmd.run
|
139
|
+
|
140
|
+
stdout.should =~ /Missing 'param1' parameter. Use "webbynode help sample" for more information./
|
141
|
+
stdout.should =~ /Usage: webbynode sample param1/
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should report an unknown option" do
|
145
|
+
Sample99 = Class.new(Webbynode::Command)
|
146
|
+
cmd = Sample99.new("--unknown")
|
147
|
+
lambda { cmd.run }.should_not raise_error
|
148
|
+
stdout.should =~ /Unknown option: unknown/
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should parse arguments as params" do
|
152
|
+
Sample1 = Class.new(Webbynode::Command)
|
153
|
+
Sample1.parameter :param1, ""
|
154
|
+
Sample1.parameter :param2, ""
|
155
|
+
|
156
|
+
cmd = Sample1.new("param1", "param2")
|
157
|
+
cmd.params.first.value.should == "param1"
|
158
|
+
cmd.params.last.value.should == "param2"
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should parse arguments starting with -- as options" do
|
162
|
+
Sample2 = Class.new(Webbynode::Command)
|
163
|
+
Sample2.option :provided, ""
|
164
|
+
|
165
|
+
cmd = Sample2.new("--provided=auto")
|
166
|
+
cmd.option(:provided).should == "auto"
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should parse arguments without values as true" do
|
170
|
+
Sample3 = Class.new(Webbynode::Command)
|
171
|
+
Sample3.option :force, ""
|
172
|
+
|
173
|
+
wn = Sample3.new("--force")
|
174
|
+
wn.option(:force).should be_true
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should provide option names as symbols" do
|
178
|
+
Sample4 = Class.new(Webbynode::Command)
|
179
|
+
Sample4.option :provided, ""
|
180
|
+
|
181
|
+
wn = Sample4.new("--provided=auto")
|
182
|
+
wn.option(:provided).should == "auto"
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should parse quoted values" do
|
186
|
+
Sample5 = Class.new(Webbynode::Command)
|
187
|
+
Sample5.option :name, ""
|
188
|
+
|
189
|
+
wn = Sample5.new("--name=\"Felipe Coury\"")
|
190
|
+
wn.option(:name).should == "Felipe Coury"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "parsing mixed options and parameters" do
|
195
|
+
class Cmd < Webbynode::Command
|
196
|
+
parameter :param1, String, "param1"
|
197
|
+
parameter :param2, String, "param2"
|
198
|
+
option :provided, "option1"
|
199
|
+
option :force, "option2"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should provide option names as strings and symbols" do
|
203
|
+
wn = Cmd.new("--provided=auto", "param1", "--force", "param2")
|
204
|
+
wn.option(:provided) == "auto"
|
205
|
+
wn.option(:force).should be_true
|
206
|
+
lambda { wn.option(:another) }.should raise_error(Webbynode::Command::CommandError)
|
207
|
+
wn.param_values.should == ["param1", "param2"]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "handling Unauthorized API errors" do
|
212
|
+
class UnauthorizedCommand < Webbynode::Command
|
213
|
+
def execute
|
214
|
+
raise Webbynode::ApiClient::Unauthorized
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should output a friendly message" do
|
219
|
+
cmd = UnauthorizedCommand.new
|
220
|
+
cmd.run
|
221
|
+
|
222
|
+
stdout.should =~ /Your credentials didn't match any Webbynode account./
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "parsing array parameters" do
|
227
|
+
class ArrayCmd < Webbynode::Command
|
228
|
+
parameter :param1, String, "param1"
|
229
|
+
parameter :param2, String, "param2"
|
230
|
+
parameter :param_array, Array, "array"
|
231
|
+
option :option, String, "descr"
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should parse params and all remaining as the array param" do
|
235
|
+
cmd = ArrayCmd.new("param1", "param2", "arr1", "arr2", "arr3", "arr4")
|
236
|
+
cmd.param(:param1).should == "param1"
|
237
|
+
cmd.param(:param2).should == "param2"
|
238
|
+
cmd.param(:param_array).should == ["arr1", "arr2", "arr3", "arr4"]
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should ignore options" do
|
242
|
+
cmd = ArrayCmd.new("param1", "param2", "--option=tough", "arr1", "arr2", "arr3", "arr4")
|
243
|
+
cmd.option(:option).should == "tough"
|
244
|
+
cmd.param(:param1).should == "param1"
|
245
|
+
cmd.param(:param2).should == "param2"
|
246
|
+
cmd.param(:param_array).should == ["arr1", "arr2", "arr3", "arr4"]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context "with a webbynode uninitialized application" do
|
251
|
+
class NewCommand < Webbynode::Command
|
252
|
+
requires_initialization!
|
253
|
+
end
|
254
|
+
|
255
|
+
before do
|
256
|
+
command.should_receive(:remote_executor).any_number_of_times.and_return(re)
|
257
|
+
command.should_receive(:git).any_number_of_times.and_return(git)
|
258
|
+
command.should_receive(:io).any_number_of_times.and_return(io)
|
259
|
+
command.should_receive(:pushand).any_number_of_times.and_return(pushand)
|
260
|
+
command.should_receive(:server).any_number_of_times.and_return(server)
|
261
|
+
end
|
262
|
+
|
263
|
+
let(:command) { NewCommand.new("some") }
|
264
|
+
|
265
|
+
it "should not have a git repository" do
|
266
|
+
git.should_receive(:present?).and_return(false)
|
267
|
+
lambda { command.validate_initialization }.should raise_error(Webbynode::Command::CommandError,
|
268
|
+
"Ahn!? Hello, McFly, anybody home?")
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should not have webbynode git remote" do
|
272
|
+
git.should_receive(:remote_webbynode?).and_return(false)
|
273
|
+
lambda { command.validate_initialization }.should raise_error(Webbynode::Command::CommandError,
|
274
|
+
"Webbynode has not been initialized for this git repository.")
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should not have a pushand file" do
|
278
|
+
git.should_receive(:present?).and_return(true)
|
279
|
+
io.should_receive(:directory?).with(".webbynode").and_return(true)
|
280
|
+
pushand.should_receive(:present?).and_return(false)
|
281
|
+
lambda { command.validate_initialization }.should raise_error(Webbynode::Command::CommandError,
|
282
|
+
"Could not find .pushand file, has Webbynode been initialized for this repository?")
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Commands::AddBackup do
|
5
|
+
def tie_dependencies(cmd)
|
6
|
+
cmd.should_receive(:io).any_number_of_times.and_return(io)
|
7
|
+
cmd.should_receive(:remote_executor).any_number_of_times.and_return(re)
|
8
|
+
cmd
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:io) { double("io").as_null_object }
|
12
|
+
let(:re) { double("remote_executor").as_null_object }
|
13
|
+
let(:cmd) {
|
14
|
+
cmd = Webbynode::Commands::AddBackup.new
|
15
|
+
tie_dependencies(cmd)
|
16
|
+
}
|
17
|
+
|
18
|
+
it "should allow user to specify a retention period, in days" do
|
19
|
+
io.should_receive(:app_name).and_return("app")
|
20
|
+
io.should_receive(:general_settings).any_number_of_times.and_return({ "aws_key" => "abc", "aws_secret" => "def" })
|
21
|
+
re.should_receive(:exec).with("config_app_backup").with(%Q(config_app_backup app "abc" "def" 10), true)
|
22
|
+
|
23
|
+
cmd = tie_dependencies(Webbynode::Commands::AddBackup.new("--retain=10"))
|
24
|
+
cmd.run
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should ask user's aws key and secret, if missing from ~/.weebynode" do
|
28
|
+
io.should_receive(:general_settings).any_number_of_times.and_return({})
|
29
|
+
|
30
|
+
io.should_receive(:add_general_setting).with("aws_key", "aws_key")
|
31
|
+
io.should_receive(:add_general_setting).with("aws_secret", "aws_secret")
|
32
|
+
|
33
|
+
cmd.should_receive(:ask).with("AWS secret: ").and_return("aws_secret")
|
34
|
+
cmd.should_receive(:ask).with("AWS key: ").and_return("aws_key")
|
35
|
+
cmd.run
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should abort the configuration if user provides a blank AWS key" do
|
39
|
+
io.should_receive(:general_settings).any_number_of_times.and_return({})
|
40
|
+
|
41
|
+
io.should_receive(:add_general_setting).never
|
42
|
+
io.should_receive(:add_general_setting).never
|
43
|
+
|
44
|
+
cmd.should_receive(:ask).with("AWS secret: ").never
|
45
|
+
cmd.should_receive(:ask).with("AWS key: ").and_return("")
|
46
|
+
cmd.run
|
47
|
+
|
48
|
+
stdout.should =~ /Aborted./
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not ask for key/secret if already present" do
|
52
|
+
io.should_receive(:general_settings).any_number_of_times.and_return({ "aws_key" => "abc", "aws_secret" => "def" })
|
53
|
+
|
54
|
+
cmd.should_receive(:ask).with("AWS secret: ").never
|
55
|
+
cmd.should_receive(:ask).with("AWS key: ").never
|
56
|
+
cmd.run
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should execute the config_app_backup utility on the server" do
|
60
|
+
io.should_receive(:app_name).and_return("app_name")
|
61
|
+
io.should_receive(:general_settings).any_number_of_times.and_return({ "aws_key" => "awskey", "aws_secret" => "awsecret" })
|
62
|
+
re.should_receive(:exec).with("config_app_backup").with(%Q(config_app_backup app_name "awskey" "awsecret"), true)
|
63
|
+
|
64
|
+
cmd.run
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Commands::AddKey do
|
5
|
+
let(:server) { double("server") }
|
6
|
+
|
7
|
+
it "should have a constant pointing to the ssh key location" do
|
8
|
+
Webbynode::Commands::AddKey::LocalSshKey.should == "#{ENV['HOME']}/.ssh/id_rsa.pub"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be aliased to addkey" do
|
12
|
+
Webbynode::Commands.should_receive(:const_get).with("AddKey")
|
13
|
+
Webbynode::Command.for("addkey")
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when successful" do
|
17
|
+
it "should upload the local ssh key into the server" do
|
18
|
+
server.should_receive(:add_ssh_key).with(Webbynode::Commands::AddKey::LocalSshKey, nil)
|
19
|
+
|
20
|
+
cmd = Webbynode::Commands::AddKey.new
|
21
|
+
cmd.should_receive(:server).any_number_of_times.and_return(server)
|
22
|
+
cmd.execute
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should create an ssh key with a provided passphrase" do
|
26
|
+
server.should_receive(:add_ssh_key).with(Webbynode::Commands::AddKey::LocalSshKey, "my_passphrase")
|
27
|
+
|
28
|
+
cmd = Webbynode::Commands::AddKey.new("--passphrase=my_passphrase")
|
29
|
+
cmd.should_receive(:server).any_number_of_times.and_return(server)
|
30
|
+
cmd.execute
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when unsuccessful" do
|
35
|
+
let(:cmd) { Webbynode::Commands::AddKey.new }
|
36
|
+
let(:io) { double("Io").as_null_object }
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
cmd.should_receive(:io).any_number_of_times.and_return(io)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should report an error if the ssh key could not be added due to invalid authentication" do
|
43
|
+
server.should_receive(:add_ssh_key).and_raise(Webbynode::InvalidAuthentication)
|
44
|
+
|
45
|
+
cmd.should_receive(:server).any_number_of_times.and_return(server)
|
46
|
+
io.should_receive(:log).with("Could not connect to webby: invalid authentication.", true)
|
47
|
+
cmd.execute
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should report an error if the ssh key could not be added due to a permission error" do
|
51
|
+
server.should_receive(:add_ssh_key).and_raise(Webbynode::PermissionError)
|
52
|
+
|
53
|
+
cmd.should_receive(:server).any_number_of_times.and_return(server)
|
54
|
+
io.should_receive(:log).with("Could not create an SSH key: permission error.", true)
|
55
|
+
cmd.execute
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Commands::Alias do
|
5
|
+
|
6
|
+
let(:a) { Webbynode::Commands::Alias.new("add", "my_alias", "ls", "-la") }
|
7
|
+
let(:io) { double('io').as_null_object }
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
a.should_receive(:io).any_number_of_times.and_return(io)
|
11
|
+
File.stub!(:read).with(Webbynode::Commands::Alias::FilePath).
|
12
|
+
and_return(File.join(File.dirname(__FILE__), '../../fixtures/aliases'))
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have a constant pointing at the aliases file" do
|
16
|
+
Webbynode::Commands::Alias::FilePath.should eql(".webbynode/aliases")
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "params" do
|
20
|
+
it "should parse the add commands" do
|
21
|
+
a = Webbynode::Commands::Alias.new("add", "my_alias", "ls", "-la")
|
22
|
+
a.stub!(:send).with("add")
|
23
|
+
a.execute
|
24
|
+
a.action.should eql("add")
|
25
|
+
a.alias.should eql("my_alias")
|
26
|
+
a.command.should eql("ls -la")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should parse the remove commands" do
|
30
|
+
a = Webbynode::Commands::Alias.new("remove", "my_alias")
|
31
|
+
a.stub!(:send).with("remove")
|
32
|
+
a.execute
|
33
|
+
a.action.should eql("remove")
|
34
|
+
a.alias.should eql("my_alias")
|
35
|
+
a.command.should be_blank
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#exists?" do
|
40
|
+
it "should determine whether the specified alias already exists" do
|
41
|
+
a.exists?("my_alias").should be_false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should determine whether the specified alias already exists" do
|
45
|
+
a.session_aliases << "[my_alias] rake db:migrate"
|
46
|
+
a.exists?("my_alias").should be_true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#extract_command" do
|
51
|
+
it "should extract the command from the session_aliases based on the given alias if it exists" do
|
52
|
+
a = Webbynode::Commands::Alias.new
|
53
|
+
a.stub!(:read_aliases_file)
|
54
|
+
a.session_aliases << "[my_alias] rake db:migrate"
|
55
|
+
a.extract_command('my_alias').should eql("rake db:migrate")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return false because the requested alias does not exist" do
|
59
|
+
a = Webbynode::Commands::Alias.new
|
60
|
+
a.stub!(:read_aliases_file)
|
61
|
+
a.extract_command('my_alias').should be_false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "aliases file availability" do
|
66
|
+
context "when the aliases file is not present" do
|
67
|
+
it "should create it" do
|
68
|
+
io.should_receive(:file_exists?).with(Webbynode::Commands::Alias::FilePath).and_return(false)
|
69
|
+
io.should_receive(:exec).with("touch #{Webbynode::Commands::Alias::FilePath}")
|
70
|
+
a.ensure_aliases_file_exists
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when the aliases file is present" do
|
75
|
+
it "should not create it, nor overwrite it" do
|
76
|
+
io.should_receive(:file_exists?).with(Webbynode::Commands::Alias::FilePath).and_return(true)
|
77
|
+
io.should_not_receive(:exec).with("touch #{Webbynode::Commands::Alias::FilePath}")
|
78
|
+
a.ensure_aliases_file_exists
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "reading out the aliases from the file" do
|
84
|
+
it "should read out each line that has an alias" do
|
85
|
+
a.should_receive(:read_aliases_file)
|
86
|
+
a.execute
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "aliases file interaction" do
|
91
|
+
context "when writing to the file" do
|
92
|
+
it "should invoke the add method" do
|
93
|
+
a.should_receive(:send).with('add')
|
94
|
+
a.execute
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should append the new alias to the session_aliases" do
|
98
|
+
a.should_receive(:append_alias)
|
99
|
+
a.execute
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should open the file in 'write mode' to write all aliases from session_aliases to it" do
|
103
|
+
io.should_receive(:open_file).with(Webbynode::Commands::Alias::FilePath, "w")
|
104
|
+
a.execute
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not add the alias to session_aliases if the command is blank" do
|
108
|
+
a = Webbynode::Commands::Alias.new("add", "my_alias")
|
109
|
+
a.should_receive(:io).any_number_of_times.and_return(io)
|
110
|
+
io.should_receive(:log).with("You must provide a remote command for the alias.", true)
|
111
|
+
a.execute
|
112
|
+
a.session_aliases.size.should eql(0)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should not add the alias if it already exists" do
|
116
|
+
a = Webbynode::Commands::Alias.new("add", "my_alias", "custom command")
|
117
|
+
a.should_receive(:io).any_number_of_times.and_return(io)
|
118
|
+
a.stub!(:write_aliases)
|
119
|
+
a.stub!(:read_aliases_file)
|
120
|
+
a.session_aliases << "[my_alias] foo"
|
121
|
+
a.session_aliases << "[mah_alias] bar"
|
122
|
+
io.should_receive(:log).with("You already have an alias named [my_alias].", true)
|
123
|
+
a.execute
|
124
|
+
a.should have(2).session_aliases
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should not add the alias to session_aliases if the command is blank" do
|
128
|
+
a = Webbynode::Commands::Alias.new("add", "my_alias")
|
129
|
+
a.stub!(:write_aliases)
|
130
|
+
a.execute
|
131
|
+
a.session_aliases.size.should eql(0)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should display the current list of aliases after adding the new one" do
|
135
|
+
a.should_receive(:show_aliases)
|
136
|
+
a.execute
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when removing from the file" do
|
141
|
+
before(:each) do
|
142
|
+
a = Webbynode::Commands::Alias.new("remove", "my_alias")
|
143
|
+
a.should_receive(:io).any_number_of_times.and_return(io)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should invoke the remove method" do
|
147
|
+
a.should_receive(:send).with('remove')
|
148
|
+
a.execute
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should remove the alias if it exists" do
|
152
|
+
a.should_receive(:remove_alias)
|
153
|
+
a.execute
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should remove the specified alias from the array of aliases to write" do
|
157
|
+
a.stub!(:read_aliases_file)
|
158
|
+
3.times { |n| a.session_aliases << "[alias_#{n}] my_custom_alias_#{n}" }
|
159
|
+
a.should have(3).session_aliases
|
160
|
+
a.session_aliases << "[my_alias] what a nice alias"
|
161
|
+
a.should have(4).session_aliases
|
162
|
+
a.session_aliases.should include("[my_alias] what a nice alias")
|
163
|
+
a.execute
|
164
|
+
a.session_aliases.should_not include("[my_alias] what a nice alias")
|
165
|
+
a.should have(3).session_aliases
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should write to the aliases file to apply the changes" do
|
169
|
+
a.should_receive(:write_aliases)
|
170
|
+
a.execute
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should display the current list of aliases after removing the old one" do
|
174
|
+
a.should_receive(:show_aliases)
|
175
|
+
a.execute
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "reading from the file" do
|
180
|
+
before(:each) do
|
181
|
+
a = Webbynode::Commands::Alias.new("show")
|
182
|
+
a.should_receive(:io).any_number_of_times.and_return(io)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should invoke the show method" do
|
186
|
+
a.should_receive(:send).with("show")
|
187
|
+
a.execute
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should show the aliases" do
|
191
|
+
a.should_receive(:show_aliases)
|
192
|
+
a.execute
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should display all the aliases to the user if there are any" do
|
196
|
+
a.stub!(:read_aliases_file)
|
197
|
+
a.session_aliases << "[my_alias] rake db:migrate"
|
198
|
+
io.should_receive(:log).with("These are your current aliases..")
|
199
|
+
io.should_receive(:log).with("[my_alias] rake db:migrate")
|
200
|
+
a.session_aliases.should_receive(:any?).and_return(true)
|
201
|
+
a.execute
|
202
|
+
end
|
203
|
+
|
204
|
+
it "it should not display any aliases since there are none. Will display a friendly message instead." do
|
205
|
+
a.stub!(:read_aliases_file)
|
206
|
+
a.session_aliases.should_receive(:any?).and_return(false)
|
207
|
+
io.should_receive(:log).with("You have not yet set up any aliases.", true)
|
208
|
+
a.execute
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Commands::ChangeDns do
|
5
|
+
let(:git) { double("git").as_null_object }
|
6
|
+
let(:io) { double("io").as_null_object }
|
7
|
+
let(:api) { double("api").as_null_object }
|
8
|
+
let(:cmd) { Webbynode::Commands::ChangeDns.new("the.newdns.com") }
|
9
|
+
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
FakeWeb.clean_registry
|
13
|
+
cmd.should_receive(:io).any_number_of_times.and_return(io)
|
14
|
+
cmd.should_receive(:git).any_number_of_times.and_return(git)
|
15
|
+
cmd.should_receive(:api).any_number_of_times.and_return(api)
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should change pushand" do
|
20
|
+
io.should_receive(:app_name).and_return("myapp")
|
21
|
+
io.should_receive(:create_file).with(".pushand", "#! /bin/bash\nphd $0 myapp the.newdns.com\n", true)
|
22
|
+
git.should_receive(:parse_remote_ip).and_return("1.2.3.4")
|
23
|
+
api.should_receive(:create_record).with("the.newdns.com", "1.2.3.4")
|
24
|
+
|
25
|
+
cmd.run
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should give an error message if there are git changes pending" do
|
29
|
+
git.should_receive(:clean?).and_return(false)
|
30
|
+
|
31
|
+
cmd.run
|
32
|
+
stdout.should =~ /Cannot change DNS because you have pending changes. Do a git commit or add changes to .gitignore./
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when committing the DNS change" do
|
36
|
+
it "should perform a commit of .pushand" do
|
37
|
+
io.should_receive(:file_exists?).with(".webbynode/settings").and_return(false)
|
38
|
+
git.should_receive(:add).with(".pushand")
|
39
|
+
git.should_receive(:commit).with("Changed DNS to \"the.newdns.com\"")
|
40
|
+
cmd.run
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should perform a commit of .pushand and .webbynode/settings if the later exists" do
|
44
|
+
io.should_receive(:file_exists?).with(".webbynode/settings").and_return(true)
|
45
|
+
git.should_receive(:add).with(".pushand")
|
46
|
+
git.should_receive(:add).with(".webbynode/settings")
|
47
|
+
git.should_receive(:commit).with("Changed DNS to \"the.newdns.com\"")
|
48
|
+
cmd.run
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|