pbox 1.17.2

Sign up to get free protection for your applications and to get access to all the features.
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