pbox 1.17.2

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.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +40 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/pbox_bash +1639 -0
  7. data/bin/pbox +37 -0
  8. data/conf/protonbox.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +178 -0
  11. data/features/deployments_feature.rb +127 -0
  12. data/features/domains_feature.rb +49 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +186 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +701 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +96 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +326 -0
  31. data/lib/rhc/commands/deployment.rb +82 -0
  32. data/lib/rhc/commands/domain.rb +167 -0
  33. data/lib/rhc/commands/env.rb +142 -0
  34. data/lib/rhc/commands/git_clone.rb +29 -0
  35. data/lib/rhc/commands/logout.rb +51 -0
  36. data/lib/rhc/commands/member.rb +148 -0
  37. data/lib/rhc/commands/port_forward.rb +197 -0
  38. data/lib/rhc/commands/server.rb +40 -0
  39. data/lib/rhc/commands/setup.rb +60 -0
  40. data/lib/rhc/commands/snapshot.rb +137 -0
  41. data/lib/rhc/commands/ssh.rb +51 -0
  42. data/lib/rhc/commands/sshkey.rb +97 -0
  43. data/lib/rhc/commands/tail.rb +47 -0
  44. data/lib/rhc/commands/threaddump.rb +14 -0
  45. data/lib/rhc/commands.rb +396 -0
  46. data/lib/rhc/config.rb +320 -0
  47. data/lib/rhc/context_helper.rb +121 -0
  48. data/lib/rhc/core_ext.rb +202 -0
  49. data/lib/rhc/coverage_helper.rb +33 -0
  50. data/lib/rhc/deployment_helpers.rb +88 -0
  51. data/lib/rhc/exceptions.rb +232 -0
  52. data/lib/rhc/git_helpers.rb +91 -0
  53. data/lib/rhc/help_formatter.rb +55 -0
  54. data/lib/rhc/helpers.rb +477 -0
  55. data/lib/rhc/highline_extensions.rb +479 -0
  56. data/lib/rhc/json.rb +51 -0
  57. data/lib/rhc/output_helpers.rb +260 -0
  58. data/lib/rhc/rest/activation.rb +11 -0
  59. data/lib/rhc/rest/alias.rb +42 -0
  60. data/lib/rhc/rest/api.rb +87 -0
  61. data/lib/rhc/rest/application.rb +332 -0
  62. data/lib/rhc/rest/attributes.rb +36 -0
  63. data/lib/rhc/rest/authorization.rb +8 -0
  64. data/lib/rhc/rest/base.rb +79 -0
  65. data/lib/rhc/rest/cartridge.rb +154 -0
  66. data/lib/rhc/rest/client.rb +650 -0
  67. data/lib/rhc/rest/deployment.rb +18 -0
  68. data/lib/rhc/rest/domain.rb +98 -0
  69. data/lib/rhc/rest/environment_variable.rb +15 -0
  70. data/lib/rhc/rest/gear_group.rb +16 -0
  71. data/lib/rhc/rest/httpclient.rb +145 -0
  72. data/lib/rhc/rest/key.rb +44 -0
  73. data/lib/rhc/rest/membership.rb +105 -0
  74. data/lib/rhc/rest/mock.rb +1024 -0
  75. data/lib/rhc/rest/user.rb +32 -0
  76. data/lib/rhc/rest.rb +148 -0
  77. data/lib/rhc/ssh_helpers.rb +378 -0
  78. data/lib/rhc/tar_gz.rb +51 -0
  79. data/lib/rhc/usage_templates/command_help.erb +51 -0
  80. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  81. data/lib/rhc/usage_templates/help.erb +35 -0
  82. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  83. data/lib/rhc/usage_templates/options_help.erb +12 -0
  84. data/lib/rhc/vendor/okjson.rb +600 -0
  85. data/lib/rhc/vendor/parseconfig.rb +178 -0
  86. data/lib/rhc/vendor/sshkey.rb +253 -0
  87. data/lib/rhc/vendor/zliby.rb +628 -0
  88. data/lib/rhc/version.rb +5 -0
  89. data/lib/rhc/wizard.rb +633 -0
  90. data/lib/rhc.rb +34 -0
  91. data/spec/coverage_helper.rb +89 -0
  92. data/spec/direct_execution_helper.rb +338 -0
  93. data/spec/keys/example.pem +23 -0
  94. data/spec/keys/example_private.pem +27 -0
  95. data/spec/keys/server.pem +19 -0
  96. data/spec/rest_spec_helper.rb +31 -0
  97. data/spec/rhc/assets/cert.crt +22 -0
  98. data/spec/rhc/assets/cert_key_rsa +27 -0
  99. data/spec/rhc/assets/empty.txt +0 -0
  100. data/spec/rhc/assets/env_vars.txt +7 -0
  101. data/spec/rhc/assets/env_vars_2.txt +1 -0
  102. data/spec/rhc/assets/foo.txt +1 -0
  103. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  104. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  105. data/spec/rhc/auth_spec.rb +442 -0
  106. data/spec/rhc/cli_spec.rb +188 -0
  107. data/spec/rhc/command_spec.rb +435 -0
  108. data/spec/rhc/commands/account_spec.rb +42 -0
  109. data/spec/rhc/commands/alias_spec.rb +333 -0
  110. data/spec/rhc/commands/app_spec.rb +754 -0
  111. data/spec/rhc/commands/apps_spec.rb +39 -0
  112. data/spec/rhc/commands/authorization_spec.rb +145 -0
  113. data/spec/rhc/commands/cartridge_spec.rb +641 -0
  114. data/spec/rhc/commands/deployment_spec.rb +286 -0
  115. data/spec/rhc/commands/domain_spec.rb +383 -0
  116. data/spec/rhc/commands/env_spec.rb +493 -0
  117. data/spec/rhc/commands/git_clone_spec.rb +80 -0
  118. data/spec/rhc/commands/logout_spec.rb +86 -0
  119. data/spec/rhc/commands/member_spec.rb +228 -0
  120. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  121. data/spec/rhc/commands/server_spec.rb +69 -0
  122. data/spec/rhc/commands/setup_spec.rb +118 -0
  123. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  124. data/spec/rhc/commands/ssh_spec.rb +163 -0
  125. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  126. data/spec/rhc/commands/tail_spec.rb +81 -0
  127. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  128. data/spec/rhc/config_spec.rb +407 -0
  129. data/spec/rhc/helpers_spec.rb +524 -0
  130. data/spec/rhc/highline_extensions_spec.rb +314 -0
  131. data/spec/rhc/json_spec.rb +30 -0
  132. data/spec/rhc/rest_application_spec.rb +248 -0
  133. data/spec/rhc/rest_client_spec.rb +752 -0
  134. data/spec/rhc/rest_spec.rb +740 -0
  135. data/spec/rhc/targz_spec.rb +55 -0
  136. data/spec/rhc/wizard_spec.rb +756 -0
  137. data/spec/spec_helper.rb +575 -0
  138. data/spec/wizard_spec_helper.rb +330 -0
  139. metadata +435 -0
@@ -0,0 +1,89 @@
1
+ unless RUBY_VERSION < '1.9'
2
+ require 'simplecov'
3
+
4
+ # Patch to get correct coverage count, filed
5
+ # https://github.com/colszowka/simplecov/issues/146 upstream.
6
+ class SimpleCov::Result
7
+ def missed_lines
8
+ return @missed_lines if defined? @missed_lines
9
+ @missed_lines = 0
10
+ @files.each do |file|
11
+ @missed_lines += file.missed_lines.count
12
+ end
13
+ @missed_lines
14
+ end
15
+
16
+ def print_missed_lines
17
+ @files.each do |file|
18
+ file.missed_lines.each do |line|
19
+ STDERR.puts "MISSED #{file.filename}:#{line.number}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ unless SimpleCov.respond_to? :minimum_coverage=
26
+ module SimpleCov
27
+ def self.minimum_coverage=(value)
28
+ @minimum_coverage = value
29
+ end
30
+ def self.minimum_coverage
31
+ @minimum_coverage || -1
32
+ end
33
+ end
34
+
35
+ SimpleCov.at_exit do
36
+ begin
37
+ SimpleCov.result.format!
38
+ SimpleCov.result.print_missed_lines if SimpleCov.result.covered_percent.between?(98.0,99.9999999)
39
+ if SimpleCov.result.covered_percent < SimpleCov.minimum_coverage
40
+ STDERR.puts "Coverage not above #{SimpleCov.minimum_coverage}, build failed."
41
+ exit 1
42
+ end
43
+ rescue Exception => e
44
+ STDERR.puts "Exception at exit, #{e.message}"
45
+ end
46
+ end
47
+ else
48
+ SimpleCov.at_exit do
49
+ begin
50
+ SimpleCov.result.format!
51
+ SimpleCov.result.print_missed_lines if SimpleCov.result.covered_percent.between?(98.0,99.9999999)
52
+ rescue Exception => e
53
+ STDERR.puts "Exception at exit, #{e.message}"
54
+ end
55
+ end
56
+ end
57
+
58
+ SimpleCov.minimum_coverage = 100
59
+
60
+ SimpleCov.start do
61
+
62
+ if ENV['CIRCLE_ARTIFACTS']
63
+ dir = File.join("..", "..", "..", ENV['CIRCLE_ARTIFACTS'], "coverage")
64
+ coverage_dir(dir)
65
+ else
66
+ coverage_dir 'coverage/spec/'
67
+ end
68
+
69
+ # Filters - these files will be ignored.
70
+ add_filter 'lib/rhc/vendor/' # vendored files should be taken directly and only
71
+ # namespaces changed
72
+ add_filter 'lib/rhc/rest/' # REST coverage is not yet 100%
73
+ add_filter 'lib/bin/' # This is just for safety; simplecov isn't picking these up.
74
+ add_filter 'features/' # Don't report on the files that run the cucumber tests
75
+ add_filter 'lib/rhc-feature-coverage-helper.rb'
76
+ add_filter 'spec/' # Don't report on the files that run the spec tests
77
+ add_filter 'vendor'
78
+
79
+ # Groups - general categories of test areas
80
+ add_group('Commands') { |src_file| src_file.filename.include?(File.join(%w[lib rhc commands])) }
81
+ add_group('RHC Lib') { |src_file| src_file.filename.include?(File.join(%w[lib rhc])) }
82
+ add_group('REST') { |src_file| src_file.filename.include?(File.join(%w[lib rhc/rest])) }
83
+ add_group('Test') { |src_file| src_file.filename.include?(File.join(%w[features])) or
84
+ src_file.filename.include?(File.join(%w[spec])) }
85
+
86
+ # Note, the #:nocov: coverage exclusion should only be used on external functions
87
+ # that cannot be nondestructively tested in a developer environment.
88
+ end
89
+ end
@@ -0,0 +1,338 @@
1
+ require 'open4'
2
+ require 'rhc/helpers'
3
+
4
+ $source_bin_pbox = File.expand_path('bin/pbox')
5
+
6
+ SimpleCov.minimum_coverage = 0 # No coverage testing for features
7
+
8
+ #
9
+ # PROTONBOX_DEBUG=true TEST_INSECURE=1 TEST_USERNAME=test1 TEST_PASSWORD=password \
10
+ # PROTONBOX_SERVER=hostname \
11
+ # bundle exec rspec features/*_feature.rb
12
+ #
13
+
14
+ module RhcExecutionHelper
15
+ class Result < Struct.new(:args, :status, :stdout, :stderr)
16
+ def to_s
17
+ "Ran #{args.inspect} and got #{status}\n#{'-'*50}\n#{stdout}#{'-'*50}\n#{stderr}"
18
+ end
19
+ def successful?
20
+ status == 0
21
+ end
22
+ end
23
+
24
+ def when_running(*args)
25
+ subject{ pbox *args }
26
+ let(:output){ subject.stdout }
27
+ let(:status){ subject.status }
28
+ before{ standard_config }
29
+ end
30
+
31
+ def a_web_cartridge
32
+ if ENV['PROTONBOX_TARGET'] == 'rhel' || !File.exist?("/etc/fedora-release")
33
+ 'php-5.3'
34
+ else
35
+ 'php-5.5'
36
+ end
37
+ end
38
+
39
+ def an_addon_cartridge
40
+ 'mysql-5'
41
+ end
42
+
43
+ def pbox(*args)
44
+ opts = args.pop if args.last.is_a? Hash
45
+ opts ||= {}
46
+ if user = opts[:as]
47
+ args << '--pblogin'
48
+ args << user.login
49
+ if user.attributes.has_key? :token
50
+ args << '--token'
51
+ args << user.attributes[:token]
52
+ elsif user.attributes.has_key? :password
53
+ args << '--password'
54
+ args << user.attributes[:password]
55
+ end
56
+ elsif !server_supports_sessions?
57
+ args << '--password'
58
+ args << ENV['TEST_PASSWORD']
59
+ end
60
+ oldenv = if opts[:env]
61
+ old = ENV.to_hash
62
+ ENV.update(opts[:env])
63
+ old
64
+ end
65
+ execute_command(args.unshift(pbox_executable), opts[:with])
66
+ ensure
67
+ ENV.replace(oldenv) if oldenv
68
+ end
69
+
70
+ def execute_command(args, stdin="", tty=true)
71
+ stdin = stdin.join("\n") if stdin.is_a? Array
72
+ stdout, stderr =
73
+ if debug?
74
+ [debug, debug].map{ |t| RHC::Helpers::StringTee.new(t) }
75
+ else
76
+ [StringIO.new, StringIO.new]
77
+ end
78
+
79
+ args.map!(&:to_s)
80
+ status = Open4.spawn(args, 'stdout' => stdout, 'stderr' => stderr, 'stdin' => stdin, 'quiet' => true)
81
+ stdout, stderr = [stdout, stderr].map(&:string)
82
+ Result.new(args, status, stdout, stderr).tap do |r|
83
+ debug.puts "\n[#{example_description}] #{r}" if debug?
84
+ end
85
+ end
86
+
87
+ def pbox_executable
88
+ ENV['PROTONBOX_TEST_SYSTEM'] ? 'pbox' : $source_bin_pbox
89
+ end
90
+
91
+ def client
92
+ @client ||= (@environment && @environment[:client]) || begin
93
+ WebMock.allow_net_connect!
94
+ opts = {:server => ENV['PROTONBOX_SERVER']}
95
+ if token = RHC::Auth::TokenStore.new(File.expand_path("~/.protonbox")).get(ENV['TEST_USERNAME'], ENV['PROTONBOX_SERVER'])
96
+ opts[:token] = token
97
+ else
98
+ opts[:user] = ENV['TEST_USERNAME']
99
+ opts[:password] = ENV['TEST_PASSWORD']
100
+ end
101
+ opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if ENV['TEST_INSECURE'] == '1'
102
+ env = RHC::Rest::Client.new(opts)
103
+ @environment[:client] = env if @environment
104
+ env
105
+ end
106
+ end
107
+
108
+ def base_client(user, password)
109
+ opts = {:server => ENV['PROTONBOX_SERVER']}
110
+ opts[:user] = user
111
+ opts[:password] = password
112
+ opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if ENV['TEST_INSECURE'] == '1'
113
+ RHC::Rest::Client.new(opts)
114
+ end
115
+
116
+ def no_applications(constraint=nil)
117
+ debug.puts "Removing applications that match #{constraint}" if debug?
118
+ apps = client.reset.applications
119
+ apps.each do |app|
120
+ next if constraint && !(app.name =~ constraint)
121
+ debug.puts " removing #{app.name}" if debug?
122
+ app.destroy
123
+ end
124
+ end
125
+
126
+ def other_users
127
+ $other_users ||= begin
128
+ (ENV['TEST_OTHER_USERS'] || "other1:a,other2:b,other3:c,other4:d").split(',').map{ |s| s.split(':') }.inject({}) do |h, (u, p)|
129
+ register_user(u,p) unless ENV['REGISTER_USER'].nil?
130
+ h[u] = base_client(u, p).user
131
+ h[u].attributes[:password] = p
132
+ h
133
+ end
134
+ end
135
+ end
136
+
137
+ def no_members(object)
138
+ object.delete_members
139
+ object.members.length.should == 1
140
+ end
141
+
142
+ def has_an_application(for_user=nil)
143
+ c = for_user ? for_user.client : client
144
+ debug.puts "Creating or reusing an app" if debug?
145
+ apps = c.applications
146
+ apps.find{|app| !app.scalable?} or begin
147
+ domain = has_a_domain(for_user)
148
+ debug.puts " creating a new application" if debug?
149
+ c.domains.first.add_application("test#{random}", :cartridges => [a_web_cartridge])
150
+ end
151
+ end
152
+
153
+ def has_a_scalable_application(for_user=nil)
154
+ c = for_user ? for_user.client : client
155
+ debug.puts "Creating or reusing a scalable app" if debug?
156
+ apps = c.applications
157
+ apps.find(&:scalable?) or begin
158
+ domain = has_a_domain(for_user)
159
+ debug.puts " creating a new scalable application" if debug?
160
+ c.domains.first.add_application("scalable#{random}", :cartridges => [a_web_cartridge], :scale => true)
161
+ end
162
+ end
163
+
164
+ def has_a_domain(for_user=nil)
165
+ c = for_user ? for_user.client : client
166
+ debug.puts "Creating or reusing a domain" if debug?
167
+ domain = c.domains.first or begin
168
+ debug.puts " creating a new domain" if debug?
169
+ c.add_domain("test#{random}")
170
+ end
171
+ end
172
+
173
+ def setup_args(opts={})
174
+ c = opts[:client] || client
175
+ args = []
176
+ args << 'yes' if (ENV['TEST_INSECURE'] == '1' || false)
177
+ args << (opts[:login] || ENV['TEST_USERNAME'])
178
+ args << (opts[:password] || ENV['TEST_PASSWORD'])
179
+ args << 'yes' if server_supports_sessions?(c)
180
+ args << 'yes' # generate a key, temp dir will never have one
181
+ args << (opts[:login] || ENV['TEST_USERNAME']) if (c.find_key('default').present? rescue false) # same key name as username
182
+ args << (opts[:domain_name] || "d#{random}") if (c.domains.empty? rescue true)
183
+ args
184
+ end
185
+
186
+ def has_local_ssh_key(user)
187
+ with_environment(user) do
188
+ r = pbox :setup, :with => setup_args(:login => user.login, :password => user.attributes[:password], :domain_name => "\n")
189
+ r.status.should == 0
190
+ user
191
+ end
192
+ end
193
+
194
+ def ssh_exec_for_env
195
+ @environment[:ssh_exec]
196
+ end
197
+
198
+ def use_clean_config
199
+ environment
200
+ FileUtils.rm_rf(File.join(@environment[:dir], ".protonbox"))
201
+ client.reset
202
+ end
203
+
204
+ def standard_config
205
+ environment(:standard) do
206
+ r = pbox :setup, :with => setup_args
207
+ raise "Unable to configure standard config" if r.status != 0
208
+ end
209
+ client.reset
210
+ end
211
+
212
+ def debug?
213
+ @debug ||= !!ENV['PROTONBOX_DEBUG']
214
+ end
215
+
216
+ def debug (*args)
217
+ @debug_stream ||= begin
218
+ if debug?
219
+ if ENV['PROTONBOX_DEBUG'] == 'true'
220
+ STDERR
221
+ else
222
+ File.open(ENV['PROTONBOX_DEBUG'], 'w')
223
+ end
224
+ else
225
+ StringIO.new
226
+ end
227
+ end
228
+ end
229
+
230
+ def random
231
+ @environment[:id]
232
+ end
233
+
234
+ def server_supports_sessions?(c=client)
235
+ @environment && c.supports_sessions?
236
+ end
237
+
238
+ def with_environment(user, &block)
239
+ previous = @environment
240
+ @environment, @client = nil
241
+ env = ENV.to_hash
242
+ ENV['TEST_RANDOM_USER'] = nil
243
+ ENV['TEST_USERNAME'] = user.login
244
+ ENV['TEST_PASSWORD'] = user.attributes[:password]
245
+ environment("custom_#{user.login}")
246
+ yield
247
+ ensure
248
+ @environment = previous
249
+ ENV.replace(env)
250
+ end
251
+
252
+ private
253
+ def example_description
254
+ if respond_to?(:example) && example
255
+ example.metadata[:full_description]
256
+ else
257
+ self.class.example.metadata[:full_description]
258
+ end
259
+ end
260
+
261
+ def environment(id=nil)
262
+ unless @environment
263
+ is_new = false
264
+ e = Environments.get(id){ is_new = true}
265
+ update_env(e)
266
+
267
+ dir = Dir.mktmpdir('pbox_features_test')
268
+ at_exit{ FileUtils.rm_rf(dir) } unless ENV['PROTONBOX_DEBUG_DIRS']
269
+ Dir.chdir(dir)
270
+
271
+ @client = e[:client]
272
+ @environment = e
273
+ yield if block_given? && is_new
274
+ end
275
+ @environment
276
+ end
277
+
278
+ def update_env(config)
279
+ ENV['HOME'] = config[:dir]
280
+ ENV['PROTONBOX_SERVER'] ||= 'api.protonbox.com'
281
+ if ENV['TEST_RANDOM_USER']
282
+ {
283
+ 'TEST_USERNAME' => "test_user_#{config[:id]}",
284
+ 'TEST_PASSWORD' => "password",
285
+ }.each_pair{ |k,v| ENV[k] = v }
286
+ else
287
+ ENV['TEST_USERNAME'] or raise "No TEST_USERNAME set"
288
+ ENV['TEST_PASSWORD'] or raise "No TEST_PASSWORD set"
289
+ end
290
+
291
+ register_user(ENV['TEST_USERNAME'],ENV['TEST_PASSWORD']) unless ENV['REGISTER_USER'].nil?
292
+ ENV['GIT_SSH'] = config[:ssh_exec]
293
+ end
294
+
295
+ def register_user(user,password)
296
+ if File.exists?("/etc/openshift/plugins.d/openshift-origin-auth-mongo.conf")
297
+ command = "bash -c 'unset GEM_HOME; unset GEM_PATH; oo-register-user -l admin -p admin --username #{user} --userpass #{password}'"
298
+ if Object.const_defined?('Bundler')
299
+ Bundler::with_clean_env do
300
+ system command
301
+ end
302
+ else
303
+ system command
304
+ end
305
+ elsif File.exists?("/etc/openshift/plugins.d/openshift-origin-auth-remote-user.conf")
306
+ system "/usr/bin/htpasswd -b /etc/openshift/htpasswd #{user} #{password}"
307
+ else
308
+ #ignore
309
+ print "Unknown auth plugin. Not registering user #{user}/#{password}."
310
+ print "Modify #{__FILE__}:239 if user registration is required."
311
+ cmd = nil
312
+ end
313
+ end
314
+ end
315
+
316
+ module Environments
317
+ def self.get(id, &block)
318
+ (@environments ||= {})[id] ||= begin
319
+ dir = Dir.mktmpdir('pbox_features')
320
+ at_exit{ FileUtils.rm_rf(dir) } unless ENV['PROTONBOX_DEBUG_DIRS']
321
+ id = Random.rand(1000000)
322
+ ssh_exec = create_ssh_exec(dir)
323
+ yield if block_given?
324
+ {:dir => dir, :id => id, :ssh_exec => ssh_exec}
325
+ end
326
+ end
327
+ def self.create_ssh_exec(dir, for_user=nil)
328
+ ssh_exec = File.join(dir, "ssh_exec#{for_user ? "_#{for_user}" : ""}")
329
+ IO.write(ssh_exec, "#!/bin/sh\nssh -o StrictHostKeyChecking=no -i #{dir}/.ssh/id_rsa \"$@\"")
330
+ FileUtils.chmod("u+x", ssh_exec)
331
+ ssh_exec
332
+ end
333
+ end
334
+
335
+ RSpec.configure do |config|
336
+ config.include(RhcExecutionHelper)
337
+ config.extend(RhcExecutionHelper)
338
+ end
@@ -0,0 +1,23 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIID4DCCAsgCCQDLI3UAX4mf4DANBgkqhkiG9w0BAQUFADCBsTELMAkGA1UEBhMC
3
+ VVMxFzAVBgNVBAgMDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHDAdSYWxlaWdoMRAw
4
+ DgYDVQQKDAdSZWQgSGF0MRcwFQYDVQQLDA5PcGVuU2hpZnQgVGVzdDEiMCAGA1UE
5
+ AwwZdGVzdC5vcGVuc2hpZnQucmVkaGF0LmNvbTEoMCYGCSqGSIb3DQEJARYZdGVz
6
+ dEBvcGVuc2hpZnQucmVkaGF0LmNvbTAeFw0xMjEyMjIyMTI1MDFaFw0xMzEyMjIy
7
+ MTI1MDFaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmEx
8
+ EDAOBgNVBAcMB1JhbGVpZ2gxEDAOBgNVBAoMB1JlZCBIYXQxFzAVBgNVBAsMDk9w
9
+ ZW5TaGlmdCBUZXN0MSIwIAYDVQQDDBl0ZXN0Lm9wZW5zaGlmdC5yZWRoYXQuY29t
10
+ MSgwJgYJKoZIhvcNAQkBFhl0ZXN0QG9wZW5zaGlmdC5yZWRoYXQuY29tMIIBIjAN
11
+ BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA08M8AZMgpYY+BJ6Of2LVf+vGKCmP
12
+ 0nMSGe9ESy2LDlgF5TRhg38XyryvkzBI1IBc/0+VuDxh5IbxGFUkBNsdVz9xfKKB
13
+ b1LBxVI9QuhlKyY0V+VsUAwMLOQGh7YnThBrLlSE4+oWha5mnfnC4qRaeI3LOOYe
14
+ jCaVH3ee/+gzcGKf5IW+cSbF97/++38AHHIW8x87sBfZBkP05ZiVKW1zsMS1HZMa
15
+ wc2JfvZaJZZqzezphwzfPxS11MbucceZEIqj1u47qT6957dZ/uDpmS+uPZBMS/FZ
16
+ xsnHpUIiAAP1Dm4jQXON62NfrR54Jr0O7/Z4XV42GF6R0Z2xEuoP1CDUmwIDAQAB
17
+ MA0GCSqGSIb3DQEBBQUAA4IBAQBx9MAVgYBSWGlc1Ja5vJYeYOc1eRUAGljWQN1Y
18
+ t3/iEenIu8ZLEYKqUQEFzDvjUhaVOyW4XpoLR6SQdcvOGt54aYQ5a5sRPmXtaJjm
19
+ 9ic3lJuZ+c4He4APl7j0xQ0IQPNwbqkIe6MFxISq0/4+iJDQgOTmoXm5WKKP1b48
20
+ 8s3xyJaky2LEKoUvng81/TjvOE6i7MPSGBaT64kGm1DwYjLGm8C7Q8e6fDpTAR9H
21
+ ukfpcIRls7mrqtP4vvhf5+NngJ6Ubo7hrcrWLijGub1+QAo8XlXxp9258sED+Vyx
22
+ 0596NONiYyu3h7eyD4BcawfSE0dPm0bNcq+XTMnhK3tVriTB
23
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEA08M8AZMgpYY+BJ6Of2LVf+vGKCmP0nMSGe9ESy2LDlgF5TRh
3
+ g38XyryvkzBI1IBc/0+VuDxh5IbxGFUkBNsdVz9xfKKBb1LBxVI9QuhlKyY0V+Vs
4
+ UAwMLOQGh7YnThBrLlSE4+oWha5mnfnC4qRaeI3LOOYejCaVH3ee/+gzcGKf5IW+
5
+ cSbF97/++38AHHIW8x87sBfZBkP05ZiVKW1zsMS1HZMawc2JfvZaJZZqzezphwzf
6
+ PxS11MbucceZEIqj1u47qT6957dZ/uDpmS+uPZBMS/FZxsnHpUIiAAP1Dm4jQXON
7
+ 62NfrR54Jr0O7/Z4XV42GF6R0Z2xEuoP1CDUmwIDAQABAoIBAQCrb/ani7Y1a13Q
8
+ HZFdneUcwANXxnYSOWihKGzQtBlMzoRPUD3V2FGpp2I5NjDwIM+pPoQGeJQEEB8l
9
+ xN/5Mm8pkEpPTbyeJJCNMAw6m6wz56Uet7UdhPNicGS9AAIIGBC9nF1Nqtj69vtK
10
+ z8Yv+EDqMlkhQmPesOmvZQeLRDBIvYUdKFMc2tvBBqAkVUbcpRICUmHbAjyGs3qi
11
+ +K3eBym9Hhv5ICLNAsvSHUwb/vVN0uvr5qMrcl8kFWBsNgCac6dj3eAMU90olV4x
12
+ BjmRBln30RlwbVbUKownVqpyCi+JCEENQ74Dcg9eQkpyTC/csL+7E1IeaLoz8aKA
13
+ uAGhF6SRAoGBAP5jtNY70HHPDjyB4ySkuaJKvt316MASqOp79Q4vvrAPVAuX2LlX
14
+ ce0WzFid5ZssfTBQ5QnX3gDGnJ+daZS3QwgquDEfyR8rdkxnhfcjrl79+vLom394
15
+ vUMA8dS/ctk2lN7UQq3qXkqg2cBkJ2sd0FkjYgRmdWcVysKEOrxiCi7DAoGBANUa
16
+ cSEoLfluI4XPfeXe6IYlfdnQkk+0uyUD+XnKPj3Sh8YEh0xx/24fAIY9gEtTSiXK
17
+ E+a0iVoRcF6Kr/1jj4BYoZTG67RqsJWDr8ISnMES+dfQoKOWQg4GTPbCvMlluBwH
18
+ dPCgDS3xgXw7MmJTsnvn69nVQTIzFZFZ5GAJ1pVJAoGAGpvFQ49YGz9kJtITNzb/
19
+ r8kPs9nP8Z9CCdzTYht+X54K1XeZlLFf2kPDNhW1+YgqxA4CFwh8USp1IYDulT6i
20
+ BU2qnIDNobQDGLTPX21dBNSeFiBce3Xeng6QPQeVdMDvy2r6WoSkPjwa6rPPJ7Yj
21
+ n99ClmE9MH4oCjaYijHbDM8CgYBb3mtY7PZs6oNb42iWGbPKaQ1JQnZg8DwhqAX7
22
+ 8ClHA6TOxBMD7L0+XxUdyhOt5Xk4s1ZDBh+UeaIkz8sxBKPPo+X8uojQnZIE0uGJ
23
+ W/bB8YlN9b3a6CMP4r15P9idRkHJq5lJRuaHoO6+fNKquwReEEyH+zyBBK7Om58t
24
+ m/ArKQKBgQCcamRni3FOi6kK8YT/cv4Tobx4e8qwOJcX+93E8DdrB2UP3MLfkwA5
25
+ thThxl4Lub50bgtUJ5yfNDS0nCZed/Ax/SqzizvCCJbw7BqSOBbJv/BSsql3k1FD
26
+ hoBg8a1zkB8dDQNoKj2Om5NM7U+rL1Ujp9uW/qcLaejuks3C441FGw==
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDKzCCApSgAwIBAgICOcMwDQYJKoZIhvcNAQEFBQAwgbExCzAJBgNVBAYTAi0t
3
+ MRIwEAYDVQQIDAlTb21lU3RhdGUxETAPBgNVBAcMCFNvbWVDaXR5MRkwFwYDVQQK
4
+ DBBTb21lT3JnYW5pemF0aW9uMR8wHQYDVQQLDBZTb21lT3JnYW5pemF0aW9uYWxV
5
+ bml0MRkwFwYDVQQDDBBpcC0xMC0xMi0xMjMtMjI5MSQwIgYJKoZIhvcNAQkBFhVy
6
+ b290QGlwLTEwLTEyLTEyMy0yMjkwHhcNMTIxMjE2MDUyNzA3WhcNMTMxMjE2MDUy
7
+ NzA3WjCBsTELMAkGA1UEBhMCLS0xEjAQBgNVBAgMCVNvbWVTdGF0ZTERMA8GA1UE
8
+ BwwIU29tZUNpdHkxGTAXBgNVBAoMEFNvbWVPcmdhbml6YXRpb24xHzAdBgNVBAsM
9
+ FlNvbWVPcmdhbml6YXRpb25hbFVuaXQxGTAXBgNVBAMMEGlwLTEwLTEyLTEyMy0y
10
+ MjkxJDAiBgkqhkiG9w0BCQEWFXJvb3RAaXAtMTAtMTItMTIzLTIyOTCBnzANBgkq
11
+ hkiG9w0BAQEFAAOBjQAwgYkCgYEA5yEY0irLovUbcFoCnhon8zo4yp68+UBBtJ3A
12
+ 0apkSHhU+P29/YgKTbMoSu0xGTiDnih77KY3jq5SS3O7kKMrqA8otqp96Hl4iB+X
13
+ KNa9njZIP5FS3RmS2nOzrlNQvSwOjK4cHJYkzH6ozIBOgz3qaCNC8skmNCdb0LmZ
14
+ TX9lYssCAwEAAaNQME4wHQYDVR0OBBYEFIoxHQJuFHsreItT4b6Vx9XB5rrtMB8G
15
+ A1UdIwQYMBaAFIoxHQJuFHsreItT4b6Vx9XB5rrtMAwGA1UdEwQFMAMBAf8wDQYJ
16
+ KoZIhvcNAQEFBQADgYEAHDAQGgA5PmauN0GKJuUbHkH/L7cBgxs6B2Rnbx8r+zJM
17
+ a3OdnEhJRwhfXEsw47Uo7Uo78auCPNO5VQCMxmSwejJ7BbsWuqpKpKL/UsZv3qeJ
18
+ pyXCQnzYnYsuTe1b72AZ7ek6S4s5Utc5L+sqWOM+WcKODC5yxrEQPrtMjXKNXZY=
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,31 @@
1
+ require 'webmock/rspec'
2
+ require 'rhc/rest'
3
+ require 'rhc/rest/mock'
4
+ require 'rhc/exceptions'
5
+ require 'base64'
6
+
7
+ RSpec::Matchers.define :have_same_attributes_as do |expected|
8
+ match do |actual|
9
+ (actual.instance_variables == expected.instance_variables) &&
10
+ (actual.instance_variables.map { |i| instance_variable_get(i) } ==
11
+ expected.instance_variables.map { |i| instance_variable_get(i) })
12
+ end
13
+ end
14
+
15
+ # ruby 1.8 does not have strict_encode
16
+ if RUBY_VERSION.to_f == 1.8
17
+ module Base64
18
+ def strict_encode64(value)
19
+ encode64(value).delete("\n")
20
+ end
21
+ end
22
+ end
23
+
24
+ module RestSpecHelper
25
+ include RHC::Rest::Mock::Helpers
26
+ include RHC::Rest::Mock
27
+ end
28
+
29
+ RSpec.configure do |configuration|
30
+ include(RestSpecHelper)
31
+ end
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDoDCCAogCCQDzF8AJCHnrbjANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMC
3
+ VVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxDzANBgNVBAoMBnJl
4
+ ZGhhdDESMBAGA1UECwwJb3BlbnNoaWZ0MRIwEAYDVQQDDAlvcGVuc2hpZnQxKDAm
5
+ BgkqhkiG9w0BCQEWGWluZm9Ab3BlbnNoaWZ0LnJlZGhhdC5jb20wHhcNMTMwMjE5
6
+ MjExMTQ4WhcNMTQwMjE5MjExMTQ4WjCBkTELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
7
+ AkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxDzANBgNVBAoMBnJlZGhhdDESMBAGA1UE
8
+ CwwJb3BlbnNoaWZ0MRIwEAYDVQQDDAlvcGVuc2hpZnQxKDAmBgkqhkiG9w0BCQEW
9
+ GWluZm9Ab3BlbnNoaWZ0LnJlZGhhdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
10
+ DwAwggEKAoIBAQDAEbH4MCi3iIDP1HS+/Xwu8SjdSc5WJX6htV7hJpmFZ8HohV/8
11
+ ba0v6aM9IJIIt+sIe2J62t/9G3leOdIHBxeACN4fV2l/iA/fvxvlnFKeD7sHm9Oc
12
+ Yj1H6YYJ57sIOf/oLDpJl6l3Rw8VC3+3W0/lzlVpA8qt7fpkiW7XQJCPplUSrdVC
13
+ 3okQ2T5NAod5+wVIOqELgE5bLX1LRs5VPsjytHkJ7rKXs55FHR3kpsoImn5xD0Ky
14
+ 6lRn8cIMolQoyN5HIGr8f5P+07hrHibve8jje/DKTssb5yEUAEmh6iGHQsRAnsUW
15
+ QoIEUOLqQCu9re2No4G52Kl2xQIjyJF7rCfxAgMBAAEwDQYJKoZIhvcNAQEFBQAD
16
+ ggEBAGHrya/ZkiAje2kHsOajXMlO2+y1iLfUDcRLuEWpUa8sI5EM4YtemQrsupFp
17
+ 8lVYG5C4Vh8476oF9t8Wex5eH3ocwbSvPIUqE07hdmrubiMq4wxFVRYq7g9lHAnx
18
+ l+bABuN/orbAcPcGAGg7AkXVoAc3Fza/ZcgMcw7NOtDTEss70V9OdgCfQUJL0KdO
19
+ hCO8bQ1EaEiq6zEh8RpZe8mu+f/GYATX1I+eJUc6F6cn83oJjE9bqAVzk7TzTHeK
20
+ EBKN50C14wWtXeG7n2+ugaVO+0xnvHeUrQBLHSRyOHqxXrQQ5XmzcaBiyI0f2IQM
21
+ Hst1BVXyX0n/L/ZoYYsv5juJmDo=
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAwBGx+DAot4iAz9R0vv18LvEo3UnOViV+obVe4SaZhWfB6IVf
3
+ /G2tL+mjPSCSCLfrCHtietrf/Rt5XjnSBwcXgAjeH1dpf4gP378b5ZxSng+7B5vT
4
+ nGI9R+mGCee7CDn/6Cw6SZepd0cPFQt/t1tP5c5VaQPKre36ZIlu10CQj6ZVEq3V
5
+ Qt6JENk+TQKHefsFSDqhC4BOWy19S0bOVT7I8rR5Ce6yl7OeRR0d5KbKCJp+cQ9C
6
+ supUZ/HCDKJUKMjeRyBq/H+T/tO4ax4m73vI43vwyk7LG+chFABJoeohh0LEQJ7F
7
+ FkKCBFDi6kArva3tjaOBudipdsUCI8iRe6wn8QIDAQABAoIBAG/on4JVRRQSw8LU
8
+ LiWt+jI7ryyoOUH2XL8JtzuGSwLwvomlVJT2rmbxQXx3Qr8zsgziHzIn30RRQrkF
9
+ BXu0xRuDjzBBtSVqeJ1Mc4uoNncEAVxgjb5bewswZDnXPCGB8bosMtX4OPRXgdEo
10
+ PwTtfjMOsrMaU3hd5Xu4m81tQA2BvwOlx8aYDyH0jeTnervc5uRGbeTBQG4Bu40E
11
+ rWNmXvgNq2EzTAwbbN6Ma97gw9KgXnM4Nlh29Fxb5TBeUU9lkzuTZAZIDXKIm7AG
12
+ UwMbj/A038yAumYQtThTE/3e4W3rn7F2Vko900bC4aAC1KQOAzjIeQqzqkVxWTWq
13
+ 4SUFQAECgYEA/ODwifOTuI6hdZK6JRgc4wp6Rc0fkqHuxLzABXoIGuSVlWyimqIN
14
+ ZySAkpo5EW6DNraRJxNCOBmWeGPEhHGrea+JPiPEwCK0F7SxvSmg3jzNzw3Es31T
15
+ ecET7eDwuSOY9v4XDzLyiXXkEUUReD7Ng2hEYL+HaQrl5jWj4lxgq/ECgYEAwnCb
16
+ Krz7FwX8AqtFAEi6uUrc12k1xYKQfrwSxbfdK2vBBUpgB71Iq/fqP+1BittEljDG
17
+ 8f4jEtMBFfEPhLzGIHaI3UiHUHXS4GetA77TRgR8lnKKpj1FcMIY2iKU479707O5
18
+ Q08pgWRUDQ8BVg2ePgbo5QjLMc/rv7UF3AHvPAECgYB/auAIwqDGN6gHU/1TP4ke
19
+ pWLi1O55tfpXSzv+BnUbB96PQgPUop7aP7xBIlBrBiI7aVZOOBf/qHT3CF421geu
20
+ 8tHWa7NxlIrl/vgn9lfGYyDYmXlpb1amXLEsBVGGF/e1TGZWFDe9J5fZU9HvosVu
21
+ 1xTNIvSZ6xHYI2MGZcGYIQKBgEYeebaV5C7PV6xWu1F46O19U9rS9DM//H/XryVi
22
+ Qv4vo7IWuj7QQe7SPsXC98ntfPR0rqoCLf/R3ChfgGsr8H8wf/bc+v9HHj8S5E/f
23
+ dy1e3Nccg2ej3PDm7jNsGSlwmmUkAQGHAL7KwYzcBm1UB+bycvZ1j2FtS+UckPpg
24
+ MDgBAoGALD8PkxHb4U4DtbNFSYRrUdvS9heav/yph3lTMfifNkOir36io6v8RPgb
25
+ D2bHKKZgmYlTgJrxD45Er9agC5jclJO35QRU/OfGf3GcnABkBI7vlvUKADAo65Sq
26
+ weZkdJnbrIadcvLOHOzkKC9m+rxFTC9VoN1dwK2zwYvUXfa1VJA=
27
+ -----END RSA PRIVATE KEY-----
File without changes
@@ -0,0 +1,7 @@
1
+ FOO=123
2
+ BAR=456
3
+ MY_PROTONBOX_ENV_VAR=mongodb://user:pass@host:port/
4
+ MY_EMPTY_ENV_VAR=
5
+ ZEE
6
+ LOL
7
+ MUST NOT BE INCLUDED
@@ -0,0 +1 @@
1
+ AND=123
@@ -0,0 +1 @@
1
+ foo
@@ -0,0 +1 @@
1
+ foo
Binary file