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,303 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestDeployCommand < Test::Unit::TestCase
|
|
4
|
+
should "map 'deploy' to DeployCommand" do
|
|
5
|
+
Command.create("deploy").class.should == DeployCommand
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
should "present the options when none given" do
|
|
9
|
+
command "deploy"
|
|
10
|
+
stdout.should =~ /You have to tell what you want to deploy \(a stack or a plugin\) and to which server/
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
should "show an error when the wrong item is set to deploy" do
|
|
14
|
+
command "deploy something"
|
|
15
|
+
stdout.should_not =~ /Command deploy is invalid/
|
|
16
|
+
stdout.should =~ /You have to tell what you want to deploy \(a stack or a plugin\) and to which server/
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# === PLUGIN DEPLOYMENT ===
|
|
20
|
+
|
|
21
|
+
should "show an error when the plugin is not found" do
|
|
22
|
+
with_plugins("empty", "plugin%5Bname%5D=my_plugin")
|
|
23
|
+
command "deploy plugin my_plugin server"
|
|
24
|
+
stdout.should =~ /Plugin 'my_plugin' was not found/
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "show an error when plugin found but server not found" do
|
|
28
|
+
with_plugins("by_name", "plugin%5Bname%5D=my_plugin")
|
|
29
|
+
with_server_list("empty", "server%5Bhostname%5D=slicey")
|
|
30
|
+
command "deploy plugin my_plugin slicey"
|
|
31
|
+
stdout.should =~ /Server 'slicey' was not found/
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "tell the user if there's a problem submitting the deployment of a plugin" do
|
|
35
|
+
with_plugins("by_name", "plugin%5Bname%5D=my_plugin")
|
|
36
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
37
|
+
with_new_deployment("error")
|
|
38
|
+
|
|
39
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
40
|
+
when_asked " Idade: ", :answer => "31"
|
|
41
|
+
|
|
42
|
+
agree_with "Continue with plugin installation?\n"
|
|
43
|
+
|
|
44
|
+
command "deploy plugin my_plugin slicey"
|
|
45
|
+
stdout.should =~ /There was a problem submitting your deployment: This is an error/
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
should "stop deploying if user disagree of continueing" do
|
|
49
|
+
with_plugins("by_name", "plugin%5Bname%5D=my_plugin")
|
|
50
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
51
|
+
with_new_deployment("error")
|
|
52
|
+
|
|
53
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
54
|
+
when_asked " Idade: ", :answer => "31"
|
|
55
|
+
|
|
56
|
+
disagree_of "Continue with plugin installation?\n"
|
|
57
|
+
|
|
58
|
+
command "deploy plugin my_plugin slicey"
|
|
59
|
+
stdout.should =~ /Aborted./
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
should "submit the deployment when plugin and server exists" do
|
|
63
|
+
with_plugins("by_name", "plugin%5Bname%5D=my_plugin")
|
|
64
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
65
|
+
with_new_deployment
|
|
66
|
+
|
|
67
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
68
|
+
when_asked " Idade: ", :answer => "31"
|
|
69
|
+
|
|
70
|
+
agree_with "Continue with plugin installation?\n"
|
|
71
|
+
|
|
72
|
+
uri = StackFu::API.gsub(/api/, "flipper:abc123@api")
|
|
73
|
+
FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001.json",
|
|
74
|
+
:response => fixture("deployments"))
|
|
75
|
+
|
|
76
|
+
FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=",
|
|
77
|
+
:response => fixture("logs"))
|
|
78
|
+
|
|
79
|
+
FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true",
|
|
80
|
+
:response => fixture("logs"))
|
|
81
|
+
|
|
82
|
+
FakeWeb.register_uri(:get,
|
|
83
|
+
"#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=4b0b34c9e1054e3104000109",
|
|
84
|
+
:response => fixture("logs_partial"))
|
|
85
|
+
|
|
86
|
+
command "deploy plugin my_plugin slicey"
|
|
87
|
+
|
|
88
|
+
stdout.should =~ /Preparing:/
|
|
89
|
+
stdout.should =~ /my_plugin/
|
|
90
|
+
stdout.should =~ /This will deploy my plugin/
|
|
91
|
+
stdout.should =~ /Enqueued for execution \(deployment id 4b0b3421e1054e3102000001 at Tue Nov 24 01:17:25 UTC 2009\)/
|
|
92
|
+
stdout.should_not =~ /Please review the configuration for your deployment:/
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
should "indicate an error ocurred" # do
|
|
96
|
+
# with_plugins("by_name", "plugin%5Bname%5D=my_plugin")
|
|
97
|
+
# with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
98
|
+
# with_new_deployment
|
|
99
|
+
#
|
|
100
|
+
# when_asked " Nome: ", :answer => "Felipe"
|
|
101
|
+
# when_asked " Idade: ", :answer => "31"
|
|
102
|
+
#
|
|
103
|
+
# agree_with "Continue with plugin installation?\n"
|
|
104
|
+
#
|
|
105
|
+
# uri = StackFu::API.gsub(/api/, "flipper:abc123@api")
|
|
106
|
+
# FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001.json",
|
|
107
|
+
# :response => fixture("deployments"))
|
|
108
|
+
#
|
|
109
|
+
# FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=",
|
|
110
|
+
# :response => fixture("logs"))
|
|
111
|
+
#
|
|
112
|
+
# FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true",
|
|
113
|
+
# :response => fixture("logs"))
|
|
114
|
+
#
|
|
115
|
+
# FakeWeb.register_uri(:get,
|
|
116
|
+
# "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=4b0b34c9e1054e3104000109",
|
|
117
|
+
# :response => fixture("logs_partial"))
|
|
118
|
+
#
|
|
119
|
+
# d "\n--start--"
|
|
120
|
+
# command "deploy plugin my_plugin slicey"
|
|
121
|
+
# d "--end--\n"
|
|
122
|
+
#
|
|
123
|
+
# stdout.should =~ /Preparing:/
|
|
124
|
+
# stdout.should =~ /my_plugin/
|
|
125
|
+
# stdout.should =~ /This will deploy my plugin/
|
|
126
|
+
# stdout.should =~ /Enqueued for execution \(deployment id 4b0b3421e1054e3102000001 at Tue Nov 24 01:17:25 UTC 2009\)/
|
|
127
|
+
# stdout.should =~ /Please review the configuration for your deployment:/
|
|
128
|
+
# stdout.should =~ /Nome: Felipe/
|
|
129
|
+
# stdout.should =~ /Idade: Felipe/
|
|
130
|
+
#end
|
|
131
|
+
|
|
132
|
+
# === STACK DEPLOYMENT ===
|
|
133
|
+
|
|
134
|
+
should "show an error when the stack is not found" do
|
|
135
|
+
with_stacks("empty", "stack%5Bname%5D=my_stack")
|
|
136
|
+
command "deploy stack my_stack server"
|
|
137
|
+
stdout.should =~ /Stack 'my_stack' was not found/
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
should "show an error when server not found" do
|
|
141
|
+
with_stacks("by_name", "stack%5Bname%5D=my_stack")
|
|
142
|
+
with_server_list("empty", "server%5Bhostname%5D=slicey")
|
|
143
|
+
command "deploy stack my_stack slicey"
|
|
144
|
+
stdout.should =~ /Server 'slicey' was not found/
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
should "tell the user if there's a problem submitting the deployment" do
|
|
148
|
+
with_stacks("by_name", "stack%5Bname%5D=my_stack")
|
|
149
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
150
|
+
with_new_deployment("error")
|
|
151
|
+
|
|
152
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
153
|
+
when_asked " Idade: ", :answer => "31"
|
|
154
|
+
|
|
155
|
+
agree_with "This will destroy current contents of your server. Are you sure?\n"
|
|
156
|
+
|
|
157
|
+
command "deploy stack my_stack slicey"
|
|
158
|
+
stdout.should =~ /There was a problem submitting your deployment: This is an error/
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
should "submit the deployment when stack and server exists" do
|
|
162
|
+
with_stacks("by_name", "stack%5Bname%5D=my_stack")
|
|
163
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
164
|
+
with_new_deployment
|
|
165
|
+
|
|
166
|
+
uri = StackFu::API.gsub(/api/, "flipper:abc123@api")
|
|
167
|
+
FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001.json",
|
|
168
|
+
:response => fixture("deployments"))
|
|
169
|
+
|
|
170
|
+
FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=",
|
|
171
|
+
:response => fixture("logs"))
|
|
172
|
+
|
|
173
|
+
FakeWeb.register_uri(:get, "#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true",
|
|
174
|
+
:response => fixture("logs"))
|
|
175
|
+
|
|
176
|
+
FakeWeb.register_uri(:get,
|
|
177
|
+
"#{uri}/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=4b0b34c9e1054e3104000109",
|
|
178
|
+
:response => fixture("logs_partial"))
|
|
179
|
+
|
|
180
|
+
# require 'net/http'
|
|
181
|
+
# require 'uri'
|
|
182
|
+
#
|
|
183
|
+
# Net::HTTP.start('api.stackfu.com') {|http|
|
|
184
|
+
# req = Net::HTTP::Get.new('/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true')
|
|
185
|
+
# req.basic_auth 'flipper', 'abc123'
|
|
186
|
+
# response = http.request(req)
|
|
187
|
+
# # ppd JSON.load(response.body)
|
|
188
|
+
# }
|
|
189
|
+
#
|
|
190
|
+
# Net::HTTP.start('api.stackfu.com') {|http|
|
|
191
|
+
# req = Net::HTTP::Get.new('/deployments/4b0b3421e1054e3102000001/logs.json?formatted=true&from=4b0b34c9e1054e3104000109')
|
|
192
|
+
# req.basic_auth 'flipper', 'abc123'
|
|
193
|
+
# response = http.request(req)
|
|
194
|
+
# # d response.body
|
|
195
|
+
# # d JSON.load(response.body)["id"]
|
|
196
|
+
# # d JSON.load(response.body)["log"]
|
|
197
|
+
# }
|
|
198
|
+
|
|
199
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
200
|
+
when_asked " Idade: ", :answer => "31"
|
|
201
|
+
|
|
202
|
+
agree_with "This will destroy current contents of your server. Are you sure?\n"
|
|
203
|
+
|
|
204
|
+
command "deploy stack my_stack slicey"
|
|
205
|
+
|
|
206
|
+
stdout.should =~ /Deploying:/
|
|
207
|
+
stdout.should =~ /Ubuntu 8.10/
|
|
208
|
+
stdout.should =~ /my_stack/
|
|
209
|
+
stdout.should =~ /This will deploy my stack/
|
|
210
|
+
stdout.should =~ /Enqueued for execution \(deployment id 4b0b3421e1054e3102000001 at Tue Nov 24 01:17:25 UTC 2009\)/
|
|
211
|
+
stdout.should_not =~ /Please review the configuration for your deployment:/
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
should "pass the params" do
|
|
215
|
+
stack = mock("stack")
|
|
216
|
+
stack.expects(:name).returns("my_stack")
|
|
217
|
+
stack.expects(:operating_system).returns("ubuntu_810")
|
|
218
|
+
stack.expects(:description).returns("My stack description")
|
|
219
|
+
|
|
220
|
+
control = mock("control")
|
|
221
|
+
control.expects(:label).at_least_once.returns("Nome")
|
|
222
|
+
control.expects(:name).at_least_once.returns("name")
|
|
223
|
+
control.expects(:_type).at_least_once.returns("Textbox")
|
|
224
|
+
stack.expects(:controls).at_least_once.returns([control])
|
|
225
|
+
|
|
226
|
+
ApiHooks::Stack.expects(:find).returns([stack])
|
|
227
|
+
|
|
228
|
+
server = mock("server")
|
|
229
|
+
server.expects(:id).twice.returns(123)
|
|
230
|
+
ApiHooks::Server.expects(:find).returns([server])
|
|
231
|
+
|
|
232
|
+
deployment = mock("deployment")
|
|
233
|
+
deployment.expects(:save).returns(true)
|
|
234
|
+
|
|
235
|
+
ApiHooks::Deployment.expects(:new).with(:stack => stack, :server_id => server.id, :params => {"name" => "Felipe"}).returns(deployment)
|
|
236
|
+
|
|
237
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
238
|
+
|
|
239
|
+
agree_with "This will destroy current contents of your server. Are you sure?\n"
|
|
240
|
+
|
|
241
|
+
command "deploy stack my_stack slicey --no-follow"
|
|
242
|
+
stdout.should =~ /Deploying:/
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
should "not tell the user to enter values if they are all provided" do
|
|
246
|
+
with_stacks("by_name", "stack%5Bname%5D=my_stack")
|
|
247
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
248
|
+
with_new_deployment
|
|
249
|
+
|
|
250
|
+
agree_with "This will destroy current contents of your server. Are you sure?\n"
|
|
251
|
+
|
|
252
|
+
command "deploy stack my_stack slicey --nome=Felipe --idade=31 --no-follow"
|
|
253
|
+
|
|
254
|
+
stdout.should =~ /Deploying:/
|
|
255
|
+
stdout.should =~ /Ubuntu 8.10/
|
|
256
|
+
stdout.should =~ /my_stack/
|
|
257
|
+
stdout.should =~ /This will deploy my stack/
|
|
258
|
+
stdout.should_not =~ /Please configure your deployment by answering the configuration settings below./
|
|
259
|
+
stdout.should =~ /Please review the configuration for your deployment:/
|
|
260
|
+
stdout.should =~ /Nome/
|
|
261
|
+
stdout.should =~ /Felipe/
|
|
262
|
+
stdout.should =~ /Idade/
|
|
263
|
+
stdout.should =~ /31/
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
should "submit the deployment asking only for parameters not provided" do
|
|
267
|
+
with_stacks("by_name", "stack%5Bname%5D=my_stack")
|
|
268
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
269
|
+
with_new_deployment
|
|
270
|
+
|
|
271
|
+
when_asked " Idade: ", :answer => "31"
|
|
272
|
+
|
|
273
|
+
agree_with "This will destroy current contents of your server. Are you sure?\n"
|
|
274
|
+
|
|
275
|
+
command "deploy stack my_stack slicey --nome=Felipe --no-follow"
|
|
276
|
+
|
|
277
|
+
stdout.should =~ /Deploying:/
|
|
278
|
+
stdout.should =~ /Ubuntu 8.10/
|
|
279
|
+
stdout.should =~ /my_stack/
|
|
280
|
+
stdout.should =~ /This will deploy my stack/
|
|
281
|
+
stdout.should =~ /Please review the configuration for your deployment:/
|
|
282
|
+
stdout.should =~ /Nome/
|
|
283
|
+
stdout.should =~ /Felipe/
|
|
284
|
+
stdout.should =~ /Idade/
|
|
285
|
+
stdout.should =~ /31/
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
should "submit the deployment using options should validate values" do
|
|
289
|
+
with_stacks("by_name", "stack%5Bname%5D=my_stack")
|
|
290
|
+
with_server_list("by_name", "server%5Bhostname%5D=slicey")
|
|
291
|
+
with_new_deployment
|
|
292
|
+
|
|
293
|
+
when_asked " Nome: ", :answer => "Felipe"
|
|
294
|
+
when_asked " Idade: ", :answer => "31"
|
|
295
|
+
|
|
296
|
+
agree_with "This will destroy current contents of your server. Are you sure?\n"
|
|
297
|
+
|
|
298
|
+
command "deploy stack my_stack slicey --idade=Abc --no-follow"
|
|
299
|
+
|
|
300
|
+
stdout.should =~ /Value for idade should be numeric/
|
|
301
|
+
stdout.should_not =~ /Please review the configuration for your deployment:/
|
|
302
|
+
end
|
|
303
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestDumpCommand < Test::Unit::TestCase
|
|
4
|
+
context "validations" do
|
|
5
|
+
should "map 'dump' to DumpCommand" do
|
|
6
|
+
Command.create("dump").class.should == DumpCommand
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
should "require a parameter with stack or plugin" do
|
|
10
|
+
command "dump"
|
|
11
|
+
stdout.should =~ /You have to tell what you want to dump: a stack or a plugin/
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "require a parameter with stack or plugin" do
|
|
15
|
+
command "dump my_girlfriend"
|
|
16
|
+
stdout.should =~ /You have to tell what you want to dump: a stack or a plugin/
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "dump a stack requirements" do
|
|
21
|
+
should "require the stack name" do
|
|
22
|
+
command "dump stack"
|
|
23
|
+
stdout.should =~ /requires 1 parameter\./
|
|
24
|
+
stdout.should =~ /stackfu dump stack STACK_NAME/
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "display an error when the stack is not found" do
|
|
28
|
+
with_stacks("empty", "stack%5Bname%5D=my_stack")
|
|
29
|
+
command "dump stack my_stack"
|
|
30
|
+
stdout.should =~ /Stack 'my_stack' was not found/
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
should "display the stack name on the error message" do
|
|
34
|
+
with_stacks("empty", "stack%5Bname%5D=my_other_stack")
|
|
35
|
+
command "dump stack my_other_stack"
|
|
36
|
+
stdout.should =~ /Stack 'my_other_stack' was not found/
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
should "ask before overwriting an existing folder" do
|
|
40
|
+
with_stacks("multiple", "stack%5Bname%5D=my_stack")
|
|
41
|
+
|
|
42
|
+
DumpCommand.any_instance.expects(:directory?).with("my_stack").returns(true)
|
|
43
|
+
disagree_of("There is already a folder called 'my_stack'. Do you want to overwrite its contents?")
|
|
44
|
+
|
|
45
|
+
command "dump stack my_stack"
|
|
46
|
+
stdout.should =~ /Aborted./
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "a valid dump stack command" do
|
|
51
|
+
setup do
|
|
52
|
+
with_stacks("multiple", "stack%5Bname%5D=my_stack")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
should "create a directory structure that describes the stack" do
|
|
56
|
+
expects_stack("stackfu-installer")
|
|
57
|
+
with_stacks("stackfu-installer", "stack%5Bname%5D=stackfu-installer")
|
|
58
|
+
|
|
59
|
+
command "dump stack stackfu-installer"
|
|
60
|
+
stdout.should =~ /^\tcreate stackfu-installer\//
|
|
61
|
+
stdout.should =~ /^\tcreate stackfu-installer\/stack.yml/
|
|
62
|
+
stdout.should =~ /^\tcreate stackfu-installer\/config\//
|
|
63
|
+
stdout.should =~ /^\tcreate stackfu-installer\/config\/01-controls.yml/
|
|
64
|
+
stdout.should =~ /^\tcreate stackfu-installer\/config\/02-requirements.yml/
|
|
65
|
+
stdout.should =~ /^\tcreate stackfu-installer\/config\/03-scripts.yml/
|
|
66
|
+
stdout.should =~ /^\tcreate stackfu-installer\/config\/04-validations.yml/
|
|
67
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\//
|
|
68
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\//
|
|
69
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/dotfiles_installation.sh.erb/
|
|
70
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/github_credentials_setup.sh.erb/
|
|
71
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/nginx_and_passenger.sh.erb/
|
|
72
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/redis_installation.sh.erb/
|
|
73
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/resque_installation.sh.erb/
|
|
74
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/ruby_environment.sh.erb/
|
|
75
|
+
stdout.should =~ /^\tcreate stackfu-installer\/script\/stackfu.sh.erb/
|
|
76
|
+
stdout.should =~ /^Stack stackfu-installer dumped successfully/
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context "helper methods" do
|
|
81
|
+
should "create a folder" do
|
|
82
|
+
Dir.expects(:mkdir).with("my_stack")
|
|
83
|
+
File.stubs(:directory?).once.returns(false)
|
|
84
|
+
dc = DumpCommand.new(["stack", "my_stack"])
|
|
85
|
+
dc.send(:create_folder, "my_stack")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
should "create a folder based on the param" do
|
|
89
|
+
Dir.expects(:mkdir).with("my_stack_yey")
|
|
90
|
+
dc = DumpCommand.new(["stack", "my_stack"])
|
|
91
|
+
dc.send(:create_folder, "my_stack_yey")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
should "create a file" do
|
|
95
|
+
file = mock("stack.yml")
|
|
96
|
+
|
|
97
|
+
File.expects(:open).with("stack.yml", "w").yields(file)
|
|
98
|
+
file.expects(:write).with("abcdef")
|
|
99
|
+
|
|
100
|
+
dc = DumpCommand.new(["stack", "my_stack"])
|
|
101
|
+
dc.send(:create_file, "stack.yml", "abcdef")
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def expects_stack(stack_name)
|
|
108
|
+
DumpCommand.any_instance.expects(:directory?).with(stack_name).returns(false)
|
|
109
|
+
|
|
110
|
+
expects_create_folder stack_name
|
|
111
|
+
expects_create_yaml_file "#{stack_name}/stack.yml"
|
|
112
|
+
|
|
113
|
+
expects_create_folder stack_name, "config"
|
|
114
|
+
expects_create_yaml_file "#{stack_name}/config/01-controls.yml"
|
|
115
|
+
expects_create_yaml_file "#{stack_name}/config/02-requirements.yml"
|
|
116
|
+
expects_create_yaml_file "#{stack_name}/config/03-scripts.yml"
|
|
117
|
+
expects_create_yaml_file "#{stack_name}/config/04-validations.yml"
|
|
118
|
+
|
|
119
|
+
expects_create_folder stack_name, "script"
|
|
120
|
+
expects_create_file "#{stack_name}/script/dotfiles_installation.sh.erb"
|
|
121
|
+
expects_create_file "#{stack_name}/script/github_credentials_setup.sh.erb"
|
|
122
|
+
expects_create_file "#{stack_name}/script/nginx_and_passenger.sh.erb"
|
|
123
|
+
expects_create_file "#{stack_name}/script/redis_installation.sh.erb"
|
|
124
|
+
expects_create_file "#{stack_name}/script/resque_installation.sh.erb"
|
|
125
|
+
expects_create_file "#{stack_name}/script/ruby_environment.sh.erb"
|
|
126
|
+
expects_create_file "#{stack_name}/script/stackfu.sh.erb"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def expects_create_file(file_name)
|
|
130
|
+
DumpCommand.any_instance.expects(:write_file).with(file_name, load(file_name))
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def expects_create_yaml_file(file_name)
|
|
134
|
+
DumpCommand.any_instance.expects(:write_file).with do |name, attrs|
|
|
135
|
+
ok = name == file_name
|
|
136
|
+
ok = ok && YAML::load(load(file_name)) == YAML::load(attrs)
|
|
137
|
+
|
|
138
|
+
# unless ok
|
|
139
|
+
# d "Expected attrs: #{YAML::load(load(file_name)).inspect}"
|
|
140
|
+
# d " Got attrs: #{YAML::load(attrs).inspect}"
|
|
141
|
+
# end
|
|
142
|
+
|
|
143
|
+
ok
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def expects_create_folder(stack_name, dir_name="")
|
|
148
|
+
dir_name = "/#{dir_name}" if dir_name.present?
|
|
149
|
+
DumpCommand.any_instance.expects(:mkdir).with("#{stack_name}#{dir_name}")
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def load(file)
|
|
153
|
+
File.open(File.join(File.dirname(__FILE__), "../../fixtures/stack", file)).read
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestGenerateCommand < Test::Unit::TestCase
|
|
4
|
+
context "empty command" do
|
|
5
|
+
should "present the options" do
|
|
6
|
+
command "generate"
|
|
7
|
+
stdout.should =~ /You have to tell what you want to generate/
|
|
8
|
+
stdout.should =~ /stack/
|
|
9
|
+
stdout.should =~ /plugin/
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
%w(stack plugin).each do |what|
|
|
14
|
+
context "command generate #{what}" do
|
|
15
|
+
## Normal behavior
|
|
16
|
+
|
|
17
|
+
should "show the requirement parameter if none given" do
|
|
18
|
+
command "generate #{what}"
|
|
19
|
+
stdout.should =~ /#{what.upcase}_NAME/
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
should "generate the #{what} file and the script folder even when no script is given" do
|
|
23
|
+
expect_create :dir => "test", :file => "#{what}.yml"
|
|
24
|
+
expect_create :dir => "test/script"
|
|
25
|
+
expect_create :dir => "test/config", :file => "01-controls.yml"
|
|
26
|
+
expect_create :dir => "test/config", :file => "02-requirements.yml"
|
|
27
|
+
expect_create :dir => "test/config", :file => "03-scripts.yml"
|
|
28
|
+
expect_create :dir => "test/config", :file => "04-validations.yml"
|
|
29
|
+
|
|
30
|
+
command "generate #{what} test"
|
|
31
|
+
stdout.should =~ /#{what.titleize} test created successfully/
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "generate proper tree with one scripts passed" do
|
|
35
|
+
expect_create :dir => "other", :file => "#{what}.yml"
|
|
36
|
+
expect_create :dir => "other/script", :file => "install_counter_strike_server.sh.erb"
|
|
37
|
+
expect_create :dir => "other/config", :file => "01-controls.yml"
|
|
38
|
+
expect_create :dir => "other/config", :file => "02-requirements.yml"
|
|
39
|
+
expect_create :dir => "other/config", :file => "03-scripts.yml",
|
|
40
|
+
:contents => [/install_counter_strike_server/, /Install Counter Strike Server/]
|
|
41
|
+
expect_create :dir => "other/config", :file => "04-validations.yml"
|
|
42
|
+
|
|
43
|
+
command "generate #{what} other install_counter_strike_server:script"
|
|
44
|
+
stdout.should =~ /#{what.titleize} other created successfully/
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
should "generate proper tree with scripts and controls" do
|
|
48
|
+
expect_create :dir => "test", :file => "#{what}.yml"
|
|
49
|
+
expect_create :dir => "test/script", :file => "install_counter_strike_server.sh.erb"
|
|
50
|
+
expect_create :dir => "test/script", :file => "show_me_the_money.sh.erb"
|
|
51
|
+
expect_create :dir => "test/config", :file => "01-controls.yml",
|
|
52
|
+
:contents => [
|
|
53
|
+
/name: clan_name/, /label: Clan Name/, /type: Textbox/,
|
|
54
|
+
/name: clan_password/, /label: Clan Password/, /type: Password/
|
|
55
|
+
]
|
|
56
|
+
expect_create :dir => "test/config", :file => "02-requirements.yml"
|
|
57
|
+
expect_create :dir => "test/config", :file => "03-scripts.yml",
|
|
58
|
+
:contents => [
|
|
59
|
+
/install_counter_strike_server/, /Install Counter Strike Server/,
|
|
60
|
+
/show_me_the_money/, /Show Me The Money/
|
|
61
|
+
]
|
|
62
|
+
expect_create :dir => "test/config", :file => "04-validations.yml"
|
|
63
|
+
|
|
64
|
+
command "generate #{what} test clan_name:textbox clan_password:password install_counter_strike_server:script show_me_the_money:script"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
## Error conditions
|
|
68
|
+
|
|
69
|
+
should "raise an error message if one of the params is unknown" do
|
|
70
|
+
command "generate #{what} test abcdef"
|
|
71
|
+
stdout.should =~ /Don't know how to generate a #{what} with abcdef. Use 'stackfu help generate' for more information./
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
should "raise an error message if one of the params is of invalid type" do
|
|
75
|
+
command "generate #{what} test yogurt:food"
|
|
76
|
+
stdout.should =~ /Don't know how to generate a #{what} with food yogurt. Use 'stackfu help generate' for more information./
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
should "raise a nice error when mkdir fails" do
|
|
80
|
+
expect_create :dir => "test", :file => "#{what}.yml", :raise => [IOError, "Error description"]
|
|
81
|
+
command "generate #{what} test"
|
|
82
|
+
stdout.should =~ /There was an error creating your #{what}: Error description/
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
should "raise a nice error when mkdir fails because there is a file with same name" do
|
|
86
|
+
expect_create :dir => "test", :file => "#{what}.yml", :raise => [Errno::EEXIST, "Error description"]
|
|
87
|
+
command "generate #{what} test"
|
|
88
|
+
stdout.should =~ /There was an error creating your #{what}: File exists - Error description/
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
def expect_create(opts={})
|
|
95
|
+
expect = GenerateCommand.any_instance.expects(:create).with do |dir, file, contents|
|
|
96
|
+
dir_match = opts[:dir] ? dir == opts[:dir] : true
|
|
97
|
+
file_match = opts[:file] ? file == opts[:file] : true
|
|
98
|
+
contents_match = opts[:contents] ?
|
|
99
|
+
opts[:contents].each do |c|
|
|
100
|
+
break true if contents =~ c
|
|
101
|
+
false
|
|
102
|
+
end : true
|
|
103
|
+
block_match = block_given? ? yield(dir, file, contents) : true
|
|
104
|
+
|
|
105
|
+
its_a_match = dir_match and file_match and contents_match and block_match
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
if opts[:raise]
|
|
109
|
+
expect.raises(opts[:raise].first, opts[:raise].last)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestHelpCommand < Test::Unit::TestCase
|
|
4
|
+
context "creating" do
|
|
5
|
+
should "show default help message if no subcommand was given" do
|
|
6
|
+
stackfu = "stackfu".foreground(:green).bright
|
|
7
|
+
|
|
8
|
+
cmd = HelpCommand.new([])
|
|
9
|
+
cmd.expects(:puts).with "#{"StackFu #{StackFu::VERSION}".foreground(:green).bright}, a server deployment manager."
|
|
10
|
+
cmd.expects(:puts).with " (c) 2009-2020 StackFu - http://stackfu.com"
|
|
11
|
+
cmd.expects(:puts).with ""
|
|
12
|
+
cmd.expects(:puts).with " Usage:"
|
|
13
|
+
cmd.expects(:puts).with " #{stackfu} #{"command".foreground(:cyan)} [arguments...] [options...]"
|
|
14
|
+
cmd.expects(:puts).with ""
|
|
15
|
+
cmd.expects(:puts).with " Examples:"
|
|
16
|
+
cmd.expects(:puts).with " #{stackfu} #{"generate".foreground(:cyan)} stack lamp"
|
|
17
|
+
cmd.expects(:puts).with " #{stackfu} #{"pub".foreground(:cyan)}"
|
|
18
|
+
cmd.expects(:puts).with " #{stackfu} #{"deploy".foreground(:cyan)} lamp server1"
|
|
19
|
+
cmd.expects(:puts).with ""
|
|
20
|
+
cmd.expects(:puts).with " Commands:"
|
|
21
|
+
cmd.expects(:puts).with " #{"help".foreground(:cyan)} you already know about this one, dontcha?"
|
|
22
|
+
cmd.expects(:puts).with " #{"config".foreground(:cyan)} configure StackFu CLI options"
|
|
23
|
+
cmd.expects(:puts).with " #{"server".foreground(:cyan)} create, delete, update and deploy to StackFu servers"
|
|
24
|
+
cmd.expects(:puts).with " #{"generate".foreground(:cyan)} [stack|plugin] creates a new stack or plugin in current_dir/name"
|
|
25
|
+
cmd.expects(:puts).with " #{"publish".foreground(:cyan)} publishes the item on the current folder to StackFu.com"
|
|
26
|
+
cmd.expects(:puts).with ""
|
|
27
|
+
cmd.expects(:puts).with " For a complete guide on using StackFu from command line:"
|
|
28
|
+
cmd.expects(:puts).with " #{"http://stackfu.com/guides/stackfu-cli".underline}"
|
|
29
|
+
|
|
30
|
+
cmd.run
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class TestListCommand < Test::Unit::TestCase
|
|
4
|
+
should "map 'list' to ServerCommand" do
|
|
5
|
+
Command.create("list").class.should == ListCommand
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
should "tell the user if no stack found" do
|
|
9
|
+
with_users
|
|
10
|
+
with_stacks("empty")
|
|
11
|
+
with_plugins("empty")
|
|
12
|
+
command "list"
|
|
13
|
+
stdout.should =~ /You have nothing to list yet. To generate stacks or plugins, try the 'stackfu generate' command/
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "list 1 stack" do
|
|
17
|
+
with_users
|
|
18
|
+
with_stacks
|
|
19
|
+
with_plugins("empty")
|
|
20
|
+
command "list"
|
|
21
|
+
stdout.should =~ /Listing 1 stack/
|
|
22
|
+
stdout.should =~ /Type/
|
|
23
|
+
stdout.should =~ /Name/
|
|
24
|
+
stdout.should =~ /my_stack/
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "list 1 plugin" do
|
|
28
|
+
with_users
|
|
29
|
+
with_stacks("empty")
|
|
30
|
+
with_plugins
|
|
31
|
+
command "list"
|
|
32
|
+
stdout.should =~ /Listing 1 plugin/
|
|
33
|
+
stdout.should =~ /Type/
|
|
34
|
+
stdout.should =~ /plugin/
|
|
35
|
+
stdout.should =~ /Name/
|
|
36
|
+
stdout.should =~ /my_plugin/
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
should "list 1 plugin and 2 stacks" do
|
|
40
|
+
with_users
|
|
41
|
+
with_stacks("multiple")
|
|
42
|
+
with_plugins
|
|
43
|
+
command "list --plain"
|
|
44
|
+
stdout.should =~ /Listing 2 stacks and 1 plugin/
|
|
45
|
+
stdout.should =~ /Type/
|
|
46
|
+
stdout.should =~ /plugin/
|
|
47
|
+
stdout.should =~ /Name/
|
|
48
|
+
stdout.should =~ /my_plugin plugin/
|
|
49
|
+
stdout.should =~ /my_stack/
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
should "list 2 stacks" do
|
|
53
|
+
with_users
|
|
54
|
+
with_stacks("multiple")
|
|
55
|
+
with_plugins("empty")
|
|
56
|
+
command "list"
|
|
57
|
+
stdout.should =~ /Listing 2 stacks/
|
|
58
|
+
stdout.should =~ /Type/
|
|
59
|
+
stdout.should =~ /Name/
|
|
60
|
+
stdout.should =~ /my_stack/
|
|
61
|
+
stdout.should =~ /another_stack/
|
|
62
|
+
end
|
|
63
|
+
end
|