rhc 1.4.8 → 1.5.13
Sign up to get free protection for your applications and to get access to all the features.
- data/features/application.feature +1 -0
- data/features/lib/rhc_helper/app.rb +5 -3
- data/features/lib/rhc_helper/commandify.rb +2 -1
- data/features/step_definitions/application_steps.rb +2 -1
- data/features/support/env.rb +4 -1
- data/lib/rhc/auth/basic.rb +18 -13
- data/lib/rhc/auth/token.rb +98 -0
- data/lib/rhc/auth/token_store.rb +51 -0
- data/lib/rhc/auth.rb +3 -1
- data/lib/rhc/command_runner.rb +1 -0
- data/lib/rhc/commands/account.rb +47 -1
- data/lib/rhc/commands/alias.rb +2 -4
- data/lib/rhc/commands/app.rb +23 -18
- data/lib/rhc/commands/authorization.rb +93 -0
- data/lib/rhc/commands/base.rb +11 -3
- data/lib/rhc/commands/cartridge.rb +8 -16
- data/lib/rhc/commands/git_clone.rb +2 -3
- data/lib/rhc/commands/port_forward.rb +10 -11
- data/lib/rhc/commands/setup.rb +4 -1
- data/lib/rhc/commands/snapshot.rb +4 -3
- data/lib/rhc/commands/tail.rb +3 -4
- data/lib/rhc/commands/threaddump.rb +1 -2
- data/lib/rhc/commands.rb +37 -3
- data/lib/rhc/config.rb +10 -1
- data/lib/rhc/context_helper.rb +5 -1
- data/lib/rhc/core_ext.rb +10 -0
- data/lib/rhc/exceptions.rb +0 -12
- data/lib/rhc/git_helpers.rb +12 -0
- data/lib/rhc/helpers.rb +31 -1
- data/lib/rhc/output_helpers.rb +19 -3
- data/lib/rhc/rest/api.rb +2 -1
- data/lib/rhc/rest/application.rb +5 -4
- data/lib/rhc/rest/authorization.rb +10 -0
- data/lib/rhc/rest/base.rb +6 -1
- data/lib/rhc/rest/client.rb +243 -122
- data/lib/rhc/rest/domain.rb +0 -15
- data/lib/rhc/rest/gear_group.rb +0 -1
- data/lib/rhc/rest/mock.rb +118 -16
- data/lib/rhc/rest/user.rb +0 -1
- data/lib/rhc/rest.rb +28 -8
- data/lib/rhc/ssh_helpers.rb +5 -2
- data/lib/rhc/tar_gz.rb +16 -5
- data/lib/rhc/usage_templates/help.erb +1 -1
- data/lib/rhc/wizard.rb +54 -10
- data/spec/coverage_helper.rb +9 -0
- data/spec/rhc/auth_spec.rb +229 -22
- data/spec/rhc/cli_spec.rb +15 -0
- data/spec/rhc/command_spec.rb +100 -8
- data/spec/rhc/commands/account_spec.rb +75 -1
- data/spec/rhc/commands/app_spec.rb +23 -5
- data/spec/rhc/commands/authorization_spec.rb +120 -0
- data/spec/rhc/commands/domain_spec.rb +2 -2
- data/spec/rhc/commands/git_clone_spec.rb +24 -0
- data/spec/rhc/commands/port_forward_spec.rb +22 -23
- data/spec/rhc/commands/server_spec.rb +2 -2
- data/spec/rhc/commands/setup_spec.rb +12 -0
- data/spec/rhc/config_spec.rb +7 -3
- data/spec/rhc/helpers_spec.rb +62 -9
- data/spec/rhc/rest_application_spec.rb +24 -0
- data/spec/rhc/rest_client_spec.rb +66 -56
- data/spec/rhc/rest_spec.rb +11 -2
- data/spec/rhc/wizard_spec.rb +61 -12
- data/spec/spec_helper.rb +125 -42
- data/spec/wizard_spec_helper.rb +1 -0
- metadata +9 -3
@@ -19,6 +19,7 @@ Feature: Application Operations
|
|
19
19
|
| running | snapshot | the snapshot | be found |
|
20
20
|
| running | tidied | it | succeed |
|
21
21
|
| running | shown | it | succeed |
|
22
|
+
| running | visualized| it | succeed |
|
22
23
|
| running | stopped | the application | not be accessible |
|
23
24
|
| stopped | started | the application | be accessible |
|
24
25
|
# After the app is deleted, it is resolving to the OpenShift server
|
@@ -36,9 +36,11 @@ module RHCHelper
|
|
36
36
|
# Setup questions asked by wizard which are passed in below:
|
37
37
|
# 1 - username
|
38
38
|
# 2 - password
|
39
|
-
# 3 -
|
39
|
+
# 3 - should we support an api token, if server supports it
|
40
|
+
# 4 - upload SSH keys
|
40
41
|
# 4 - if no namespace is found, create namespace? (blank is no)
|
41
42
|
args = [$username, $password]
|
43
|
+
args << 'no' if $supports_auth_tokens
|
42
44
|
args << 'yes' unless ($keyed_users ||= []).include?($username)
|
43
45
|
args << '' # always skip namespace
|
44
46
|
if $namespace
|
@@ -103,9 +105,9 @@ module RHCHelper
|
|
103
105
|
|
104
106
|
# Get a REST client to verify the application is on the server
|
105
107
|
def is_created?
|
106
|
-
new_client.
|
108
|
+
new_client.find_application($namespace,name)
|
107
109
|
true
|
108
|
-
rescue RHC::ApplicationNotFoundException
|
110
|
+
rescue RHC::Rest::ApplicationNotFoundException
|
109
111
|
false
|
110
112
|
end
|
111
113
|
|
@@ -43,8 +43,9 @@ module RHCHelper
|
|
43
43
|
cmd.gsub!('add alias', 'add-alias')
|
44
44
|
cmd.gsub!('remove alias', 'remove-alias')
|
45
45
|
cmd.gsub!('force stop', 'force-stop')
|
46
|
+
cmd.gsub!('show gears', 'show --gears')
|
46
47
|
|
47
|
-
|
48
|
+
cmd
|
48
49
|
end
|
49
50
|
|
50
51
|
# Print out the command arguments based on the state of the application instance
|
@@ -70,7 +70,8 @@ When /^the application is (\w+)$/ do |command|
|
|
70
70
|
:shown => :show,
|
71
71
|
:tidied => :tidy,
|
72
72
|
:snapshot => :snapshot_save,
|
73
|
-
:deleted => :delete
|
73
|
+
:deleted => :delete,
|
74
|
+
:visualized => :show_gears,
|
74
75
|
}
|
75
76
|
|
76
77
|
# Use an alias if it exists, or just remove 'ed' (like from started)
|
data/features/support/env.rb
CHANGED
@@ -67,7 +67,7 @@ set_endpoint
|
|
67
67
|
raise "Username not found in environment (RHC_USERNAME)" unless $username
|
68
68
|
raise "Password not found in environment (RHC_PASSWORD)" unless $password
|
69
69
|
|
70
|
-
$user_register_script_format = "
|
70
|
+
$user_register_script_format = "oo-register-user -l admin -p admin --username %s --userpass %s"
|
71
71
|
if ENV['REGISTER_USER']
|
72
72
|
command = $user_register_script_format % [$username,$password]
|
73
73
|
%x[#{command}]
|
@@ -97,6 +97,9 @@ def clean_applications(leave_domain = false)
|
|
97
97
|
$namespace = nil unless leave_domain
|
98
98
|
$keyed_users = []
|
99
99
|
|
100
|
+
client = RHC::Rest::Client.new(:url => $end_point, :user => $username, :password => $password, :verify_mode => OpenSSL::SSL::VERIFY_NONE)
|
101
|
+
$supports_auth_tokens = client.supports_sessions?
|
102
|
+
|
100
103
|
users.each do |user|
|
101
104
|
_log "\tUser: #{user}"
|
102
105
|
client = RHC::Rest::Client.new(:url => $end_point, :user => user, :password => $password, :verify_mode => OpenSSL::SSL::VERIFY_NONE)
|
data/lib/rhc/auth/basic.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module RHC::Auth
|
2
2
|
class Basic
|
3
|
-
attr_reader :cookie
|
4
|
-
|
5
3
|
def initialize(*args)
|
6
4
|
if args[0].is_a?(String) or args.length > 1
|
7
5
|
@username, @password = args
|
@@ -15,30 +13,37 @@ module RHC::Auth
|
|
15
13
|
end
|
16
14
|
|
17
15
|
def to_request(request)
|
18
|
-
(request[:cookies] ||= {})[:rh_sso] = cookie if cookie
|
19
16
|
request[:user] ||= username || (request[:lazy_auth] != true && ask_username) || nil
|
20
17
|
request[:password] ||= password || (username? && request[:lazy_auth] != true && ask_password) || nil
|
21
18
|
request
|
22
19
|
end
|
23
20
|
|
24
|
-
def retry_auth?(response)
|
21
|
+
def retry_auth?(response, client)
|
25
22
|
if response.status == 401
|
26
|
-
|
27
|
-
error "Username or password is not correct" if username? && password
|
28
|
-
unless @skip_interactive or @no_interactive
|
29
|
-
ask_username unless username?
|
30
|
-
ask_password
|
31
|
-
true
|
32
|
-
end
|
23
|
+
credentials_rejected
|
33
24
|
else
|
34
|
-
@cookie ||= Array(response.cookies).inject(nil){ |v, c| c.name == 'rh_sso' ? c.value : v }
|
35
25
|
false
|
36
26
|
end
|
37
27
|
end
|
38
28
|
|
29
|
+
def can_authenticate?
|
30
|
+
username? and not (password.nil? and @skip_interactive and @no_interactive)
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :username
|
34
|
+
|
39
35
|
protected
|
40
36
|
include RHC::Helpers
|
41
|
-
attr_reader :options, :
|
37
|
+
attr_reader :options, :password
|
38
|
+
|
39
|
+
def credentials_rejected
|
40
|
+
error "Username or password is not correct" if username? && password
|
41
|
+
unless @skip_interactive or @no_interactive
|
42
|
+
ask_username unless username?
|
43
|
+
ask_password
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
42
47
|
|
43
48
|
def ask_username
|
44
49
|
@username = ask("Login to #{openshift_server}: ") unless @no_interactive
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module RHC::Auth
|
2
|
+
class Token
|
3
|
+
def initialize(opt, auth=nil, store=nil)
|
4
|
+
if opt.is_a?(String)
|
5
|
+
@token = opt
|
6
|
+
else
|
7
|
+
@options = opt || Commander::Command::Options.new
|
8
|
+
@token = options[:token]
|
9
|
+
@no_interactive = options[:noprompt]
|
10
|
+
@allows_tokens = options[:use_authorization_tokens]
|
11
|
+
end
|
12
|
+
@auth = auth
|
13
|
+
@store = store
|
14
|
+
read_token
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_request(request)
|
18
|
+
if token
|
19
|
+
(request[:headers] ||= {})['authorization'] = "Bearer #{token}"
|
20
|
+
elsif auth and (!@allows_tokens or @can_get_token == false)
|
21
|
+
auth.to_request(request)
|
22
|
+
end
|
23
|
+
request
|
24
|
+
end
|
25
|
+
|
26
|
+
def retry_auth?(response, client)
|
27
|
+
if response.status == 401
|
28
|
+
token_rejected(response, client)
|
29
|
+
else
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def username
|
35
|
+
auth && auth.respond_to?(:username) && auth.username || options[:username]
|
36
|
+
end
|
37
|
+
|
38
|
+
def save(token)
|
39
|
+
store.put(username, openshift_server, token) if store
|
40
|
+
@token = token
|
41
|
+
end
|
42
|
+
|
43
|
+
def can_authenticate?
|
44
|
+
token || auth && auth.can_authenticate?
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
include RHC::Helpers
|
49
|
+
attr_reader :options, :token, :auth, :store
|
50
|
+
|
51
|
+
def token_rejected(response, client)
|
52
|
+
has_token = !!token
|
53
|
+
@token = nil
|
54
|
+
|
55
|
+
unless auth && auth.can_authenticate?
|
56
|
+
if has_token
|
57
|
+
raise RHC::Rest::TokenExpiredOrInvalid, "Your authorization token is expired or invalid."
|
58
|
+
end
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
if has_token
|
63
|
+
if cannot_retry?
|
64
|
+
raise RHC::Rest::TokenExpiredOrInvalid, "Your authorization token is expired or invalid."
|
65
|
+
end
|
66
|
+
if not client.supports_sessions?
|
67
|
+
raise RHC::Rest::AuthorizationsNotSupported
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@can_get_token = client.supports_sessions? && @allows_tokens
|
72
|
+
|
73
|
+
if has_token
|
74
|
+
warn "Your authorization token has expired. Please sign in now to continue."
|
75
|
+
elsif @can_get_token
|
76
|
+
info "Please sign in to start a new session to #{openshift_server}."
|
77
|
+
end
|
78
|
+
|
79
|
+
return auth.retry_auth?(response, client) unless @can_get_token
|
80
|
+
|
81
|
+
if auth_token = client.new_session(:auth => auth)
|
82
|
+
@fetch_once = true
|
83
|
+
save(auth_token.token)
|
84
|
+
true
|
85
|
+
else
|
86
|
+
auth.retry_auth?(response, client)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def read_token
|
91
|
+
@token ||= store.get(username, openshift_server) if store
|
92
|
+
end
|
93
|
+
|
94
|
+
def cannot_retry?
|
95
|
+
!@fetch_once && @no_interactive
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module RHC::Auth
|
2
|
+
class TokenStore
|
3
|
+
def initialize(dir)
|
4
|
+
@dir = dir
|
5
|
+
end
|
6
|
+
|
7
|
+
def get(login, server)
|
8
|
+
self[key(login,server)]
|
9
|
+
end
|
10
|
+
|
11
|
+
def put(login, server, token)
|
12
|
+
self[key(login,server)] = token
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear
|
16
|
+
Dir[File.join(@dir, "token_*")].
|
17
|
+
each{ |f| File.delete(f) unless File.directory?(f) }.
|
18
|
+
present?
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def path(key)
|
23
|
+
File.join(@dir, filename(key))
|
24
|
+
end
|
25
|
+
|
26
|
+
def filename(key)
|
27
|
+
"token_#{Base64.encode64(Digest::MD5.digest(key)).gsub(/[^\w\@]/,'')}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def []=(key, value)
|
31
|
+
file = path(key)
|
32
|
+
FileUtils.mkdir_p File.dirname(file)
|
33
|
+
File.open(file, 'w'){ |f| f.write(value) }
|
34
|
+
File.chmod(0600, file)
|
35
|
+
value
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](key)
|
39
|
+
s = IO.read(path(key)).presence
|
40
|
+
s = s.strip.gsub(/[\n\r\t]/,'') if s
|
41
|
+
s
|
42
|
+
rescue Errno::ENOENT
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def key(login, server)
|
47
|
+
"#{login || ''}@#{server}"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/rhc/auth.rb
CHANGED
data/lib/rhc/command_runner.rb
CHANGED
@@ -61,6 +61,7 @@ module RHC
|
|
61
61
|
run_active_command
|
62
62
|
rescue InvalidCommandError => e
|
63
63
|
if provided_arguments.empty?
|
64
|
+
return RHC::Wizard.new.run unless RHC::Wizard.has_configuration?
|
64
65
|
say RHC::HelpFormatter.new(self).render
|
65
66
|
else
|
66
67
|
RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
|
data/lib/rhc/commands/account.rb
CHANGED
@@ -12,7 +12,7 @@ module RHC::Commands
|
|
12
12
|
def run
|
13
13
|
user = rest_client.user
|
14
14
|
|
15
|
-
say_table nil, get_properties(user, :login, :plan_id, :consumed_gears, :max_gears) + get_properties(user.capabilities, :gear_sizes), :delete => true
|
15
|
+
say_table nil, get_properties(user, :login, :plan_id, :consumed_gears, :max_gears) + get_properties(user.capabilities, :gear_sizes).unshift(['Server', openshift_server]), :delete => true
|
16
16
|
|
17
17
|
if openshift_online_server?
|
18
18
|
else
|
@@ -20,5 +20,51 @@ module RHC::Commands
|
|
20
20
|
|
21
21
|
0
|
22
22
|
end
|
23
|
+
|
24
|
+
summary "End the current session"
|
25
|
+
description <<-DESC
|
26
|
+
Logout ends your current session on the server and then removes
|
27
|
+
all of the local session files. If you are using multiple
|
28
|
+
servers and configurations this will remove all of your local
|
29
|
+
session files.
|
30
|
+
|
31
|
+
The --all option will terminate all authorizations on your
|
32
|
+
account. Any previously generated authorizations will be
|
33
|
+
deleted and external tools that integrate with your account
|
34
|
+
will no longer be able to log in.
|
35
|
+
DESC
|
36
|
+
option '--all', "Remove all authorizations on your account."
|
37
|
+
alias_action 'logout', :root_command => true
|
38
|
+
def logout
|
39
|
+
if options.all
|
40
|
+
rest_client.user # force authentication
|
41
|
+
say "Deleting all authorizations associated with your account ... "
|
42
|
+
begin
|
43
|
+
rest_client.delete_authorizations
|
44
|
+
success "done"
|
45
|
+
rescue RHC::Rest::AuthorizationsNotSupported
|
46
|
+
info "not supported"
|
47
|
+
end
|
48
|
+
elsif options.token
|
49
|
+
options.noprompt = true
|
50
|
+
say "Ending session on server ... "
|
51
|
+
begin
|
52
|
+
rest_client.delete_authorization(options.token)
|
53
|
+
success "deleted"
|
54
|
+
rescue RHC::Rest::AuthorizationsNotSupported
|
55
|
+
info "not supported"
|
56
|
+
rescue RHC::Rest::TokenExpiredOrInvalid
|
57
|
+
info "already closed"
|
58
|
+
rescue => e
|
59
|
+
debug_error(e)
|
60
|
+
warn e.message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
0
|
65
|
+
ensure
|
66
|
+
token_store.clear
|
67
|
+
success "All local sessions removed."
|
68
|
+
end
|
23
69
|
end
|
24
70
|
end
|
data/lib/rhc/commands/alias.rb
CHANGED
@@ -14,8 +14,7 @@ module RHC::Commands
|
|
14
14
|
option ["-n", "--namespace namespace"], "Namespace of your application", :context => :namespace_context, :required => true
|
15
15
|
alias_action :"app add-alias", :root_command => true, :deprecated => true
|
16
16
|
def add(app, app_alias)
|
17
|
-
|
18
|
-
rest_app = rest_domain.find_application(app)
|
17
|
+
rest_app = rest_client.find_application(options.namespace, app)
|
19
18
|
response = rest_app.add_alias(app_alias)
|
20
19
|
results { say response.messages.first } if response.messages
|
21
20
|
0
|
@@ -28,8 +27,7 @@ module RHC::Commands
|
|
28
27
|
option ["-n", "--namespace namespace"], "Namespace of your application", :context => :namespace_context, :required => true
|
29
28
|
alias_action :"app remove-alias", :root_command => true, :deprecated => true
|
30
29
|
def remove(app, app_alias)
|
31
|
-
|
32
|
-
rest_app = rest_domain.find_application(app)
|
30
|
+
rest_app = rest_client.find_application(options.namespace, app)
|
33
31
|
response = rest_app.remove_alias(app_alias)
|
34
32
|
results { say response.messages.first } if response.messages
|
35
33
|
0
|
data/lib/rhc/commands/app.rb
CHANGED
@@ -59,7 +59,7 @@ module RHC::Commands
|
|
59
59
|
|
60
60
|
raise ArgumentError, "You have named both your main application and your Jenkins application '#{name}'. In order to continue you'll need to specify a different name with --enable-jenkins or choose a different application name." if jenkins_app_name == name && enable_jenkins?
|
61
61
|
|
62
|
-
raise RHC::DomainNotFoundException.new("No domains found. Please create a domain with 'rhc domain create <namespace>' before creating applications.") if rest_client.domains.empty?
|
62
|
+
raise RHC::Rest::DomainNotFoundException.new("No domains found. Please create a domain with 'rhc domain create <namespace>' before creating applications.") if rest_client.domains.empty?
|
63
63
|
rest_domain = rest_client.find_domain(options.namespace)
|
64
64
|
rest_app = nil
|
65
65
|
|
@@ -177,9 +177,7 @@ module RHC::Commands
|
|
177
177
|
argument :app, "The application you wish to delete", ["-a", "--app name"], :context => :app_context
|
178
178
|
alias_action :destroy, :deprecated => true
|
179
179
|
def delete(app)
|
180
|
-
|
181
|
-
rest_domain = rest_client.find_domain(options.namespace)
|
182
|
-
rest_app = rest_domain.find_application(app)
|
180
|
+
rest_app = rest_client.find_application(options.namespace, app)
|
183
181
|
|
184
182
|
confirm_action "#{color("This is a non-reversible action! Your application code and data will be permanently deleted if you continue!", :yellow)}\n\nAre you sure you want to delete the application '#{app}'?"
|
185
183
|
|
@@ -260,18 +258,18 @@ module RHC::Commands
|
|
260
258
|
syntax "<app> [--namespace namespace]"
|
261
259
|
argument :app, "The name of the application you are getting information on", ["-a", "--app app"], :context => :app_context
|
262
260
|
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
263
|
-
option ["--state"], "Get the current state of the application
|
261
|
+
option ["--state"], "Get the current state of the cartridges in this application"
|
262
|
+
option ["--gears"], "Show the ID, state, and cartridges on each gear in this application"
|
264
263
|
def show(app_name)
|
265
|
-
domain = rest_client.find_domain(options.namespace)
|
266
|
-
app = domain.find_application(app_name)
|
267
264
|
|
268
265
|
if options.state
|
269
|
-
|
270
|
-
|
271
|
-
say "Gear group #{gg.cartridges.collect { |c| c['name'] }.join('+')} is #{gg.gears.first['state']}"
|
272
|
-
end
|
266
|
+
gear_groups_for_app(app_name).each do |gg|
|
267
|
+
say "Cartridge #{gg.cartridges.collect { |c| c['name'] }.join(', ')} is #{gear_group_state(gg.gears.map{ |g| g['state'] })}"
|
273
268
|
end
|
269
|
+
elsif options.gears
|
270
|
+
say table(gear_groups_for_app(app_name).map{ |gg| gg.gears.map{ |g| [g['id'], g['state'], gg.cartridges.map{ |c| c['name'] }.join(", ")] } }.flatten(1))
|
274
271
|
else
|
272
|
+
app = rest_client.find_application(options.namespace, app_name, :include => :cartridges)
|
275
273
|
display_app(app, app.cartridges)
|
276
274
|
end
|
277
275
|
|
@@ -288,16 +286,15 @@ module RHC::Commands
|
|
288
286
|
raise ArgumentError, "No application specified" unless app_name.present?
|
289
287
|
raise OptionParser::InvalidOption, "No system SSH available. Please use the --ssh option to specify the path to your SSH executable, or install SSH." unless options.ssh or has_ssh?
|
290
288
|
|
291
|
-
|
292
|
-
app = domain.find_application(app_name)
|
289
|
+
rest_app = rest_client.find_application(options.namespace, app_name)
|
293
290
|
|
294
|
-
say "Connecting to #{
|
291
|
+
say "Connecting to #{rest_app.ssh_string.to_s} ..."
|
295
292
|
if options.ssh
|
296
293
|
debug "Using user specified SSH: #{options.ssh}"
|
297
|
-
Kernel.send(:system, "#{options.ssh} #{
|
294
|
+
Kernel.send(:system, "#{options.ssh} #{rest_app.ssh_string.to_s}")
|
298
295
|
else
|
299
296
|
debug "Using system ssh"
|
300
|
-
Kernel.send(:system, "ssh #{
|
297
|
+
Kernel.send(:system, "ssh #{rest_app.ssh_string.to_s}")
|
301
298
|
end
|
302
299
|
end
|
303
300
|
|
@@ -337,9 +334,17 @@ module RHC::Commands
|
|
337
334
|
RHC::SSHWizard.new(rest_client, config, options).run
|
338
335
|
end
|
339
336
|
|
337
|
+
def gear_groups_for_app(app_name)
|
338
|
+
rest_client.find_application_gear_groups(options.namespace, app_name)
|
339
|
+
end
|
340
|
+
|
341
|
+
def gear_group_state(states)
|
342
|
+
return states[0] if states.length == 1 || states.uniq.length == 1
|
343
|
+
"#{states.select{ |s| s == 'started' }.count}/#{states.length} started"
|
344
|
+
end
|
345
|
+
|
340
346
|
def app_action(app, action, *args)
|
341
|
-
|
342
|
-
rest_app = rest_domain.find_application(app)
|
347
|
+
rest_app = rest_client.find_application(options.namespace, app)
|
343
348
|
result = rest_app.send action, *args
|
344
349
|
result
|
345
350
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module RHC::Commands
|
2
|
+
class Authorization < Base
|
3
|
+
|
4
|
+
summary "Display the authorization tokens created under 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 OpenShift REST API with
|
10
|
+
a set of privleges 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
|
+
def run
|
15
|
+
rest_client.authorizations.each{ |auth| paragraph{ display_authorization(auth, options.token) } } or info "No authorizations"
|
16
|
+
|
17
|
+
0
|
18
|
+
end
|
19
|
+
|
20
|
+
option "--scopes SCOPES", "A comma delimited list of scopes (e.g. 'scope1,scope2')"
|
21
|
+
option "--note NOTE", "A description of this authorization (optional)"
|
22
|
+
option "--expires-in SECONDS", "The number of seconds before this authorization expires (optional)"
|
23
|
+
summary "Add an authorization to your account"
|
24
|
+
description <<-DESC
|
25
|
+
Add an authorization to your account. An authorization token grants
|
26
|
+
access to the OpenShift REST API with a set of privleges called 'scopes'
|
27
|
+
for a limited time. You can add an optional note to each authorization
|
28
|
+
token to assist you in remembering what is available.
|
29
|
+
|
30
|
+
To view the list of scopes supported by this server, run this command
|
31
|
+
without any options.
|
32
|
+
|
33
|
+
You may pass multiple scopes to the --scopes option inside of double
|
34
|
+
quotes (--scopes \"scope1 scope2\") or by separating them with commas
|
35
|
+
(--scopes scope1,scope2).
|
36
|
+
|
37
|
+
The server will enforce a maximum and default expiration that may
|
38
|
+
differ for each scope. If you request an expiration longer than the
|
39
|
+
server maximum, you will be given the default value.
|
40
|
+
DESC
|
41
|
+
def add
|
42
|
+
unless options.scopes
|
43
|
+
say "When adding an authorization, you must specify which permissions clients will have."
|
44
|
+
scope_help
|
45
|
+
say "Run 'rhc authorization add --help' to see more options"
|
46
|
+
return 0
|
47
|
+
end
|
48
|
+
|
49
|
+
say "Adding authorization ... "
|
50
|
+
auth = rest_client.add_authorization(:scope => options.scopes, :note => options.note, :expires_in => options.expires_in)
|
51
|
+
success "done"
|
52
|
+
paragraph{ display_authorization(auth) }
|
53
|
+
|
54
|
+
0
|
55
|
+
end
|
56
|
+
|
57
|
+
summary "Delete one or more authorization tokens"
|
58
|
+
syntax "<token_or_id> [...<token_or_id>]"
|
59
|
+
description <<-DESC
|
60
|
+
Delete one or more of the authorization tokens associated with
|
61
|
+
your account. After deletion, any clients using the token will
|
62
|
+
no longer have access to OpenShift and will need to reauthenticate.
|
63
|
+
DESC
|
64
|
+
argument :auth_token, "The token you wish to delete", ['--auth-token TOKEN'], :arg_type => :list
|
65
|
+
def delete(tokens)
|
66
|
+
raise ArgumentError, "You must specify one or more tokens to delete" if tokens.blank?
|
67
|
+
say "Deleting authorization ... "
|
68
|
+
tokens.each{ |token| rest_client.delete_authorization(token) }
|
69
|
+
success "done"
|
70
|
+
0
|
71
|
+
end
|
72
|
+
|
73
|
+
summary "Delete all authorization tokens from your account"
|
74
|
+
description <<-DESC
|
75
|
+
Delete all the authorization tokens associated with your account.
|
76
|
+
After deletion, any clients using those tokens will need to
|
77
|
+
reauthenticate.
|
78
|
+
DESC
|
79
|
+
def delete_all
|
80
|
+
say "Deleting all authorizations ... "
|
81
|
+
rest_client.delete_authorizations
|
82
|
+
success "done"
|
83
|
+
0
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
def scope_help
|
88
|
+
descriptions = rest_client.authorization_scope_list
|
89
|
+
paragraph{ say table(descriptions, :header => ['Scope', 'Description']) }
|
90
|
+
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)." }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/rhc/commands/base.rb
CHANGED
@@ -28,8 +28,16 @@ class RHC::Commands::Base
|
|
28
28
|
# the output (or failures) into exceptions and
|
29
29
|
# formatted object output. Most interactions
|
30
30
|
# should be through this call pattern.
|
31
|
-
def rest_client
|
32
|
-
@rest_client ||=
|
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)
|
35
|
+
client_from_options(:auth => auth)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def token_store
|
40
|
+
@token_store ||= RHC::Auth::TokenStore.new(config.home_conf_path)
|
33
41
|
end
|
34
42
|
|
35
43
|
def help(*args)
|
@@ -79,7 +87,7 @@ class RHC::Commands::Base
|
|
79
87
|
indent = o.scan(/^[ \t]*(?=\S)/).min.size || 0
|
80
88
|
options[:description] =
|
81
89
|
o.gsub(/^[ \t]{#{indent}}/, '').
|
82
|
-
gsub(/(\b)\s*\n(?!\s*\n)(\S)/m, '\1 \2').
|
90
|
+
gsub(/(\b|')\s*\n(?!\s*\n)(\S)/m, '\1 \2').
|
83
91
|
gsub(/\n+\Z/, '').
|
84
92
|
gsub(/\n{3,}/, "\n\n")
|
85
93
|
end
|
@@ -46,8 +46,7 @@ module RHC::Commands
|
|
46
46
|
|
47
47
|
say "Adding #{cart.name} to application '#{options.app}' ... "
|
48
48
|
|
49
|
-
|
50
|
-
rest_app = rest_domain.find_application(options.app)
|
49
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
51
50
|
rest_cartridge = rest_app.add_cartridge(cart.name)
|
52
51
|
|
53
52
|
success "Success"
|
@@ -65,8 +64,7 @@ module RHC::Commands
|
|
65
64
|
option ["-a", "--app app"], "Application you are adding the cartridge to", :context => :app_context, :required => true
|
66
65
|
argument :cartridge, "The name of the cartridge", ["-c", "--cartridge cart_type"]
|
67
66
|
def show(cartridge)
|
68
|
-
|
69
|
-
rest_app = rest_domain.find_application(options.app)
|
67
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
70
68
|
rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
|
71
69
|
|
72
70
|
display_cart(rest_cartridge)
|
@@ -82,9 +80,7 @@ module RHC::Commands
|
|
82
80
|
option ["--confirm"], "Pass to confirm removing the cartridge"
|
83
81
|
alias_action :"app cartridge remove", :root_command => true, :deprecated => true
|
84
82
|
def remove(cartridge)
|
85
|
-
|
86
|
-
rest_domain = rest_client.find_domain(options.namespace)
|
87
|
-
rest_app = rest_domain.find_application(options.app)
|
83
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
88
84
|
rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
|
89
85
|
|
90
86
|
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}'?"
|
@@ -136,8 +132,7 @@ module RHC::Commands
|
|
136
132
|
option ["-a", "--app app"], "Application the cartridge belongs to", :context => :app_context, :required => true
|
137
133
|
alias_action :"app cartridge status", :root_command => true, :deprecated => true
|
138
134
|
def status(cartridge)
|
139
|
-
|
140
|
-
rest_app = rest_domain.find_application(options.app)
|
135
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
141
136
|
rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
|
142
137
|
results { rest_cartridge.status.each{ |msg| say msg['message'] } }
|
143
138
|
0
|
@@ -164,8 +159,7 @@ module RHC::Commands
|
|
164
159
|
def scale(cartridge)
|
165
160
|
raise RHC::MissingScalingValueException unless options.min || options.max
|
166
161
|
|
167
|
-
|
168
|
-
rest_app = rest_domain.find_application(options.app)
|
162
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
169
163
|
rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
|
170
164
|
|
171
165
|
raise RHC::CartridgeNotScalableException unless rest_cartridge.scalable?
|
@@ -195,8 +189,7 @@ module RHC::Commands
|
|
195
189
|
option ["-f", "--force"], "Force the action"
|
196
190
|
def storage(cartridge)
|
197
191
|
cartridges = Array(cartridge)
|
198
|
-
|
199
|
-
rest_app = rest_domain.find_application(options.app)
|
192
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
200
193
|
|
201
194
|
# Pull the desired action
|
202
195
|
#
|
@@ -257,11 +250,10 @@ module RHC::Commands
|
|
257
250
|
include RHC::CartridgeHelpers
|
258
251
|
|
259
252
|
def cartridge_action(cartridge, action, &block)
|
260
|
-
|
261
|
-
rest_app = rest_domain.find_application(options.app)
|
253
|
+
rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
|
262
254
|
rest_cartridge = check_cartridges(cartridge, :from => rest_app.cartridges).first
|
263
255
|
result = rest_cartridge.send action
|
264
|
-
resp = [result, rest_cartridge, rest_app
|
256
|
+
resp = [result, rest_cartridge, rest_app]
|
265
257
|
yield resp if block_given?
|
266
258
|
resp
|
267
259
|
end
|