stackfu 0.1.0
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.
- data/CHANGELOG +24 -0
- data/Manifest +118 -0
- data/README +0 -0
- data/README.md +218 -0
- data/Rakefile +73 -0
- data/bin/stackfu +10 -0
- data/lib/stackfu/api_hooks.rb +17 -0
- data/lib/stackfu/app.rb +69 -0
- data/lib/stackfu/commands/command.rb +127 -0
- data/lib/stackfu/commands/config_command.rb +43 -0
- data/lib/stackfu/commands/deploy_command.rb +144 -0
- data/lib/stackfu/commands/dump_command.rb +101 -0
- data/lib/stackfu/commands/generate_command.rb +107 -0
- data/lib/stackfu/commands/help_command.rb +28 -0
- data/lib/stackfu/commands/list_command.rb +26 -0
- data/lib/stackfu/commands/publish_command.rb +108 -0
- data/lib/stackfu/commands/server_command.rb +124 -0
- data/lib/stackfu/helpers/providers_credentials.rb +82 -0
- data/lib/stackfu/helpers/rendering.rb +201 -0
- data/lib/stackfu/operating_systems.rb +30 -0
- data/lib/stackfu.rb +88 -0
- data/stackfu-installer/config/01-controls.yml +17 -0
- data/stackfu-installer/config/02-requirements.yml +3 -0
- data/stackfu-installer/config/03-scripts.yml +16 -0
- data/stackfu-installer/config/04-validations.yml +3 -0
- data/stackfu-installer/script/dotfiles_installation.sh.erb +22 -0
- data/stackfu-installer/script/github_credentials_setup.sh.erb +31 -0
- data/stackfu-installer/script/nginx_and_passenger.sh.erb +83 -0
- data/stackfu-installer/script/redis_installation.sh.erb +33 -0
- data/stackfu-installer/script/resque_installation.sh.erb +7 -0
- data/stackfu-installer/script/ruby_environment.sh.erb +20 -0
- data/stackfu-installer/script/stackfu.sh.erb +114 -0
- data/stackfu-installer/stack.yml +5 -0
- data/stackfu.gemspec +60 -0
- data/templates/01-controls.yml.erb +31 -0
- data/templates/02-requirements.yml.erb +26 -0
- data/templates/03-scripts.yml.erb +34 -0
- data/templates/04-validations.yml.erb +17 -0
- data/templates/script.sh.erb +7 -0
- data/templates/stack.yml.erb +17 -0
- data/test/fixtures/add_server_error +7 -0
- data/test/fixtures/deployment_add +7 -0
- data/test/fixtures/deployment_add_error +8 -0
- data/test/fixtures/deployments +7 -0
- data/test/fixtures/logs +7 -0
- data/test/fixtures/logs_partial +7 -0
- data/test/fixtures/plugin_add +6 -0
- data/test/fixtures/plugin_add_error +8 -0
- data/test/fixtures/plugin_deployment_add +7 -0
- data/test/fixtures/plugin_not_found +7 -0
- data/test/fixtures/plugin_unauthorized +8 -0
- data/test/fixtures/plugins +7 -0
- data/test/fixtures/plugins_by_name +7 -0
- data/test/fixtures/plugins_by_name_other +7 -0
- data/test/fixtures/plugins_empty +7 -0
- data/test/fixtures/plugins_multiple +7 -0
- data/test/fixtures/providers +7 -0
- data/test/fixtures/providers_servers +7 -0
- data/test/fixtures/server_add +6 -0
- data/test/fixtures/server_add_dupe +7 -0
- data/test/fixtures/server_add_error +7 -0
- data/test/fixtures/server_delete +7 -0
- data/test/fixtures/server_delete_error +7 -0
- data/test/fixtures/servers +7 -0
- data/test/fixtures/servers_by_name +7 -0
- data/test/fixtures/servers_empty +8 -0
- data/test/fixtures/servers_not_found +26 -0
- data/test/fixtures/servers_unauthorized +8 -0
- data/test/fixtures/servers_webbynode +7 -0
- data/test/fixtures/stack/stackfu-installer/config/01-controls.yml +22 -0
- data/test/fixtures/stack/stackfu-installer/config/02-requirements.yml +1 -0
- data/test/fixtures/stack/stackfu-installer/config/03-scripts.yml +23 -0
- data/test/fixtures/stack/stackfu-installer/config/04-validations.yml +1 -0
- data/test/fixtures/stack/stackfu-installer/script/dotfiles_installation.sh.erb +22 -0
- data/test/fixtures/stack/stackfu-installer/script/github_credentials_setup.sh.erb +31 -0
- data/test/fixtures/stack/stackfu-installer/script/nginx_and_passenger.sh.erb +83 -0
- data/test/fixtures/stack/stackfu-installer/script/redis_installation.sh.erb +33 -0
- data/test/fixtures/stack/stackfu-installer/script/resque_installation.sh.erb +7 -0
- data/test/fixtures/stack/stackfu-installer/script/ruby_environment.sh.erb +20 -0
- data/test/fixtures/stack/stackfu-installer/script/stackfu.sh.erb +76 -0
- data/test/fixtures/stack/stackfu-installer/stack.yml +5 -0
- data/test/fixtures/stack_add +6 -0
- data/test/fixtures/stack_add_error +8 -0
- data/test/fixtures/stack_add_error_dupe +8 -0
- data/test/fixtures/stack_adds_by_name +7 -0
- data/test/fixtures/stack_delete_not_found +7 -0
- data/test/fixtures/stacks +7 -0
- data/test/fixtures/stacks_by_name +7 -0
- data/test/fixtures/stacks_by_name_other +7 -0
- data/test/fixtures/stacks_empty +7 -0
- data/test/fixtures/stacks_multiple +7 -0
- data/test/fixtures/stacks_not_found +7 -0
- data/test/fixtures/stacks_realworld +7 -0
- data/test/fixtures/stacks_stackfu-installer +7 -0
- data/test/fixtures/stacks_unauthorized +8 -0
- data/test/fixtures/stacks_with_controls +0 -0
- data/test/fixtures/users +7 -0
- data/test/fixtures/users_no_credentials +7 -0
- data/test/fixtures/users_update +6 -0
- data/test/stack.yml +26 -0
- data/test/support/custom_matchers.rb +69 -0
- data/test/support/fixtures.rb +98 -0
- data/test/support/io_stub.rb +10 -0
- data/test/support/web_fixtures.rb +91 -0
- data/test/test_helper.rb +186 -0
- data/test/unit/commands/test_command.rb +112 -0
- data/test/unit/commands/test_config_command.rb +92 -0
- data/test/unit/commands/test_deploy_command.rb +303 -0
- data/test/unit/commands/test_dump_command.rb +155 -0
- data/test/unit/commands/test_generate_command.rb +112 -0
- data/test/unit/commands/test_help_command.rb +33 -0
- data/test/unit/commands/test_list_command.rb +63 -0
- data/test/unit/commands/test_publish_command.rb +265 -0
- data/test/unit/commands/test_server_command.rb +259 -0
- data/test/unit/helpers/test_rendering.rb +141 -0
- data/test/unit/test_array.rb +26 -0
- data/test/unit/test_provider.rb +14 -0
- data/test/unit/test_stackfu.rb +27 -0
- metadata +311 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestPublishCommand < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
%w(plugin stack).each do |what|
|
|
6
|
+
define_method("setup_#{what}") do |*options|
|
|
7
|
+
options = options.pop || {}
|
|
8
|
+
PublishCommand.any_instance.expects("#{what}?").returns(true)
|
|
9
|
+
PublishCommand.any_instance.expects("#{['stack', 'plugin'] - [what]}?").returns(false)
|
|
10
|
+
|
|
11
|
+
PublishCommand.any_instance.expects(:read).with("#{what}.yml").returns(<<-EOS)
|
|
12
|
+
---
|
|
13
|
+
type: stack
|
|
14
|
+
name: #{options[:"#{what}_name"] || "my_#{what}"}
|
|
15
|
+
description: "This will deploy my #{what}"
|
|
16
|
+
tags: [mine, #{what}, is, nice]
|
|
17
|
+
EOS
|
|
18
|
+
PublishCommand.any_instance.expects(:read).with("config/01-controls.yml").returns(<<-EOS)
|
|
19
|
+
controls:
|
|
20
|
+
- name: nome
|
|
21
|
+
label: Nome
|
|
22
|
+
type: Textbox
|
|
23
|
+
- name: idade
|
|
24
|
+
label: Idade
|
|
25
|
+
type: Numericbox
|
|
26
|
+
EOS
|
|
27
|
+
PublishCommand.any_instance.expects(:read).with("config/02-requirements.yml").returns(<<-EOS)
|
|
28
|
+
requirements:
|
|
29
|
+
|
|
30
|
+
- type: directory
|
|
31
|
+
data: "/var"
|
|
32
|
+
error: "You need /var folder before installing"
|
|
33
|
+
EOS
|
|
34
|
+
PublishCommand.any_instance.expects(:read).with("config/03-scripts.yml").returns(options[:scripts] || <<-EOS)
|
|
35
|
+
scripts:
|
|
36
|
+
|
|
37
|
+
- description: Echoer
|
|
38
|
+
file: echoer
|
|
39
|
+
EOS
|
|
40
|
+
PublishCommand.any_instance.expects(:read).with("config/04-validations.yml").returns(<<-EOS)
|
|
41
|
+
validations:
|
|
42
|
+
- type: directory
|
|
43
|
+
data: "/etc/apache2"
|
|
44
|
+
error: Apache was not installed properly
|
|
45
|
+
EOS
|
|
46
|
+
|
|
47
|
+
unless options[:scripts]
|
|
48
|
+
PublishCommand.any_instance.expects(:read).with("script/echoer.sh.erb").returns(<<-EOS)
|
|
49
|
+
#
|
|
50
|
+
# echoe.sh
|
|
51
|
+
# Echoes a variable
|
|
52
|
+
#
|
|
53
|
+
|
|
54
|
+
echo "<%= nome %> is <%= age %> years old"
|
|
55
|
+
EOS
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
should "return true for plugin? if file plugin.yml exists" do
|
|
61
|
+
File.expects(:exists?).with("plugin.yml").returns(true)
|
|
62
|
+
PublishCommand.new.plugin?.should be_true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
should "return true for stack? if file plugin.yml exists" do
|
|
66
|
+
File.expects(:exists?).with("stack.yml").returns(true)
|
|
67
|
+
PublishCommand.new.stack?.should be_true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
%w(stack plugin).each do |what|
|
|
71
|
+
context "Publish command for a #{what}" do
|
|
72
|
+
should "check if #{what} exists before publishing" do
|
|
73
|
+
send "setup_#{what}"
|
|
74
|
+
send "with_#{what}s", "by_name", "#{what}%5Bname%5D=my_#{what}"
|
|
75
|
+
send "with_#{what}_delete", "4b08748de1054e1477000006"
|
|
76
|
+
send "with_#{what}_add"
|
|
77
|
+
|
|
78
|
+
agree_with("You already have a #{what} named my_#{what}. Do you want to update it?")
|
|
79
|
+
|
|
80
|
+
command "pub"
|
|
81
|
+
stdout.should =~ /Publishing #{what} my_#{what}/
|
|
82
|
+
stdout.should =~ /Success/
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
should "check if #{what} exists but not ask the user for confirmation if --update is provided" do
|
|
86
|
+
send "setup_#{what}"
|
|
87
|
+
send "with_#{what}s", "by_name", "#{what}%5Bname%5D=my_#{what}"
|
|
88
|
+
send "with_#{what}_delete", "4b08748de1054e1477000006"
|
|
89
|
+
send "with_#{what}_add"
|
|
90
|
+
|
|
91
|
+
command "pub --update"
|
|
92
|
+
stdout.should =~ /Publishing #{what} my_#{what}/
|
|
93
|
+
stdout.should =~ /Success/
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
should "tell the user when there's a problem deleting the #{what}" do
|
|
97
|
+
send "setup_#{what}"
|
|
98
|
+
send "with_#{what}s", "by_name", "#{what}%5Bname%5D=my_#{what}"
|
|
99
|
+
send "with_#{what}_delete", "4b08748de1054e1477000006", "server_delete_error"
|
|
100
|
+
send "with_#{what}_add"
|
|
101
|
+
|
|
102
|
+
command "pub --update"
|
|
103
|
+
stdout.should =~ /There was a problem updating your #{what}/
|
|
104
|
+
stdout.should_not =~ /Publishing #{what} my_#{what}/
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
should "be OK when #{what} doesn't exist" do
|
|
108
|
+
send "setup_#{what}"
|
|
109
|
+
send "with_#{what}s", "empty", "#{what}%5Bname%5D=my_#{what}"
|
|
110
|
+
send "with_#{what}_add"
|
|
111
|
+
|
|
112
|
+
command "pub"
|
|
113
|
+
stdout.should =~ /Publishing #{what} my_#{what}/
|
|
114
|
+
stdout.should =~ /Success/
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
should "abort if user responded false to check when #{what} exists before publishing" do
|
|
118
|
+
send "setup_#{what}"
|
|
119
|
+
send "with_#{what}s", "by_name", "#{what}%5Bname%5D=my_#{what}"
|
|
120
|
+
send "with_#{what}_add"
|
|
121
|
+
|
|
122
|
+
disagree_of("You already have a #{what} named my_#{what}. Do you want to update it?")
|
|
123
|
+
|
|
124
|
+
command "pub"
|
|
125
|
+
stdout.should =~ /Abort./
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
should "show the correct #{what} name" do
|
|
129
|
+
send "setup_#{what}", "#{what}_name".to_sym => "bli#{what}"
|
|
130
|
+
send "with_#{what}s", "by_name_other", "#{what}%5Bname%5D=bli#{what}"
|
|
131
|
+
send "with_#{what}_add"
|
|
132
|
+
|
|
133
|
+
disagree_of("You already have a #{what} named bli#{what}. Do you want to update it?")
|
|
134
|
+
|
|
135
|
+
command "pub"
|
|
136
|
+
stdout.should =~ /Abort./
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
should "be aliased to pub" do
|
|
140
|
+
send "setup_#{what}"
|
|
141
|
+
send "with_#{what}s", "empty", "#{what}%5Bname%5D=my_#{what}"
|
|
142
|
+
send "with_#{what}_add"
|
|
143
|
+
command "pub"
|
|
144
|
+
stdout.should =~ /Publishing #{what} my_#{what}/
|
|
145
|
+
stdout.should =~ /Success/
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
should "show an error when a #{what} has no scripts" do
|
|
149
|
+
send "setup_#{what}", :scripts => ""
|
|
150
|
+
command "pub"
|
|
151
|
+
stdout.should =~ /To publish a #{what} you have to define at least one script./
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
should "show an error when a script is not found" do
|
|
155
|
+
PublishCommand.any_instance.expects(:read).with("script/sample.sh.erb").raises(Errno::ENOENT)
|
|
156
|
+
send "setup_#{what}", :scripts => "scripts:\n- file: sample\n description: A script\n"
|
|
157
|
+
command "pub"
|
|
158
|
+
stdout.should =~ /The template file for the script 'A script' was not found./
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
should "show an error if there's no stack.yml and no plugin.yml on the current folder" do
|
|
162
|
+
PublishCommand.any_instance.expects(:stack?).returns(false)
|
|
163
|
+
PublishCommand.any_instance.expects(:plugin?).returns(false)
|
|
164
|
+
|
|
165
|
+
command "publish"
|
|
166
|
+
stdout.should =~ /Couldn't find an item to publish on current folder./
|
|
167
|
+
stdout.should =~ /Make sure you have a file named 'stack.yml'/
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
should "read #{what}.yml file when present" do
|
|
171
|
+
send "setup_#{what}"
|
|
172
|
+
send "with_#{what}s", "empty", "#{what}%5Bname%5D=my_#{what}"
|
|
173
|
+
send "with_#{what}_add"
|
|
174
|
+
|
|
175
|
+
PublishCommand.any_instance.expects(:publish).with { |stack|
|
|
176
|
+
stack.name.should == "my_#{what}"
|
|
177
|
+
stack.description.should == "This will deploy my #{what}"
|
|
178
|
+
|
|
179
|
+
stack.requirements.size.should == 1
|
|
180
|
+
stack.requirements.first.attributes['type'].should == "directory"
|
|
181
|
+
stack.requirements.first.data.should == "/var"
|
|
182
|
+
|
|
183
|
+
stack.controls.size.should == 2
|
|
184
|
+
stack.controls.first.name.should == "nome"
|
|
185
|
+
stack.controls.first.label.should == "Nome"
|
|
186
|
+
stack.controls.first._type.should == "Textbox"
|
|
187
|
+
stack.controls.last._type.should == "Numericbox"
|
|
188
|
+
|
|
189
|
+
stack.validations.size.should == 1
|
|
190
|
+
stack.validations.first.attributes['type'].should == "directory"
|
|
191
|
+
stack.validations.first.data.should == "/etc/apache2"
|
|
192
|
+
|
|
193
|
+
stack.executions.first.script.should =~ /Echoes a variable/
|
|
194
|
+
true
|
|
195
|
+
}.returns(true)
|
|
196
|
+
|
|
197
|
+
command "publish"
|
|
198
|
+
stdout.should =~ /Publishing #{what} my_#{what}/
|
|
199
|
+
stdout.should =~ /Success/
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
should "report server errors" do
|
|
203
|
+
send "setup_#{what}"
|
|
204
|
+
send "with_#{what}s", "empty", "#{what}%5Bname%5D=my_#{what}"
|
|
205
|
+
send "with_#{what}_add", "error"
|
|
206
|
+
|
|
207
|
+
command "publish"
|
|
208
|
+
stdout.should =~ /Publishing #{what} my_#{what}/
|
|
209
|
+
stdout.should =~ /Operating system can't be empty/
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
# private
|
|
214
|
+
|
|
215
|
+
# def send "setup_#{what}"(options={})
|
|
216
|
+
# PublishCommand.any_instance.expects(:read).with("stack.yml").returns(<<-EOS)
|
|
217
|
+
# ---
|
|
218
|
+
# type: stack
|
|
219
|
+
# name: #{options[:stack_name] || "my_stack"}
|
|
220
|
+
# description: "This will deploy my stack"
|
|
221
|
+
# tags: [mine, stack, is, nice]
|
|
222
|
+
# EOS
|
|
223
|
+
# PublishCommand.any_instance.expects(:read).with("config/01-controls.yml").returns(<<-EOS)
|
|
224
|
+
# controls:
|
|
225
|
+
# - name: nome
|
|
226
|
+
# label: Nome
|
|
227
|
+
# type: Textbox
|
|
228
|
+
# - name: idade
|
|
229
|
+
# label: Idade
|
|
230
|
+
# type: Numericbox
|
|
231
|
+
# EOS
|
|
232
|
+
# PublishCommand.any_instance.expects(:read).with("config/02-requirements.yml").returns(<<-EOS)
|
|
233
|
+
# requirements:
|
|
234
|
+
#
|
|
235
|
+
# - type: directory
|
|
236
|
+
# data: "/var"
|
|
237
|
+
# error: "You need /var folder before installing"
|
|
238
|
+
# EOS
|
|
239
|
+
# PublishCommand.any_instance.expects(:read).with("config/03-scripts.yml").returns(options[:scripts] || <<-EOS)
|
|
240
|
+
# scripts:
|
|
241
|
+
#
|
|
242
|
+
# - description: Echoer
|
|
243
|
+
# file: echoer
|
|
244
|
+
# EOS
|
|
245
|
+
# PublishCommand.any_instance.expects(:read).with("config/04-validations.yml").returns(<<-EOS)
|
|
246
|
+
# validations:
|
|
247
|
+
# - type: directory
|
|
248
|
+
# data: "/etc/apache2"
|
|
249
|
+
# error: Apache was not installed properly
|
|
250
|
+
# EOS
|
|
251
|
+
#
|
|
252
|
+
# unless options[:scripts]
|
|
253
|
+
# PublishCommand.any_instance.expects(:read).with("script/echoer.sh.erb").returns(<<-EOS)
|
|
254
|
+
# #
|
|
255
|
+
# # echoe.sh
|
|
256
|
+
# # Echoes a variable
|
|
257
|
+
# #
|
|
258
|
+
#
|
|
259
|
+
# echo "<%= nome %> is <%= age %> years old"
|
|
260
|
+
# EOS
|
|
261
|
+
# end
|
|
262
|
+
# end
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
end
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestServerCommand < Test::Unit::TestCase
|
|
4
|
+
should "map 'servers' to ServerCommand" do
|
|
5
|
+
Command.create("servers").class.should == ServerCommand
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
should "map 'server' to ServerCommand" do
|
|
9
|
+
Command.create("server").class.should == ServerCommand
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context "list servers with invalid user" do
|
|
13
|
+
should "return an user friendly error" do
|
|
14
|
+
with_server_list("unauthorized")
|
|
15
|
+
command "server list"
|
|
16
|
+
stdout.should =~ /Access denied for user 'flipper'/
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "list servers with 404" do
|
|
21
|
+
should "return an user friendly error" do
|
|
22
|
+
with_server_list("not_found")
|
|
23
|
+
command "server list"
|
|
24
|
+
stdout.should =~ /There was an internal error contacting StackFu backend./
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "indicate user have no servers" do
|
|
29
|
+
with_server_list "empty"
|
|
30
|
+
command "server list"
|
|
31
|
+
stdout.should =~ /You have no servers under your account. Try adding some with 'server add' command.\n/
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "add command" do
|
|
35
|
+
should "require two parameters" do
|
|
36
|
+
command "server add Slicehost"
|
|
37
|
+
stdout.should =~ /requires 2 parameters/
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "adding a server" do
|
|
42
|
+
should "fail when adding to add the same server twice" do
|
|
43
|
+
with_users
|
|
44
|
+
with_server_add("dupe")
|
|
45
|
+
|
|
46
|
+
command "server add Slicehost slicey"
|
|
47
|
+
stdout.should =~ /already exists in your account./
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
should "ask for credentials before the walkthrough if user have no credentials" do
|
|
51
|
+
with_users "no_credentials"
|
|
52
|
+
with_users_add
|
|
53
|
+
with_providers
|
|
54
|
+
with_provider("slicehost", "servers")
|
|
55
|
+
with_server_add
|
|
56
|
+
|
|
57
|
+
when_asked_to_choose "\nSelect the provider:",
|
|
58
|
+
:with_options => ["Webbynode", "Slicehost", "Linode"],
|
|
59
|
+
:answer => 1
|
|
60
|
+
|
|
61
|
+
when_asked "", :answer => "abc123"
|
|
62
|
+
|
|
63
|
+
when_asked_to_choose "\nSelect the server:",
|
|
64
|
+
:with_options => ["slicey", "peeps"],
|
|
65
|
+
:answer => 1
|
|
66
|
+
|
|
67
|
+
command "server add"
|
|
68
|
+
|
|
69
|
+
stdout.should =~ /Slicehost credentials saved/
|
|
70
|
+
stdout.should =~ /Server peeps added successfully/
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
should "fail when adding to add the same server twice and using the walkthrough" do
|
|
74
|
+
with_users
|
|
75
|
+
with_providers
|
|
76
|
+
with_provider("slicehost", "servers")
|
|
77
|
+
with_server_add("dupe")
|
|
78
|
+
|
|
79
|
+
when_asked_to_choose "\nSelect the provider:",
|
|
80
|
+
:with_options => ["Webbynode", "Slicehost", "Linode"],
|
|
81
|
+
:answer => 1
|
|
82
|
+
|
|
83
|
+
when_asked_to_choose "\nSelect the server:",
|
|
84
|
+
:with_options => ["slicey", "peeps"],
|
|
85
|
+
:answer => 1
|
|
86
|
+
|
|
87
|
+
command "server add"
|
|
88
|
+
|
|
89
|
+
stdout.should =~ /already exists in your account./
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
should "guide the user to add a server when no params are given" do
|
|
93
|
+
with_users
|
|
94
|
+
with_providers
|
|
95
|
+
with_provider("slicehost", "servers")
|
|
96
|
+
with_server_add
|
|
97
|
+
|
|
98
|
+
when_asked_to_choose "\nSelect the provider:",
|
|
99
|
+
:with_options => ["Webbynode", "Slicehost", "Linode"],
|
|
100
|
+
:answer => 1
|
|
101
|
+
|
|
102
|
+
when_asked_to_choose "\nSelect the server:",
|
|
103
|
+
:with_options => ["slicey", "peeps"],
|
|
104
|
+
:answer => 1
|
|
105
|
+
|
|
106
|
+
command "server add"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "adding a webbynode server" do
|
|
111
|
+
should "abort when user enters 'abort' into the API login field" do
|
|
112
|
+
with_users "no_credentials"
|
|
113
|
+
|
|
114
|
+
when_asked "Webbynode Login:", :answer => 'abort'
|
|
115
|
+
command "server add webbynode sandbox"
|
|
116
|
+
|
|
117
|
+
stdout.should =~ /Aborted adding server./
|
|
118
|
+
stdout.should =~ /Enter your Webbynode API credentials/
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
should "abort when user enters 'abort' into the API token field" do
|
|
122
|
+
with_users "no_credentials"
|
|
123
|
+
|
|
124
|
+
when_asked "Webbynode Login:", :answer => 'fcoury@me.com'
|
|
125
|
+
when_asked "Webbynode Token:", :answer => 'abort'
|
|
126
|
+
|
|
127
|
+
command "server add webbynode sandbox"
|
|
128
|
+
|
|
129
|
+
stdout.should =~ /Aborted adding server./
|
|
130
|
+
stdout.should =~ /Enter your Webbynode API credentials/
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
should "show the help message when user enters 'help' into the API login field" do
|
|
134
|
+
with_users "no_credentials"
|
|
135
|
+
|
|
136
|
+
when_asked "Webbynode Login:", :answer => 'help'
|
|
137
|
+
when_asked "Webbynode Login:", :answer => 'abort'
|
|
138
|
+
command "server add webbynode sandbox"
|
|
139
|
+
|
|
140
|
+
stdout.should =~ /== Webbynode StackFu integration ==/
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
should "ask for credentials when none were given before" do
|
|
144
|
+
with_users "no_credentials"
|
|
145
|
+
with_users_add
|
|
146
|
+
with_server_add
|
|
147
|
+
|
|
148
|
+
when_asked "Webbynode Login:", :answer => 'fcoury@me.com'
|
|
149
|
+
when_asked "Webbynode Token:", :answer => 'abc123456'
|
|
150
|
+
|
|
151
|
+
command "server add webbynode sandbox"
|
|
152
|
+
stdout.should =~ /Webbynode credentials saved./
|
|
153
|
+
stdout.should =~ /Server sandbox added successfully/
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
should "add the server if proper credentials given" do
|
|
157
|
+
with_users
|
|
158
|
+
with_users_add
|
|
159
|
+
with_server_add
|
|
160
|
+
|
|
161
|
+
command "server add webbynode sandbox"
|
|
162
|
+
stdout.should =~ /Server sandbox added successfully/
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
should "delete the server if proper credentials given and server exists" do
|
|
166
|
+
with_users
|
|
167
|
+
with_server_list("webbynode")
|
|
168
|
+
with_server_delete
|
|
169
|
+
|
|
170
|
+
command "server delete sandbox"
|
|
171
|
+
stdout.should =~ /Server sandbox deleted successfully/
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
should "show the webbynode server when listing servers" do
|
|
175
|
+
with_users
|
|
176
|
+
with_server_list("webbynode")
|
|
177
|
+
|
|
178
|
+
command "server"
|
|
179
|
+
stdout.should =~ /Name/
|
|
180
|
+
stdout.should =~ /Provider/
|
|
181
|
+
stdout.should =~ /IP/
|
|
182
|
+
stdout.should =~ /Status/
|
|
183
|
+
|
|
184
|
+
stdout.should =~ /sandbox/
|
|
185
|
+
stdout.should =~ /Webbynode/
|
|
186
|
+
stdout.should =~ /208\.88\.125\.207/
|
|
187
|
+
stdout.should =~ /running/
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
context "adding a slicehost server" do
|
|
192
|
+
should "abort when user enters 'abort' into the API password field" do
|
|
193
|
+
with_users "no_credentials"
|
|
194
|
+
|
|
195
|
+
when_asked "", :answer => 'abort'
|
|
196
|
+
command "server add slicehost slicey"
|
|
197
|
+
|
|
198
|
+
stdout.should =~ /Aborted adding server./
|
|
199
|
+
stdout.should =~ /Enter your Slicehost API password/
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
should "show the help message when user enters 'help' into the API password field" do
|
|
203
|
+
with_users "no_credentials"
|
|
204
|
+
|
|
205
|
+
when_asked "", :answer => 'help'
|
|
206
|
+
when_asked "", :answer => 'abort'
|
|
207
|
+
command "server add slicehost slicey"
|
|
208
|
+
|
|
209
|
+
stdout.should =~ /== Slicehost StackFu integration ==/
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
should "ask for credentials when none were given before" do
|
|
213
|
+
with_users "no_credentials"
|
|
214
|
+
with_users_add
|
|
215
|
+
with_server_add
|
|
216
|
+
|
|
217
|
+
when_asked "", :answer => "abc123"
|
|
218
|
+
|
|
219
|
+
command "server add slicehost slicey"
|
|
220
|
+
stdout.should =~ /Server slicey added successfully/
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
should "add the server if proper credentials given" do
|
|
224
|
+
with_users
|
|
225
|
+
with_users_add
|
|
226
|
+
with_server_add
|
|
227
|
+
|
|
228
|
+
command "server add slicehost slicey"
|
|
229
|
+
stdout.should =~ /Server slicey added successfully/
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
should "delete the server if proper credentials given and server exists" do
|
|
233
|
+
with_users
|
|
234
|
+
with_server_list
|
|
235
|
+
with_server_delete
|
|
236
|
+
|
|
237
|
+
command "server delete slicey"
|
|
238
|
+
stdout.should =~ /Server slicey deleted successfully/
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
should "show a selection when same server hostname repeats in more than one provider"
|
|
242
|
+
|
|
243
|
+
should "show the slicehost server when listing servers" do
|
|
244
|
+
with_users
|
|
245
|
+
with_server_list
|
|
246
|
+
|
|
247
|
+
command "server"
|
|
248
|
+
stdout.should =~ /Name/
|
|
249
|
+
stdout.should =~ /Provider/
|
|
250
|
+
stdout.should =~ /IP/
|
|
251
|
+
stdout.should =~ /Status/
|
|
252
|
+
|
|
253
|
+
stdout.should =~ /slicey/
|
|
254
|
+
stdout.should =~ /Slicehost/
|
|
255
|
+
stdout.should =~ /174\.143\.145\.37/
|
|
256
|
+
stdout.should =~ /running/
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestRendering < Test::Unit::TestCase
|
|
4
|
+
include StackFu::Rendering
|
|
5
|
+
|
|
6
|
+
class Pizza
|
|
7
|
+
attr_accessor :flavor, :size, :price
|
|
8
|
+
|
|
9
|
+
def initialize(flavor, size, price)
|
|
10
|
+
@flavor = flavor
|
|
11
|
+
@size = size
|
|
12
|
+
@price = price
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "lists" do
|
|
17
|
+
should "render a list with the object collection and all properties by default" do
|
|
18
|
+
pizzas = [
|
|
19
|
+
Pizza.new("Mozzarella", "Large", 14.99),
|
|
20
|
+
Pizza.new("Margheritta", "Large", 15.99),
|
|
21
|
+
Pizza.new("Pequenita", nil, 5.99),
|
|
22
|
+
Pizza.new("Pepperoni", "Large", 17.99)
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
table = table(:class => Pizza, :collection => pizzas, :display => [:flavor, :size, :price], :ansi => false)
|
|
26
|
+
table.should =~ /^Listing 4 pizzas:/
|
|
27
|
+
table.should =~ / Flavor Size Price/
|
|
28
|
+
table.should =~ / ------------ ------ -----/
|
|
29
|
+
table.should =~ / Mozzarella Large 14.99/
|
|
30
|
+
table.should =~ / Margheritta Large 15.99/
|
|
31
|
+
table.should =~ / Pequenita 5.99/
|
|
32
|
+
table.should =~ / Pepperoni Large 17.99/
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
should "accept a block and render based on the block" do
|
|
36
|
+
pizzas = [
|
|
37
|
+
Pizza.new("Mozzarella", "Large", 14.99),
|
|
38
|
+
Pizza.new("Margheritta", "Large", 15.99),
|
|
39
|
+
Pizza.new("Pequenita", nil, 5.99),
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
table = table(:class => Pizza, :collection => pizzas, :display => [:flavor, :size, :price], :ansi => false) do |item|
|
|
43
|
+
["Mah #{item.flavor}", "#{item.size.try(:downcase)}", item.price + 2]
|
|
44
|
+
end
|
|
45
|
+
table.should =~ /^Listing 3 pizzas:/
|
|
46
|
+
table.should =~ / Flavor Size Price/
|
|
47
|
+
table.should =~ / ---------------- ------ -----/
|
|
48
|
+
table.should =~ / Mah Mozzarella large 16.99/
|
|
49
|
+
table.should =~ / Mah Margheritta large 17.99/
|
|
50
|
+
table.should =~ / Mah Pequenita 7.99/
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
should "pluralize the description before the table" do
|
|
54
|
+
class Dash < Pizza
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
pizzas = [
|
|
58
|
+
Dash.new("Mozzarella", "Large", 14.99)
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
table = table(:class => Dash, :collection => pizzas, :display => [:flavor, :size, :price], :ansi => false) do |item|
|
|
62
|
+
["Mah #{item.flavor}", "#{item.size.try(:downcase)}", item.price + 2]
|
|
63
|
+
end
|
|
64
|
+
table.should =~ /^Listing 1 dash:/
|
|
65
|
+
table.should =~ / Flavor Size Price/
|
|
66
|
+
table.should =~ / --------------- ------ -----/
|
|
67
|
+
table.should =~ / Mah Mozzarella large 16.99/
|
|
68
|
+
|
|
69
|
+
pizzas << Dash.new("Minina", "Large", 14.99)
|
|
70
|
+
|
|
71
|
+
table = table(:class => Dash, :collection => pizzas, :display => [:flavor, :size, :price], :ansi => false) do |item|
|
|
72
|
+
["Mah #{item.flavor}", "#{item.size.try(:downcase)}", item.price + 2]
|
|
73
|
+
end
|
|
74
|
+
table.should =~ /^Listing 2 dashes:/
|
|
75
|
+
table.should =~ / Flavor Size Price/
|
|
76
|
+
table.should =~ / --------------- ------ -----/
|
|
77
|
+
table.should =~ / Mah Mozzarella large 16.99/
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
should "render an empty message if no items" do
|
|
81
|
+
pizzas = []
|
|
82
|
+
table = table(:class => Pizza, :collection => pizzas, :display => [:flavor, :size, :price], :ansi => false)
|
|
83
|
+
table.should =~ /No pizzas./
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
should "render a custom empty message if no items and custom message passed" do
|
|
87
|
+
pizzas = []
|
|
88
|
+
table = table(:class => Pizza, :collection => pizzas,
|
|
89
|
+
:display => [:flavor, :size, :price], :empty => "Sorry dude, no pizzas!")
|
|
90
|
+
table.should =~ /Sorry dude, no pizzas!/
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
should "two objects with same duck type" do
|
|
94
|
+
class Animal
|
|
95
|
+
attr_accessor :name
|
|
96
|
+
def initialize(name)
|
|
97
|
+
@name = name
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class Dog < Animal
|
|
102
|
+
def legs; 4; end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class Spider < Animal
|
|
106
|
+
def legs; 8; end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
class Fly < Animal
|
|
110
|
+
def legs; 6; end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
animals = [Dog.new("Jimmy"), Dog.new("Buddy"), Fly.new("Buggah"), Spider.new("Mommy")]
|
|
114
|
+
table = table(
|
|
115
|
+
:class => [Dog, Fly, Spider],
|
|
116
|
+
:display => [:name, :legs],
|
|
117
|
+
:collection => animals, :ansi => false
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
table.should =~ /^Listing 2 dogs, 1 fly and 1 spider/
|
|
121
|
+
table.should =~ / Name Legs /
|
|
122
|
+
table.should =~ / ------- -----/
|
|
123
|
+
table.should =~ / Jimmy 4/
|
|
124
|
+
table.should =~ / Buddy 4/
|
|
125
|
+
table.should =~ / Buggah 6/
|
|
126
|
+
table.should =~ / Mommy 8/
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
should "render a custom headline" do
|
|
130
|
+
pizzas = [Pizza.new("Mozzarella", "Large", 14.99)]
|
|
131
|
+
table = table(
|
|
132
|
+
:class => Pizza,
|
|
133
|
+
:collection => pizzas,
|
|
134
|
+
:display => [:flavor, :size, :price],
|
|
135
|
+
:header => "We have some pizzas for you")
|
|
136
|
+
|
|
137
|
+
table.should =~ /^We have some pizzas for you/
|
|
138
|
+
table.should_not =~ /^Listing 1 pizza/
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestArray < Test::Unit::TestCase
|
|
4
|
+
should "delete correctly with delete_first" do
|
|
5
|
+
arr = ["a","v","a"]
|
|
6
|
+
arr2 = [{ "felipe" => "yes" }, { "others" => "no" }]
|
|
7
|
+
|
|
8
|
+
arr.delete_first("z").should == nil
|
|
9
|
+
arr.delete_first("a").should == "a"
|
|
10
|
+
arr.should == ["v", "a"]
|
|
11
|
+
|
|
12
|
+
arr.delete_first {|i| i == "a"}.should == "a"
|
|
13
|
+
arr.should == ["v"]
|
|
14
|
+
|
|
15
|
+
arr2.delete_first { |i| i.keys.first == "felipe" }.values.first.should == "yes"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
should "transform into a struct using to_struct" do
|
|
19
|
+
structs = [{"name" => "Felipe", "id" => "1"},{:name => "Pablo", :id => 2}].to_structs
|
|
20
|
+
|
|
21
|
+
structs.first.name.should == "Felipe"
|
|
22
|
+
structs.first.id.should == "1"
|
|
23
|
+
structs.last.name.should == "Pablo"
|
|
24
|
+
structs.last.id.should == 2
|
|
25
|
+
end
|
|
26
|
+
end
|