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,20 @@
1
+ require 'rhc/commands/base'
2
+
3
+ module RHC::Commands
4
+ class Apps < Base
5
+ summary "List all your applications"
6
+ description "Display the list of applications that you own. Includes information about each application."
7
+ def run
8
+ applications = rest_client.applications(:include => :cartridges).sort
9
+
10
+ info "In order to deploy applications, you must create a domain with 'pbox setup' or 'pbox create-domain'." and return 1 if applications.empty? && rest_client.domains.empty?
11
+
12
+ applications.each{ |a| display_app(a, a.cartridges) }.blank? and
13
+ info "No applications. Use 'pbox create-app'." and
14
+ return 1
15
+
16
+ success "You have #{applications.length} applications"
17
+ 0
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,96 @@
1
+ module RHC::Commands
2
+ class Authorization < Base
3
+
4
+ summary "Show the authorization tokens for your account"
5
+ description <<-DESC
6
+ Shows the full list of authorization tokens on your account. You
7
+ can add, edit, or delete authorizations with subcommands.
8
+
9
+ An authorization token grants access to the ProtonBox REST API with
10
+ a set of privileges called 'scopes' for a limited time. You can
11
+ add an optional note to each authorization token to assist you in
12
+ remembering what is available.
13
+ DESC
14
+ alias_action 'authorizations', :root_command => true
15
+ default_action :list
16
+ def list
17
+ rest_client.authorizations.each{ |auth| paragraph{ display_authorization(auth, token_for_user) } } or info "No authorizations"
18
+
19
+ 0
20
+ end
21
+
22
+ option "--scopes SCOPES", "A comma delimited list of scopes (e.g. 'scope1,scope2')"
23
+ option "--note NOTE", "A description of this authorization (optional)"
24
+ option "--expires-in SECONDS", "The number of seconds before this authorization expires (optional)"
25
+ summary "Add an authorization to your account"
26
+ syntax "--scopes SCOPES [--note NOTE] [--expires-in SECONDS]"
27
+ description <<-DESC
28
+ Add an authorization to your account. An authorization token grants
29
+ access to the ProtonBox REST API with a set of privileges called 'scopes'
30
+ for a limited time. You can add an optional note to each authorization
31
+ token to assist you in remembering what is available.
32
+
33
+ To view the list of scopes supported by this server, run this command
34
+ without any options.
35
+
36
+ You may pass multiple scopes to the --scopes option inside of double
37
+ quotes (--scopes \"scope1 scope2\") or by separating them with commas
38
+ (--scopes scope1,scope2).
39
+
40
+ The server will enforce a maximum and default expiration that may
41
+ differ for each scope. If you request an expiration longer than the
42
+ server maximum, you will be given the default value.
43
+ DESC
44
+ def add
45
+ unless options.scopes
46
+ say "When adding an authorization, you must specify which permissions clients will have."
47
+ scope_help
48
+ say "Run 'pbox authorization add --help' to see more options"
49
+ return 0
50
+ end
51
+
52
+ say "Adding authorization ... "
53
+ auth = rest_client.add_authorization(:scope => options.scopes, :note => options.note, :expires_in => options.expires_in)
54
+ success "done"
55
+ paragraph{ display_authorization(auth) }
56
+
57
+ 0
58
+ end
59
+
60
+ summary "Delete one or more authorization tokens"
61
+ syntax "<token_or_id> [...<token_or_id>]"
62
+ description <<-DESC
63
+ Delete one or more of the authorization tokens associated with
64
+ your account. After deletion, any clients using the token will
65
+ no longer have access to ProtonBox and will need to reauthenticate.
66
+ DESC
67
+ argument :auth_token, "The token you wish to delete", ['--auth-token TOKEN'], :type => :list
68
+ def delete(tokens)
69
+ raise ArgumentError, "You must specify one or more tokens to delete" if tokens.blank?
70
+ say "Deleting authorization ... "
71
+ tokens.each{ |token| rest_client.delete_authorization(token) }
72
+ success "done"
73
+ 0
74
+ end
75
+
76
+ summary "Delete all authorization tokens from your account"
77
+ description <<-DESC
78
+ Delete all the authorization tokens associated with your account.
79
+ After deletion, any clients using those tokens will need to
80
+ reauthenticate.
81
+ DESC
82
+ def delete_all
83
+ say "Deleting all authorizations ... "
84
+ rest_client.delete_authorizations
85
+ success "done"
86
+ 0
87
+ end
88
+
89
+ protected
90
+ def scope_help
91
+ descriptions = rest_client.authorization_scope_list
92
+ paragraph{ say table(descriptions, :header => ['Scope', 'Description']) }
93
+ paragraph{ say "You may pass multiple scopes to the --scopes option inside of double quotes (--scopes \"scope1 scope2\") or by separating them with commas (--scopes scope1,scope2)." }
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,174 @@
1
+ require 'commander'
2
+ require 'commander/delegates'
3
+ require 'rhc/helpers'
4
+ require 'rhc/wizard'
5
+ require 'rhc/config'
6
+ require 'rhc/commands'
7
+ require 'rhc/exceptions'
8
+ require 'rhc/context_helper'
9
+
10
+ class RHC::Commands::Base
11
+
12
+ attr_writer :options, :config
13
+
14
+ def initialize(options=Commander::Command::Options.new,
15
+ config=RHC::Config.new)
16
+ @options, @config = options, config
17
+ end
18
+
19
+ protected
20
+ include RHC::Helpers
21
+ include RHC::ContextHelpers
22
+
23
+ attr_reader :options, :config
24
+
25
+ # Return a client object capable of making calls
26
+ # to the ProtonBox API that transforms intent
27
+ # and options, to remote calls, and then handle
28
+ # the output (or failures) into exceptions and
29
+ # formatted object output. Most interactions
30
+ # should be through this call pattern.
31
+ def rest_client(opts={})
32
+ @rest_client ||= begin
33
+ auth = RHC::Auth::Basic.new(options)
34
+ auth = RHC::Auth::Token.new(options, auth, token_store) if (options.use_authorization_tokens || options.token) && !(options.pblogin && options.password)
35
+ debug "Authenticating with #{auth.class}"
36
+ client_from_options(:auth => auth)
37
+ end
38
+
39
+ if opts[:min_api] && opts[:min_api].to_f > @rest_client.api_version_negotiated.to_f
40
+ raise RHC::ServerAPINotSupportedException.new(opts[:min_api], @rest_client.api_version_negotiated)
41
+ end
42
+
43
+ @rest_client
44
+ end
45
+
46
+ def token_store
47
+ @token_store ||= RHC::Auth::TokenStore.new(config.home_conf_path)
48
+ end
49
+
50
+ def help(*args)
51
+ raise ArgumentError, "Please specify an action to take"
52
+ end
53
+
54
+ class InvalidCommand < StandardError ; end
55
+
56
+ def self.method_added(method)
57
+ return if self == RHC::Commands::Base
58
+ return if private_method_defined? method
59
+ return if protected_method_defined? method
60
+
61
+ prefix = self.object_name
62
+ method_name = method.to_s == 'run' ? nil : method.to_s.gsub("_", "-")
63
+ name = [prefix, method_name].compact
64
+ raise InvalidCommand, "Either object_name must be set or a non default method defined" if name.empty?
65
+
66
+ aliases.each{ |a| a[:action].unshift(prefix) unless a[:root_command] } if prefix
67
+
68
+ RHC::Commands.add((@options || {}).merge({
69
+ :name => name,
70
+ :class => self,
71
+ :method => method
72
+ }));
73
+
74
+ @options = nil
75
+ end
76
+
77
+ def self.object_name(value=nil)
78
+ @object_name ||= begin
79
+ value ||= if self.name && !self.name.empty?
80
+ self.name.split('::').last
81
+ end
82
+ value.to_s.split(/(?=[A-Z])/).join('-').downcase if value
83
+ end
84
+ end
85
+
86
+ def self.description(*args)
87
+ o = args.join(' ')
88
+ options[:description] = o.strip_heredoc
89
+ end
90
+ def self.summary(value)
91
+ options[:summary] = value
92
+ end
93
+ def self.syntax(value)
94
+ options[:syntax] = value
95
+ end
96
+ #def self.deprecated(msg)
97
+ # options[:deprecated] = msg
98
+ #end
99
+ def self.suppress_wizard
100
+ @suppress_wizard = true
101
+ end
102
+
103
+ def self.suppress_wizard?
104
+ @suppress_wizard
105
+ end
106
+
107
+ #
108
+ # Provide an alias to the command. The alias will not be shown in help, but will
109
+ # be available in autocompletion and at execution time.
110
+ #
111
+ # Supported options:
112
+ #
113
+ # :deprecated - if true, a warning will be displayed when the command is executed
114
+ # :root_command - if true, do not prepend the object name to the command
115
+ #
116
+ def self.alias_action(action, options={})
117
+ options[:action] = action.is_a?(Array) ? action : action.to_s.split(' ')
118
+ aliases << options
119
+ end
120
+
121
+ def self.option(switches, description, options={})
122
+ options_metadata << {:switches => switches,
123
+ :description => description,
124
+ :required => options[:required],
125
+ :covered_by => options[:covered_by],
126
+ :deprecated => options[:deprecated],
127
+ :type => options[:type],
128
+ :hide => options[:hide],
129
+ :default => options[:default],
130
+ }
131
+ end
132
+
133
+ def self.argument(name, description, switches=[], options={})
134
+ arg_type = options[:type]
135
+
136
+ option_symbol = Commander::Runner.switch_to_sym(switches.last)
137
+ args_metadata << {:name => name,
138
+ :description => description,
139
+ :switches => switches,
140
+ :option_symbol => option_symbol,
141
+ :covered_by => options[:covered_by],
142
+ :optional => options[:optional],
143
+ :default => options[:default],
144
+ :allow_nil => options[:allow_nil],
145
+ :hide => options[:hide],
146
+ :type => arg_type}
147
+ end
148
+
149
+ def self.default_action(action)
150
+ options[:default] = action unless action == :help
151
+ name = self.object_name
152
+ raise InvalidCommand, "object_name must be set" if name.empty?
153
+
154
+ RHC::Commands.add((@options || {}).merge({
155
+ :name => name,
156
+ :class => self,
157
+ :method => options[:default]
158
+ }));
159
+ end
160
+
161
+ private
162
+ def self.options_metadata
163
+ options[:options] ||= []
164
+ end
165
+ def self.args_metadata
166
+ options[:args] ||= []
167
+ end
168
+ def self.aliases
169
+ options[:aliases] ||= []
170
+ end
171
+ def self.options
172
+ @options ||= {}
173
+ end
174
+ end
@@ -0,0 +1,326 @@
1
+ require 'rhc/commands/base'
2
+ require 'rhc/cartridge_helpers'
3
+
4
+ module RHC::Commands
5
+ class Cartridge < Base
6
+ summary "Manage your application cartridges"
7
+ syntax "<action>"
8
+ description <<-DESC
9
+ Cartridges add functionality to ProtonBox applications. Each application
10
+ has one web cartridge to listen for HTTP requests, and any number
11
+ of addon cartridges. Addons may include databases like MySQL and Mongo,
12
+ administrative tools like phpMyAdmin, or build clients like Jenkins.
13
+
14
+ Most cartridges that listen for incoming network traffic are placed on
15
+ one or more gears (a small server instance). Other cartridges may be
16
+ available across all of the gears of an application to listen for changes
17
+ (like Jenkins) or provide environment variables.
18
+
19
+ Use the 'cartridges' command to see a list of all available cartridges.
20
+ Add a new cartridge to your application with 'add-cartridge'. ProtonBox
21
+ also supports downloading cartridges - pass a URL in place of the cartridge
22
+ name and we'll download and install that cartridge into your app. Keep
23
+ in mind that these cartridges receive no security updates. Note that
24
+ not all ProtonBox servers allow downloaded cartridges.
25
+
26
+ For scalable applications, use the 'cartridge-scale' command on the web
27
+ cartridge to set the minimum and maximum scale.
28
+
29
+ Commands that affect a cartridge within an application will affect all
30
+ gears the cartridge is installed to.
31
+ DESC
32
+ default_action :help
33
+
34
+ summary "List available cartridges"
35
+ syntax ''
36
+ option ["-v", "--verbose"], "Display more details about each cartridge"
37
+ alias_action :"app cartridge list", :root_command => true, :deprecated => true
38
+ alias_action :"cartridges", :root_command => true
39
+ def list
40
+ carts = rest_client.cartridges.sort_by{ |c| "#{c.type == 'standalone' && 1}_#{c.tags.include?('experimental') ? 1 : 0}_#{(c.display_name || c.name).downcase}" }
41
+
42
+ pager
43
+
44
+ if options.verbose
45
+ carts.each do |c|
46
+ paragraph do
47
+ name = c.name
48
+ name += '*' if c.usage_rate?
49
+ name = c.display_name != c.name && "#{color(c.display_name, :cyan)} [#{name}]" || name
50
+ tags = c.tags - RHC::Rest::Cartridge::HIDDEN_TAGS
51
+ say header([name, "(#{c.only_in_existing? ? 'addon' : 'web'})"])
52
+ say c.description
53
+ paragraph{ say "Tagged with: #{tags.sort.join(', ')}" } if tags.present?
54
+ paragraph{ say format_usage_message(c) } if c.usage_rate?
55
+ end
56
+ end
57
+ else
58
+ say table(carts.collect do |c|
59
+ [c.usage_rate? ? "#{c.name} (*)" : c.name,
60
+ c.display_name,
61
+ c.only_in_existing? ? 'addon' : 'web']
62
+ end)
63
+ end
64
+
65
+ paragraph{ say "Note: Web cartridges can only be added to new applications." }
66
+ paragraph{ say "(*) denotes a cartridge with additional usage costs." } if carts.any? { |c| c.usage_rate? }
67
+
68
+ 0
69
+ end
70
+
71
+ summary "Add a cartridge to your application"
72
+ syntax "<cartridge_type> [--namespace NAME] [--app NAME]"
73
+ takes_application
74
+ option ["-e", "--env VARIABLE=VALUE"], "Environment variable(s) to be set on this cartridge, or path to a file containing environment variables", :type => :list
75
+ option ["-g", "--gear-size SIZE"], "Gear size controls how much memory and CPU your cartridge can use"
76
+ argument :cart_type, "The type of the cartridge you are adding (run 'pbox cartridge list' to obtain a list of available cartridges)", ["-c", "--cartridge cart_type"]
77
+ alias_action :"app cartridge add", :root_command => true, :deprecated => true
78
+ def add(cart_type)
79
+ cart = check_cartridges(cart_type, :from => not_standalone_cartridges).first
80
+
81
+ say "Adding #{cart.short_name} to application '#{options.app}' ... "
82
+
83
+ say format_usage_message(cart) if cart.usage_rate?
84
+
85
+ rest_app = find_app(:include => :cartridges)
86
+
87
+ supports_env_vars = rest_app.supports_add_cartridge_with_env_vars?
88
+ supports_gear_size = rest_app.supports_add_cartridge_with_gear_size?
89
+
90
+ cart.environment_variables = collect_env_vars(options.env).map { |item| item.to_hash } if options.env && supports_env_vars
91
+ cart.gear_size = options.gear_size if options.gear_size && supports_gear_size
92
+
93
+ rest_cartridge = rest_app.add_cartridge(cart)
94
+
95
+ success "done"
96
+
97
+ rest_cartridge.environment_variables = cart.environment_variables if cart.environment_variables.present?
98
+
99
+ paragraph{ display_cart(rest_cartridge) }
100
+ paragraph{ say "Use 'pbox env --help' to manage environment variable(s) on this cartridge and application." } if cart.environment_variables.present?
101
+ paragraph{ warn "Server does not support environment variables." if options.env && !supports_env_vars }
102
+ paragraph{ warn "Server does not support gear sizes for cartridges." if options.gear_size && !supports_gear_size }
103
+ paragraph{ rest_cartridge.messages.each { |msg| success msg } }
104
+
105
+ 0
106
+ end
107
+
108
+ summary "Show useful information about a cartridge"
109
+ syntax "<cartridge> [--namespace NAME] [--app NAME]"
110
+ takes_application
111
+ argument :cartridge, "The name of the cartridge", ["-c", "--cartridge cart_type"]
112
+ def show(cartridge)
113
+ rest_app = find_app(:include => :cartridges)
114
+ rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
115
+
116
+ display_cart(rest_cartridge)
117
+
118
+ 0
119
+ end
120
+
121
+ summary "Remove a cartridge from your application"
122
+ syntax "<cartridge> [--namespace NAME] [--app NAME]"
123
+ argument :cartridge, "The name of the cartridge you are removing", ["-c", "--cartridge cartridge"]
124
+ takes_application
125
+ option ["--confirm"], "Pass to confirm removing the cartridge"
126
+ alias_action :"app cartridge remove", :root_command => true, :deprecated => true
127
+ def remove(cartridge)
128
+ rest_app = find_app(:include => :cartridges)
129
+ rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
130
+
131
+ confirm_action "Removing a cartridge is a destructive operation that may result in loss of data associated with the cartridge.\n\nAre you sure you wish to remove #{rest_cartridge.name} from '#{rest_app.name}'?"
132
+
133
+ say "Removing #{rest_cartridge.name} from '#{rest_app.name}' ... "
134
+ rest_cartridge.destroy
135
+ success "removed"
136
+
137
+ paragraph{ rest_cartridge.messages.each { |msg| success msg } }
138
+
139
+ 0
140
+ end
141
+
142
+ summary "Start a cartridge"
143
+ syntax "<cartridge> [--namespace NAME] [--app NAME]"
144
+ argument :cart_type, "The name of the cartridge you are stopping", ["-c", "--cartridge cartridge"]
145
+ takes_application
146
+ alias_action :"app cartridge start", :root_command => true, :deprecated => true
147
+ def start(cartridge)
148
+ cartridge_action(cartridge, :start, 'Starting %s ... ')
149
+ 0
150
+ end
151
+
152
+ summary "Stop a cartridge"
153
+ syntax "<cartridge> [--namespace NAME] [--app NAME]"
154
+ argument :cart_type, "The name of the cartridge you are stopping", ["-c", "--cartridge cartridge"]
155
+ takes_application
156
+ alias_action :"app cartridge stop", :root_command => true, :deprecated => true
157
+ def stop(cartridge)
158
+ cartridge_action(cartridge, :stop, 'Stopping %s ... ')
159
+ 0
160
+ end
161
+
162
+ summary "Restart a cartridge"
163
+ syntax "<cartridge_type> [--namespace NAME] [--app NAME]"
164
+ argument :cart_type, "The name of the cartridge you are restarting", ["-c", "--cartridge cartridge"]
165
+ takes_application
166
+ alias_action :"app cartridge restart", :root_command => true, :deprecated => true
167
+ def restart(cartridge)
168
+ cartridge_action(cartridge, :restart, 'Restarting %s ... ')
169
+ 0
170
+ end
171
+
172
+ summary "Get current the status of a cartridge"
173
+ syntax "<cartridge> [--namespace NAME] [--app NAME]"
174
+ argument :cart_type, "The name of the cartridge you are getting the status of", ["-c", "--cartridge cartridge"]
175
+ takes_application
176
+ alias_action :"app cartridge status", :root_command => true, :deprecated => true
177
+ def status(cartridge)
178
+ rest_app = find_app(:include => :cartridges)
179
+ rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
180
+ results { rest_cartridge.status.each{ |msg| say msg['message'] } }
181
+ 0
182
+ end
183
+
184
+ summary "Reload the cartridge's configuration"
185
+ syntax "<cartridge> [--namespace NAME] [--app NAME]"
186
+ argument :cart_type, "The name of the cartridge you are reloading", ["-c", "--cartridge cartridge"]
187
+ takes_application
188
+ alias_action :"app cartridge reload", :root_command => true, :deprecated => true
189
+ def reload(cartridge)
190
+ cartridge_action(cartridge, :reload, 'Reloading %s ... ')
191
+ 0
192
+ end
193
+
194
+ summary "Set the scale range for a cartridge"
195
+ description <<-DESC
196
+ Each cartridge capable of scaling may have a minimum and a maximum set, although within that range
197
+ each type of cartridge may make decisions to autoscale. Web cartridges will scale based on incoming
198
+ request traffic - see http://devcenter.protonbox.com/scaling for more information. Non web
199
+ cartridges such as databases may require specific increments of scaling (1, 3, 5) in order to
200
+ properly function. Please consult the cartridge documentation for more on specifics of scaling.
201
+
202
+ Set both values the same to guarantee a scale value. You may pecify both values with the argument
203
+ 'multiplier' or use '--min' and '--max' independently.
204
+
205
+ Scaling may take several minutes or more if the server must provision multiple gears. Your operation
206
+ will continue in the background if your client is disconnected.
207
+ DESC
208
+ syntax "<cartridge> [multiplier] [--namespace NAME] [--app NAME] [--min min] [--max max]"
209
+ argument :cartridge, "The name of the cartridge you are scaling", ["-c", "--cartridge cartridge"]
210
+ argument :multiplier, "The number of instances of this cartridge you need", [], :optional => true, :hide => true
211
+ takes_application
212
+ option ["--min min", Integer], "Minimum scaling value"
213
+ option ["--max max", Integer], "Maximum scaling value"
214
+ def scale(cartridge, multiplier)
215
+ options.default(:min => Integer(multiplier), :max => Integer(multiplier)) if multiplier rescue raise ArgumentError, "Multiplier must be a positive integer."
216
+
217
+ raise RHC::MissingScalingValueException unless options.min || options.max
218
+
219
+ rest_app = find_app(:include => :cartridges)
220
+ rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
221
+
222
+ raise RHC::CartridgeNotScalableException unless rest_cartridge.scalable?
223
+
224
+ warn "This operation will run until the application is at the minimum scale and may take several minutes."
225
+ say "Setting scale range for #{rest_cartridge.name} ... "
226
+
227
+ cart = rest_cartridge.set_scales({
228
+ :scales_from => options.min,
229
+ :scales_to => options.max
230
+ })
231
+
232
+ success "done"
233
+ paragraph{ display_cart(cart) }
234
+
235
+ 0
236
+ rescue RHC::Rest::TimeoutException => e
237
+ raise unless e.on_receive?
238
+ info "The server has closed the connection, but your scaling operation is still in progress. Please check the status of your operation via 'pbox show-app'."
239
+ 1
240
+ end
241
+
242
+ summary 'View/manipulate storage on a cartridge'
243
+ syntax '<cartridge> -a app [--show] [--add|--remove|--set amount] [--namespace NAME]'
244
+ argument :cart_type, "The name of the cartridge", ["-c", "--cartridge cart_type"], :type => :list
245
+ takes_application
246
+ option ["--show"], "Show the current base and additional storage capacity"
247
+ option ["--add amount"], "Add the indicated amount to the additional storage capacity"
248
+ option ["--remove amount"], "Remove the indicated amount from the additional storage capacity"
249
+ option ["--set amount"], "Set the specified amount of additional storage capacity"
250
+ option ["-f", "--force"], "Force the action"
251
+ def storage(cartridge)
252
+ cartridges = Array(cartridge)
253
+ rest_client(:min_api => 1.3).api
254
+ rest_app = find_app(:include => :cartridges)
255
+
256
+ # Pull the desired action
257
+ #
258
+ actions = options.__hash__.keys & [:show, :add, :remove, :set]
259
+
260
+ # Ensure that only zero or one action was selected
261
+ raise RHC::AdditionalStorageArgumentsException if actions.length > 1
262
+
263
+ operation = actions.first || :show
264
+ amount = options.__hash__[operation]
265
+
266
+ # Perform a storage change action if requested
267
+ if operation == :show
268
+ results do
269
+ if cartridges.length == 0
270
+ display_cart_storage_list rest_app.cartridges
271
+ else
272
+ check_cartridges(cartridge, :from => rest_app.cartridges).each do |cart|
273
+ display_cart_storage_info cart, cart.display_name
274
+ end
275
+ end
276
+ end
277
+ else
278
+ raise RHC::MultipleCartridgesException,
279
+ 'Exactly one cartridge must be specified for this operation' if cartridges.length != 1
280
+
281
+ rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
282
+ amount = amount.match(/^(\d+)(GB)?$/i)
283
+ raise RHC::AdditionalStorageValueException if amount.nil?
284
+
285
+ # If the amount is specified, find the regex match and convert to a number
286
+ amount = amount[1].to_i
287
+ total_amount = rest_cartridge.additional_gear_storage
288
+
289
+ if operation == :add
290
+ total_amount += amount
291
+ elsif operation == :remove
292
+ if amount > total_amount && !options.force
293
+ raise RHC::AdditionalStorageRemoveException
294
+ else
295
+ total_amount = [total_amount - amount, 0].max
296
+ end
297
+ else
298
+ total_amount = amount
299
+ end
300
+
301
+ say "Set storage on cartridge ... "
302
+ cart = rest_cartridge.set_storage(:additional_gear_storage => total_amount)
303
+ success "set to #{total_amount}GB"
304
+ paragraph{ display_cart_storage_info cart }
305
+ end
306
+
307
+ 0
308
+ end
309
+
310
+ private
311
+ include RHC::CartridgeHelpers
312
+
313
+ def cartridge_action(cartridge, action, message=nil)
314
+ rest_app = find_app(:include => :cartridges)
315
+ rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
316
+ say message % [rest_cartridge.name] if message
317
+ result = rest_cartridge.send(action)
318
+ resp = [result, rest_cartridge, rest_app]
319
+ if message
320
+ success "done"
321
+ result.messages.each{ |s| paragraph{ say s } }
322
+ end
323
+ resp
324
+ end
325
+ end
326
+ end