rhc 0.98.16 → 1.0.4

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 (94) hide show
  1. data/bin/rhc +7 -49
  2. data/bin/rhc-app +14 -3
  3. data/bin/rhc-chk +16 -16
  4. data/bin/rhc-create-app +2 -0
  5. data/bin/rhc-create-domain +1 -2
  6. data/bin/rhc-ctl-app +12 -3
  7. data/bin/rhc-ctl-domain +1 -2
  8. data/bin/rhc-domain +1 -2
  9. data/bin/rhc-domain-info +1 -2
  10. data/bin/rhc-port-forward +1 -2
  11. data/bin/rhc-snapshot +3 -0
  12. data/bin/rhc-sshkey +1 -2
  13. data/bin/rhc-tail-files +1 -1
  14. data/bin/rhc-user-info +1 -3
  15. data/features/application.feature +4 -1
  16. data/features/domain.feature +0 -4
  17. data/features/geared_application.feature +11 -0
  18. data/features/lib/rhc_helper/app.rb +16 -5
  19. data/features/lib/rhc_helper/cartridge.rb +25 -9
  20. data/features/lib/rhc_helper/commandify.rb +34 -7
  21. data/features/lib/rhc_helper/domain.rb +2 -2
  22. data/features/lib/rhc_helper/httpify.rb +24 -14
  23. data/features/lib/rhc_helper/persistable.rb +1 -1
  24. data/features/lib/rhc_helper/sshkey.rb +11 -7
  25. data/features/lib/rhc_helper.rb +5 -3
  26. data/features/multiple_cartridge.feature +1 -1
  27. data/features/scaled_application.feature +48 -0
  28. data/features/sshkey.feature +37 -31
  29. data/features/step_definitions/application_steps.rb +18 -7
  30. data/features/step_definitions/cartridge_steps.rb +29 -3
  31. data/features/step_definitions/domain_steps.rb +2 -2
  32. data/features/step_definitions/sshkey_steps.rb +34 -34
  33. data/features/support/assumptions.rb +21 -9
  34. data/features/support/before_hooks.rb +24 -6
  35. data/features/support/env.rb +45 -19
  36. data/lib/rhc/cartridge_helper.rb +27 -0
  37. data/lib/rhc/cli.rb +1 -1
  38. data/lib/rhc/command_runner.rb +31 -3
  39. data/lib/rhc/commands/alias.rb +38 -0
  40. data/lib/rhc/commands/app.rb +478 -0
  41. data/lib/rhc/commands/base.rb +42 -12
  42. data/lib/rhc/commands/cartridge.rb +189 -0
  43. data/lib/rhc/commands/domain.rb +11 -49
  44. data/lib/rhc/commands/port-forward.rb +0 -1
  45. data/lib/rhc/commands/setup.rb +2 -1
  46. data/lib/rhc/commands/snapshot.rb +118 -0
  47. data/lib/rhc/commands/sshkey.rb +24 -38
  48. data/lib/rhc/commands/tail.rb +24 -0
  49. data/lib/rhc/commands/threaddump.rb +16 -0
  50. data/lib/rhc/commands.rb +33 -7
  51. data/lib/rhc/config.rb +28 -12
  52. data/lib/rhc/context_helper.rb +19 -5
  53. data/lib/rhc/core_ext.rb +86 -0
  54. data/lib/rhc/exceptions.rb +44 -0
  55. data/lib/rhc/git_helper.rb +59 -0
  56. data/lib/rhc/helpers.rb +86 -5
  57. data/lib/rhc/output_helpers.rb +213 -0
  58. data/lib/rhc/rest/application.rb +134 -67
  59. data/lib/rhc/rest/base.rb +48 -0
  60. data/lib/rhc/rest/cartridge.rb +40 -44
  61. data/lib/rhc/rest/client.rb +127 -59
  62. data/lib/rhc/rest/domain.rb +29 -39
  63. data/lib/rhc/rest/gear_group.rb +10 -0
  64. data/lib/rhc/rest/key.rb +8 -23
  65. data/lib/rhc/rest/user.rb +8 -24
  66. data/lib/rhc/rest.rb +22 -11
  67. data/lib/rhc/ssh_key_helpers.rb +47 -0
  68. data/lib/rhc/usage_templates/help.erb +0 -1
  69. data/lib/rhc/version.rb +3 -3
  70. data/lib/rhc/wizard.rb +123 -225
  71. data/lib/rhc-common.rb +43 -62
  72. data/spec/rest_spec_helper.rb +159 -36
  73. data/spec/rhc/cli_spec.rb +29 -1
  74. data/spec/rhc/command_spec.rb +32 -35
  75. data/spec/rhc/commands/alias_spec.rb +123 -0
  76. data/spec/rhc/commands/app_spec.rb +414 -0
  77. data/spec/rhc/commands/cartridge_spec.rb +342 -0
  78. data/spec/rhc/commands/domain_spec.rb +8 -8
  79. data/spec/rhc/commands/setup_spec.rb +17 -6
  80. data/spec/rhc/commands/snapshot_spec.rb +140 -0
  81. data/spec/rhc/commands/sshkey_spec.rb +26 -4
  82. data/spec/rhc/commands/tail_spec.rb +34 -0
  83. data/spec/rhc/commands/threaddump_spec.rb +83 -0
  84. data/spec/rhc/config_spec.rb +39 -13
  85. data/spec/rhc/context_spec.rb +51 -0
  86. data/spec/rhc/helpers_spec.rb +52 -12
  87. data/spec/rhc/rest_application_spec.rb +16 -3
  88. data/spec/rhc/rest_client_spec.rb +144 -36
  89. data/spec/rhc/rest_spec.rb +1 -1
  90. data/spec/rhc/wizard_spec.rb +133 -232
  91. data/spec/spec_helper.rb +4 -3
  92. metadata +56 -31
  93. data/features/support/ssh.sh +0 -2
  94. data/spec/rhc/common_spec.rb +0 -49
@@ -10,13 +10,12 @@ require 'rhc/context_helper'
10
10
  class RHC::Commands::Base
11
11
 
12
12
  attr_writer :options, :config
13
+ attr_reader :messages
13
14
 
14
15
  def initialize(options=Commander::Command::Options.new,
15
16
  config=nil)
16
17
  @options, @config = options, config
17
-
18
- # apply timeout here even though it isn't quite a global
19
- $rest_timeout = @options.timeout ? @options.timeout.to_i : nil
18
+ @messages = []
20
19
  end
21
20
 
22
21
  def validate_args_and_options(args_metadata, options_metadata, args)
@@ -24,7 +23,21 @@ class RHC::Commands::Base
24
23
  options_metadata.each do |option_meta|
25
24
  arg = option_meta[:arg]
26
25
 
26
+ # Check to see if we've provided a value for an option tagged as deprecated
27
+ if (!(val = @options.__hash__[arg]).nil? && dep_info = option_meta[:deprecated])
28
+ # Get the arg for the correct option and what the value should be
29
+ (correct_arg, default) = dep_info.values_at(:key, :value)
30
+ # Set the default value for the correct option to the passed value
31
+ ## Note: If this isn't triggered, then the original default will be honored
32
+ ## If the user specifies any value for the correct option, it will be used
33
+ options.default correct_arg => default
34
+ # Alert the users if they're using a deprecated option
35
+ (correct, incorrect) = [options_metadata.find{|x| x[:arg] == correct_arg },option_meta].flatten.map{|x| x[:switches].join(", ") }
36
+ deprecated_option(incorrect, correct)
37
+ end
38
+
27
39
  context_helper = option_meta[:context_helper]
40
+
28
41
  @options.__hash__[arg] = self.send(context_helper) if @options.__hash__[arg].nil? and context_helper
29
42
  raise ArgumentError.new("Missing required option '#{arg}'.") if option_meta[:required] and @options.__hash__[arg].nil?
30
43
  end
@@ -34,7 +47,7 @@ class RHC::Commands::Base
34
47
  fill_args = args.reverse
35
48
  args_metadata.each_with_index do |arg_meta, i|
36
49
  # check options
37
- value = @options.__hash__[arg_meta[:name]]
50
+ value = @options.__hash__[arg_meta[:option_symbol]] unless arg_meta[:option_symbol].nil?
38
51
  if value
39
52
  arg_slots[i] = value
40
53
  elsif arg_meta[:arg_type] == :list
@@ -87,12 +100,20 @@ class RHC::Commands::Base
87
100
  username = ask "To connect to #{openshift_server} enter your OpenShift login (email or Red Hat login id): "
88
101
  config.config_user(username)
89
102
  end
90
- password = RHC::Config.password || RHC::get_password
103
+ config.password = config.password || RHC::get_password
91
104
 
92
- RHC::Rest::Client.new(openshift_rest_node, username, password, @options.debug)
105
+ RHC::Rest::Client.new(openshift_rest_node, username, config.password, @options.debug)
93
106
  end
94
107
  end
95
108
 
109
+ def help(*args)
110
+ ac = Commander::Runner.instance.active_command
111
+ Commander::Runner.instance.command(:help).run(ac.name, *args)
112
+ end
113
+
114
+ def debug?
115
+ @options.debug
116
+ end
96
117
 
97
118
  class InvalidCommand < StandardError ; end
98
119
 
@@ -106,7 +127,7 @@ class RHC::Commands::Base
106
127
  return if private_method_defined? method
107
128
  return if protected_method_defined? method
108
129
 
109
- method_name = method.to_s == 'run' ? nil : method.to_s
130
+ method_name = method.to_s == 'run' ? nil : method.to_s.gsub("_", "-")
110
131
  name = [method_name]
111
132
  name.unshift(self.object_name).compact!
112
133
  raise InvalidCommand, "Either object_name must be set or a non default method defined" if name.empty?
@@ -115,6 +136,7 @@ class RHC::Commands::Base
115
136
  :class => self,
116
137
  :method => method
117
138
  }));
139
+
118
140
  @options = nil
119
141
  end
120
142
 
@@ -127,8 +149,8 @@ class RHC::Commands::Base
127
149
  end
128
150
  end
129
151
 
130
- def self.description(value)
131
- options[:description] = value
152
+ def self.description(*args)
153
+ options[:description] = args.join(' ')
132
154
  end
133
155
  def self.summary(value)
134
156
  options[:summary] = value
@@ -136,7 +158,9 @@ class RHC::Commands::Base
136
158
  def self.syntax(value)
137
159
  options[:syntax] = value
138
160
  end
139
-
161
+ def self.deprecated(msg)
162
+ options[:deprecated] = msg
163
+ end
140
164
  def self.suppress_wizard
141
165
  @suppress_wizard = true
142
166
  end
@@ -159,7 +183,8 @@ class RHC::Commands::Base
159
183
  options_metadata << {:switches => switches,
160
184
  :description => description,
161
185
  :context_helper => options[:context],
162
- :required => options[:required]
186
+ :required => options[:required],
187
+ :deprecated => options[:deprecated]
163
188
  }
164
189
  end
165
190
 
@@ -168,7 +193,12 @@ class RHC::Commands::Base
168
193
  raise ArgumentError("Only the last argument descriptor for an action can be a list") if arg_type == :list and list_argument_defined?
169
194
  list_argument_defined true if arg_type == :list
170
195
 
171
- args_metadata << {:name => name, :description => description, :switches => switches, :arg_type => arg_type}
196
+ option_symbol = Commander::Runner.switch_to_sym(switches.last)
197
+ args_metadata << {:name => name,
198
+ :description => description,
199
+ :switches => switches,
200
+ :option_symbol => option_symbol,
201
+ :arg_type => arg_type}
172
202
  end
173
203
 
174
204
  def self.default_action(action)
@@ -0,0 +1,189 @@
1
+ require 'rhc/commands/base'
2
+ require 'rhc/cartridge_helper'
3
+
4
+ module RHC::Commands
5
+ class Cartridge < Base
6
+ summary "Manage your application cartridges"
7
+ syntax "<action>"
8
+ alias_action :"app cartridge", :root_command => true, :deprecated => true
9
+ default_action :list
10
+
11
+ summary "List supported embedded cartridges"
12
+ alias_action :"app cartridge list", :root_command => true, :deprecated => true
13
+ def list
14
+ carts = rest_client.find_cartridges(:type => 'embedded').collect { |c| c.name }
15
+ results { say "#{carts.join(', ')}" }
16
+ 0
17
+ end
18
+
19
+ summary "Add a cartridge to your application"
20
+ syntax "<cartridge_type> [--namespace namespace] [--app app]"
21
+ option ["-n", "--namespace namespace"], "Namespace of the application you are adding the cartridge to", :context => :namespace_context, :required => true
22
+ option ["-a", "--app app"], "Application you are adding the cartridge to", :context => :app_context, :required => true
23
+ argument :cart_type, "The type of the cartridge you are adding (run 'rhc cartridge list' to obtain a list of available cartridges)", ["-c", "--cartridge cart_type"]
24
+ alias_action :"app cartridge add", :root_command => true, :deprecated => true
25
+ def add(cart_type)
26
+ cart = find_cartridge rest_client, cart_type
27
+
28
+ say "Adding '#{cart.name}' to application '#{options.app}'"
29
+
30
+ rest_domain = rest_client.find_domain(options.namespace)
31
+ rest_app = rest_domain.find_application(options.app)
32
+ rest_cartridge = rest_app.add_cartridge(cart.name)
33
+ say "Success"
34
+
35
+ display_cart(rest_cartridge,rest_cartridge.properties[:cart_data])
36
+
37
+ 0
38
+ end
39
+
40
+ summary "Show useful information about a cartridge"
41
+ syntax "<cartridge> [--namespace namespace] [--app app]"
42
+ option ["-n", "--namespace namespace"], "Namespace of the application you are adding the cartridge to", :context => :namespace_context, :required => true
43
+ option ["-a", "--app app"], "Application you are adding the cartridge to", :context => :app_context, :required => true
44
+ argument :cartridge, "The name of the cartridge", ["-c", "--cartridge cart_type"]
45
+ def show(cartridge)
46
+ rest_domain = rest_client.find_domain(options.namespace)
47
+ rest_app = rest_domain.find_application(options.app)
48
+ rest_cartridge = find_cartridge rest_app, cartridge, nil
49
+
50
+ display_cart(rest_cartridge,rest_cartridge.properties[:cart_data])
51
+
52
+ 0
53
+ end
54
+
55
+ summary "Remove a cartridge from your application"
56
+ syntax "<cartridge> [--namespace namespace] [--app app]"
57
+ argument :cartridge, "The name of the cartridge you are removing", ["-c", "--cartridge cartridge"]
58
+ option ["-n", "--namespace namespace"], "Namespace of the application you are removing the cartridge from", :context => :namespace_context, :required => true
59
+ option ["-a", "--app app"], "Application you are removing the cartridge from", :context => :app_context, :required => true
60
+ option ["--confirm"], "Safety switch - if this switch is not passed a warning is printed out and the cartridge will not be removed"
61
+ alias_action :"app cartridge remove", :root_command => true, :deprecated => true
62
+ def remove(cartridge)
63
+ unless options.confirm
64
+ results { say "Removing a cartridge is a destructive operation that may result in loss of data associated with the cartridge. You must pass the --confirm switch to this command in order to to remove the cartridge." }
65
+ return 1
66
+ end
67
+
68
+ rest_domain = rest_client.find_domain(options.namespace)
69
+ rest_app = rest_domain.find_application(options.app)
70
+ rest_cartridge = rest_app.find_cartridge cartridge, :type => "embedded"
71
+ rest_cartridge.destroy
72
+
73
+ results { say "Success: Cartridge '#{rest_cartridge.name}' removed from application '#{rest_app.name}'." }
74
+ 0
75
+ end
76
+
77
+ summary "Start a cartridge"
78
+ syntax "<cartridge> [--namespace namespace] [--app app]"
79
+ argument :cart_type, "The name of the cartridge you are stopping", ["-c", "--cartridge cartridge"]
80
+ option ["-n", "--namespace namespace"], "Namespace of the application the cartrdige belongs to", :context => :namespace_context, :required => true
81
+ option ["-a", "--app app"], "Application the cartridge", :context => :app_context, :required => true
82
+ alias_action :"app cartridge start", :root_command => true, :deprecated => true
83
+ def start(cartridge)
84
+ cartridge_action cartridge, :start
85
+
86
+ results { say "#{cartridge} started!" }
87
+ 0
88
+ end
89
+
90
+ summary "Stop a cartridge"
91
+ syntax "<cartridge> [--namespace namespace] [--app app]"
92
+ argument :cart_type, "The name of the cartridge you are stopping", ["-c", "--cartridge cartridge"]
93
+ option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
94
+ option ["-a", "--app app"], "Application you the cartridge belongs to", :context => :app_context, :required => true
95
+ alias_action :"app cartridge stop", :root_command => true, :deprecated => true
96
+ def stop(cartridge)
97
+ cartridge_action cartridge, :stop
98
+
99
+ results { say "#{cartridge} stopped!" }
100
+ 0
101
+ end
102
+
103
+ summary "Restart a cartridge"
104
+ syntax "<cartridge_type> [--namespace namespace] [--app app]"
105
+ argument :cart_type, "The name of the cartridge you are restarting", ["-c", "--cartridge cartridge"]
106
+ option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
107
+ option ["-a", "--app app"], "Application the cartridge belongs to", :context => :app_context, :required => true
108
+ alias_action :"app cartridge restart", :root_command => true, :deprecated => true
109
+ def restart(cartridge)
110
+ cartridge_action cartridge, :restart
111
+
112
+ results { say "#{cartridge} restarted!" }
113
+ 0
114
+ end
115
+
116
+ summary "Get current the status of a cartridge"
117
+ syntax "<cartridge> [--namespace namespace] [--app app]"
118
+ argument :cart_type, "The name of the cartridge you are getting the status of", ["-c", "--cartridge cartridge"]
119
+ option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
120
+ option ["-a", "--app app"], "Application the cartridge belongs to", :context => :app_context, :required => true
121
+ alias_action :"app cartridge status", :root_command => true, :deprecated => true
122
+ def status(cartridge)
123
+ rest_domain = rest_client.find_domain(options.namespace)
124
+ rest_app = rest_domain.find_application(options.app)
125
+ rest_cartridge = find_cartridge(rest_app, cartridge)
126
+ msgs = rest_cartridge.status
127
+ results {
128
+ msgs.each do |msg|
129
+ say msg['message']
130
+ end
131
+ }
132
+ 0
133
+ end
134
+
135
+ summary "Reload the cartridge's configuration"
136
+ syntax "<cartridge> [--namespace namespace] [--app app]"
137
+ argument :cart_type, "The name of the cartridge you are reloading", ["-c", "--cartridge cartridge"]
138
+ option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
139
+ option ["-a", "--app app"], "Application the cartridge belongs to", :context => :app_context, :required => true
140
+ alias_action :"app cartridge reload", :root_command => true, :deprecated => true
141
+ def reload(cartridge)
142
+ cartridge_action cartridge, :reload
143
+
144
+ results { say "#{cartridge} config reloaded!" }
145
+ 0
146
+ end
147
+
148
+ summary "Set the scaling range of a cartridge"
149
+ syntax "<cartridge> [--timeout timeout] [--namespace namespace] [--app app] [--min min] [--max max]"
150
+ argument :cart_type, "The name of the cartridge you are reloading", ["-c", "--cartridge cartridge"]
151
+ option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
152
+ option ["-a", "--app app"], "Application the cartridge belongs to", :context => :app_context, :required => true
153
+ option ["--timeout timeout"], "Timeout, in seconds, for the session"
154
+ option ["--min min", Integer], "Minimum scaling value"
155
+ option ["--max max", Integer], "Maximum scaling value"
156
+ def scale(cartridge)
157
+ raise RHC::MissingScalingValueException unless options.min || options.max
158
+
159
+ rest_domain = rest_client.find_domain(options.namespace)
160
+ rest_app = rest_domain.find_application(options.app)
161
+ rest_cartridge = find_cartridge rest_app, cartridge, nil
162
+
163
+ raise RHC::CartridgeNotScalableException unless rest_cartridge.scalable?
164
+
165
+ cart = rest_cartridge.set_scales({
166
+ :scales_from => options.min,
167
+ :scales_to => options.max
168
+ })
169
+
170
+ results do
171
+ say "Success: Scaling values updated"
172
+ display_cart(cart)
173
+ end
174
+
175
+ 0
176
+ end
177
+
178
+ private
179
+ include RHC::CartridgeHelpers
180
+
181
+ def cartridge_action(cartridge, action)
182
+ rest_domain = rest_client.find_domain(options.namespace)
183
+ rest_app = rest_domain.find_application(options.app)
184
+ rest_cartridge = find_cartridge rest_app, cartridge
185
+ result = rest_cartridge.send action
186
+ [result, rest_cartridge, rest_app, rest_domain]
187
+ end
188
+ end
189
+ end
@@ -7,9 +7,8 @@ module RHC::Commands
7
7
  default_action :show
8
8
 
9
9
  summary "Define a namespace for your applications to share."
10
- syntax "<namespace> [--timeout timeout]"
10
+ syntax "<namespace>"
11
11
  argument :namespace, "Namespace for your application(s) (alphanumeric)", ["-n", "--namespace namespace"]
12
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
13
12
  def create(namespace)
14
13
  paragraph { say "Creating domain with namespace '#{namespace}'" }
15
14
  rest_client.add_domain(namespace)
@@ -23,21 +22,16 @@ module RHC::Commands
23
22
  end
24
23
 
25
24
  summary "Change current namespace (will change application urls)"
26
- syntax "<namespace> [--timeout timeout]"
27
- argument :namespace, "Namespace to change", ["-n", "--namespace namespace"]
28
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
25
+ syntax "<old namespace> <new namespace>"
26
+ argument :old_namespace, "Old namespace to change", []
27
+ argument :new_namespace, "New namespace to change", ["-n", "--namespace namespace"]
29
28
  alias_action :alter
30
- def update(namespace)
31
- # TODO: Support multiple domains. Right now we assume one domain so
32
- # you don't have to send in the name of the domain you want to change
33
- # but in the future this will be manditory if you have more than one
34
- # domain. Figure out how to support overloading of commands
35
- domain = rest_client.domains
36
- raise RHC::DomainNotFoundException, "No domains are registered to the user #{config.username}. Please use 'rhc domain create' to create one." if domain.empty?
29
+ def update(old_namespace, new_namespace)
30
+ domain = rest_client.find_domain(old_namespace)
37
31
 
38
- say "Changing namespace '#{domain[0].id}' to '#{namespace}'..."
32
+ say "Changing namespace '#{domain.id}' to '#{new_namespace}'..."
39
33
 
40
- domain[0].update(namespace)
34
+ domain.update(new_namespace)
41
35
 
42
36
  results do
43
37
  say "Success!"
@@ -51,43 +45,12 @@ module RHC::Commands
51
45
  def show
52
46
  domain = rest_client.domains.first
53
47
 
54
- if domain
55
- paragraph do
56
- say "Applications in #{domain.id}:"
57
- apps = domain.applications
58
- if apps.length == 0
59
- say "No applications. You can use 'rhc app create' to create new applications."
60
- else
61
- apps.each_with_index do |a,i|
62
- carts = a.cartridges
63
- section(:top => (i == 0 ? 1 : 2)) do
64
- header "%s @ %s" % [a.name, a.app_url]
65
- say "Created: #{date(a.creation_time)}"
66
- #say " UUID: #{a.uuid}"
67
- say "Git URL: #{a.git_url}" if a.git_url
68
- say "Aliases: #{a.aliases.join(', ')}" if a.aliases and not a.aliases.empty?
69
- if carts.present?
70
- say "\nCartridges:"
71
- carts.each do |c|
72
- connection_url = c.property(:cart_data, :connection_url) || c.property(:cart_data, :job_url) || c.property(:cart_data, :monitoring_url)
73
- value = connection_url ? " - #{connection_url['value']}" : ""
74
- say " #{c.name}#{value}"
75
- end
76
- else
77
- say "Cartridges: none"
78
- end
79
- end
80
- end
81
- end
82
- end
83
- else
84
- say "No domain exists. You can use 'rhc domain create' to create a namespace for applications." unless domain
85
- end
48
+ display_domain(domain)
49
+
86
50
  0
87
51
  end
88
52
 
89
53
  summary "Run a status check on your domain"
90
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
91
54
  def status
92
55
  args = []
93
56
 
@@ -102,9 +65,8 @@ module RHC::Commands
102
65
  end
103
66
 
104
67
  summary "Deletes your domain."
105
- syntax "<namespace> [--timeout timeout]"
68
+ syntax "<namespace>"
106
69
  argument :namespace, "Namespace you wish to destroy", ["-n", "--namespace namespace"]
107
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
108
70
  alias_action :destroy
109
71
  def delete(namespace)
110
72
  domain = rest_client.find_domain namespace
@@ -9,7 +9,6 @@ module RHC::Commands
9
9
  summary "Forward remote ports to the workstation"
10
10
  option ["-n", "--namespace namespace"], "Namespace of the application you are port forwarding to", :context => :namespace_context, :required => true
11
11
  argument :app, "Application you are port forwarding to (required)", ["-a", "--app app"]
12
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
13
12
  def run(app)
14
13
 
15
14
  rest_domain = rest_client.find_domain options.namespace
@@ -8,7 +8,8 @@ module RHC::Commands
8
8
 
9
9
  summary "Easy to use wizard for getting started with OpenShift."
10
10
  def run
11
- RHC::RerunWizard.new(config).run ? 0 : 1
11
+ raise OptionParser::InvalidOption, "Setup can not be run with the --noprompt option" if options.noprompt
12
+ RHC::RerunWizard.new(config, options).run ? 0 : 1
12
13
  end
13
14
  end
14
15
  end
@@ -0,0 +1,118 @@
1
+ require 'rhc/commands/base'
2
+
3
+ module RHC::Commands
4
+ class Snapshot < Base
5
+ summary "Pull down application snapshot for a user."
6
+ syntax "<action>"
7
+ alias_action :"app snapshot", :root_command => true
8
+ default_action :help
9
+
10
+ summary "Pull down application snapshot for the specified application."
11
+ syntax "<application>"
12
+ option ["-n", "--namespace namespace"], "Namespace of the application you are saving a snapshot", :context => :namespace_context, :required => true
13
+ option ["-f", "--filepath filepath"], "Local path to save tarball (default: ./$APPNAME.tar.gz)"
14
+ argument :app, "Application you are saving a snapshot (required)", ["-a", "--app app"]
15
+ alias_action :"app snapshot save", :root_command => true, :deprecated => true
16
+ def save(app)
17
+ ssh_uri = URI.parse(rest_client.find_domain(options.namespace).find_application(app).ssh_url)
18
+ filename = options.filepath ? options.filepath : "#{app}.tar.gz"
19
+
20
+ ssh_cmd = "ssh #{ssh_uri.user}@#{ssh_uri.host} 'snapshot' > #{filename}"
21
+ debug ssh_cmd
22
+
23
+ say "Pulling down a snapshot to #{filename}..."
24
+
25
+ begin
26
+
27
+ if ! RHC::Helpers.windows?
28
+ output = Kernel.send(:`, ssh_cmd)
29
+ if $?.exitstatus != 0
30
+ debug output
31
+ raise RHC::SnapshotSaveException.new "Error in trying to save snapshot. You can try to save manually by running:\n#{ssh_cmd}"
32
+ end
33
+ else
34
+ Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh|
35
+ File.open(filename, 'wb') do |file|
36
+ ssh.exec! "snapshot" do |channel, stream, data|
37
+ if stream == :stdout
38
+ file.write(data)
39
+ else
40
+ debug data
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
47
+ debug e.backtrace
48
+ raise RHC::SnapshotSaveException.new "Error in trying to save snapshot. You can try to save manually by running:\n#{ssh_cmd}"
49
+ end
50
+ results { say "Success" }
51
+ 0
52
+ end
53
+
54
+ summary "Restores a previously saved snapshot."
55
+ syntax "<application>"
56
+ option ["-n", "--namespace namespace"], "Namespace of the application you are saving a snapshot", :context => :namespace_context, :required => true
57
+ option ["-f", "--filepath filepath"], "Local path to save tarball (default: ./$APPNAME.tar.gz)"
58
+ argument :app, "Application you are saving a snapshot (required)", ["-a", "--app app"]
59
+ alias_action :"app snapshot restore", :root_command => true, :deprecated => true
60
+ def restore(app)
61
+
62
+ filename = options.filepath ? options.filepath : "#{app}.tar.gz"
63
+
64
+ if File.exists? filename
65
+
66
+ include_git = RHC::Helpers.windows? ? true : RHC::TarGz.contains(filename, './*/git')
67
+
68
+ ssh_uri = URI.parse(rest_client.find_domain(options.namespace).find_application(app).ssh_url)
69
+
70
+ ssh_cmd = "cat #{filename} | ssh #{ssh_uri.user}@#{ssh_uri.host} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'"
71
+
72
+ say "Restoring from snapshot #{filename}..."
73
+ debug ssh_cmd
74
+
75
+ begin
76
+ if ! RHC::Helpers.windows?
77
+ output = Kernel.` ssh_cmd
78
+ if $?.exitstatus != 0
79
+ debug output
80
+ raise RHC::SnapshotRestoreException.new "Error in trying to restore snapshot. You can try to restore manually by running:\n#{ssh_cmd}"
81
+ end
82
+ else
83
+ ssh = Net::SSH.start(ssh_uri.host, ssh_uri.user)
84
+ ssh.open_channel do |channel|
85
+ channel.exec("restore#{include_git ? ' INCLUDE_GIT' : ''}") do |ch, success|
86
+ channel.on_data do |ch, data|
87
+ say data
88
+ end
89
+ channel.on_extended_data do |ch, type, data|
90
+ say data
91
+ end
92
+ channel.on_close do |ch|
93
+ say "Terminating..."
94
+ end
95
+ File.open(filename, 'rb') do |file|
96
+ file.chunk(1024) do |chunk|
97
+ channel.send_data chunk
98
+ end
99
+ end
100
+ channel.eof!
101
+ end
102
+ end
103
+ ssh.loop
104
+ end
105
+ rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
106
+ debug e.backtrace
107
+ raise RHC::SnapshotRestoreException.new "Error in trying to restore snapshot. You can try to restore manually by running:\n#{ssh_cmd}"
108
+ end
109
+
110
+ else
111
+ raise RHC::SnapshotRestoreException.new "Archive not found: #{filename}"
112
+ end
113
+ results { say "Success" }
114
+ 0
115
+ end
116
+
117
+ end
118
+ end
@@ -5,65 +5,58 @@ require 'rhc/commands/base'
5
5
  module RHC::Commands
6
6
  class Sshkey < Base
7
7
  include RHC::SSHKeyHelpers
8
-
8
+
9
9
  summary 'Manage multiple keys for the registered rhcloud user.'
10
10
  syntax '<action>'
11
11
  default_action :list
12
-
12
+
13
13
  summary 'Display all the SSH keys for the user account'
14
14
  syntax ''
15
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
16
15
  def list
17
- ssh_keys = rest_client.sshkeys
18
16
  results do
19
- result = ''
20
-
21
- ssh_keys.each do |key|
22
- result += format(key, erb)
17
+ result = rest_client.sshkeys.inject('') do |r, key|
18
+ r += format(key, erb)
23
19
  end
24
-
20
+
25
21
  say result
26
22
  end
27
-
23
+
28
24
  0
29
25
  end
30
-
26
+
31
27
  summary 'List the SSH key with the given name'
32
28
  syntax '<name>'
33
29
  argument :name, 'SSH key to display', []
34
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
35
30
  def show(name)
36
31
  key = rest_client.find_key(name)
37
32
  say format(key, erb)
38
-
33
+
39
34
  0
40
35
  end
41
36
 
42
37
  summary 'Add SSH key to the user account'
43
- syntax '<name> <SSH Key file>'
38
+ syntax '<name> <path to SSH key file>'
44
39
  argument :name, 'Name for this key', []
45
40
  argument :key, 'SSH public key filepath', []
46
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
41
+ option ['--confirm'], 'Bypass key validation'
47
42
  def add(name, key)
48
- begin
49
- file = File.open(key)
50
- rescue Errno::ENOENT => e
51
- raise ::RHC::KeyFileNotExistentException.new("File '#{key}' does not exist.")
52
- rescue Errno::EACCES => e
53
- raise ::RHC::KeyFileAccessDeniedException.new("Access denied to '#{key}'.")
54
- end
55
- type, content, comment = file.gets.chomp.split
56
-
43
+ type, content, comment = ssh_key_triple_for(key)
44
+
57
45
  # validate the user input before sending it to the server
58
46
  begin
59
47
  Net::SSH::KeyFactory.load_data_public_key "#{type} #{content}"
60
- rescue NotImplementedError, Net::SSH::Exception => e
61
- raise ::RHC::KeyDataInvalidException.new("File '#{key}' contains invalid data")
48
+ rescue NotImplementedError, OpenSSL::PKey::PKeyError, Net::SSH::Exception => e
49
+ debug e.inspect
50
+ if options.confirm
51
+ warn 'The key you are uploading is not recognized. You may not be able to authenticate to your application through Git or SSH.'
52
+ else
53
+ raise ::RHC::KeyDataInvalidException.new("File '#{key}' does not appear to be a recognizable key file (#{e}). You may specify the '--confirm' flag to add the key anyway.")
54
+ end
62
55
  end
63
56
 
64
57
  rest_client.add_key(name, content, type)
65
58
  results { say "SSH key #{key} has been added as '#{name}'" }
66
-
59
+
67
60
  0
68
61
  end
69
62
 
@@ -71,25 +64,18 @@ module RHC::Commands
71
64
  syntax '<name>'
72
65
  alias_action :delete
73
66
  argument :name, 'SSH key to remove', []
74
- option ["--timeout timeout"], "Timeout, in seconds, for the session"
75
67
  def remove(name)
76
68
  rest_client.delete_key(name)
77
69
  results { say "SSH key '#{name}' has been removed" }
78
-
70
+
79
71
  0
80
72
  end
81
-
73
+
82
74
  private
83
75
  # shared ERB template for formatting SSH Key
84
76
  def erb
85
77
  return @erb if @erb # cache
86
- @erb = ERB.new <<-FORMAT
87
- Name: <%= key.name %>
88
- Type: <%= key.type %>
89
- Fingerprint: <%= key.fingerprint %>
90
-
91
- FORMAT
78
+ @erb = ::RHC::Helpers.ssh_key_display_format
92
79
  end
93
-
94
80
  end
95
- end
81
+ end