MuranoCLI 3.2.0.beta.1 → 3.2.0.beta.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/.trustme.plugin +137 -0
- data/.trustme.sh +217 -117
- data/.trustme.vim +9 -3
- data/Gemfile +9 -3
- data/MuranoCLI.gemspec +8 -5
- data/Rakefile +1 -0
- data/dockers/Dockerfile.2.2.9 +6 -3
- data/dockers/Dockerfile.2.3.6 +6 -3
- data/dockers/Dockerfile.2.4.3 +6 -3
- data/dockers/Dockerfile.2.5.0 +6 -3
- data/dockers/Dockerfile.GemRelease +10 -8
- data/dockers/Dockerfile.m4 +23 -5
- data/dockers/docker-test.sh +65 -28
- data/docs/completions/murano_completion-bash +751 -57
- data/docs/develop.rst +10 -9
- data/lib/MrMurano/AccountBase.rb +95 -6
- data/lib/MrMurano/Commander-Entry.rb +9 -4
- data/lib/MrMurano/Config-Migrate.rb +2 -0
- data/lib/MrMurano/Config.rb +94 -26
- data/lib/MrMurano/Content.rb +1 -1
- data/lib/MrMurano/Exchange.rb +77 -42
- data/lib/MrMurano/Gateway.rb +1 -1
- data/lib/MrMurano/HttpAuthed.rb +20 -7
- data/lib/MrMurano/Logs.rb +10 -1
- data/lib/MrMurano/ProjectFile.rb +1 -1
- data/lib/MrMurano/ReCommander.rb +129 -73
- data/lib/MrMurano/Solution-ServiceConfig.rb +18 -11
- data/lib/MrMurano/Solution-Services.rb +78 -50
- data/lib/MrMurano/Solution-Users.rb +1 -1
- data/lib/MrMurano/Solution.rb +13 -63
- data/lib/MrMurano/SyncUpDown-Core.rb +185 -77
- data/lib/MrMurano/SyncUpDown-Item.rb +29 -4
- data/lib/MrMurano/SyncUpDown.rb +11 -11
- data/lib/MrMurano/Webservice-Cors.rb +1 -1
- data/lib/MrMurano/Webservice-Endpoint.rb +28 -17
- data/lib/MrMurano/Webservice-File.rb +103 -43
- data/lib/MrMurano/commands/domain.rb +1 -0
- data/lib/MrMurano/commands/element.rb +585 -0
- data/lib/MrMurano/commands/exchange.rb +211 -204
- data/lib/MrMurano/commands/gb.rb +1 -0
- data/lib/MrMurano/commands/globals.rb +17 -7
- data/lib/MrMurano/commands/init.rb +115 -101
- data/lib/MrMurano/commands/keystore.rb +1 -1
- data/lib/MrMurano/commands/logs.rb +2 -1
- data/lib/MrMurano/commands/postgresql.rb +17 -7
- data/lib/MrMurano/commands/service.rb +572 -0
- data/lib/MrMurano/commands/show.rb +7 -3
- data/lib/MrMurano/commands/solution.rb +2 -1
- data/lib/MrMurano/commands/solution_picker.rb +31 -15
- data/lib/MrMurano/commands/status.rb +205 -169
- data/lib/MrMurano/commands/sync.rb +70 -38
- data/lib/MrMurano/commands/token.rb +59 -14
- data/lib/MrMurano/commands/usage.rb +1 -0
- data/lib/MrMurano/commands.rb +2 -0
- data/lib/MrMurano/hash.rb +91 -0
- data/lib/MrMurano/http.rb +55 -6
- data/lib/MrMurano/makePretty.rb +47 -0
- data/lib/MrMurano/optparse.rb +60 -45
- data/lib/MrMurano/variegated/TruthyFalsey.rb +48 -0
- data/lib/MrMurano/variegated/ruby_dig.rb +64 -0
- data/lib/MrMurano/verbosing.rb +113 -3
- data/lib/MrMurano/version.rb +1 -1
- data/spec/Account_spec.rb +34 -20
- data/spec/Business_spec.rb +12 -9
- data/spec/Config_spec.rb +7 -1
- data/spec/Content_spec.rb +17 -1
- data/spec/GatewayBase_spec.rb +5 -2
- data/spec/GatewayDevice_spec.rb +4 -2
- data/spec/GatewayResource_spec.rb +4 -1
- data/spec/GatewaySettings_spec.rb +4 -1
- data/spec/HttpAuthed_spec.rb +73 -0
- data/spec/Http_spec.rb +32 -35
- data/spec/ProjectFile_spec.rb +1 -1
- data/spec/Solution-ServiceConfig_spec.rb +4 -1
- data/spec/Solution-ServiceEventHandler_spec.rb +6 -3
- data/spec/Solution-ServiceModules_spec.rb +4 -1
- data/spec/Solution-UsersRoles_spec.rb +4 -1
- data/spec/Solution_spec.rb +4 -1
- data/spec/SyncUpDown_spec.rb +1 -1
- data/spec/Webservice-Cors_spec.rb +4 -1
- data/spec/Webservice-Endpoint_spec.rb +9 -6
- data/spec/Webservice-File_spec.rb +17 -4
- data/spec/Webservice-Setting_spec.rb +6 -2
- data/spec/_workspace.rb +2 -0
- data/spec/cmd_common.rb +42 -13
- data/spec/cmd_content_spec.rb +17 -7
- data/spec/cmd_device_spec.rb +1 -1
- data/spec/cmd_domain_spec.rb +2 -2
- data/spec/cmd_element_spec.rb +400 -0
- data/spec/cmd_exchange_spec.rb +2 -2
- data/spec/cmd_init_spec.rb +59 -25
- data/spec/cmd_keystore_spec.rb +6 -3
- data/spec/cmd_link_spec.rb +10 -5
- data/spec/cmd_logs_spec.rb +1 -1
- data/spec/cmd_setting_application_spec.rb +18 -15
- data/spec/cmd_setting_product_spec.rb +7 -7
- data/spec/cmd_status_spec.rb +27 -17
- data/spec/cmd_syncdown_application_spec.rb +30 -3
- data/spec/cmd_syncdown_both_spec.rb +72 -18
- data/spec/cmd_syncup_spec.rb +71 -5
- data/spec/cmd_token_spec.rb +2 -2
- data/spec/cmd_usage_spec.rb +2 -2
- data/spec/dry_run_formatter.rb +27 -0
- data/spec/fixtures/dumped_config +8 -0
- data/spec/fixtures/exchange_element/element-show.json +1 -0
- data/spec/fixtures/exchange_element/swagger-mur-6407__10k.yaml +282 -0
- data/spec/fixtures/exchange_element/swagger-mur-6407__20k.yaml +588 -0
- data/spec/variegated_TruthyFalsey_spec.rb +29 -0
- metadata +51 -25
@@ -6,6 +6,7 @@
|
|
6
6
|
# Unauthorized copying of this file is strictly prohibited.
|
7
7
|
|
8
8
|
require 'highline'
|
9
|
+
require 'MrMurano/makePretty'
|
9
10
|
require 'MrMurano/verbosing'
|
10
11
|
require 'MrMurano/Exchange'
|
11
12
|
require 'MrMurano/ReCommander'
|
@@ -14,261 +15,267 @@ require 'MrMurano/commands/business'
|
|
14
15
|
# *** Business commands: Exchange Elements
|
15
16
|
# ----------------------------------------
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
class ExchangeCmd
|
19
|
+
include MrMurano::Verbose
|
20
|
+
|
21
|
+
def command_exchange_help(cmd)
|
22
|
+
cmd.syntax = %(murano exchange)
|
23
|
+
cmd.summary = %(IoT Marketplace Exchange commands)
|
24
|
+
cmd.description = %(
|
25
|
+
Commands for working with IoT Marketplace.
|
26
|
+
).strip
|
27
|
+
cmd.project_not_required = true
|
28
|
+
cmd.subcmdgrouphelp = true
|
29
|
+
|
30
|
+
cmd.action do |_args, _options|
|
31
|
+
::Commander::UI.enable_paging unless $cfg['tool.no-page']
|
32
|
+
say MrMurano::SubCmdGroupHelp.new(cmd).get_help
|
33
|
+
end
|
29
34
|
end
|
30
|
-
end
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def command_exchange_list(cmd)
|
37
|
+
cmd.syntax = %(murano exchange list [--options] [<name-or-ID>])
|
38
|
+
cmd.summary = %(List Exchange Elements)
|
39
|
+
cmd.description = %(
|
36
40
|
List Exchange Elements, either all of them, or those that are purchased or available.
|
37
41
|
|
38
42
|
Each Exchange Element is identified by an Element ID and a name.
|
39
43
|
|
40
44
|
Element status:
|
41
45
|
|
42
|
-
- added An Element that has been added to and enabled for your Business
|
46
|
+
- added An Element that has been added to and enabled for your Business
|
43
47
|
|
44
|
-
- available An Element that can be added to and enabled for your Business
|
48
|
+
- available An Element that can be added to and enabled for your Business
|
45
49
|
|
46
|
-
- available* An Element that you can use if you upgrade your Business tier
|
50
|
+
- available* An Element that you can use if you upgrade your Business tier
|
47
51
|
|
48
|
-
|
49
|
-
|
52
|
+
).strip
|
53
|
+
cmd.project_not_required = true
|
50
54
|
|
51
|
-
|
55
|
+
cmd_table_output_add_options(cmd)
|
52
56
|
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
cmd.option '--[no-]added', 'Only show Elements that have been added to the Business'
|
58
|
+
cmd.option '--[no-]elem-type', 'Show element "type"'
|
59
|
+
cmd.option '--[no-]full', 'Show all fields'
|
60
|
+
cmd.option '--[no-]other', 'Show other fields: like type, tiers, tags, and action, and apiServiceName'
|
56
61
|
|
57
|
-
|
58
|
-
|
62
|
+
# Add --id and --name options.
|
63
|
+
cmd_options_add_id_and_name(cmd)
|
59
64
|
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
cmd.action do |args, options|
|
66
|
+
cmd.verify_arg_count!(args, 1)
|
67
|
+
cmd_defaults_id_and_name(options)
|
63
68
|
|
64
|
-
|
65
|
-
|
69
|
+
xchg = MrMurano::Exchange.new
|
70
|
+
xchg.must_business_id!
|
66
71
|
|
67
|
-
|
68
|
-
|
69
|
-
show = elems
|
70
|
-
elsif options.added
|
71
|
-
show = purchased
|
72
|
-
else
|
73
|
-
show = available
|
74
|
-
end
|
72
|
+
show = filter_elements(xchg, options, args[0])
|
73
|
+
sorted = sort_elements(show)
|
75
74
|
|
76
|
-
|
75
|
+
headers, pruned = cmd_exchange_header_and_elems(sorted, options)
|
77
76
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
77
|
+
io = File.open(options.output, 'w') if options.output
|
78
|
+
xchg.outf(pruned, io) do |item, ios|
|
79
|
+
if options.idonly
|
80
|
+
ios.puts item
|
81
|
+
else
|
82
|
+
ios.puts "Found #{pruned.length} elements."
|
83
|
+
xchg.tabularize(
|
84
|
+
{
|
85
|
+
headers: headers.map(&:to_s),
|
86
|
+
rows: item,
|
87
|
+
},
|
88
|
+
ios,
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
io.close unless io.nil?
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def find_elements(xchg, options, term, skip_purchased: false)
|
97
|
+
filter_id = nil
|
98
|
+
filter_name = nil
|
99
|
+
filter_fuzzy = nil
|
100
|
+
if term
|
101
|
+
if options.id
|
102
|
+
filter_id = term
|
103
|
+
elsif options.name
|
104
|
+
filter_name = term
|
82
105
|
else
|
83
|
-
|
84
|
-
xchg.tabularize(
|
85
|
-
{
|
86
|
-
headers: headers.map(&:to_s),
|
87
|
-
rows: item,
|
88
|
-
},
|
89
|
-
ios,
|
90
|
-
)
|
106
|
+
filter_fuzzy = term
|
91
107
|
end
|
92
108
|
end
|
93
|
-
|
109
|
+
xchg.elements(
|
110
|
+
filter_id: filter_id,
|
111
|
+
filter_name: filter_name,
|
112
|
+
filter_fuzzy: filter_fuzzy,
|
113
|
+
skip_purchased: skip_purchased,
|
114
|
+
)
|
94
115
|
end
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
filter_fuzzy = nil
|
103
|
-
if term
|
104
|
-
if options.id
|
105
|
-
filter_id = term
|
106
|
-
elsif options.name
|
107
|
-
filter_name = term
|
116
|
+
|
117
|
+
def filter_elements(xchg, options, term)
|
118
|
+
elems, available, purchased = find_elements(xchg, options, term)
|
119
|
+
if options.added.nil?
|
120
|
+
elems
|
121
|
+
elsif options.added
|
122
|
+
purchased
|
108
123
|
else
|
109
|
-
|
124
|
+
available
|
110
125
|
end
|
111
126
|
end
|
112
|
-
xchg.elements(filter_id: filter_id, filter_name: filter_name, filter_fuzzy: filter_fuzzy)
|
113
|
-
end
|
114
127
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
#elems = elems.map { |elem| [elem.elementId, elem.name] }
|
126
|
-
elems = elems.map { |elem| headers.map { |key| elem.send(key) } }
|
127
|
-
elsif options.full
|
128
|
-
headers = %i[elementId name status type apiServiceName tiers tags actions markdown]
|
129
|
-
all_hdrs = (elems[0] && elems[0].meta.keys) || []
|
130
|
-
all_hdrs.each do |chk|
|
131
|
-
headers.push(chk) unless headers.include?(chk)
|
128
|
+
STATUSABLE_RANK = %i[added available upgrade].freeze
|
129
|
+
|
130
|
+
def sort_elements(elems)
|
131
|
+
elems.sort do |lhs, rhs|
|
132
|
+
if lhs.statusable != rhs.statusable
|
133
|
+
next(
|
134
|
+
STATUSABLE_RANK.index(lhs.statusable) <=> STATUSABLE_RANK.index(rhs.statusable)
|
135
|
+
)
|
136
|
+
end
|
137
|
+
lhs.name <=> rhs.name
|
132
138
|
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
#elems = elems.map { |elem| headers.map { |key| elem.send(key) } }
|
141
|
-
elems = elems.map do |elem|
|
139
|
+
end
|
140
|
+
|
141
|
+
def cmd_exchange_header_and_elems_others(elems)
|
142
|
+
elems.map do |elem|
|
143
|
+
elem_actions = elem.actions.nil? && [] || elem.actions.map do |action|
|
144
|
+
action.map { |key, val| "#{key}: #{val}" }.join("\n")
|
145
|
+
end
|
142
146
|
[
|
143
147
|
elem.elementId,
|
144
148
|
elem.type,
|
145
149
|
elem.apiServiceName,
|
146
|
-
#elem.tiers,
|
147
|
-
#elem.tiers.join(' | '),
|
148
150
|
elem.tiers.join("\n"),
|
149
|
-
#elem.tags,
|
150
|
-
#elem.tags.join(' | '),
|
151
151
|
elem.tags.join("\n"),
|
152
|
-
|
153
|
-
elem.actions.map { |actn| actn.map { |key, val| "#{key}: #{val}" }.join("\n") }.join("\n"),
|
154
|
-
#elem.markdown.gsub("\n", '\\n'),
|
152
|
+
elem_actions.join("\n"),
|
155
153
|
]
|
156
154
|
end
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
155
|
+
end
|
156
|
+
|
157
|
+
def cmd_exchange_header_and_elems_default(headers, elems, width_avail)
|
158
|
+
elems.map do |elem|
|
159
|
+
headers.map do |key|
|
160
|
+
full = elem.send(key)
|
161
|
+
next(full) if width_avail.nil? || key != :description || full.empty?
|
162
|
+
MrMurano::Pretties.split_text_on_whitespace(full, width_avail)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def cmd_exchange_header_and_elems(elems, options)
|
168
|
+
# MAYBE/2017-08-31: If you `-c outformat=json`, each Element is a
|
169
|
+
# list of values, rather than a dictionary. Wouldn't the JSON be
|
170
|
+
# easier to consume if each Element was a dict, rather than list?
|
171
|
+
if options.idonly
|
172
|
+
headers = %i[elementId]
|
173
|
+
elems = elems.map(&:elementId)
|
174
|
+
elsif options.brief
|
175
|
+
headers = %i[elementId name]
|
176
|
+
headers += [:status] unless options.added
|
177
|
+
elems = elems.map { |elem| headers.map { |key| elem.send(key) } }
|
178
|
+
elsif options.full
|
179
|
+
headers = %i[elementId name status type apiServiceName tiers tags actions markdown]
|
180
|
+
all_hdrs = (elems[0] && elems[0].meta.keys) || []
|
181
|
+
all_hdrs.each do |chk|
|
182
|
+
headers.push(chk) unless headers.include?(chk)
|
175
183
|
end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
#
|
180
|
-
|
181
|
-
|
184
|
+
elems = elems.map { |elem| headers.map { |key| elem.send(key) || '' } }
|
185
|
+
elsif options.other
|
186
|
+
# NOTE: Showing columns not displayed when --other not specified,
|
187
|
+
# except not showing :markdown, ever.
|
188
|
+
headers = %i[elementId type apiServiceName tiers tags actions]
|
189
|
+
elems = cmd_exchange_header_and_elems_others(elems)
|
182
190
|
else
|
183
|
-
|
191
|
+
# 2017-08-28: There are 9 keys, and one of them -- :markdown -- is a
|
192
|
+
# lot of text, so rather than, e.g., elems[0].meta.keys, be selective.
|
193
|
+
headers = %i[elementId name]
|
194
|
+
headers += [:type] if options.elem_type
|
195
|
+
headers += [:status] unless options.added
|
196
|
+
headers += [:description]
|
197
|
+
width_avail = MrMurano::Pretties.width_last_column(headers, elems)
|
198
|
+
elems = cmd_exchange_header_and_elems_default(headers, elems, width_avail)
|
184
199
|
end
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
200
|
+
headers.delete(:type) if options.elem_type == false
|
201
|
+
[headers, elems]
|
202
|
+
end
|
203
|
+
|
204
|
+
def command_exchange_purchase(cmd)
|
205
|
+
cmd.syntax = %(murano exchange purchase [--options] <name-or-ID>)
|
206
|
+
cmd.summary = %(Add an Exchange Element to your Business)
|
207
|
+
cmd.description = %(
|
208
|
+
Add an Exchange Element to your Business.
|
209
|
+
).strip
|
210
|
+
# It feels a little weird to not require a project, but all
|
211
|
+
# we need is the Business ID; this action does not apply to
|
212
|
+
# solutions.
|
213
|
+
cmd.project_not_required = true
|
214
|
+
|
215
|
+
# Add --id and --name options.
|
216
|
+
cmd_options_add_id_and_name(cmd)
|
217
|
+
|
218
|
+
cmd.action do |args, options|
|
219
|
+
cmd.verify_arg_count!(args, 1, ['Missing Element name or ID'])
|
220
|
+
cmd_defaults_id_and_name(options)
|
221
|
+
|
222
|
+
xchg = MrMurano::Exchange.new
|
223
|
+
xchg.must_business_id!
|
224
|
+
|
225
|
+
# If the user specifies filter_id, we could try to fetch that Element
|
226
|
+
# directly (e.g., by calling exchange/<bizId>/element/<elemId>),
|
227
|
+
# but the response doesn't specify if the Element is purchased or not.
|
228
|
+
# So we grab everything from /element/ and /purchase/.
|
229
|
+
|
230
|
+
elems, _available, purchased = find_elements(xchg, options, args[0])
|
231
|
+
|
232
|
+
elems_must_found_one!(elems, xchg)
|
233
|
+
if purchased.length == 1
|
234
|
+
# I.e., elems.status == :added
|
235
|
+
xchg.warning(
|
236
|
+
'The specified element has already been purchased: ' \
|
237
|
+
"#{xchg.fancy_ticks(purchased[0].name)} (#{purchased[0].elementId})"
|
238
|
+
)
|
239
|
+
exit 2
|
240
|
+
elsif elems.first.status == :upgrade
|
241
|
+
xchg.warning('Please upgrade your Business to add this Element. Visit:')
|
242
|
+
xchg.warning(' https://www.exosite.io/business/settings/upgrade')
|
243
|
+
exit 2
|
212
244
|
end
|
245
|
+
|
246
|
+
xchg.purchase(elems.first.elementId)
|
213
247
|
end
|
214
248
|
end
|
215
|
-
[headers, elems]
|
216
|
-
end
|
217
249
|
|
218
|
-
|
219
|
-
c.syntax = %(murano exchange purchase [--options] <name-or-ID>)
|
220
|
-
c.summary = %(Add an Exchange Element to your Business)
|
221
|
-
c.description = %(
|
222
|
-
Add an Exchange Element to your Business.
|
223
|
-
).strip
|
224
|
-
# It feels a little weird to not require a project, but all
|
225
|
-
# we need is the Business ID; this action does not apply to
|
226
|
-
# solutions.
|
227
|
-
c.project_not_required = true
|
228
|
-
|
229
|
-
# Add --id and --name options.
|
230
|
-
cmd_options_add_id_and_name(c)
|
231
|
-
|
232
|
-
c.action do |args, options|
|
233
|
-
c.verify_arg_count!(args, 1, ['Missing Element name or ID'])
|
234
|
-
cmd_defaults_id_and_name(options)
|
235
|
-
|
236
|
-
xchg = MrMurano::Exchange.new
|
237
|
-
xchg.must_business_id!
|
238
|
-
|
239
|
-
# If the user specifies filter_id, we could try to fetch that Element
|
240
|
-
# directly (e.g., by calling exchange/<bizId>/element/<elemId>),
|
241
|
-
# but the response doesn't specify if the Element is purchased or not.
|
242
|
-
# So we grab everything from /element/ and /purchase/.
|
243
|
-
|
244
|
-
elems, _available, purchased = find_elements(xchg, options, args[0])
|
250
|
+
def elems_must_found_one!(elems, xchg)
|
245
251
|
if elems.length > 1
|
246
|
-
idents = elems.map { |elem| "#{xchg.fancy_ticks(elem.name)}
|
247
|
-
idents[-1] = 'and ' + idents[-1]
|
252
|
+
idents = elems.map { |elem| "#{elem.elementId}: #{xchg.fancy_ticks(elem.name)}" }
|
248
253
|
xchg.warning(
|
249
|
-
|
250
|
-
"#{idents.join(
|
254
|
+
"Please be more specific: More than one matching element was found:\n " \
|
255
|
+
"#{idents.join("\n ")}"
|
251
256
|
)
|
252
257
|
exit 2
|
253
258
|
elsif elems.empty?
|
254
259
|
xchg.warning('No matching element was found.')
|
255
260
|
exit 2
|
256
|
-
elsif purchased.length == 1
|
257
|
-
# I.e., elems.status == :added
|
258
|
-
xchg.warning(
|
259
|
-
'The specified element has already been purchased: ' \
|
260
|
-
"#{xchg.fancy_ticks(purchased[0].name)} (#{purchased[0].elementId})"
|
261
|
-
)
|
262
|
-
exit 2
|
263
|
-
elsif elems.first.status == :upgrade
|
264
|
-
xchg.warning('Please upgrade your Business to add this Element. Visit:')
|
265
|
-
xchg.warning(' https://www.exosite.io/business/settings/upgrade')
|
266
|
-
exit 2
|
267
261
|
end
|
268
|
-
|
269
|
-
xchg.purchase(elems.first.elementId)
|
262
|
+
elems.first
|
270
263
|
end
|
271
264
|
end
|
272
|
-
|
273
|
-
|
265
|
+
|
266
|
+
def wire_cmd_exchange
|
267
|
+
exchange_cmd = ExchangeCmd.new
|
268
|
+
|
269
|
+
command(:exchange) { |cmd| exchange_cmd.command_exchange_help(cmd) }
|
270
|
+
|
271
|
+
command('exchange list') { |cmd| exchange_cmd.command_exchange_list(cmd) }
|
272
|
+
alias_command 'exchange list available', 'exchange list', '--no-added'
|
273
|
+
alias_command 'exchange list purchased', 'exchange list', '--added'
|
274
|
+
|
275
|
+
command('exchange purchase') { |cmd| exchange_cmd.command_exchange_purchase(cmd) }
|
276
|
+
alias_command 'exchange add', 'exchange purchase'
|
277
|
+
alias_command 'exchange buy', 'exchange purchase'
|
278
|
+
end
|
279
|
+
|
280
|
+
wire_cmd_exchange
|
274
281
|
|
data/lib/MrMurano/commands/gb.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
require 'MrMurano/verbosing'
|
9
9
|
require 'MrMurano/Config'
|
10
|
+
require 'MrMurano/variegated/TruthyFalsey'
|
10
11
|
|
11
12
|
global_option('--[no-]color', %(Disable fancy output)) do |value|
|
12
13
|
HighLine.use_color = value
|
@@ -14,16 +15,20 @@ global_option('--[no-]color', %(Disable fancy output)) do |value|
|
|
14
15
|
end
|
15
16
|
|
16
17
|
global_option('-c', '--config KEY=VALUE', %(Set a single config key)) do |param|
|
18
|
+
# a=b :> ['a', 'b']
|
19
|
+
# a= :> ['a', '']
|
20
|
+
# a :> ['a', nil]
|
17
21
|
key, value = param.split('=', 2)
|
18
|
-
# a=b :> ["a", "b"]
|
19
|
-
# a= :> ["a", ""]
|
20
|
-
# a :> ["a"]
|
21
22
|
raise "Bad config '#{param}'" if key.nil?
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
section, ikey = key.split('.', 2)
|
24
|
+
if ikey.nil?
|
25
|
+
ikey = section
|
26
|
+
section = 'tool'
|
27
|
+
key = "#{section}.#{ikey}"
|
26
28
|
end
|
29
|
+
# If existing config setting is a boolean, coerce value as such,
|
30
|
+
# rather than setting a string, e.g., false, not "false".
|
31
|
+
$cfg[key] = TruthyFalsey.coerce_boolean(value, $cfg[key])
|
27
32
|
end
|
28
33
|
|
29
34
|
global_option('-C', '--configfile FILE', %(Load additional configuration file)) do |file|
|
@@ -89,6 +94,11 @@ global_option('--debug', %(Show debug messages)) do
|
|
89
94
|
$cfg['tool.debug'] = true
|
90
95
|
end
|
91
96
|
|
97
|
+
# 2018-04-24: (lb): Let's *not* advertise this, shall we?
|
98
|
+
# global_option('--developer', %(Enable developer mode)) do
|
99
|
+
# $cfg['tool.developer'] = true
|
100
|
+
# end
|
101
|
+
|
92
102
|
global_option('--sid VALUE', %(Override application or product ID)) do |value|
|
93
103
|
$cfg['application.id'] = value
|
94
104
|
$cfg['product.id'] = value
|