startapp 0.1.6
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.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/autocomplete/rhc_bash +1672 -0
- data/bin/app +37 -0
- data/conf/express.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +191 -0
- data/features/deployments_feature.rb +129 -0
- data/features/domains_feature.rb +58 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +166 -0
- data/lib/rhc/auth/basic.rb +64 -0
- data/lib/rhc/auth/token.rb +102 -0
- data/lib/rhc/auth/token_store.rb +53 -0
- data/lib/rhc/auth.rb +5 -0
- data/lib/rhc/autocomplete.rb +66 -0
- data/lib/rhc/autocomplete_templates/bash.erb +39 -0
- data/lib/rhc/cartridge_helpers.rb +118 -0
- data/lib/rhc/cli.rb +40 -0
- data/lib/rhc/command_runner.rb +185 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +726 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +115 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +329 -0
- data/lib/rhc/commands/clone.rb +66 -0
- data/lib/rhc/commands/configure.rb +20 -0
- data/lib/rhc/commands/create.rb +100 -0
- data/lib/rhc/commands/delete.rb +19 -0
- data/lib/rhc/commands/deploy.rb +32 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +172 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/force_stop.rb +17 -0
- data/lib/rhc/commands/git_clone.rb +34 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/logs.rb +21 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/reload.rb +17 -0
- data/lib/rhc/commands/restart.rb +17 -0
- data/lib/rhc/commands/scp.rb +54 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/show.rb +43 -0
- data/lib/rhc/commands/snapshot.rb +137 -0
- data/lib/rhc/commands/ssh.rb +51 -0
- data/lib/rhc/commands/sshkey.rb +97 -0
- data/lib/rhc/commands/start.rb +17 -0
- data/lib/rhc/commands/stop.rb +17 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands/tidy.rb +17 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +321 -0
- data/lib/rhc/context_helper.rb +121 -0
- data/lib/rhc/core_ext.rb +202 -0
- data/lib/rhc/coverage_helper.rb +33 -0
- data/lib/rhc/deployment_helpers.rb +111 -0
- data/lib/rhc/exceptions.rb +256 -0
- data/lib/rhc/git_helpers.rb +106 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +481 -0
- data/lib/rhc/highline_extensions.rb +479 -0
- data/lib/rhc/json.rb +51 -0
- data/lib/rhc/output_helpers.rb +260 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/alias.rb +42 -0
- data/lib/rhc/rest/api.rb +87 -0
- data/lib/rhc/rest/application.rb +348 -0
- data/lib/rhc/rest/attributes.rb +36 -0
- data/lib/rhc/rest/authorization.rb +8 -0
- data/lib/rhc/rest/base.rb +79 -0
- data/lib/rhc/rest/cartridge.rb +162 -0
- data/lib/rhc/rest/client.rb +650 -0
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/domain.rb +98 -0
- data/lib/rhc/rest/environment_variable.rb +15 -0
- data/lib/rhc/rest/gear_group.rb +16 -0
- data/lib/rhc/rest/httpclient.rb +145 -0
- data/lib/rhc/rest/key.rb +44 -0
- data/lib/rhc/rest/membership.rb +105 -0
- data/lib/rhc/rest/mock.rb +1042 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/scp_helpers.rb +27 -0
- data/lib/rhc/ssh_helpers.rb +380 -0
- data/lib/rhc/tar_gz.rb +51 -0
- data/lib/rhc/usage_templates/command_help.erb +51 -0
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/lib/rhc/usage_templates/help.erb +61 -0
- data/lib/rhc/usage_templates/missing_help.erb +1 -0
- data/lib/rhc/usage_templates/options_help.erb +12 -0
- data/lib/rhc/vendor/okjson.rb +600 -0
- data/lib/rhc/vendor/parseconfig.rb +178 -0
- data/lib/rhc/vendor/sshkey.rb +253 -0
- data/lib/rhc/vendor/zliby.rb +628 -0
- data/lib/rhc/version.rb +5 -0
- data/lib/rhc/wizard.rb +637 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +82 -0
- data/spec/direct_execution_helper.rb +339 -0
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +31 -0
- data/spec/rhc/assets/cert.crt +22 -0
- data/spec/rhc/assets/cert_key_rsa +27 -0
- data/spec/rhc/assets/empty.txt +0 -0
- data/spec/rhc/assets/env_vars.txt +7 -0
- data/spec/rhc/assets/env_vars_2.txt +1 -0
- data/spec/rhc/assets/foo.txt +1 -0
- data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
- data/spec/rhc/assets/targz_sample.tar.gz +0 -0
- data/spec/rhc/auth_spec.rb +442 -0
- data/spec/rhc/cli_spec.rb +186 -0
- data/spec/rhc/command_spec.rb +435 -0
- data/spec/rhc/commands/account_spec.rb +42 -0
- data/spec/rhc/commands/alias_spec.rb +333 -0
- data/spec/rhc/commands/app_spec.rb +777 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +157 -0
- data/spec/rhc/commands/cartridge_spec.rb +665 -0
- data/spec/rhc/commands/clone_spec.rb +41 -0
- data/spec/rhc/commands/deployment_spec.rb +327 -0
- data/spec/rhc/commands/domain_spec.rb +401 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +102 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +247 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/scp_spec.rb +77 -0
- data/spec/rhc/commands/server_spec.rb +69 -0
- data/spec/rhc/commands/setup_spec.rb +118 -0
- data/spec/rhc/commands/snapshot_spec.rb +179 -0
- data/spec/rhc/commands/ssh_spec.rb +163 -0
- data/spec/rhc/commands/sshkey_spec.rb +188 -0
- data/spec/rhc/commands/tail_spec.rb +81 -0
- data/spec/rhc/commands/threaddump_spec.rb +84 -0
- data/spec/rhc/config_spec.rb +407 -0
- data/spec/rhc/helpers_spec.rb +531 -0
- data/spec/rhc/highline_extensions_spec.rb +314 -0
- data/spec/rhc/json_spec.rb +30 -0
- data/spec/rhc/rest_application_spec.rb +258 -0
- data/spec/rhc/rest_client_spec.rb +752 -0
- data/spec/rhc/rest_spec.rb +740 -0
- data/spec/rhc/targz_spec.rb +55 -0
- data/spec/rhc/wizard_spec.rb +756 -0
- data/spec/spec_helper.rb +575 -0
- data/spec/wizard_spec_helper.rb +330 -0
- metadata +469 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class OutputTests < SimpleDelegator
|
|
4
|
+
def initialize(terminal)
|
|
5
|
+
super
|
|
6
|
+
@print_num = 0
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
[:say, :agree, :ask, :choose].each do |sym|
|
|
10
|
+
define_method(sym) do |*args, &block|
|
|
11
|
+
__getobj__.send(sym, *args, &block)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def next_print_num
|
|
16
|
+
@print_num += 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def output
|
|
20
|
+
say "section #{next_print_num}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def output_no_breaks
|
|
24
|
+
say "section #{next_print_num} "
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def section_same_line
|
|
28
|
+
section { output_no_breaks; say 'word' }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def section_no_breaks
|
|
32
|
+
section { output_no_breaks }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def section_one_break
|
|
36
|
+
section { output }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def sections_equal_bottom_top
|
|
40
|
+
section(:bottom => 1) { output }
|
|
41
|
+
section(:top => 1) { output }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def sections_larger_bottom
|
|
45
|
+
section(:bottom => 2) { output }
|
|
46
|
+
section(:top => 1) { output }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def sections_larger_top
|
|
50
|
+
section(:bottom => 1) { output }
|
|
51
|
+
section(:top => 2) { output }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sections_four_on_three_lines
|
|
55
|
+
section { output }
|
|
56
|
+
section(:top => 1) { output_no_breaks }
|
|
57
|
+
section(:bottom => 1) { output }
|
|
58
|
+
section(:top => 1) { output }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def outside_newline
|
|
62
|
+
section(:bottom => -1) { output }
|
|
63
|
+
say "\n"
|
|
64
|
+
section(:top => 1) { output }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def section_1_1
|
|
68
|
+
section(:top => 1, :bottom => 1) { say "section" }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def section_paragraph
|
|
72
|
+
paragraph { say "section" }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# call section without output to reset spacing to 0
|
|
76
|
+
def reset
|
|
77
|
+
__getobj__.instance_variable_set(:@margin, 0)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
describe HighLine::Header do
|
|
83
|
+
it("should join a header"){ described_class.new("ab cd", 0).to_a.should == ["ab cd", '-----'] }
|
|
84
|
+
it("should wrap a header"){ described_class.new("ab cd", 4).to_a.should == ["ab", "cd", '--'] }
|
|
85
|
+
it("should wrap an array header"){ described_class.new(["ab cd"], 4).to_a.should == ["ab", "cd", '--'] }
|
|
86
|
+
it("should combine an array header"){ described_class.new(["ab", "cd"], 5).to_a.should == ["ab cd", '-----'] }
|
|
87
|
+
it("should wrap on array header boundaries"){ described_class.new(["abcd", "e"], 5).to_a.should == ["abcd", "e", '----'] }
|
|
88
|
+
it("should indent an array header"){ described_class.new(["ab", "cd"], 4, ' ').to_a.should == ["ab", " cd", '---'] }
|
|
89
|
+
it("should indent after a wrap"){ described_class.new(["ab cd", "ef gh", "ij"], 4, ' ').to_a.should == ["ab", "cd", " ef", " gh", " ij", '---'] }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe HighLineExtension do
|
|
93
|
+
subject{ MockHighLineTerminal.new }
|
|
94
|
+
|
|
95
|
+
it("default_max_width should depend on wrap"){ subject.wrap_at = nil; subject.default_max_width.should be_nil}
|
|
96
|
+
it("default_max_width should handle indentation"){ subject.wrap_at = 10; subject.indent{ subject.default_max_width.should == 10 - subject.indentation.length } }
|
|
97
|
+
|
|
98
|
+
it "should wrap the terminal" do
|
|
99
|
+
subject.wrap_at = 10
|
|
100
|
+
subject.say "Lorem ipsum dolor sit amet"
|
|
101
|
+
output = subject.read
|
|
102
|
+
output.should match "Lorem\nipsum\ndolor sit\namet\n"
|
|
103
|
+
end
|
|
104
|
+
it "should wrap the terminal" do
|
|
105
|
+
subject.wrap_at = 16
|
|
106
|
+
subject.say "Lorem ipsum dolor sit amet"
|
|
107
|
+
output = subject.read
|
|
108
|
+
output.should == "Lorem ipsum\ndolor sit amet\n"
|
|
109
|
+
end
|
|
110
|
+
it "should not wrap the terminal" do
|
|
111
|
+
subject.wrap_at = 50
|
|
112
|
+
subject.say "Lorem ipsum dolor sit amet"
|
|
113
|
+
output = subject.read
|
|
114
|
+
output.should == "Lorem ipsum dolor sit amet\n"
|
|
115
|
+
end
|
|
116
|
+
it "should wrap the terminal when using color codes" do
|
|
117
|
+
subject.wrap_at = 10
|
|
118
|
+
subject.say subject.color("Lorem ipsum", :red)
|
|
119
|
+
output = subject.read
|
|
120
|
+
output.should == "\e[31mLorem\e\[0m\n\e[31mipsum\e[0m\n"
|
|
121
|
+
end
|
|
122
|
+
it "should wrap the terminal with other escape characters" do
|
|
123
|
+
subject.wrap_at = 10
|
|
124
|
+
subject.say "Lorem ipsum dolor sit am\eet"
|
|
125
|
+
output = subject.read
|
|
126
|
+
output.should == "Lorem\nipsum\ndolor sit\nam\eet\n"
|
|
127
|
+
end
|
|
128
|
+
it "should wrap the terminal when words are smaller than wrap length" do
|
|
129
|
+
subject.wrap_at = 3
|
|
130
|
+
subject.say "Antidisestablishmentarianism"
|
|
131
|
+
output = subject.read
|
|
132
|
+
output.should == "Antidisestablishmentarianism\n"
|
|
133
|
+
end
|
|
134
|
+
it "should terminate an open line if wrapping occurs" do
|
|
135
|
+
subject.wrap_at = 10
|
|
136
|
+
subject.say "Foo "
|
|
137
|
+
subject.say "Lorem ipsum"
|
|
138
|
+
output = subject.read
|
|
139
|
+
output.should match "Foo \nLorem\nipsum\n"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should handle an empty table" do
|
|
143
|
+
subject.table([]).to_a.should == []
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should handle a nested empty table" do
|
|
147
|
+
subject.table([[]]).to_a.should == []
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should normalize variables" do
|
|
151
|
+
subject.table([
|
|
152
|
+
["a", 5],
|
|
153
|
+
[nil, ['a', 'b']],
|
|
154
|
+
]).to_a.should == [
|
|
155
|
+
"a 5",
|
|
156
|
+
" a",
|
|
157
|
+
" b",
|
|
158
|
+
]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should wrap a table based on a max width" do
|
|
162
|
+
subject.table([["abcd efgh", "1234 6789 a"]], :width => 9, :heading => 'Test').to_a.should == [
|
|
163
|
+
'Test',
|
|
164
|
+
'----',
|
|
165
|
+
"abcd 1234",
|
|
166
|
+
"efgh 6789",
|
|
167
|
+
" a"
|
|
168
|
+
]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# FIXME: Ragged edges still left by the algorithm
|
|
172
|
+
# 104 total width, 1: 32/52, 2: 8/61, 113 total width
|
|
173
|
+
it "should handle when columns are evenly split" do
|
|
174
|
+
subject.table([
|
|
175
|
+
["#{'a'*32} #{'b'*19}", "#{'c'*8} "*6+"d"*7]
|
|
176
|
+
], :width => 104).to_a.should == [
|
|
177
|
+
"a"*32+" "+'b'*19+" "+Array.new(5, 'c'*8).join(' '),
|
|
178
|
+
' '*53+"#{'c'*8} "+'d'*7
|
|
179
|
+
]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "should allocate columns fairly in a table" do
|
|
183
|
+
subject.table([["abcd", "12345 67890"]], :width => 10).to_a.should == [
|
|
184
|
+
"abcd 12345",
|
|
185
|
+
" 67890",
|
|
186
|
+
]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "should not wrap without a width" do
|
|
190
|
+
subject.table([["abcd", "12345 67890"]]).to_a.should == [
|
|
191
|
+
"abcd 12345 67890",
|
|
192
|
+
]
|
|
193
|
+
end
|
|
194
|
+
it "should implement each_line on the table" do
|
|
195
|
+
subject.table([["abcd", "12345 67890"]]).each_line.next.should == "abcd 12345 67890"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should display headers" do
|
|
199
|
+
subject.table([["abcd", "12345 67890"]], :header => ['abcdef', '123'], :width => 12).to_a.should == [
|
|
200
|
+
'abcdef 123',
|
|
201
|
+
'------ -----',
|
|
202
|
+
"abcd 12345",
|
|
203
|
+
" 67890",
|
|
204
|
+
]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "should give the header priority over width when color is involved" do
|
|
208
|
+
subject.table([["\e[31mabcd\e[0m", "1234567890"]], :header => ['abcdef', '123'], :width => 12).to_a.should == [
|
|
209
|
+
'abcdef 123',
|
|
210
|
+
'------ ----------',
|
|
211
|
+
"\e[31mabcd\e[0m 1234567890",
|
|
212
|
+
]
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should add a header to a table" do
|
|
216
|
+
subject.table([["abcd efgh", "1234 6789 a"]], :width => 9, :heading => "Alongtextstring").to_a.should == [
|
|
217
|
+
"Alongtext",
|
|
218
|
+
"string",
|
|
219
|
+
"---------",
|
|
220
|
+
"abcd 1234",
|
|
221
|
+
"efgh 6789",
|
|
222
|
+
" a"
|
|
223
|
+
]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "should indent a table" do
|
|
227
|
+
subject.table([["abcd efgh", "1234 6789 a"]], :indent => ' ', :width => 10).to_a.should == [
|
|
228
|
+
" abcd 1234",
|
|
229
|
+
" efgh 6789",
|
|
230
|
+
" a"
|
|
231
|
+
]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "should not wrap table when not enough minimum width" do
|
|
235
|
+
subject.table([["ab cd", "12 34"]], :width => 4).to_a.should == [
|
|
236
|
+
"ab cd 12 34",
|
|
237
|
+
]
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "should not wrap table cells that are too wide based on a max width" do
|
|
241
|
+
subject.table([["abcdefgh", "1234567890"]], :width => 8).to_a.should == [
|
|
242
|
+
"abcdefgh 1234567890",
|
|
243
|
+
]
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should force wrap a table based on columns" do
|
|
247
|
+
subject.table([["ab cd", "123"]], :width => [6, 2]).to_a.should == [
|
|
248
|
+
"ab 123",
|
|
249
|
+
"cd",
|
|
250
|
+
]
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
context "sections" do
|
|
254
|
+
let(:tests) { OutputTests.new(subject) }
|
|
255
|
+
|
|
256
|
+
it "should print out a paragraph with open endline on the same line" do
|
|
257
|
+
tests.section_same_line
|
|
258
|
+
subject.read.should == "section 1 word\n"
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "should print out a section without any line breaks" do
|
|
262
|
+
tests.section_no_breaks
|
|
263
|
+
subject.read.should == "section 1 \n"
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "should print out a section with trailing line break" do
|
|
267
|
+
tests.section_one_break
|
|
268
|
+
subject.read.should == "section 1\n"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "should print out 2 sections with matching bottom and top margins generating one space between" do
|
|
272
|
+
tests.sections_equal_bottom_top
|
|
273
|
+
subject.read.should == "section 1\n\nsection 2\n"
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it "should print out 2 sections with larger bottom margin generating two spaces between" do
|
|
277
|
+
tests.sections_larger_bottom
|
|
278
|
+
subject.read.should == "section 1\n\n\nsection 2\n"
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it "should print out 2 sections with larger top margin generating two spaces between" do
|
|
282
|
+
tests.sections_larger_top
|
|
283
|
+
subject.read.should == "section 1\n\n\nsection 2\n"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "should print out 4 sections and not collapse open sections" do
|
|
287
|
+
tests.sections_four_on_three_lines
|
|
288
|
+
subject.read.should == "section 1\n\nsection 2 \nsection 3\n\nsection 4\n"
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it "should show the equivalence of paragaph to section(:top => 1, :bottom => 1)" do
|
|
292
|
+
tests.section_1_1
|
|
293
|
+
section_1_1 = tests.read
|
|
294
|
+
|
|
295
|
+
tests = OutputTests.new(MockHighLineTerminal.new)
|
|
296
|
+
|
|
297
|
+
tests.section_paragraph
|
|
298
|
+
paragraph = tests.read
|
|
299
|
+
|
|
300
|
+
section_1_1.should == paragraph
|
|
301
|
+
end
|
|
302
|
+
it "should combine sections" do
|
|
303
|
+
tests.section_1_1
|
|
304
|
+
tests.section_paragraph
|
|
305
|
+
|
|
306
|
+
subject.read.should == "section\n\nsection\n"
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "should not collapse explicit newline sections" do
|
|
310
|
+
tests.outside_newline
|
|
311
|
+
subject.read.should == "section 1\n\n\nsection 2\n"
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rhc/json'
|
|
3
|
+
|
|
4
|
+
describe RHC::Json do
|
|
5
|
+
|
|
6
|
+
context 'with simple decoded hash as a string' do
|
|
7
|
+
subject { RHC::Json.decode '{"abc":[123,-456.789e0],"def":[456,-456.789e0],"ghi":"ghj"}' }
|
|
8
|
+
its(:length) { should == 3 }
|
|
9
|
+
it('should contain key') { subject.has_key?("abc").should be_true }
|
|
10
|
+
it('should contain key') { subject.has_key?("def").should be_true }
|
|
11
|
+
it('should contain key') { subject.has_key?("ghi").should be_true }
|
|
12
|
+
it('should not contain invalid key') { subject.has_key?("ghj").should be_false }
|
|
13
|
+
it('should contain value for key') { subject.has_value?("ghj").should be_true }
|
|
14
|
+
it('should contain array value') { subject["abc"].is_a?(Array).should be_true }
|
|
15
|
+
it('should contain array with two elements') { subject["abc"].length.should == 2 }
|
|
16
|
+
it('should contain array with an integer') { subject["abc"][0].should == 123 }
|
|
17
|
+
it('should contain array with a float') { subject["abc"][1].should == -456.789e0 }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'with simple hash' do
|
|
21
|
+
subject { RHC::Json.encode({"key" => "value"}) }
|
|
22
|
+
it('should encode to proper json') { subject.should == '{"key":"value"}' }
|
|
23
|
+
it('should encode and decode to the same hash') { RHC::Json.decode(subject).should == {"key" => "value"} }
|
|
24
|
+
it('should decode and encode to the same string') { RHC::Json.encode(RHC::Json.decode('{"x":"y"}')).should == '{"x":"y"}' }
|
|
25
|
+
it('should decode symbol keys') { RHC::Json.decode('{"key":"ok"}', {:symbolize_keys => true}).has_key?(:key).should be_true }
|
|
26
|
+
it('should decode symbol keys') { RHC::Json.decode('{"key":"ok"}', {:symbolize_keys => true})[:key].should == "ok" }
|
|
27
|
+
it('should encode symbol keys') { RHC::Json.encode({:key => "ok"}).should == '{"key":"ok"}' }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rest_spec_helper'
|
|
3
|
+
require 'base64'
|
|
4
|
+
|
|
5
|
+
module RHC
|
|
6
|
+
module Rest
|
|
7
|
+
describe Application do
|
|
8
|
+
let (:client) { RHC::Rest::Client.new('test.domain.com', 'test_user', 'test pass') }
|
|
9
|
+
let (:app_links) { mock_response_links(mock_app_links('mock_domain','mock_app')) }
|
|
10
|
+
let (:app_aliases) { ['alias1','alias2'] }
|
|
11
|
+
let (:app_obj) {
|
|
12
|
+
args = {
|
|
13
|
+
'domain_id' => 'mock_domain',
|
|
14
|
+
'name' => 'mock_app',
|
|
15
|
+
'creation_time' => Time.now.to_s,
|
|
16
|
+
'uuid' => 1234,
|
|
17
|
+
'aliases' => app_aliases,
|
|
18
|
+
'server_identity' => mock_uri,
|
|
19
|
+
'links' => app_links
|
|
20
|
+
}
|
|
21
|
+
args.merge!(attributes) if defined?(attributes)
|
|
22
|
+
RHC::Rest::Application.new(args, client)
|
|
23
|
+
}
|
|
24
|
+
context "#new" do
|
|
25
|
+
it "returns an application object" do
|
|
26
|
+
app = app_obj
|
|
27
|
+
app.should be_an_instance_of RHC::Rest::Application
|
|
28
|
+
app.send(:links).length.should equal(app_links.length)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#ssh_string" do
|
|
33
|
+
context "with valid url" do
|
|
34
|
+
subject{ described_class.new('ssh_url' => "ssh://foo@bar.com/path") }
|
|
35
|
+
its(:ssh_string){ should == "foo@bar.com" }
|
|
36
|
+
end
|
|
37
|
+
context "with bad url" do
|
|
38
|
+
subject{ described_class.new('ssh_url' => "ssh://") }
|
|
39
|
+
its(:ssh_string){ should == "ssh://" }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#host" do
|
|
44
|
+
context "with bad url" do
|
|
45
|
+
subject{ described_class.new('app_url' => "http://") }
|
|
46
|
+
its(:app_url){ should == "http://" }
|
|
47
|
+
its(:host){ should be_nil }
|
|
48
|
+
end
|
|
49
|
+
context "with http url" do
|
|
50
|
+
subject{ described_class.new('app_url' => "http://bar.com/path") }
|
|
51
|
+
its(:app_url){ should == "http://bar.com/path" }
|
|
52
|
+
its(:host){ should == "bar.com" }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "#add_cartridge" do
|
|
57
|
+
context "with a name" do
|
|
58
|
+
before{ stub_api_request(:any, app_links['ADD_CARTRIDGE']['relative'], false).with(:body => {:name => 'mock_cart_0'}.to_json).to_return(mock_cartridge_response) }
|
|
59
|
+
it "accepts a string" do
|
|
60
|
+
cart = app_obj.add_cartridge('mock_cart_0')
|
|
61
|
+
cart.should be_an_instance_of RHC::Rest::Cartridge
|
|
62
|
+
cart.name.should == 'mock_cart_0'
|
|
63
|
+
end
|
|
64
|
+
it "accepts an object" do
|
|
65
|
+
cart = app_obj.add_cartridge(double(:name => 'mock_cart_0', :url => nil))
|
|
66
|
+
cart.should be_an_instance_of RHC::Rest::Cartridge
|
|
67
|
+
cart.name.should == 'mock_cart_0'
|
|
68
|
+
end
|
|
69
|
+
it "accepts a hash" do
|
|
70
|
+
cart = app_obj.add_cartridge(:name => 'mock_cart_0')
|
|
71
|
+
cart.should be_an_instance_of RHC::Rest::Cartridge
|
|
72
|
+
cart.name.should == 'mock_cart_0'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "with a URL cart" do
|
|
77
|
+
before{ stub_api_request(:any, app_links['ADD_CARTRIDGE']['relative'], false).with(:body => {:url => 'http://foo.com'}.to_json).to_return(mock_cartridge_response(1, true)) }
|
|
78
|
+
it "raises without a param" do
|
|
79
|
+
app_obj.should_receive(:has_param?).with('ADD_CARTRIDGE','url').and_return(false)
|
|
80
|
+
expect{ app_obj.add_cartridge({:url => 'http://foo.com'}) }.to raise_error(RHC::Rest::DownloadingCartridgesNotSupported)
|
|
81
|
+
end
|
|
82
|
+
it "accepts a hash" do
|
|
83
|
+
app_obj.should_receive(:has_param?).with('ADD_CARTRIDGE','url').and_return(true)
|
|
84
|
+
cart = app_obj.add_cartridge({:url => 'http://foo.com'})
|
|
85
|
+
cart.should be_an_instance_of RHC::Rest::Cartridge
|
|
86
|
+
cart.name.should == 'mock_cart_0'
|
|
87
|
+
cart.url.should == 'http://a.url/0'
|
|
88
|
+
cart.short_name.should == 'mock_cart_0'
|
|
89
|
+
cart.display_name.should == 'mock_cart_0'
|
|
90
|
+
cart.only_in_new?.should be_true
|
|
91
|
+
cart.only_in_existing?.should be_false
|
|
92
|
+
end
|
|
93
|
+
it "accepts an object" do
|
|
94
|
+
app_obj.should_receive(:has_param?).with('ADD_CARTRIDGE','url').and_return(true)
|
|
95
|
+
cart = app_obj.add_cartridge(double(:url => 'http://foo.com'))
|
|
96
|
+
cart.should be_an_instance_of RHC::Rest::Cartridge
|
|
97
|
+
cart.name.should == 'mock_cart_0'
|
|
98
|
+
cart.url.should == 'http://a.url/0'
|
|
99
|
+
cart.short_name.should == 'mock_cart_0'
|
|
100
|
+
cart.display_name.should == 'mock_cart_0'
|
|
101
|
+
cart.only_in_new?.should be_true
|
|
102
|
+
cart.only_in_existing?.should be_false
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "#aliases" do
|
|
108
|
+
context "when the server returns an array of strings" do
|
|
109
|
+
it{ app_obj.aliases.first.should be_an_instance_of RHC::Rest::Alias }
|
|
110
|
+
it("converts to an object"){ app_obj.aliases.map(&:id).should == app_aliases }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "when the server returns an object" do
|
|
114
|
+
let(:app_aliases){ [{'id' => 'alias1'}, {'id' => 'alias2'}] }
|
|
115
|
+
it{ app_obj.aliases.first.should be_an_instance_of RHC::Rest::Alias }
|
|
116
|
+
it{ app_obj.aliases.map(&:id).should == ['alias1', 'alias2'] }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "when the server doesn't return aliases" do
|
|
120
|
+
let(:app_aliases){ nil }
|
|
121
|
+
context "when the client supports LIST_ALIASES" do
|
|
122
|
+
before{ stub_api_request(:any, app_links['LIST_ALIASES']['relative'], false).to_return(mock_alias_response(2)) }
|
|
123
|
+
it{ app_obj.aliases.first.should be_an_instance_of RHC::Rest::Alias }
|
|
124
|
+
it{ app_obj.aliases.map(&:id).should == ['www.alias0.com', 'www.alias1.com'] }
|
|
125
|
+
end
|
|
126
|
+
context "when the client doesn't support LIST_ALIASES" do
|
|
127
|
+
before{ app_links['LIST_ALIASES'] = nil }
|
|
128
|
+
it{ app_obj.aliases.should == [] }
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "#cartridges" do
|
|
134
|
+
let(:num_carts){ 0 }
|
|
135
|
+
before do
|
|
136
|
+
stub_api_request(:any, app_links['LIST_CARTRIDGES']['relative'], false).
|
|
137
|
+
to_return(mock_cartridge_response(num_carts))
|
|
138
|
+
end
|
|
139
|
+
context "with carts" do
|
|
140
|
+
let(:num_carts){ 2 }
|
|
141
|
+
it "returns a list of all cartridges in the current application" do
|
|
142
|
+
app = app_obj
|
|
143
|
+
carts = app.cartridges
|
|
144
|
+
carts.length.should == 2
|
|
145
|
+
(0..1).each do |idx|
|
|
146
|
+
carts[idx].should be_an_instance_of RHC::Rest::Cartridge
|
|
147
|
+
carts[idx].name.should == "mock_cart_#{idx}"
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
context "without carts" do
|
|
152
|
+
it "returns an empty list" do
|
|
153
|
+
app = app_obj
|
|
154
|
+
carts = app.cartridges
|
|
155
|
+
carts.length.should == 0
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
context "with carts included in initial reponse" do
|
|
159
|
+
let(:attributes){ {:cartridges => RHC::Json.decode(mock_cartridge_response(2)[:body])['data'] }}
|
|
160
|
+
it "returns a list of all cartridges in the current application" do
|
|
161
|
+
app = app_obj
|
|
162
|
+
carts = app.cartridges
|
|
163
|
+
carts.length.should == 2
|
|
164
|
+
(0..1).each do |idx|
|
|
165
|
+
carts[idx].should be_an_instance_of RHC::Rest::Cartridge
|
|
166
|
+
carts[idx].name.should == "mock_cart_#{idx}"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context "#gear_groups" do
|
|
173
|
+
before do
|
|
174
|
+
stub_api_request(:any, app_links['GET_GEAR_GROUPS']['relative'], false).
|
|
175
|
+
to_return(mock_gear_groups_response())
|
|
176
|
+
end
|
|
177
|
+
it "returns a list of all gear groups the current application" do
|
|
178
|
+
app = app_obj
|
|
179
|
+
gear_groups = app.gear_groups
|
|
180
|
+
gear_groups.length.should equal(1)
|
|
181
|
+
gear_groups[0].should be_an_instance_of RHC::Rest::GearGroup
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# These application control tests are subtle; the key lies in making sure the
|
|
186
|
+
# webmock specifies the expected body that is sent in the request.
|
|
187
|
+
# This is currently of the form "event=foo"
|
|
188
|
+
shared_examples_for "a control method" do
|
|
189
|
+
before do
|
|
190
|
+
@control_method = control_data[:method]
|
|
191
|
+
@control_call = [@control_method]
|
|
192
|
+
if control_data.has_key?(:arg)
|
|
193
|
+
@control_call << control_data[:arg]
|
|
194
|
+
end
|
|
195
|
+
@control_event = control_data.has_key?(:event) ? control_data[:event] : @control_method.to_s
|
|
196
|
+
@control_link = control_data.has_key?(:link) ? control_data[:link].upcase : @control_method.to_s.upcase
|
|
197
|
+
@control_output = control_data.has_key?(:result) ? control_data[:result] : @control_event
|
|
198
|
+
@with_payload = control_data.has_key?(:payload) ? control_data[:payload] : true
|
|
199
|
+
if @with_payload
|
|
200
|
+
stub_api_request(:any, app_links[@control_link]['relative'], false).
|
|
201
|
+
with(:body => { 'event' => @control_event }). # This is the critical part
|
|
202
|
+
to_return({ :body => { :data => @control_event }.to_json, :status => 200 })
|
|
203
|
+
else
|
|
204
|
+
stub_api_request(:any, app_links[@control_link]['relative'], false).
|
|
205
|
+
to_return({ :body => { :data => @control_event }.to_json, :status => 200 })
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
it "sends the control request to the server" do
|
|
209
|
+
app = app_obj
|
|
210
|
+
expect { app.send(*@control_call) }.to_not raise_error
|
|
211
|
+
app.send(*@control_call).should == @control_output
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context "#start" do
|
|
216
|
+
let(:control_data) { { :method => :start } }
|
|
217
|
+
it_should_behave_like "a control method"
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
context "#stop" do
|
|
221
|
+
context " and the request is not forced (force == false)" do
|
|
222
|
+
let(:control_data) { { :method => :stop } }
|
|
223
|
+
it_should_behave_like "a control method"
|
|
224
|
+
end
|
|
225
|
+
context " and the request is forced (force == true)" do
|
|
226
|
+
let(:control_data) { { :method => :stop, :arg => true, :event => 'force-stop', :link => 'stop' } }
|
|
227
|
+
it_should_behave_like "a control method"
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
context "#restart" do
|
|
232
|
+
let(:control_data) { { :method => :restart } }
|
|
233
|
+
it_should_behave_like "a control method"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
context "#delete" do
|
|
237
|
+
let(:control_data) { { :method => :delete, :payload => false } }
|
|
238
|
+
it_should_behave_like "a control method"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
context "#destroy" do
|
|
242
|
+
let(:control_data) { { :method => :destroy, :event => 'delete', :link => 'delete', :payload => false } }
|
|
243
|
+
it_should_behave_like "a control method"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
context "#scale_up" do
|
|
247
|
+
let(:control_data) { { :method => :scale_up, :event => 'scale-up', :link => 'scale_up', :payload => false } }
|
|
248
|
+
it_should_behave_like "a control method"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
context "#scale_down" do
|
|
252
|
+
let(:control_data) { { :method => :scale_down, :event => 'scale-down', :link => 'scale_down', :payload => false } }
|
|
253
|
+
it_should_behave_like "a control method"
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|