rhc 1.25.3 → 1.26.9
Sign up to get free protection for your applications and to get access to all the features.
- data/autocomplete/rhc_bash +179 -3
- data/features/core_feature.rb +1 -1
- data/features/members_feature.rb +1 -1
- data/features/server_feature.rb +98 -0
- data/lib/rhc/command_runner.rb +8 -9
- data/lib/rhc/commands.rb +13 -3
- data/lib/rhc/commands/base.rb +4 -2
- data/lib/rhc/commands/member.rb +1 -1
- data/lib/rhc/commands/server.rb +189 -3
- data/lib/rhc/commands/setup.rb +1 -1
- data/lib/rhc/config.rb +98 -39
- data/lib/rhc/context_helper.rb +3 -1
- data/lib/rhc/core_ext.rb +18 -10
- data/lib/rhc/exceptions.rb +24 -0
- data/lib/rhc/helpers.rb +11 -18
- data/lib/rhc/highline_extensions.rb +2 -2
- data/lib/rhc/output_helpers.rb +28 -2
- data/lib/rhc/rest/client.rb +0 -2
- data/lib/rhc/rest/membership.rb +1 -3
- data/lib/rhc/rest/mock.rb +2 -1
- data/lib/rhc/server_helpers.rb +46 -0
- data/lib/rhc/servers.rb +192 -0
- data/lib/rhc/usage_templates/command_help.erb +1 -1
- data/lib/rhc/wizard.rb +76 -15
- data/spec/direct_execution_helper.rb +1 -0
- data/spec/rhc/commands/app_spec.rb +2 -0
- data/spec/rhc/commands/server_spec.rb +493 -38
- data/spec/rhc/commands/setup_spec.rb +1 -0
- data/spec/rhc/servers_spec.rb +191 -0
- data/spec/rhc/wizard_spec.rb +19 -2
- data/spec/spec_helper.rb +20 -0
- data/spec/wizard_spec_helper.rb +28 -5
- metadata +11 -5
data/lib/rhc/context_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rhc/git_helpers'
|
2
|
+
require 'rhc/server_helpers'
|
2
3
|
|
3
4
|
module RHC
|
4
5
|
#
|
@@ -7,6 +8,7 @@ module RHC
|
|
7
8
|
#
|
8
9
|
module ContextHelpers
|
9
10
|
include RHC::GitHelpers
|
11
|
+
include RHC::ServerHelpers
|
10
12
|
|
11
13
|
def self.included(other)
|
12
14
|
other.module_eval do
|
@@ -136,7 +138,7 @@ module RHC
|
|
136
138
|
end
|
137
139
|
|
138
140
|
def server_context(defaults=nil, arg=nil)
|
139
|
-
value =
|
141
|
+
value = libra_server_env || (!options.clean && config['libra_server']) || openshift_online_server
|
140
142
|
defaults[arg] = value if defaults && arg
|
141
143
|
value
|
142
144
|
end
|
data/lib/rhc/core_ext.rb
CHANGED
@@ -7,6 +7,7 @@ class Object
|
|
7
7
|
def present?
|
8
8
|
!blank?
|
9
9
|
end
|
10
|
+
|
10
11
|
def blank?
|
11
12
|
respond_to?(:empty?) ? empty? : !self
|
12
13
|
end
|
@@ -171,16 +172,10 @@ end
|
|
171
172
|
|
172
173
|
class Hash
|
173
174
|
def stringify_keys!
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
elsif v.is_a? Array
|
179
|
-
v.each{ |value| value.stringify_keys! if value.is_a? Hash }
|
180
|
-
end
|
181
|
-
self[(key.to_s rescue key) || key] = v
|
182
|
-
end
|
183
|
-
self
|
175
|
+
transform_keys!(:to_s)
|
176
|
+
end
|
177
|
+
def symbolize_keys!
|
178
|
+
transform_keys!(:to_sym)
|
184
179
|
end
|
185
180
|
def slice!(*args)
|
186
181
|
s = []
|
@@ -199,4 +194,17 @@ class Hash
|
|
199
194
|
# right wins if there is no left
|
200
195
|
merge!( other_hash ){|key,left,right| left }
|
201
196
|
end
|
197
|
+
protected
|
198
|
+
def transform_keys!(operation)
|
199
|
+
keys.each do |key|
|
200
|
+
v = delete(key)
|
201
|
+
if v.is_a? Hash
|
202
|
+
v.transform_keys!(operation)
|
203
|
+
elsif v.is_a? Array
|
204
|
+
v.each{ |value| value.transform_keys!(operation) if value.is_a? Hash }
|
205
|
+
end
|
206
|
+
self[(key.send(operation) rescue key) || key] = v
|
207
|
+
end
|
208
|
+
self
|
209
|
+
end
|
202
210
|
end
|
data/lib/rhc/exceptions.rb
CHANGED
@@ -85,6 +85,30 @@ module RHC
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
class ServerNicknameExistsException < Exception
|
89
|
+
def initialize(nickname)
|
90
|
+
super "You already have a server configured with the nickname '#{nickname}'", 164
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class ServerHostnameExistsException < Exception
|
95
|
+
def initialize(hostname)
|
96
|
+
super "You already have a server configured with the hostname '#{hostname}'", 165
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class ServerNotConfiguredException < Exception
|
101
|
+
def initialize(server)
|
102
|
+
super "You don't have any server configured with the hostname or nickname '#{server}'", 166
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class ServerInUseException < Exception
|
107
|
+
def initialize(message="Server in use")
|
108
|
+
super message, 167
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
88
112
|
class GitPermissionDenied < GitException; end
|
89
113
|
class GitDirectoryExists < GitException; end
|
90
114
|
|
data/lib/rhc/helpers.rb
CHANGED
@@ -2,6 +2,7 @@ require 'commander/user_interaction'
|
|
2
2
|
require 'rhc/version'
|
3
3
|
require 'rhc/config'
|
4
4
|
require 'rhc/output_helpers'
|
5
|
+
require 'rhc/server_helpers'
|
5
6
|
require 'rbconfig'
|
6
7
|
|
7
8
|
require 'resolv'
|
@@ -23,6 +24,7 @@ module RHC
|
|
23
24
|
include Commander::UI
|
24
25
|
include Commander::UI::AskForClass
|
25
26
|
include RHC::OutputHelpers
|
27
|
+
include RHC::ServerHelpers
|
26
28
|
|
27
29
|
extend self
|
28
30
|
|
@@ -108,7 +110,7 @@ module RHC
|
|
108
110
|
|
109
111
|
global_option '-d', '--debug', "Turn on debugging", :hide => true
|
110
112
|
|
111
|
-
global_option '--server
|
113
|
+
global_option '--server HOSTNAME', String, 'An OpenShift server hostname (default: openshift.redhat.com)'
|
112
114
|
global_option '-k', '--insecure', "Allow insecure SSL connections. Potential security risk.", :hide => true
|
113
115
|
|
114
116
|
global_option '--limit INTEGER', Integer, "Maximum number of simultaneous operations to execute.", :hide => true
|
@@ -152,19 +154,10 @@ module RHC
|
|
152
154
|
ROLES[s.downcase]
|
153
155
|
end
|
154
156
|
|
155
|
-
def openshift_server
|
156
|
-
to_host((options.server rescue nil) || ENV['LIBRA_SERVER'] || "openshift.redhat.com")
|
157
|
-
end
|
158
|
-
def openshift_online_server?
|
159
|
-
openshift_server =~ /openshift.redhat.com$/i
|
160
|
-
end
|
161
|
-
def openshift_url
|
162
|
-
"https://#{openshift_server}"
|
163
|
-
end
|
164
|
-
|
165
157
|
def to_host(s)
|
166
158
|
s =~ %r(^http(?:s)?://) ? URI(s).host : s
|
167
159
|
end
|
160
|
+
|
168
161
|
def to_uri(s)
|
169
162
|
begin
|
170
163
|
URI(s =~ %r(^http(?:s)?://) ? s : "https://#{s}")
|
@@ -187,12 +180,6 @@ module RHC
|
|
187
180
|
[uri.host, uri.user]
|
188
181
|
end
|
189
182
|
|
190
|
-
def openshift_rest_endpoint
|
191
|
-
uri = to_uri((options.server rescue nil) || ENV['LIBRA_SERVER'] || "openshift.redhat.com")
|
192
|
-
uri.path = '/broker/rest/api' if uri.path.blank? || uri.path == '/'
|
193
|
-
uri
|
194
|
-
end
|
195
|
-
|
196
183
|
def token_for_user
|
197
184
|
options.token or (token_store.get(options.rhlogin, options.server) if options.rhlogin && options.use_authorization_tokens)
|
198
185
|
end
|
@@ -350,7 +337,8 @@ module RHC
|
|
350
337
|
:downloaded_cartridge_url => 'From',
|
351
338
|
:auto_deploy => 'Deployment',
|
352
339
|
:sha1 => 'SHA1',
|
353
|
-
:ref => 'Git Reference'
|
340
|
+
:ref => 'Git Reference',
|
341
|
+
:use_authorization_tokens => 'Use Auth Tokens'
|
354
342
|
})
|
355
343
|
|
356
344
|
headings[value]
|
@@ -476,6 +464,11 @@ module RHC
|
|
476
464
|
env_vars
|
477
465
|
end
|
478
466
|
|
467
|
+
def to_boolean(s, or_nil=false)
|
468
|
+
return nil if s.nil? && or_nil
|
469
|
+
s.is_a?(String) ? !!(s =~ /^(true|t|yes|y|1)$/i) : s
|
470
|
+
end
|
471
|
+
|
479
472
|
BOUND_WARNING = self.method(:warn).to_proc
|
480
473
|
end
|
481
474
|
end
|
@@ -110,8 +110,8 @@ class HighLineExtension < HighLine
|
|
110
110
|
@wrap_at ? @wrap_at - indentation.length : nil
|
111
111
|
end
|
112
112
|
|
113
|
-
def header(str,opts
|
114
|
-
say Header.new(str, default_max_width, ' ')
|
113
|
+
def header(str, opts={}, &block)
|
114
|
+
say Header.new(str, default_max_width, ' ', (opts[:color]))
|
115
115
|
if block_given?
|
116
116
|
indent &block
|
117
117
|
end
|
data/lib/rhc/output_helpers.rb
CHANGED
@@ -3,7 +3,7 @@ module RHC
|
|
3
3
|
|
4
4
|
def display_team(team, ids=false)
|
5
5
|
paragraph do
|
6
|
-
header ["Team #{team.name}", ("(owned by #{team.owner})" if team.owner.present?)] do
|
6
|
+
header ["Team #{team.name}", ("(owned by #{team.owner.name})" if team.owner.present?)] do
|
7
7
|
section(:bottom => 1) do
|
8
8
|
say format_table \
|
9
9
|
nil,
|
@@ -21,7 +21,7 @@ module RHC
|
|
21
21
|
|
22
22
|
def display_domain(domain, applications=nil, ids=false)
|
23
23
|
paragraph do
|
24
|
-
header ["Domain #{domain.name}", ("(owned by #{domain.owner})" if domain.owner.present?)] do
|
24
|
+
header ["Domain #{domain.name}", ("(owned by #{domain.owner.name})" if domain.owner.present?)] do
|
25
25
|
section(:bottom => 1) do
|
26
26
|
say format_table \
|
27
27
|
nil,
|
@@ -70,6 +70,32 @@ module RHC
|
|
70
70
|
display_app(rest_app, nil, [:auto_deploy, :keep_deployments, :deployment_type, :deployment_branch])
|
71
71
|
end
|
72
72
|
|
73
|
+
def display_server(server)
|
74
|
+
paragraph do
|
75
|
+
header ["Server '#{server.nickname || to_host(server.hostname)}'", ("(in use)" if server.default?)], {:color => (:green if server.default?)} do
|
76
|
+
section(:bottom => 1) do
|
77
|
+
say format_table \
|
78
|
+
nil,
|
79
|
+
get_properties(
|
80
|
+
server,
|
81
|
+
:hostname,
|
82
|
+
:login,
|
83
|
+
:use_authorization_tokens,
|
84
|
+
:insecure,
|
85
|
+
:timeout,
|
86
|
+
:ssl_version,
|
87
|
+
:ssl_client_cert_file,
|
88
|
+
:ssl_ca_file
|
89
|
+
),
|
90
|
+
{
|
91
|
+
:delete => true,
|
92
|
+
:color => (:green if server.default?)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
73
99
|
def format_cart_header(cart)
|
74
100
|
[
|
75
101
|
cart.name,
|
data/lib/rhc/rest/client.rb
CHANGED
data/lib/rhc/rest/membership.rb
CHANGED
data/lib/rhc/rest/mock.rb
CHANGED
@@ -608,8 +608,8 @@ module RHC::Rest::Mock
|
|
608
608
|
d = MockRestDomain.new(self, id)
|
609
609
|
if extra
|
610
610
|
d.attributes['creation_time'] = '2013-07-21T15:00:44Z'
|
611
|
-
d.attributes['members'] = [{'owner' => true, 'name' => 'a_user_name'}]
|
612
611
|
d.attributes['allowed_gear_sizes'] = ['small']
|
612
|
+
d.add_member(RHC::Rest::Membership::Member.new(:id => '1', :role => 'admin', :explicit_role => 'admin', :owner => true, :login => 'a_user_name', :type => 'user'))
|
613
613
|
end
|
614
614
|
@domains << d
|
615
615
|
d
|
@@ -723,6 +723,7 @@ module RHC::Rest::Mock
|
|
723
723
|
@name = id
|
724
724
|
@applications = []
|
725
725
|
self.attributes = {:links => mock_response_links(mock_domain_links(id))}
|
726
|
+
init_members
|
726
727
|
end
|
727
728
|
|
728
729
|
def rename(id)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rhc/servers'
|
2
|
+
|
3
|
+
module RHC
|
4
|
+
module ServerHelpers
|
5
|
+
def openshift_server
|
6
|
+
to_host(openshift_raw_server)
|
7
|
+
end
|
8
|
+
|
9
|
+
def openshift_online_server?
|
10
|
+
openshift_server =~ openshift_online_server_regex
|
11
|
+
end
|
12
|
+
|
13
|
+
def openshift_online_server
|
14
|
+
'openshift.redhat.com'
|
15
|
+
end
|
16
|
+
|
17
|
+
def openshift_online_server_regex
|
18
|
+
/^#{openshift_online_server.gsub(/\./, '\.')}$/i
|
19
|
+
end
|
20
|
+
|
21
|
+
def openshift_url
|
22
|
+
"https://#{openshift_server}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def openshift_rest_endpoint
|
26
|
+
uri = to_uri(openshift_raw_server)
|
27
|
+
uri.path = '/broker/rest/api' if uri.path.blank? || uri.path == '/'
|
28
|
+
uri
|
29
|
+
end
|
30
|
+
|
31
|
+
def libra_server_env
|
32
|
+
ENV['LIBRA_SERVER']
|
33
|
+
end
|
34
|
+
|
35
|
+
def rhc_server_env
|
36
|
+
ENV['RHC_SERVER']
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def openshift_raw_server
|
41
|
+
server = (options.server rescue nil) || ENV['LIBRA_SERVER'] || (config['libra_server'] rescue nil) || openshift_online_server
|
42
|
+
@servers ||= RHC::Servers.new
|
43
|
+
(@servers.find(server).hostname rescue nil) || server
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/rhc/servers.rb
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rhc/helpers'
|
4
|
+
require 'rhc/server_helpers'
|
5
|
+
|
6
|
+
module RHC
|
7
|
+
class Server
|
8
|
+
include RHC::ServerHelpers
|
9
|
+
attr_accessor :hostname, :nickname, :login
|
10
|
+
attr_accessor :use_authorization_tokens, :insecure, :timeout
|
11
|
+
attr_accessor :ssl_version, :ssl_client_cert_file, :ssl_ca_file
|
12
|
+
attr_accessor :default
|
13
|
+
|
14
|
+
def self.from_yaml_hash(hash)
|
15
|
+
hash.symbolize_keys!
|
16
|
+
Server.new(hash.delete(:hostname), hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(hostname, args={})
|
20
|
+
@hostname = RHC::Servers.to_host(hostname)
|
21
|
+
@nickname = args[:nickname]
|
22
|
+
@login = args[:login]
|
23
|
+
@use_authorization_tokens = RHC::Helpers.to_boolean(args[:use_authorization_tokens], true)
|
24
|
+
@insecure = RHC::Helpers.to_boolean(args[:insecure], true)
|
25
|
+
@timeout = Integer(args[:timeout]) if args[:timeout].present?
|
26
|
+
@ssl_version = args[:ssl_version]
|
27
|
+
@ssl_client_cert_file = args[:ssl_client_cert_file]
|
28
|
+
@ssl_ca_file = args[:ssl_ca_file]
|
29
|
+
@default = args[:default]
|
30
|
+
end
|
31
|
+
|
32
|
+
def default?
|
33
|
+
!!@default
|
34
|
+
end
|
35
|
+
|
36
|
+
def designation
|
37
|
+
@nickname || @hostname
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_yaml_hash
|
41
|
+
{}.tap do |h|
|
42
|
+
instance_variables.each do |k|
|
43
|
+
h[k.to_s.delete('@')] = instance_variable_get(k)
|
44
|
+
end
|
45
|
+
end.reject{|k, v| v.nil? || k == 'default'}.inject({}){|h, (k, v)| h[k] = v.is_a?(String) ? v.to_s : v; h }
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_config
|
49
|
+
RHC::Vendor::ParseConfig.new.tap do |config|
|
50
|
+
h = to_yaml_hash
|
51
|
+
h['default_rhlogin'] = h.delete('login')
|
52
|
+
h['libra_server'] = h.delete('hostname')
|
53
|
+
h.each{|k, v| config.add(k, v)}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
@nickname ? "#{@nickname} (#{@hostname})" : @hostname
|
59
|
+
end
|
60
|
+
|
61
|
+
def <=>(other)
|
62
|
+
designation <=> other.designation
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Servers
|
67
|
+
include RHC::ServerHelpers
|
68
|
+
attr_reader :servers
|
69
|
+
|
70
|
+
def initialize(config=nil)
|
71
|
+
@servers ||= load || []
|
72
|
+
sync_from_config(config)
|
73
|
+
end
|
74
|
+
|
75
|
+
def reload(config=nil)
|
76
|
+
@servers = load || []
|
77
|
+
sync_from_config(config)
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def path
|
82
|
+
File.join(RHC::Config.home_dir, '.openshift', "#{ENV['OPENSHIFT_SERVERS'].presence || 'servers'}.yml")
|
83
|
+
end
|
84
|
+
|
85
|
+
def present?
|
86
|
+
File.exists?(path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.to_host(hostname)
|
90
|
+
uri = RHC::Helpers.to_uri(hostname)
|
91
|
+
uri.scheme == 'https' && uri.port == URI::HTTPS::DEFAULT_PORT ? uri.host : hostname
|
92
|
+
end
|
93
|
+
|
94
|
+
def add(hostname, args={})
|
95
|
+
raise RHC::ServerHostnameExistsException.new(hostname) if hostname_exists?(hostname)
|
96
|
+
raise RHC::ServerNicknameExistsException.new(args[:nickname]) if args[:nickname] && nickname_exists?(args[:nickname])
|
97
|
+
|
98
|
+
args[:nickname] = suggest_server_nickname(Servers.to_host(hostname)) unless args[:nickname].present?
|
99
|
+
|
100
|
+
Server.new(hostname, args).tap{ |server| @servers << server }
|
101
|
+
end
|
102
|
+
|
103
|
+
def update(server, args={})
|
104
|
+
find(server).tap do |s|
|
105
|
+
args.each do |k, v|
|
106
|
+
s.send("#{k}=", v) unless v.nil?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_or_update(hostname, args={})
|
112
|
+
update(hostname, args) rescue add(hostname, args)
|
113
|
+
end
|
114
|
+
|
115
|
+
def remove(server)
|
116
|
+
@servers.delete(find(server))
|
117
|
+
end
|
118
|
+
|
119
|
+
def list
|
120
|
+
@servers || []
|
121
|
+
end
|
122
|
+
|
123
|
+
def find(server)
|
124
|
+
exists?(server).tap{|s| raise RHC::ServerNotConfiguredException.new(server) unless s }
|
125
|
+
end
|
126
|
+
|
127
|
+
def nickname_exists?(nickname)
|
128
|
+
list.select{|s| s.nickname.present? && s.nickname == nickname}.first
|
129
|
+
end
|
130
|
+
|
131
|
+
def hostname_exists?(hostname)
|
132
|
+
hostname = Servers.to_host(hostname)
|
133
|
+
list.select{|s| s.hostname == hostname}.first
|
134
|
+
end
|
135
|
+
|
136
|
+
def exists?(server)
|
137
|
+
hostname_exists?(server) || nickname_exists?(server)
|
138
|
+
end
|
139
|
+
|
140
|
+
def default
|
141
|
+
list.select(&:default?).first || list.first
|
142
|
+
end
|
143
|
+
|
144
|
+
def sync_from_config(config)
|
145
|
+
unless config.nil? || !config.has_configs_from_files?
|
146
|
+
o = config.to_options
|
147
|
+
add_or_update(
|
148
|
+
o[:server],
|
149
|
+
:login => o[:rhlogin],
|
150
|
+
:use_authorization_tokens => o[:use_authorization_tokens],
|
151
|
+
:insecure => o[:insecure],
|
152
|
+
:timeout => o[:timeout],
|
153
|
+
:ssl_version => o[:ssl_version],
|
154
|
+
:ssl_client_cert_file => o[:ssl_client_cert_file],
|
155
|
+
:ssl_ca_file => o[:ssl_ca_file])
|
156
|
+
list.each{|server| server.default = server.hostname == o[:server]}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def save!
|
161
|
+
FileUtils.mkdir_p File.dirname(path)
|
162
|
+
File.open(path, 'w') do |c|
|
163
|
+
c.puts list.collect{|s| {'server' => s.to_yaml_hash}}.to_yaml
|
164
|
+
end
|
165
|
+
self
|
166
|
+
end
|
167
|
+
|
168
|
+
def backup
|
169
|
+
FileUtils.cp(path, "#{path}.bak") if File.exists? path
|
170
|
+
end
|
171
|
+
|
172
|
+
protected
|
173
|
+
def load
|
174
|
+
(YAML.load_file(path) || [] rescue []).collect do |e|
|
175
|
+
Server.from_yaml_hash e['server']
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def suggest_server_nickname(hostname)
|
180
|
+
suggestion = (case hostname
|
181
|
+
when openshift_online_server_regex
|
182
|
+
'online'
|
183
|
+
when /^(.*)\.#{openshift_online_server.gsub(/\./, '\.')}$/i
|
184
|
+
$1
|
185
|
+
else
|
186
|
+
'server' + ((list.compact.map{|i| i.match(/^server(\d+)$/)}.compact.map{|i| i[1]}.map(&:to_i).max + 1).to_s rescue '1')
|
187
|
+
end)
|
188
|
+
s = nickname_exists?(suggestion)
|
189
|
+
s.present? && s.hostname != hostname ? nil : suggestion
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|