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,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