stackfu 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/CHANGELOG +24 -0
  2. data/Manifest +118 -0
  3. data/README +0 -0
  4. data/README.md +218 -0
  5. data/Rakefile +73 -0
  6. data/bin/stackfu +10 -0
  7. data/lib/stackfu/api_hooks.rb +17 -0
  8. data/lib/stackfu/app.rb +69 -0
  9. data/lib/stackfu/commands/command.rb +127 -0
  10. data/lib/stackfu/commands/config_command.rb +43 -0
  11. data/lib/stackfu/commands/deploy_command.rb +144 -0
  12. data/lib/stackfu/commands/dump_command.rb +101 -0
  13. data/lib/stackfu/commands/generate_command.rb +107 -0
  14. data/lib/stackfu/commands/help_command.rb +28 -0
  15. data/lib/stackfu/commands/list_command.rb +26 -0
  16. data/lib/stackfu/commands/publish_command.rb +108 -0
  17. data/lib/stackfu/commands/server_command.rb +124 -0
  18. data/lib/stackfu/helpers/providers_credentials.rb +82 -0
  19. data/lib/stackfu/helpers/rendering.rb +201 -0
  20. data/lib/stackfu/operating_systems.rb +30 -0
  21. data/lib/stackfu.rb +88 -0
  22. data/stackfu-installer/config/01-controls.yml +17 -0
  23. data/stackfu-installer/config/02-requirements.yml +3 -0
  24. data/stackfu-installer/config/03-scripts.yml +16 -0
  25. data/stackfu-installer/config/04-validations.yml +3 -0
  26. data/stackfu-installer/script/dotfiles_installation.sh.erb +22 -0
  27. data/stackfu-installer/script/github_credentials_setup.sh.erb +31 -0
  28. data/stackfu-installer/script/nginx_and_passenger.sh.erb +83 -0
  29. data/stackfu-installer/script/redis_installation.sh.erb +33 -0
  30. data/stackfu-installer/script/resque_installation.sh.erb +7 -0
  31. data/stackfu-installer/script/ruby_environment.sh.erb +20 -0
  32. data/stackfu-installer/script/stackfu.sh.erb +114 -0
  33. data/stackfu-installer/stack.yml +5 -0
  34. data/stackfu.gemspec +60 -0
  35. data/templates/01-controls.yml.erb +31 -0
  36. data/templates/02-requirements.yml.erb +26 -0
  37. data/templates/03-scripts.yml.erb +34 -0
  38. data/templates/04-validations.yml.erb +17 -0
  39. data/templates/script.sh.erb +7 -0
  40. data/templates/stack.yml.erb +17 -0
  41. data/test/fixtures/add_server_error +7 -0
  42. data/test/fixtures/deployment_add +7 -0
  43. data/test/fixtures/deployment_add_error +8 -0
  44. data/test/fixtures/deployments +7 -0
  45. data/test/fixtures/logs +7 -0
  46. data/test/fixtures/logs_partial +7 -0
  47. data/test/fixtures/plugin_add +6 -0
  48. data/test/fixtures/plugin_add_error +8 -0
  49. data/test/fixtures/plugin_deployment_add +7 -0
  50. data/test/fixtures/plugin_not_found +7 -0
  51. data/test/fixtures/plugin_unauthorized +8 -0
  52. data/test/fixtures/plugins +7 -0
  53. data/test/fixtures/plugins_by_name +7 -0
  54. data/test/fixtures/plugins_by_name_other +7 -0
  55. data/test/fixtures/plugins_empty +7 -0
  56. data/test/fixtures/plugins_multiple +7 -0
  57. data/test/fixtures/providers +7 -0
  58. data/test/fixtures/providers_servers +7 -0
  59. data/test/fixtures/server_add +6 -0
  60. data/test/fixtures/server_add_dupe +7 -0
  61. data/test/fixtures/server_add_error +7 -0
  62. data/test/fixtures/server_delete +7 -0
  63. data/test/fixtures/server_delete_error +7 -0
  64. data/test/fixtures/servers +7 -0
  65. data/test/fixtures/servers_by_name +7 -0
  66. data/test/fixtures/servers_empty +8 -0
  67. data/test/fixtures/servers_not_found +26 -0
  68. data/test/fixtures/servers_unauthorized +8 -0
  69. data/test/fixtures/servers_webbynode +7 -0
  70. data/test/fixtures/stack/stackfu-installer/config/01-controls.yml +22 -0
  71. data/test/fixtures/stack/stackfu-installer/config/02-requirements.yml +1 -0
  72. data/test/fixtures/stack/stackfu-installer/config/03-scripts.yml +23 -0
  73. data/test/fixtures/stack/stackfu-installer/config/04-validations.yml +1 -0
  74. data/test/fixtures/stack/stackfu-installer/script/dotfiles_installation.sh.erb +22 -0
  75. data/test/fixtures/stack/stackfu-installer/script/github_credentials_setup.sh.erb +31 -0
  76. data/test/fixtures/stack/stackfu-installer/script/nginx_and_passenger.sh.erb +83 -0
  77. data/test/fixtures/stack/stackfu-installer/script/redis_installation.sh.erb +33 -0
  78. data/test/fixtures/stack/stackfu-installer/script/resque_installation.sh.erb +7 -0
  79. data/test/fixtures/stack/stackfu-installer/script/ruby_environment.sh.erb +20 -0
  80. data/test/fixtures/stack/stackfu-installer/script/stackfu.sh.erb +76 -0
  81. data/test/fixtures/stack/stackfu-installer/stack.yml +5 -0
  82. data/test/fixtures/stack_add +6 -0
  83. data/test/fixtures/stack_add_error +8 -0
  84. data/test/fixtures/stack_add_error_dupe +8 -0
  85. data/test/fixtures/stack_adds_by_name +7 -0
  86. data/test/fixtures/stack_delete_not_found +7 -0
  87. data/test/fixtures/stacks +7 -0
  88. data/test/fixtures/stacks_by_name +7 -0
  89. data/test/fixtures/stacks_by_name_other +7 -0
  90. data/test/fixtures/stacks_empty +7 -0
  91. data/test/fixtures/stacks_multiple +7 -0
  92. data/test/fixtures/stacks_not_found +7 -0
  93. data/test/fixtures/stacks_realworld +7 -0
  94. data/test/fixtures/stacks_stackfu-installer +7 -0
  95. data/test/fixtures/stacks_unauthorized +8 -0
  96. data/test/fixtures/stacks_with_controls +0 -0
  97. data/test/fixtures/users +7 -0
  98. data/test/fixtures/users_no_credentials +7 -0
  99. data/test/fixtures/users_update +6 -0
  100. data/test/stack.yml +26 -0
  101. data/test/support/custom_matchers.rb +69 -0
  102. data/test/support/fixtures.rb +98 -0
  103. data/test/support/io_stub.rb +10 -0
  104. data/test/support/web_fixtures.rb +91 -0
  105. data/test/test_helper.rb +186 -0
  106. data/test/unit/commands/test_command.rb +112 -0
  107. data/test/unit/commands/test_config_command.rb +92 -0
  108. data/test/unit/commands/test_deploy_command.rb +303 -0
  109. data/test/unit/commands/test_dump_command.rb +155 -0
  110. data/test/unit/commands/test_generate_command.rb +112 -0
  111. data/test/unit/commands/test_help_command.rb +33 -0
  112. data/test/unit/commands/test_list_command.rb +63 -0
  113. data/test/unit/commands/test_publish_command.rb +265 -0
  114. data/test/unit/commands/test_server_command.rb +259 -0
  115. data/test/unit/helpers/test_rendering.rb +141 -0
  116. data/test/unit/test_array.rb +26 -0
  117. data/test/unit/test_provider.rb +14 -0
  118. data/test/unit/test_stackfu.rb +27 -0
  119. 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