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,121 @@
1
+ require 'rhc/git_helpers'
2
+
3
+ module RHC
4
+ #
5
+ # Methods in this module should not attempt to read from the options hash
6
+ # in a recursive manner (server_context can't read options.server).
7
+ #
8
+ module ContextHelpers
9
+ include RHC::GitHelpers
10
+
11
+ def self.included(other)
12
+ other.module_eval do
13
+ def self.takes_domain(opts={})
14
+ if opts[:argument]
15
+ argument :namespace, "Name of a domain", ["-n", "--namespace NAME"], :allow_nil => true, :default => :from_local_git
16
+ else
17
+ option ["-n", "--namespace NAME"], "Name of a domain", :default => :from_local_git
18
+ end
19
+ end
20
+ # Does not take defaults to avoid conflicts
21
+ def self.takes_application_or_domain(opts={})
22
+ option ["-n", "--namespace NAME"], "Name of a domain"
23
+ option ["-a", "--app NAME"], "Name of an application"
24
+ if opts[:argument]
25
+ argument :target, "The name of a domain, or an application name with domain (domain or domain/application)", ["-t", "--target NAME_OR_PATH"], :allow_nil => true, :covered_by => [:application_id, :namespace, :app]
26
+ end
27
+ end
28
+ def self.takes_application(opts={})
29
+ if opts[:argument]
30
+ argument :app, "Name of an application", ["-a", "--app NAME"], :allow_nil => true, :default => :from_local_git, :covered_by => :application_id
31
+ else
32
+ option ["-a", "--app NAME"], "Name of an application", :default => :from_local_git, :covered_by => :application_id
33
+ end
34
+ option ["-n", "--namespace NAME"], "Name of a domain", :default => :from_local_git
35
+ option ["--application-id ID"], "ID of an application", :hide => true, :default => :from_local_git, :covered_by => :app
36
+ end
37
+ end
38
+ end
39
+
40
+ def find_domain(opts={})
41
+ domain = options.namespace || options.target || namespace_context
42
+ if domain
43
+ rest_client.find_domain(domain)
44
+ else
45
+ raise ArgumentError, "You must specify a domain with -n."
46
+ end
47
+ end
48
+
49
+ def find_app_or_domain(opts={})
50
+ domain, app =
51
+ if options.target.present?
52
+ options.target.split(/\//)
53
+ elsif options.namespace || options.app
54
+ if options.app =~ /\//
55
+ options.app.split(/\//)
56
+ else
57
+ [options.namespace || namespace_context, options.app]
58
+ end
59
+ end
60
+ if app && domain
61
+ rest_client.find_application(domain, app)
62
+ elsif domain
63
+ rest_client.find_domain(domain)
64
+ else
65
+ raise ArgumentError, "You must specify a domain with -n, or an application with -a."
66
+ end
67
+ end
68
+
69
+ def find_app(opts={})
70
+ if id = options.application_id
71
+ if opts.delete(:with_gear_groups)
72
+ return rest_client.find_application_by_id_gear_groups(id, opts)
73
+ else
74
+ return rest_client.find_application_by_id(id, opts)
75
+ end
76
+ end
77
+ domain, app =
78
+ if options.app
79
+ if options.app =~ /\//
80
+ options.app.split(/\//)
81
+ else
82
+ [options.namespace || namespace_context, options.app]
83
+ end
84
+ end
85
+ if app && domain
86
+ if opts.delete(:with_gear_groups)
87
+ rest_client.find_application_gear_groups(domain, app, opts)
88
+ else
89
+ rest_client.find_application(domain, app, opts)
90
+ end
91
+ else
92
+ raise ArgumentError, "You must specify an application with -a, or run this command from within a Git directory cloned from ProtonBox."
93
+ end
94
+ end
95
+
96
+ def server_context(defaults=nil, arg=nil)
97
+ value = ENV['PROTONBOX_SERVER'] || (!options.clean && config['protonbox_server']) || "api.protonbox.com"
98
+ defaults[arg] = value if defaults && arg
99
+ value
100
+ end
101
+
102
+ def from_local_git(defaults, arg)
103
+ @local_git_config ||= {
104
+ :application_id => git_config_get('pbox.app-id').presence,
105
+ :app => git_config_get('pbox.app-name').presence,
106
+ :namespace => git_config_get('pbox.domain-name').presence,
107
+ }
108
+ defaults[arg] ||= @local_git_config[arg] unless @local_git_config[arg].nil?
109
+ @local_git_config
110
+ end
111
+
112
+ def namespace_context
113
+ # right now we don't have any logic since we only support one domain
114
+ # TODO: add domain lookup based on uuid
115
+ domain = rest_client.domains.first
116
+ raise RHC::NoDomainsForUser if domain.nil?
117
+
118
+ domain.name
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,202 @@
1
+ # From Rails core_ext/object.rb
2
+ require 'rhc/json'
3
+ require 'open-uri'
4
+ require 'httpclient'
5
+
6
+ class Object
7
+ def present?
8
+ !blank?
9
+ end
10
+ def blank?
11
+ respond_to?(:empty?) ? empty? : !self
12
+ end
13
+
14
+ def presence
15
+ present? ? self : nil
16
+ end
17
+
18
+ # Avoid a conflict if to_json is already defined
19
+ unless Object.new.respond_to? :to_json
20
+ def to_json(options=nil)
21
+ RHC::Json.encode(self)
22
+ end
23
+ end
24
+ end
25
+
26
+ class Array
27
+ # From rails
28
+ def split(value = nil)
29
+ using_block = block_given?
30
+
31
+ inject([[]]) do |results, element|
32
+ if (using_block && yield(element)) || (value == element)
33
+ results << []
34
+ else
35
+ results.last << element
36
+ end
37
+
38
+ results
39
+ end
40
+ end
41
+ end
42
+
43
+ class File
44
+ def chunk(chunk_size=1024)
45
+ yield read(chunk_size) until eof?
46
+ end
47
+ end
48
+
49
+ class String
50
+ # Wrap string by the given length, and join it with the given character.
51
+ # The method doesn't distinguish between words, it will only work based on
52
+ # the length.
53
+ def wrap(wrap_length=80, char="\n")
54
+ scan(/.{#{wrap_length}}|.+/).join(char)
55
+ end
56
+
57
+ def strip_heredoc
58
+ indent = scan(/^[ \t]*(?=\S)/).min.size || 0
59
+ gsub(/^[ \t]{#{indent}}/, '').
60
+ gsub(/(\b|\S)[^\S\n]*\n(\S)/m, '\1 \2').
61
+ gsub(/\n+\Z/, '').
62
+ gsub(/\n{3,}/, "\n\n")
63
+ end
64
+
65
+ ANSI_ESCAPE_SEQUENCE = /\e\[(\d{1,2}(?:;\d{1,2})*[@-~])/
66
+ ANSI_ESCAPE_MATCH = '\e\[\d+(?:;\d+)*[@-~]'
67
+ CHAR_SKIP_ANSI = "(?:(?:#{ANSI_ESCAPE_MATCH})+.?|.(?:#{ANSI_ESCAPE_MATCH})*)"
68
+
69
+ #
70
+ # Split the given string at limit, treating ANSI escape sequences as
71
+ # zero characters in length. Will insert an ANSI reset code (\e[0m)
72
+ # at the end of each line containing an ANSI code, assuming that a
73
+ # reset was not in the wrapped segment.
74
+ #
75
+ # All newlines are preserved.
76
+ #
77
+ # Lines longer than limit without natural breaks will be forcibly
78
+ # split at the exact limit boundary.
79
+ #
80
+ # Returns an Array
81
+ #
82
+ def textwrap_ansi(limit, breakword=true)
83
+ re = breakword ? /
84
+ (
85
+ # Match substrings that end in whitespace shorter than limit
86
+ #{CHAR_SKIP_ANSI}{1,#{limit}} # up to limit
87
+ (?:\s+|$) # require the limit to end on whitespace
88
+ |
89
+ # Match substrings equal to the limit
90
+ #{CHAR_SKIP_ANSI}{1,#{limit}}
91
+ )
92
+ /x :
93
+ /
94
+ (
95
+ # Match substrings that end in whitespace shorter than limit
96
+ #{CHAR_SKIP_ANSI}{1,#{limit}}
97
+ (?:\s|$) # require the limit to end on whitespace
98
+ |
99
+ # Match all continguous whitespace strings
100
+ #{CHAR_SKIP_ANSI}+?
101
+ (?:\s|$)
102
+ (?:\s+|$)?
103
+ )
104
+ /x
105
+ escapes = []
106
+
107
+ split("\n",-1).inject([]) do |a, line|
108
+ if line.length < limit
109
+ a << line
110
+ else
111
+ line.scan(re) do |segment, other|
112
+ if escapes.present?
113
+ a << escapes.map{ |s| "\e[#{s}"}.join
114
+ a[-1] << segment.rstrip
115
+ else
116
+ a << segment.rstrip
117
+ end
118
+
119
+ segment.scan(ANSI_ESCAPE_SEQUENCE).map{ |e| e.first }.each do |e|
120
+ case e
121
+ when '0m' then escapes.clear
122
+ else escapes << e
123
+ end
124
+ end
125
+ a[-1] << "\e[0m" if escapes.present?
126
+ end
127
+ end
128
+ a
129
+ end
130
+ end
131
+
132
+ def strip_ansi
133
+ gsub(ANSI_ESCAPE_SEQUENCE, '')
134
+ end
135
+ end
136
+
137
+ unless HTTP::Message.method_defined? :ok?
138
+ #:nocov:
139
+ class HTTP::Message
140
+ def ok?
141
+ HTTP::Status.successful?(status)
142
+ end
143
+ end
144
+ #:nocov:
145
+ end
146
+
147
+ unless DateTime.method_defined? :to_time
148
+ #:nocov:
149
+ class DateTime
150
+ def to_time
151
+ Time.parse(to_s)
152
+ end
153
+ end
154
+ #:nocov:
155
+ end
156
+
157
+ #
158
+ # Allow http => https redirection, see
159
+ # http://bugs.ruby-lang.org/issues/859 to 1.8.7 for rough
160
+ # outline of change.
161
+ #
162
+ module OpenURI
163
+ def self.redirectable?(uri1, uri2) # :nodoc:
164
+ # This test is intended to forbid a redirection from http://... to
165
+ # file:///etc/passwd.
166
+ # However this is ad hoc. It should be extensible/configurable.
167
+ uri1.scheme.downcase == uri2.scheme.downcase ||
168
+ (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:https?|ftp)\z/i =~ uri2.scheme)
169
+ end
170
+ end
171
+
172
+ class Hash
173
+ def stringify_keys!
174
+ keys.each do |key|
175
+ v = delete(key)
176
+ if v.is_a? Hash
177
+ v.stringify_keys!
178
+ elsif v.is_a? Array
179
+ v.each{ |value| value.stringify_keys! if value.is_a? Hash }
180
+ end
181
+ self[(key.to_s rescue key) || key] = v
182
+ end
183
+ self
184
+ end
185
+ def slice!(*args)
186
+ s = []
187
+ args.inject([]) do |a, k|
188
+ s << [k, delete(k)] if has_key?(k)
189
+ end
190
+ s
191
+ end
192
+ def slice(*args)
193
+ args.inject({}) do |h, k|
194
+ h[k] = self[k] if has_key?(k)
195
+ h
196
+ end
197
+ end
198
+ def reverse_merge!(other_hash)
199
+ # right wins if there is no left
200
+ merge!( other_hash ){|key,left,right| left }
201
+ end
202
+ end
@@ -0,0 +1,33 @@
1
+ # Must be the first module imported at entry points (executables that run
2
+ # in seperate processes from the test harness) otherwise coverage will be
3
+ # incomplete
4
+
5
+ if RUBY_VERSION >= '1.9' and ENV['PROTONBOX_FEATURE_COVERAGE']
6
+ require 'simplecov'
7
+ SimpleCov.start do
8
+ coverage_dir 'coverage/features/'
9
+ command_name 'Integration Tests'
10
+
11
+ # Filters - these files will be ignored.
12
+ add_filter 'lib/rhc/vendor/' # vendored files should be taken directly and only
13
+ # namespaces changed
14
+ add_filter 'features/' # Don't report on the files that run the cucumber tests
15
+ add_filter 'lib/rhc-feature-coverage-helper.rb'
16
+ add_filter 'spec/' # Don't report on the files that run the spec tests
17
+
18
+ # Groups - general categories of test areas
19
+ add_group('Commands') { |src_file| src_file.filename.include?(File.join(%w[lib rhc commands])) }
20
+ add_group('RHC Lib') { |src_file| src_file.filename.include?(File.join(%w[lib rhc])) }
21
+ add_group('REST') { |src_file| src_file.filename.include?(File.join(%w[lib rhc/rest])) }
22
+ add_group('Test') { |src_file| src_file.filename.include?(File.join(%w[features])) or
23
+ src_file.filename.include?(File.join(%w[spec])) }
24
+
25
+ use_merging = true
26
+ # Note, the #:nocov: coverage exclusion should only be used on external functions
27
+ # that cannot be nondestructively tested in a developer environment.
28
+ end
29
+
30
+ # suppress output
31
+ SimpleCov.at_exit do
32
+ end
33
+ end
@@ -0,0 +1,88 @@
1
+ require 'rhc/ssh_helpers'
2
+
3
+ module RHC
4
+ module DeploymentHelpers
5
+
6
+ extend self
7
+
8
+ include RHC::SSHHelpers
9
+
10
+ protected
11
+
12
+ def deploy_artifact(rest_app, artifact, hot_deploy, force_clean_build)
13
+ File.file?(artifact) ?
14
+ deploy_local_file(rest_app, artifact, hot_deploy, force_clean_build) :
15
+ artifact =~ /^#{URI::regexp}$/ ?
16
+ deploy_file_from_url(rest_app, artifact, hot_deploy, force_clean_build) :
17
+ deploy_git_ref(rest_app, artifact, hot_deploy, force_clean_build)
18
+ end
19
+
20
+ def deploy_git_ref(rest_app, ref, hot_deploy, force_clean_build)
21
+ say "Deployment of git ref '#{ref}' in progress for application #{rest_app.name} ..."
22
+
23
+ ssh_url = URI(rest_app.ssh_url)
24
+ remote_cmd = "gear deploy #{ref}#{hot_deploy ? ' --hot-deploy' : ''}#{force_clean_build ? ' --force-clean-build' : ''}"
25
+
26
+ begin
27
+ ssh_ruby(ssh_url.host, ssh_url.user, remote_cmd)
28
+ success "Success"
29
+ rescue
30
+ ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
31
+ warn "Error deploying git ref. You can try to deploy manually with:\n#{ssh_cmd}"
32
+ raise
33
+ end
34
+ end
35
+
36
+ def deploy_local_file(rest_app, filename, hot_deploy, force_clean_build)
37
+ filename = File.expand_path(filename)
38
+ say "Deployment of file '#{filename}' in progress for application #{rest_app.name} ..."
39
+
40
+ ssh_url = URI(rest_app.ssh_url)
41
+ remote_cmd = "oo-binary-deploy#{hot_deploy ? ' --hot-deploy' : ''}#{force_clean_build ? ' --force-clean-build' : ''}"
42
+
43
+ begin
44
+ ssh_send_file_ruby(ssh_url.host, ssh_url.user, remote_cmd, filename)
45
+ success "Success"
46
+ rescue
47
+ ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
48
+ warn "Error deploying local file. You can try to deploy manually with:\n#{ssh_cmd}"
49
+ raise
50
+ end
51
+ end
52
+
53
+ def deploy_file_from_url(rest_app, file_url, hot_deploy, force_clean_build)
54
+ say "Deployment of file '#{file_url}' in progress for application #{rest_app.name} ..."
55
+
56
+ ssh_url = URI(rest_app.ssh_url)
57
+ file_url = URI(file_url)
58
+
59
+ remote_cmd = "oo-binary-deploy#{hot_deploy ? ' --hot-deploy' : ''}#{force_clean_build ? ' --force-clean-build' : ''}"
60
+
61
+ begin
62
+ ssh_send_url_ruby(ssh_url.host, ssh_url.user, remote_cmd, file_url)
63
+ success "Success"
64
+ rescue
65
+ ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
66
+ warn "Error deploying file from url. You can try to deploy manually with:\n#{ssh_cmd}"
67
+ raise
68
+ end
69
+ end
70
+
71
+ def activate_deployment(rest_app, deployment_id)
72
+ say "Activating deployment '#{deployment_id}' on application #{rest_app.name} ..."
73
+
74
+ ssh_url = URI(rest_app.ssh_url)
75
+ remote_cmd = "gear activate #{deployment_id}"
76
+
77
+ begin
78
+ ssh_ruby(ssh_url.host, ssh_url.user, remote_cmd)
79
+ success "Success"
80
+ rescue
81
+ ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
82
+ warn "Error activating deployment. You can try to activate manually with:\n#{ssh_cmd}"
83
+ raise
84
+ end
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,232 @@
1
+ module RHC
2
+ class Exception < StandardError
3
+ attr_reader :code
4
+ def initialize(message=nil, code=1)
5
+ super(message)
6
+ @code = code
7
+ end
8
+ end
9
+
10
+ class ConfirmationError < Exception
11
+ def initialize(message="This action requires the --confirm option (or entering 'yes' at a prompt) to run.", code=1)
12
+ super(message, code)
13
+ end
14
+ end
15
+
16
+ class CartridgeNotFoundException < Exception
17
+ def initialize(message="Cartridge not found")
18
+ super message, 154
19
+ end
20
+ end
21
+
22
+ class AliasNotFoundException < Exception
23
+ def initialize(message="Alias not found")
24
+ super message, 156
25
+ end
26
+ end
27
+
28
+ class MultipleCartridgesException < Exception
29
+ def initialize(message="Multiple cartridge found")
30
+ super message, 155
31
+ end
32
+ end
33
+
34
+ class EnvironmentVariableNotFoundException < Exception
35
+ def initialize(message="Environment variable not found")
36
+ super message, 157
37
+ end
38
+ end
39
+
40
+ class EnvironmentVariablesNotSupportedException < Exception
41
+ def initialize(message="Server does not support environment variables")
42
+ super message, 158
43
+ end
44
+ end
45
+
46
+ class EnvironmentVariableNotProvidedException < Exception
47
+ def initialize(message="Environment variable not provided")
48
+ super message, 159
49
+ end
50
+ end
51
+
52
+ class JenkinsNotInstalledOnServer < Exception
53
+ def initialize(message="There is no installed cartridge that exposes Jenkins")
54
+ super message, 160
55
+ end
56
+ end
57
+
58
+ class KeyNotFoundException < Exception
59
+ def initialize(message="SSHKey not found")
60
+ super message, 118
61
+ end
62
+ end
63
+
64
+ class GitException < Exception
65
+ def initialize(message="Git returned an error")
66
+ super message, 216
67
+ end
68
+ end
69
+
70
+ class GitPermissionDenied < GitException; end
71
+ class GitDirectoryExists < GitException; end
72
+
73
+ class DeprecatedError < RuntimeError; end
74
+
75
+ class KeyFileNotExistentException < Exception
76
+ def initialize(message="SSH Key file not found")
77
+ super message, 128
78
+ end
79
+ end
80
+
81
+ class KeyFileAccessDeniedException < Exception
82
+ def initialize(message = "Insufficient acces to SSH Key file")
83
+ super message, 128
84
+ end
85
+ end
86
+
87
+ class KeyDataInvalidException < Exception
88
+ def initialize(message = "SSH Key file contains invalid data")
89
+ super message, 128
90
+ end
91
+ end
92
+
93
+ class PermissionDeniedException < Exception
94
+ def initialize(message="Permission denied")
95
+ super message, 129
96
+ end
97
+ end
98
+
99
+ class NoPortsToForwardException < Exception
100
+ def initialize(message="No available ports to forward")
101
+ super message, 102
102
+ end
103
+ end
104
+
105
+ class PortForwardFailedException < Exception
106
+ def initialize(message="Port forward failed")
107
+ super message, 1
108
+ end
109
+ end
110
+
111
+ class SnapshotSaveException < Exception
112
+ def initialize(message="Error trying to save snapshot")
113
+ super message, 130
114
+ end
115
+ end
116
+
117
+ class SnapshotRestoreException < Exception
118
+ def initialize(message="Error trying to restore snapshot")
119
+ super message, 130
120
+ end
121
+ end
122
+
123
+ class DeploymentNotFoundException < Exception
124
+ def initialize(message="Deployment not found")
125
+ super message, 131
126
+ end
127
+ end
128
+
129
+ class DeploymentsNotSupportedException < Exception
130
+ def initialize(message="The server does not support deployments")
131
+ super message, 132
132
+ end
133
+ end
134
+
135
+ class MissingScalingValueException < Exception
136
+ def initialize(message="Must provide either a min or max value for scaling")
137
+ super message
138
+ end
139
+ end
140
+
141
+ class CartridgeNotScalableException < Exception
142
+ def initialize(message="Cartridge is not scalable")
143
+ super message
144
+ end
145
+ end
146
+
147
+ class ConnectionFailed < Exception
148
+ end
149
+
150
+ class SSHAuthenticationFailed < Exception
151
+ def initialize(host, user)
152
+ super "Authentication to server #{host} with user #{user} failed"
153
+ end
154
+ end
155
+
156
+ class SSHConnectionRefused < ConnectionFailed
157
+ def initialize(host, user)
158
+ super "The server #{host} refused a connection with user #{user}. The application may be unavailable.", 1
159
+ end
160
+ end
161
+
162
+ class SSHCommandFailed < Exception
163
+ def initialize(exit_status, message=nil)
164
+ super message || "SSH command finished with exit status = #{exit_status}", 133
165
+ end
166
+ end
167
+
168
+ class AdditionalStorageArgumentsException < Exception
169
+ def initialize(message="Only one storage action can be performed at a time.")
170
+ super message, 1
171
+ end
172
+ end
173
+
174
+ class AdditionalStorageValueException < Exception
175
+ def initialize(message="The amount format must be a number, optionally followed by 'GB' (ex.: 5GB)")
176
+ super message, 1
177
+ end
178
+ end
179
+
180
+ class AdditionalStorageRemoveException < Exception
181
+ def initialize(message="The amount of additional storage to be removed exceeds the total amount in use. Add the -f flag to override.")
182
+ super message, 1
183
+ end
184
+ end
185
+
186
+ class ChangeMembersOnResourceNotSupported < Exception
187
+ def initialize(message="You can only add or remove members on a domain.")
188
+ super message, 1
189
+ end
190
+ end
191
+
192
+ class MembersNotSupported < Exception
193
+ def initialize(message="The server does not support adding or removing members.")
194
+ super message, 1
195
+ end
196
+ end
197
+
198
+ class UnsupportedError < Exception
199
+ def initialize(message="This operation is not supported by the server.")
200
+ super message, 1
201
+ end
202
+ end
203
+ class NoPerGearOperations < UnsupportedError
204
+ def initialize
205
+ super "The server does not support operations on individual gears."
206
+ end
207
+ end
208
+ class ServerAPINotSupportedException < UnsupportedError
209
+ def initialize(min_version, current_version)
210
+ super "The server does not support this command (requires #{min_version}, found #{current_version})."
211
+ end
212
+ end
213
+ class OperationNotSupportedException < UnsupportedError; end
214
+
215
+ class InvalidURIException < Exception
216
+ def initialize(uri)
217
+ super "Invalid URI specified: #{uri}"
218
+ end
219
+ end
220
+
221
+ class InvalidSSHExecutableException < Exception
222
+ def initialize(message="Invalid or missing SSH executable")
223
+ super message
224
+ end
225
+ end
226
+
227
+ class NoDomainsForUser < Exception
228
+ def initialize(message="In order to deploy applications, you must create a domain with 'pbox setup' or 'pbox create-domain'.")
229
+ super message, 1
230
+ end
231
+ end
232
+ end