MuranoCLI 3.2.0.beta.9 → 3.2.1.pre.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Rakefile +5 -0
- data/dockers/README.rst +7 -0
- data/dockers/RELEASE.rst +6 -3
- data/dockers/docker-test.sh +45 -17
- data/docs/completions/murano_completion-bash +211 -86
- data/lib/MrMurano/Account.rb +72 -4
- data/lib/MrMurano/Business.rb +163 -2
- data/lib/MrMurano/Commander-Entry.rb +1 -2
- data/lib/MrMurano/Config.rb +19 -18
- data/lib/MrMurano/Content.rb +26 -19
- data/lib/MrMurano/Gateway.rb +51 -10
- data/lib/MrMurano/ReCommander.rb +1 -1
- data/lib/MrMurano/Solution-Services.rb +80 -35
- data/lib/MrMurano/Solution-Users.rb +1 -0
- data/lib/MrMurano/SyncRoot.rb +10 -3
- data/lib/MrMurano/SyncUpDown-Core.rb +47 -36
- data/lib/MrMurano/SyncUpDown-Item.rb +46 -14
- data/lib/MrMurano/SyncUpDown.rb +22 -20
- data/lib/MrMurano/Webservice-Endpoint.rb +20 -18
- data/lib/MrMurano/Webservice-File.rb +63 -20
- data/lib/MrMurano/commands/business.rb +14 -1
- data/lib/MrMurano/commands/child.rb +148 -0
- data/lib/MrMurano/commands/devices.rb +298 -149
- data/lib/MrMurano/commands/element.rb +2 -1
- data/lib/MrMurano/commands/globals.rb +3 -0
- data/lib/MrMurano/commands/network.rb +152 -33
- data/lib/MrMurano/commands/sync.rb +2 -2
- data/lib/MrMurano/commands.rb +1 -0
- data/lib/MrMurano/verbosing.rb +13 -2
- data/lib/MrMurano/version.rb +1 -1
- data/spec/Account_spec.rb +43 -11
- data/spec/Content_spec.rb +5 -3
- data/spec/GatewayBase_spec.rb +1 -1
- data/spec/GatewayDevice_spec.rb +47 -8
- data/spec/GatewayResource_spec.rb +1 -1
- data/spec/GatewaySettings_spec.rb +1 -1
- data/spec/HttpAuthed_spec.rb +17 -3
- data/spec/ProjectFile_spec.rb +59 -23
- data/spec/Setting_spec.rb +2 -1
- data/spec/Solution-ServiceConfig_spec.rb +1 -1
- data/spec/Solution-ServiceEventHandler_spec.rb +27 -20
- data/spec/Solution-ServiceModules_spec.rb +7 -5
- data/spec/Solution-UsersRoles_spec.rb +7 -1
- data/spec/Solution_spec.rb +9 -1
- data/spec/SyncRoot_spec.rb +5 -5
- data/spec/SyncUpDown_spec.rb +262 -211
- data/spec/Verbosing_spec.rb +49 -8
- data/spec/Webservice-Cors_spec.rb +10 -1
- data/spec/Webservice-Endpoint_spec.rb +84 -65
- data/spec/Webservice-File_spec.rb +16 -11
- data/spec/Webservice-Setting_spec.rb +7 -1
- data/spec/_workspace.rb +9 -0
- data/spec/cmd_business_spec.rb +5 -10
- data/spec/cmd_common.rb +67 -32
- data/spec/cmd_config_spec.rb +9 -14
- data/spec/cmd_content_spec.rb +15 -26
- data/spec/cmd_cors_spec.rb +9 -12
- data/spec/cmd_device_spec.rb +31 -45
- data/spec/cmd_domain_spec.rb +12 -10
- data/spec/cmd_element_spec.rb +18 -17
- data/spec/cmd_exchange_spec.rb +1 -4
- data/spec/cmd_init_spec.rb +56 -72
- data/spec/cmd_keystore_spec.rb +17 -26
- data/spec/cmd_link_spec.rb +13 -17
- data/spec/cmd_password_spec.rb +9 -10
- data/spec/cmd_setting_application_spec.rb +95 -68
- data/spec/cmd_setting_product_spec.rb +59 -37
- data/spec/cmd_status_spec.rb +46 -84
- data/spec/cmd_syncdown_application_spec.rb +28 -50
- data/spec/cmd_syncdown_both_spec.rb +44 -93
- data/spec/cmd_syncdown_unit_spec.rb +858 -0
- data/spec/cmd_syncup_spec.rb +21 -56
- data/spec/cmd_token_spec.rb +0 -3
- data/spec/cmd_usage_spec.rb +15 -10
- data/spec/dry_run_formatter.rb +1 -0
- data/spec/fixtures/dumped_config +4 -4
- data/spec/spec_helper.rb +3 -0
- metadata +4 -2
@@ -51,8 +51,10 @@ module MrMurano
|
|
51
51
|
# @example Initializing with an Item
|
52
52
|
# item = Item.new(:name => 'get')
|
53
53
|
# Item.new(item)
|
54
|
-
def initialize(
|
55
|
-
|
54
|
+
def initialize(hash={})
|
55
|
+
hash.each_pair do |key, val|
|
56
|
+
self[key] = val
|
57
|
+
end
|
56
58
|
end
|
57
59
|
|
58
60
|
def as_inst(key)
|
@@ -102,7 +104,7 @@ module MrMurano
|
|
102
104
|
|
103
105
|
# @return [Hash{Symbol=>Object}] A hash that represents this Item
|
104
106
|
def to_h
|
105
|
-
Hash[instance_variables.map { |k| [as_sym(k), instance_variable_get(k)] }]
|
107
|
+
Hash[instance_variables.sort.map { |k| [as_sym(k), instance_variable_get(k)] }]
|
106
108
|
end
|
107
109
|
|
108
110
|
# Adds the contents of item to self.
|
@@ -153,25 +155,38 @@ module MrMurano
|
|
153
155
|
dup.reject!(&block)
|
154
156
|
end
|
155
157
|
|
158
|
+
# Scrub local, non-BizAPI/Pegasus attrs from Item (before uploading).
|
159
|
+
def reject_ephemeral!
|
160
|
+
reject do |attr_key, _|
|
161
|
+
[
|
162
|
+
# Server-siders:
|
163
|
+
# :name,
|
164
|
+
# :script,
|
165
|
+
:local_path,
|
166
|
+
:id,
|
167
|
+
:line_beg,
|
168
|
+
:line_end,
|
169
|
+
:header,
|
170
|
+
:diff,
|
171
|
+
:selected,
|
172
|
+
:synckey,
|
173
|
+
:synctype,
|
174
|
+
:updated_at,
|
175
|
+
:dup_count,
|
176
|
+
].include? attr_key
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
156
180
|
# For unit testing.
|
157
181
|
include Comparable
|
158
182
|
def <=>(other)
|
159
183
|
# rubocop:disable Style/RedundantSelf: Redundant self detected.
|
160
|
-
# MAYBE/2017-07-18: Permanently disable Style/RedundantSelf?
|
161
184
|
self.to_h <=> other.to_h
|
162
185
|
end
|
163
186
|
|
164
187
|
def location_friendly(show_type: false, full_path: false)
|
165
|
-
|
166
|
-
|
167
|
-
desc = desc.relative_path_from(Pathname.pwd) unless full_path
|
168
|
-
desc = desc.to_s
|
169
|
-
desc = "#{desc}:#{@line_beg}" if !@line_beg.nil? && @line_beg > 0
|
170
|
-
desc = "#{desc}-#{@line_end}" if !@line_end.nil? && @line_end > 0
|
171
|
-
else
|
172
|
-
desc = @synckey
|
173
|
-
end
|
174
|
-
desc += ' [phantom]' if @phantom
|
188
|
+
desc = location_path_and_line(full_path: full_path)
|
189
|
+
desc += ' [phantom]' if defined?(@phantom) && @phantom
|
175
190
|
return desc unless show_type
|
176
191
|
unless @pp_desc.to_s.empty? || (@pp_desc == @synckey)
|
177
192
|
desc += " (#{@pp_desc})"
|
@@ -180,6 +195,23 @@ module MrMurano
|
|
180
195
|
desc += " [#{@method} #{@path}]" if (@method && @path)
|
181
196
|
desc
|
182
197
|
end
|
198
|
+
|
199
|
+
def location_path_and_line(full_path: false)
|
200
|
+
if !defined?(@local_path) || @local_path.nil?
|
201
|
+
@synckey
|
202
|
+
else
|
203
|
+
desc = @local_path
|
204
|
+
desc = desc.relative_path_from(Pathname.pwd) unless full_path
|
205
|
+
desc = desc.to_s
|
206
|
+
if defined?(@line_beg) && !@line_beg.nil? && @line_beg > 0
|
207
|
+
desc = "#{desc}:#{@line_beg}"
|
208
|
+
end
|
209
|
+
if defined?(@line_end) && !@line_end.nil? && @line_end > 0
|
210
|
+
desc = "#{desc}-#{@line_end}"
|
211
|
+
end
|
212
|
+
desc
|
213
|
+
end
|
214
|
+
end
|
183
215
|
end
|
184
216
|
end
|
185
217
|
end
|
data/lib/MrMurano/SyncUpDown.rb
CHANGED
@@ -48,7 +48,7 @@ module MrMurano
|
|
48
48
|
# :nocov:
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
51
|
+
def remove_or_clear(itemkey, _thereitem, _modify=false)
|
52
52
|
remove(itemkey)
|
53
53
|
end
|
54
54
|
|
@@ -88,13 +88,14 @@ module MrMurano
|
|
88
88
|
# @param root [Pathname,String] Root path for this resource type from config files
|
89
89
|
# @param path [Pathname,String] Path to local item
|
90
90
|
# @return [Item] hash of the details for the remote item for this path
|
91
|
-
def
|
91
|
+
def to_remote_items(root, path)
|
92
92
|
# This mess brought to you by Windows short path names.
|
93
93
|
path = Dir.glob(path.to_s).first
|
94
94
|
root = Dir.glob(root.to_s).first
|
95
95
|
path = Pathname.new(path)
|
96
96
|
root = Pathname.new(root)
|
97
|
-
Item.new(name: path.realpath.relative_path_from(root.realpath).to_s)
|
97
|
+
item = Item.new(name: path.realpath.relative_path_from(root.realpath).to_s)
|
98
|
+
[item]
|
98
99
|
end
|
99
100
|
|
100
101
|
##
|
@@ -120,7 +121,7 @@ module MrMurano
|
|
120
121
|
# @param item [Item] listing details for the item.
|
121
122
|
# @return [Pathname] path to save (or merge) remote item into
|
122
123
|
def tolocalpath(into, item)
|
123
|
-
return item[:local_path] unless item
|
124
|
+
return item[:local_path] unless item[:local_path].nil?
|
124
125
|
itemkey = @itemkey.to_sym
|
125
126
|
name = tolocalname(item, itemkey)
|
126
127
|
raise "Bad key(#{itemkey}) for #{item}" if name.nil?
|
@@ -188,9 +189,12 @@ module MrMurano
|
|
188
189
|
local.dirname.mkpath
|
189
190
|
local.open('wb') do |io|
|
190
191
|
# Do not modify remote content when diffing, e.g., do not add #ENDPOINT header.
|
191
|
-
untainted = options[:diff]
|
192
|
+
untainted = options[:diff] || false
|
192
193
|
fetch(id, untainted) do |chunk|
|
193
|
-
|
194
|
+
# First chunk may be header, if not part of script.
|
195
|
+
# Second chunk (only only chunk), is script (which may include header).
|
196
|
+
encoded = is_tmp && chunk || config_vars_encode(chunk)
|
197
|
+
io.write(encoded)
|
194
198
|
end
|
195
199
|
end
|
196
200
|
update_mtime(local, item)
|
@@ -405,7 +409,6 @@ module MrMurano
|
|
405
409
|
# @param from [Pathname] Directory of items to scan
|
406
410
|
# @return [Array<Item>] Items found
|
407
411
|
def localitems(from)
|
408
|
-
# TODO: Profile this.
|
409
412
|
debug "#{self.class}: Getting local items from:\n #{from}"
|
410
413
|
search_in = from.to_s
|
411
414
|
sf = searchFor.map { |i| ::File.join(search_in, i) }
|
@@ -416,14 +419,15 @@ module MrMurano
|
|
416
419
|
# about duplicate resources. I [lb] think this problem has existed
|
417
420
|
# but was exacerbated by the change to support sub-directory scripts
|
418
421
|
# (Nested Lua support).
|
419
|
-
|
422
|
+
files = Dir[*sf].collect { |path| File.absolute_path(path) }
|
423
|
+
files = files.uniq.flatten.compact.reject do |path|
|
420
424
|
if ::File.directory?(path)
|
421
425
|
true
|
422
426
|
else
|
423
427
|
ignoring.any? { |pattern| ignore?(path, pattern) }
|
424
428
|
end
|
425
429
|
end
|
426
|
-
items =
|
430
|
+
items = files.map do |path|
|
427
431
|
# Do not resolve symlinks, just relative paths (. and ..),
|
428
432
|
# otherwise it makes nested Lua support tricky, because
|
429
433
|
# symlinks might be outside the root item path, and then
|
@@ -433,24 +437,22 @@ module MrMurano
|
|
433
437
|
else
|
434
438
|
rpath = Pathname.new(path).expand_path
|
435
439
|
end
|
436
|
-
|
437
|
-
|
438
|
-
item.compact.map do |itm|
|
439
|
-
itm[:local_path] = rpath
|
440
|
-
itm
|
441
|
-
end
|
442
|
-
elsif !item.nil?
|
440
|
+
files_items = to_remote_items(from, rpath)
|
441
|
+
files_items.compact.map do |item|
|
443
442
|
item[:local_path] = rpath
|
444
443
|
item
|
445
444
|
end
|
446
445
|
end
|
447
|
-
|
448
|
-
|
449
|
-
items
|
446
|
+
items = items.flatten.compact.sort_by { |item| item[:local_path] }
|
447
|
+
debug_print_localitems(items)
|
448
|
+
sort_by_name(items)
|
449
|
+
end
|
450
|
+
|
451
|
+
def debug_print_localitems(items)
|
452
|
+
return unless $cfg['tool.debug']
|
450
453
|
loci = items.map { |it| it.location_friendly(full_path: true) }
|
451
454
|
item_list = loci.sort.join("\n ")
|
452
455
|
debug "#{self.class}: localitems' matches:\n #{item_list}"
|
453
|
-
sort_by_name(items)
|
454
456
|
end
|
455
457
|
|
456
458
|
def ignore?(path, pattern)
|
@@ -25,8 +25,20 @@ module MrMurano
|
|
25
25
|
attr_accessor :path
|
26
26
|
# @return [String] Acceptable Content-Type for this endpoint
|
27
27
|
attr_accessor :content_type
|
28
|
-
#
|
28
|
+
# NOTE: We do not use use_basic_auth internally, but it's passed from
|
29
|
+
# the server, so the code actually indirectly sees it in `def []=`.
|
29
30
|
attr_accessor :use_basic_auth
|
31
|
+
|
32
|
+
def reject_ephemeral!
|
33
|
+
super.reject do |attr_key, _|
|
34
|
+
[
|
35
|
+
# Server-siders:
|
36
|
+
# :method,
|
37
|
+
# :path,
|
38
|
+
# :content_type,
|
39
|
+
].include? attr_key
|
40
|
+
end
|
41
|
+
end
|
30
42
|
end
|
31
43
|
|
32
44
|
def initialize
|
@@ -170,12 +182,12 @@ module MrMurano
|
|
170
182
|
name
|
171
183
|
end
|
172
184
|
|
173
|
-
def
|
185
|
+
def to_remote_items(_from, path)
|
174
186
|
# Path could be have multiple endpoints in side, so a loop.
|
175
|
-
items = []
|
176
187
|
path = Pathname.new(path) unless path.is_a? Pathname
|
188
|
+
items = []
|
177
189
|
cur = nil
|
178
|
-
lineno =
|
190
|
+
lineno = 0
|
179
191
|
path.readlines.each do |line|
|
180
192
|
lineno += 1
|
181
193
|
md = @match_header.match(line)
|
@@ -183,20 +195,8 @@ module MrMurano
|
|
183
195
|
# header line.
|
184
196
|
cur[:line_end] = lineno - 1 unless cur.nil?
|
185
197
|
items << cur unless cur.nil?
|
186
|
-
# VERIFY/2017-07-03: The syncdown test is revealing a
|
187
|
-
# problem with casing. The original file has a lowercase
|
188
|
-
# HTTP verb, e.g., "post". This is what syncup uploaded.
|
189
|
-
# But on murano status, the local route's method is upcased
|
190
|
-
# in memory, so the status command says the route is diff.
|
191
|
-
# But on murano diff, MurCLI makes two local temp files
|
192
|
-
# to execute the diff, and it also upcases the method in
|
193
|
-
# both files, so the diff runs clean!
|
194
|
-
# 2017-07-03: (lb): Adding upcase; and recreating header.
|
195
|
-
# 2018-06-11: (lb): Added :exclude_header to deal with
|
196
|
-
# service side missing header. Which isn't an error, per se.
|
197
198
|
script_header = "--#ENDPOINT #{md[:method].upcase} #{md[:path]}"
|
198
199
|
script_header += " #{md[:ctype]}" unless md[:ctype].to_s.empty?
|
199
|
-
script_header += "\n"
|
200
200
|
cur = RouteItem.new(
|
201
201
|
method: md[:method].upcase,
|
202
202
|
path: md[:path],
|
@@ -211,8 +211,10 @@ module MrMurano
|
|
211
211
|
cur[:script] += line
|
212
212
|
end
|
213
213
|
end
|
214
|
-
|
215
|
-
|
214
|
+
unless cur.nil?
|
215
|
+
cur[:line_end] = lineno
|
216
|
+
items << cur
|
217
|
+
end
|
216
218
|
items
|
217
219
|
end
|
218
220
|
|
@@ -34,6 +34,19 @@ module MrMurano
|
|
34
34
|
attr_accessor :md5
|
35
35
|
# @return [Integer] Size in bytes of the stored file.
|
36
36
|
attr_accessor :size
|
37
|
+
|
38
|
+
def reject_ephemeral!
|
39
|
+
super.reject do |attr_key, _|
|
40
|
+
[
|
41
|
+
# Server-siders:
|
42
|
+
# :path,
|
43
|
+
# :mime_type,
|
44
|
+
:checksum,
|
45
|
+
:md5,
|
46
|
+
:size,
|
47
|
+
].include? attr_key
|
48
|
+
end
|
49
|
+
end
|
37
50
|
end
|
38
51
|
|
39
52
|
def initialize
|
@@ -212,36 +225,63 @@ module MrMurano
|
|
212
225
|
# @param root [Pathname,String] Root path for this resource type from config files
|
213
226
|
# @param path [Pathname,String] Path to local item
|
214
227
|
# @return [Item] hash of the details for the remote item for this path
|
215
|
-
def
|
216
|
-
|
217
|
-
|
228
|
+
def to_remote_items(from, path)
|
229
|
+
items = super(from, path)
|
230
|
+
|
231
|
+
name = items[0][:name]
|
218
232
|
name = '/' if name == $cfg['files.default_page']
|
219
233
|
name = "/#{name}" unless name.chars.first == '/'
|
220
234
|
|
221
|
-
mime = MIME::Types.type_for(path.to_s)[0]
|
235
|
+
mime = MIME::Types.type_for(path.to_s)[0]
|
236
|
+
mime ||= MIME::Types['application/octet-stream'][0]
|
237
|
+
|
238
|
+
file_size = path.size
|
222
239
|
|
223
240
|
# FIXME/2018-04-13: (lb): When did platform switch from SHA1 to MD5?
|
224
241
|
# Leaving this dead code block as a reminder to verify the new
|
225
242
|
# behavior is the intended behavior.
|
226
243
|
xsum_is_sha1 = false
|
227
244
|
if xsum_is_sha1
|
228
|
-
|
229
|
-
# It first converts the file to hex, then takes the SHA1 of that string
|
230
|
-
#xsum = Digest::SHA1.file(path.to_s).hexdigest
|
231
|
-
xsum = Digest::SHA1.new
|
232
|
-
path.open('rb:ASCII-8BIT') do |io|
|
233
|
-
# rubocop:disable Lint/AssignmentInCondition
|
234
|
-
# "Assignment in condition - you probably meant to use ==."
|
235
|
-
while chunk = io.read(1_048_576)
|
236
|
-
xsum << Digest.hexencode(chunk)
|
237
|
-
end
|
238
|
-
end
|
245
|
+
digobj = remote_item_checksum_sha1(path)
|
239
246
|
else
|
240
|
-
|
247
|
+
# MD5 of the empty string is not empty (it's d41d8cd98f00b204e9800998ecf8427e)
|
248
|
+
# but BizAPI (or Pegasus; whomever) sends an empty string for an empty file.
|
249
|
+
if file_size.zero?
|
250
|
+
checksum = ''
|
251
|
+
digobj = nil
|
252
|
+
else
|
253
|
+
digobj = remote_item_checksum_md5(path)
|
254
|
+
end
|
241
255
|
end
|
242
|
-
debug "Checking #{name} (#{mime.simplified} #{xsum.hexdigest})"
|
243
256
|
|
244
|
-
|
257
|
+
checksum = digobj.hexdigest unless digobj.nil?
|
258
|
+
debug "Checking #{name} (#{mime.simplified} #{checksum})"
|
259
|
+
|
260
|
+
item = FileItem.new(
|
261
|
+
path: name,
|
262
|
+
mime_type: mime.simplified,
|
263
|
+
checksum: checksum,
|
264
|
+
size: file_size,
|
265
|
+
)
|
266
|
+
[item]
|
267
|
+
end
|
268
|
+
|
269
|
+
def remote_item_checksum_sha1(path)
|
270
|
+
# NOTE: It does not actually take the SHA1 of the file. It first
|
271
|
+
# converts the file to hex, then takes the SHA1 of that string.
|
272
|
+
xsum = Digest::SHA1.new
|
273
|
+
path.open('rb:ASCII-8BIT') do |io|
|
274
|
+
# rubocop:disable Lint/AssignmentInCondition
|
275
|
+
# "Assignment in condition - you probably meant to use ==."
|
276
|
+
while chunk = io.read(1_048_576)
|
277
|
+
xsum << Digest.hexencode(chunk)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
xsum
|
281
|
+
end
|
282
|
+
|
283
|
+
def remote_item_checksum_md5(path)
|
284
|
+
Digest::MD5.file(path.to_s)
|
245
285
|
end
|
246
286
|
|
247
287
|
# @param item [FileItem] The item to get a key from
|
@@ -254,8 +294,11 @@ module MrMurano
|
|
254
294
|
# @param item_a [FileItem]
|
255
295
|
# @param item_b [FileItem]
|
256
296
|
def docmp(item_a, item_b)
|
257
|
-
(
|
258
|
-
|
297
|
+
(
|
298
|
+
item_a[:mime_type] != item_b[:mime_type] ||
|
299
|
+
item_a[:checksum] != item_b[:checksum] ||
|
300
|
+
item_a[:size] != item_b[:size]
|
301
|
+
)
|
259
302
|
end
|
260
303
|
end
|
261
304
|
|
@@ -30,6 +30,13 @@ If you need to set the business ID, try some of the following:
|
|
30
30
|
Add the ID to the user config: #{MrMurano::EXE_NAME} config business.id <ID> --user
|
31
31
|
Setup a project interactively: #{MrMurano::EXE_NAME} init
|
32
32
|
|
33
|
+
- Working with enterprise network child businesses:
|
34
|
+
Get a list of child business IDs: #{MrMurano::EXE_NAME} network children
|
35
|
+
Specify the child ID explicitly #{MrMurano::EXE_NAME} <cmd> --config business.child=<ID>
|
36
|
+
Add the child ID to a project config: #{MrMurano::EXE_NAME} config business.child <ID>
|
37
|
+
Add the child ID to the user config: #{MrMurano::EXE_NAME} config business.child <ID> --user
|
38
|
+
|
39
|
+
|
33
40
|
).strip
|
34
41
|
c.project_not_required = true
|
35
42
|
c.subcmdgrouphelp = true
|
@@ -162,6 +169,9 @@ arguments. For example,
|
|
162
169
|
).strip
|
163
170
|
c.project_not_required = true
|
164
171
|
|
172
|
+
# Add --network option
|
173
|
+
c.option('--network')
|
174
|
+
|
165
175
|
cmd_table_output_add_options(c)
|
166
176
|
|
167
177
|
c.action do |args, options|
|
@@ -181,6 +191,9 @@ Find business by name or ID.
|
|
181
191
|
|
182
192
|
cmd_table_output_add_options(c)
|
183
193
|
|
194
|
+
# Add --network option
|
195
|
+
c.option('--network')
|
196
|
+
|
184
197
|
# Add --business/-id/-name options.
|
185
198
|
cmd_option_business_pickers(c)
|
186
199
|
|
@@ -325,7 +338,7 @@ def cmd_business_find_businesses(acc, args, options)
|
|
325
338
|
end
|
326
339
|
|
327
340
|
MrMurano::Verbose.whirly_start 'Looking for businesses...'
|
328
|
-
bizz = acc.businesses(bid: bid, name: name, fuzzy: fuzzy)
|
341
|
+
bizz = acc.businesses(bid: bid, name: name, fuzzy: fuzzy, options: options)
|
329
342
|
MrMurano::Verbose.whirly_stop
|
330
343
|
|
331
344
|
bizz
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Copyright © 2016-2017 Exosite LLC. All Rights Reserved
|
2
|
+
# License: PROPRIETARY. See LICENSE.txt.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# vim:tw=0:ts=2:sw=2:et:ai
|
6
|
+
# Unauthorized copying of this file is strictly prohibited.
|
7
|
+
|
8
|
+
require 'MrMurano/ReCommander'
|
9
|
+
|
10
|
+
# *** Base network command help
|
11
|
+
# ------------------------------
|
12
|
+
command :child do |c|
|
13
|
+
c.syntax = %(murano child)
|
14
|
+
c.summary = %(About child)
|
15
|
+
c.description = %(Commands for working with enterprise business network children.)
|
16
|
+
c.project_not_required = true
|
17
|
+
c.subcmdgrouphelp = true
|
18
|
+
c.action do |_args, _options|
|
19
|
+
::Commander::UI.enable_paging unless $cfg['tool.no-page']
|
20
|
+
say MrMurano::SubCmdGroupHelp.new(c).get_help
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# View Network Child Business
|
25
|
+
command 'child show' do |c|
|
26
|
+
c.syntax = %(murano child show)
|
27
|
+
c.summary = %(View details about a child business in a business network.)
|
28
|
+
c.description = %(
|
29
|
+
View details about a child businesses in a business network.
|
30
|
+
).strip
|
31
|
+
c.example %(
|
32
|
+
View details about a child business using the parent bizid and child bizid from the config
|
33
|
+
).strip, 'murano child show'
|
34
|
+
c.example %(
|
35
|
+
View details about a child business in a business network using a passed in business.id and business.child
|
36
|
+
).strip, 'murano child show -c business.id=<PARENT_BUSINESS_ID> -c business.child=<CHILD_BUSINESS_ID>'
|
37
|
+
c.project_not_required = true
|
38
|
+
|
39
|
+
c.action do |_args, _options|
|
40
|
+
show_child
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_child
|
44
|
+
biz = MrMurano::Business.new
|
45
|
+
biz.must_business_id!
|
46
|
+
biz.must_child!
|
47
|
+
MrMurano::Verbose.whirly_start 'Fetching network child business...'
|
48
|
+
business_network = biz.get_business_network(biz.bid)
|
49
|
+
all_child_businesses = biz.view_child_businesses(biz.bid)
|
50
|
+
child_business = all_child_businesses.select { |child_biz| child_biz[:bizid] == biz.cid }[0]
|
51
|
+
MrMurano::Verbose.whirly_stop
|
52
|
+
|
53
|
+
puts('Business Network Name: ' + business_network[:name])
|
54
|
+
puts('Child Business ID: ' + child_business[:bizid])
|
55
|
+
puts('Child Business Name: ' + child_business[:name])
|
56
|
+
|
57
|
+
table = Terminal::Table.new
|
58
|
+
table.title = 'Members'
|
59
|
+
table.add_row %w[role email]
|
60
|
+
table.add_separator
|
61
|
+
|
62
|
+
child_business[:members].each do |member|
|
63
|
+
table.add_row [
|
64
|
+
member[:role],
|
65
|
+
member[:email],
|
66
|
+
]
|
67
|
+
end
|
68
|
+
puts table
|
69
|
+
|
70
|
+
return unless all_child_businesses.nil?
|
71
|
+
MrMurano::Verbose.error 'Error fetching network child businesses.'
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Add a Member to a Network Child Business
|
77
|
+
command 'child add' do |c|
|
78
|
+
c.syntax = %(murano child add <NEW_MEMBER_EMAIL>)
|
79
|
+
c.summary = %(Add a member to a network child business.)
|
80
|
+
c.description = %(
|
81
|
+
Add a member to a network child business.
|
82
|
+
).strip
|
83
|
+
c.example %(
|
84
|
+
Add a member to a child business using the parent bizid and child bizid from the config
|
85
|
+
).strip, 'murano child add <NEW_MEMBER_EMAIL>'
|
86
|
+
c.example %(
|
87
|
+
Add a member to a child business using a passed in business.id and business.child
|
88
|
+
).strip, 'murano child add <NEW_MEMBER_EMAIL> -c business.id=<PARENT_BUSINESS_ID> -c business.child=<CHILD_BUSINESS_ID>'
|
89
|
+
c.project_not_required = true
|
90
|
+
|
91
|
+
c.action do |args, _options|
|
92
|
+
if args.empty?
|
93
|
+
MrMurano::Verbose.error('Please include a new member email.')
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
add_member_to_child_business(args)
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_member_to_child_business(args)
|
100
|
+
new_member_email = args[0]
|
101
|
+
biz = MrMurano::Business.new
|
102
|
+
biz.must_business_id!
|
103
|
+
biz.must_child!
|
104
|
+
MrMurano::Verbose.whirly_start 'Adding member to child business...'
|
105
|
+
response = biz.add_member_to_child_business(biz.bid, biz.cid, new_member_email)
|
106
|
+
MrMurano::Verbose.whirly_stop
|
107
|
+
return unless response.nil?
|
108
|
+
MrMurano::Verbose.error 'Error adding member to child business.'
|
109
|
+
exit(1)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Remove a Member from a Network Child Business
|
114
|
+
command 'child remove' do |c|
|
115
|
+
c.syntax = %(murano child remove <MEMBER_EMAIL>)
|
116
|
+
c.summary = %(Remove a member from a network child business.)
|
117
|
+
c.description = %(
|
118
|
+
Remove a member from a network child business.
|
119
|
+
).strip
|
120
|
+
c.example %(Remove a member from a child business using the parent bizid and child bizid from the config
|
121
|
+
).strip, 'murano child remove <MEMBER_EMAIL>'
|
122
|
+
c.example %(
|
123
|
+
Remove a member from a child business using a passed in business.id and business.child
|
124
|
+
).strip, 'murano child remove <MEMBER_EMAIL> -c business.id=<PARENT_BUSINESS_ID> -c business.child=<CHILD_BUSINESS_ID>'
|
125
|
+
c.project_not_required = true
|
126
|
+
|
127
|
+
c.action do |args, _options|
|
128
|
+
if args.empty?
|
129
|
+
MrMurano::Verbose.error('Please include a member email.')
|
130
|
+
exit 1
|
131
|
+
end
|
132
|
+
remove_member_from_child_business(args)
|
133
|
+
end
|
134
|
+
|
135
|
+
def remove_member_from_child_business(args)
|
136
|
+
member_email = args[0]
|
137
|
+
biz = MrMurano::Business.new
|
138
|
+
biz.must_business_id!
|
139
|
+
biz.must_child!
|
140
|
+
MrMurano::Verbose.whirly_start 'Removing member from child business...'
|
141
|
+
response = biz.remove_member_from_child_business(biz.bid, biz.cid, member_email)
|
142
|
+
MrMurano::Verbose.whirly_stop
|
143
|
+
return unless response.nil?
|
144
|
+
MrMurano::Verbose.error 'Error removing member from child business.'
|
145
|
+
exit(1)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|