MuranoCLI 3.2.0.beta.1 → 3.2.0.beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
@@ -20,8 +20,10 @@ require 'MrMurano/commands/business'
|
|
|
20
20
|
require 'MrMurano/commands/solution'
|
|
21
21
|
require 'MrMurano/commands/sync'
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
class InitCmd
|
|
24
|
+
include MrMurano::Verbose
|
|
25
|
+
|
|
26
|
+
INIT_CMD_DESCRIPTION = %(
|
|
25
27
|
|
|
26
28
|
The init command helps you create a new Murano project
|
|
27
29
|
======================================================
|
|
@@ -101,115 +103,117 @@ that you can edit.
|
|
|
101
103
|
http://docs.exosite.com/
|
|
102
104
|
|
|
103
105
|
).strip
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
command :init do |c|
|
|
107
|
-
c.syntax = %(murano init)
|
|
108
|
-
c.summary = %(The easy way to start a project)
|
|
109
|
-
c.description = init_cmd_description
|
|
110
106
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
107
|
+
def command_init(cmd)
|
|
108
|
+
cmd.syntax = %(murano init)
|
|
109
|
+
cmd.summary = %(The easy way to start a project)
|
|
110
|
+
cmd.description = INIT_CMD_DESCRIPTION
|
|
114
111
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
cmd_option_product_pickers(c)
|
|
112
|
+
cmd.example %(
|
|
113
|
+
Initialize Murano project using specific Business and Solutions
|
|
114
|
+
).strip, 'murano init --business-id 12345 --product-name myprod --application-name myapp'
|
|
119
115
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
# Let user specify existing business and/or solution IDs and/or names.
|
|
117
|
+
cmd_option_business_pickers(cmd)
|
|
118
|
+
cmd_option_application_pickers(cmd)
|
|
119
|
+
cmd_option_product_pickers(cmd)
|
|
124
120
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
c.restrict_to_cur_dir = true
|
|
130
|
-
# Ask for user password if not found.
|
|
131
|
-
c.prompt_if_logged_off = true
|
|
121
|
+
cmd.option('--refresh', %(Ignore Business and Solution IDs found in the config))
|
|
122
|
+
cmd.option('--purge', %(Remove Project directories and files, and recreate anew))
|
|
123
|
+
cmd.option('--[no-]sync', %(Pull down existing remote files (generally a good thing) (default: true)))
|
|
124
|
+
cmd.option('--[no-]mkdirs', %(Create default directories))
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
# This command can be run without a project config.
|
|
127
|
+
cmd.project_not_required = true
|
|
128
|
+
# This command should not walk up the directory tree
|
|
129
|
+
# looking for a .murano/config project config file.
|
|
130
|
+
cmd.restrict_to_cur_dir = true
|
|
131
|
+
# Ask for user password if not found.
|
|
132
|
+
cmd.prompt_if_logged_off = true
|
|
136
133
|
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
cmd.action do |args, options|
|
|
135
|
+
cmd.verify_arg_count!(args, 1)
|
|
136
|
+
options.default(refresh: false, purge: false, sync: true, mkdirs: true)
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
verbage = 'Rebasing'
|
|
143
|
-
else
|
|
144
|
-
verbage = 'Creating'
|
|
145
|
-
end
|
|
146
|
-
say("#{verbage} project at #{Rainbow($cfg['location.base'].to_s).underline}")
|
|
138
|
+
acc = MrMurano::Account.new
|
|
139
|
+
validate_dir!(acc, args, options)
|
|
147
140
|
|
|
148
|
-
|
|
141
|
+
puts('')
|
|
142
|
+
if $cfg.project_exists
|
|
143
|
+
verbage = 'Rebasing'
|
|
144
|
+
else
|
|
145
|
+
verbage = 'Creating'
|
|
146
|
+
end
|
|
147
|
+
say("#{verbage} project at #{Rainbow($cfg['location.base'].to_s).underline}")
|
|
149
148
|
|
|
150
|
-
# Try to import a .Solutionfile.secret.
|
|
151
|
-
# NOTE/2017-06-29: .Solutionfile.secret and SolutionFile (see ProjectFile.rb)
|
|
152
|
-
# are old MurCLI constructs; here we just try to migrate from the old format
|
|
153
|
-
# to the new format (where config goes in .murano/config and there's an
|
|
154
|
-
# explicit directory structure; the user cannot specify a different file
|
|
155
|
-
# hierarchy).
|
|
156
|
-
MrMurano::ConfigMigrate.new.import_secret
|
|
157
|
-
|
|
158
|
-
# See if the config already specifies a Business ID. If not, see if the
|
|
159
|
-
# config contains a username and password; otherwise, ask for them. With
|
|
160
|
-
# a username and password, get the list of businesses from Murano; if
|
|
161
|
-
# just one found, use that; if more than one found, ask user which one
|
|
162
|
-
# to use; else, if no businesses found, spit out the new-account URL
|
|
163
|
-
# and tell the user to use their browser to create a new Business.
|
|
164
|
-
unless $cfg['user.name'].to_s.empty?
|
|
165
|
-
say("Found User #{Rainbow($cfg['user.name']).underline}")
|
|
166
149
|
puts('')
|
|
167
|
-
end
|
|
168
150
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
151
|
+
# Try to import a .Solutionfile.secret.
|
|
152
|
+
# NOTE/2017-06-29: .Solutionfile.secret and SolutionFile (see ProjectFile.rb)
|
|
153
|
+
# are old MurCLI constructs; here we just try to migrate from the old format
|
|
154
|
+
# to the new format (where config goes in .murano/config and there's an
|
|
155
|
+
# explicit directory structure; the user cannot specify a different file
|
|
156
|
+
# hierarchy).
|
|
157
|
+
MrMurano::ConfigMigrate.new.import_secret
|
|
158
|
+
|
|
159
|
+
# See if the config already specifies a Business ID. If not, see if the
|
|
160
|
+
# config contains a username and password; otherwise, ask for them. With
|
|
161
|
+
# a username and password, get the list of businesses from Murano; if
|
|
162
|
+
# just one found, use that; if more than one found, ask user which one
|
|
163
|
+
# to use; else, if no businesses found, spit out the new-account URL
|
|
164
|
+
# and tell the user to use their browser to create a new Business.
|
|
165
|
+
unless $cfg['user.name'].to_s.empty?
|
|
166
|
+
say("Found User #{Rainbow($cfg['user.name']).underline}")
|
|
167
|
+
puts('')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Find and verify Business by ID (from $cfg) or by name (from --business),
|
|
171
|
+
# or ask user which business to use. If user has not logged on, they will
|
|
172
|
+
# be asked for their username and/or password first.
|
|
173
|
+
biz = business_find_or_ask!(acc, options)
|
|
174
|
+
# Save the 'business.id' and 'business.name' to the project config.
|
|
175
|
+
# ([lb] guessing biz guaranteed to be not nil, but checking anyway.)
|
|
176
|
+
biz.write unless biz.nil?
|
|
177
|
+
|
|
178
|
+
# Verify or ask user to create Solutions.
|
|
179
|
+
sol_opts = {
|
|
180
|
+
create_ok: true,
|
|
181
|
+
update_cfg: true,
|
|
182
|
+
ignore_cfg: options.refresh,
|
|
183
|
+
verbose: true,
|
|
184
|
+
}
|
|
185
|
+
# Get/Create Application ID
|
|
186
|
+
sol_opts[:match_api_id] = options.application_id
|
|
187
|
+
sol_opts[:match_name] = options.application_name
|
|
188
|
+
sol_opts[:match_fuzzy] = options.application
|
|
189
|
+
appl = solution_find_or_create(biz: biz, type: :application, **sol_opts)
|
|
190
|
+
# Get/Create Product ID
|
|
191
|
+
sol_opts[:match_api_id] = options.product_id
|
|
192
|
+
sol_opts[:match_name] = options.product_name
|
|
193
|
+
sol_opts[:match_fuzzy] = options.product
|
|
194
|
+
prod = solution_find_or_create(biz: biz, type: :product, **sol_opts)
|
|
195
|
+
|
|
196
|
+
# Automatically link solutions.
|
|
197
|
+
unless appl.nil? || prod.nil?
|
|
198
|
+
link_opts = { verbose: true }
|
|
199
|
+
link_solutions(appl, prod, link_opts)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# If no ProjectFile, then write a ProjectFile.
|
|
203
|
+
write_project_file
|
|
204
|
+
|
|
205
|
+
if options.mkdirs
|
|
206
|
+
# Make the directory structure.
|
|
207
|
+
make_directories(purge: options.purge)
|
|
208
|
+
|
|
209
|
+
# For new solutions, Murano creates a few empty and example event handlers.
|
|
210
|
+
# For existing solutions, the user might already have created some files.
|
|
211
|
+
# Grab them now.
|
|
212
|
+
syncdown_new_and_existing if options.sync
|
|
213
|
+
end
|
|
211
214
|
|
|
212
|
-
|
|
215
|
+
blather_success
|
|
216
|
+
end
|
|
213
217
|
end
|
|
214
218
|
|
|
215
219
|
def highlight_id(id)
|
|
@@ -397,19 +401,29 @@ command :init do |c|
|
|
|
397
401
|
important_ids = %w[business application product].freeze
|
|
398
402
|
importantest_width = important_ids.map do |id_name|
|
|
399
403
|
cfg_key = id_name + '.id'
|
|
404
|
+
# If the user did not set up an application or product, it's ID is nil.
|
|
405
|
+
next 0 if $cfg[cfg_key].nil?
|
|
400
406
|
$cfg[cfg_key].length + id_postfix.length
|
|
401
407
|
end.max # Max the map; get the length of the longest ID.
|
|
402
408
|
important_ids.each do |id_name|
|
|
403
409
|
# cfg_key is, e.g., 'business.id', 'product.id', 'application.id'
|
|
404
410
|
cfg_key = id_name + '.id'
|
|
405
|
-
|
|
411
|
+
identifier = $cfg[cfg_key] || '<n/a>'
|
|
406
412
|
#say "#{id_name.capitalize} ID: #{highlight_id($cfg[cfg_key])}"
|
|
407
413
|
# Right-aligned:
|
|
408
414
|
tmpl = format('%%%ds: %%s', importantest_width)
|
|
409
415
|
# Left-aligned:
|
|
410
416
|
#tmpl = format('%%-%ds: %%s', importantest_width)
|
|
411
|
-
say(format(tmpl, id_name.capitalize + id_postfix, highlight_id(
|
|
417
|
+
say(format(tmpl, id_name.capitalize + id_postfix, highlight_id(identifier)))
|
|
412
418
|
end
|
|
413
419
|
puts('')
|
|
414
420
|
end
|
|
415
421
|
end
|
|
422
|
+
|
|
423
|
+
def wire_cmd_init
|
|
424
|
+
init_cmd = InitCmd.new
|
|
425
|
+
command(:init) { |cmd| init_cmd.command_init(cmd) }
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
wire_cmd_init
|
|
429
|
+
|
|
@@ -14,6 +14,7 @@ require 'MrMurano/verbosing'
|
|
|
14
14
|
require 'MrMurano/Logs'
|
|
15
15
|
require 'MrMurano/ReCommander'
|
|
16
16
|
require 'MrMurano/Solution'
|
|
17
|
+
require 'MrMurano/commands/solution_picker'
|
|
17
18
|
|
|
18
19
|
# Because Ruby 2.0 does not support quoted keys, e.g., { '$eq': 'value' }.
|
|
19
20
|
# rubocop:disable Style/HashSyntax
|
|
@@ -397,7 +398,7 @@ Use a "#{INCLUDE_INDICATOR}" or "#{EXCLUDE_INDICATOR}" prefix to include or excl
|
|
|
397
398
|
n_formatting += 1 if @options.pp
|
|
398
399
|
return unless n_formatting > 1
|
|
399
400
|
format_options = '--raw, --message-only, --one-line, --json, --yaml, or --pp'
|
|
400
|
-
|
|
401
|
+
warning "Try using just one of #{format_options}, but not two or more."
|
|
401
402
|
exit 1
|
|
402
403
|
end
|
|
403
404
|
|
|
@@ -75,11 +75,8 @@ Queries can include $# escapes that are filled from the --param option.
|
|
|
75
75
|
io = nil
|
|
76
76
|
io = File.open(options.output, 'w') if options.output
|
|
77
77
|
|
|
78
|
-
pg
|
|
79
|
-
|
|
80
|
-
# Look for date cells and pretty them. (a Hash with specific fields)
|
|
81
|
-
# All others, call to_s
|
|
82
|
-
rows = dd[:rows].map do |row|
|
|
78
|
+
def pretty_res(pg, res, ios)
|
|
79
|
+
rows = res[:rows].map do |row|
|
|
83
80
|
row.map do |cell|
|
|
84
81
|
if cell.is_a?(Hash) && cell.keys.sort == %i[day hour min month sec usec year]
|
|
85
82
|
t = Time.gm(
|
|
@@ -93,12 +90,22 @@ Queries can include $# escapes that are filled from the --param option.
|
|
|
93
90
|
end
|
|
94
91
|
pg.tabularize(
|
|
95
92
|
{
|
|
96
|
-
headers:
|
|
93
|
+
headers: res[:columns],
|
|
97
94
|
rows: rows,
|
|
98
95
|
},
|
|
99
96
|
ios
|
|
100
97
|
)
|
|
101
98
|
end
|
|
99
|
+
pg.outf(ret, io) do |dd, ios|
|
|
100
|
+
dd = dd[:result]
|
|
101
|
+
# Look for date cells and pretty them. (a Hash with specific fields)
|
|
102
|
+
# All others, call to_s
|
|
103
|
+
if dd.is_a? Array
|
|
104
|
+
dd.each { |d| pretty_res(pg, d, ios) }
|
|
105
|
+
else
|
|
106
|
+
pretty_res(pg, dd, ios)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
102
109
|
io.close unless io.nil?
|
|
103
110
|
end
|
|
104
111
|
end
|
|
@@ -149,7 +156,10 @@ extra table in your database. (__murano_cli__.migrate_version)
|
|
|
149
156
|
CREATE TABLE IF NOT EXISTS __murano_cli__.migrate_version (version integer);
|
|
150
157
|
SELECT version FROM __murano_cli__.migrate_version ORDER BY version DESC;
|
|
151
158
|
).gsub(/^\s+/, '')
|
|
152
|
-
|
|
159
|
+
if ret.nil?
|
|
160
|
+
pg.error 'Unknown Postgresql failure determining version'
|
|
161
|
+
exit 1
|
|
162
|
+
elsif !ret[:error].nil?
|
|
153
163
|
pp ret
|
|
154
164
|
exit 1
|
|
155
165
|
end
|