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
data/spec/cmd_common.rb
CHANGED
|
@@ -16,6 +16,7 @@ require 'tmpdir'
|
|
|
16
16
|
require 'webmock/rspec'
|
|
17
17
|
|
|
18
18
|
require 'MrMurano/Config'
|
|
19
|
+
require 'MrMurano/HttpAuthed'
|
|
19
20
|
|
|
20
21
|
# Prevent Commander from registering its at_exit hook.
|
|
21
22
|
# - Also print warning if spec exits, which rspec doesn't see as wrong.
|
|
@@ -50,6 +51,9 @@ at_exit do
|
|
|
50
51
|
warn('¡Unexpected spec exit killed rspec!')
|
|
51
52
|
warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
|
|
52
53
|
# DEVs: If you see this message, the last test exited unexpectedly.
|
|
54
|
+
warn('')
|
|
55
|
+
warn("Died on: #{$exited_abnormally}")
|
|
56
|
+
warn('')
|
|
53
57
|
end
|
|
54
58
|
end
|
|
55
59
|
alias original_at_exit at_exit unless defined?(original_at_exit)
|
|
@@ -96,6 +100,8 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
96
100
|
args.push '-c', 'fullerror'
|
|
97
101
|
# The spinner output would make it hard to write expects().
|
|
98
102
|
args.push '--no-progress'
|
|
103
|
+
# Save the token.
|
|
104
|
+
args.push '--cache'
|
|
99
105
|
|
|
100
106
|
if Gem.win_platform?
|
|
101
107
|
cmd = args.map do |i|
|
|
@@ -159,7 +165,7 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
159
165
|
expect(out).to \
|
|
160
166
|
eq('').or \
|
|
161
167
|
eq("No solutions found\n").or \
|
|
162
|
-
match(/^Deleted [\d]+ solutions
|
|
168
|
+
match(/^Deleted [\d]+ solutions?/)
|
|
163
169
|
expect(strip_color(err)).to eq('').or eq("No solutions found\n")
|
|
164
170
|
expect(status.exitstatus).to eq(0).or eq(1)
|
|
165
171
|
end
|
|
@@ -221,7 +227,7 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
221
227
|
# Utility fcns: Strings.
|
|
222
228
|
|
|
223
229
|
# rname makes a random Murano-acceptable Solution name.
|
|
224
|
-
def rname(name)
|
|
230
|
+
def rname(name='')
|
|
225
231
|
#"#{name}-#{Random.new.rand.hash.abs.to_s(16)}"
|
|
226
232
|
# MUR-2454: Product name may only contain letters and numbers.
|
|
227
233
|
#"#{name}#{Random.new.rand.hash.abs.to_s(16)}"
|
|
@@ -272,7 +278,7 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
272
278
|
|
|
273
279
|
def murano_command_runner(cmd, *args, wont_run: false, wont_parse: false)
|
|
274
280
|
# This is a functional test, so tell WebMock to back off.
|
|
275
|
-
|
|
281
|
+
allow_net_conn = WebMock::Config.instance.allow_net_connect != false
|
|
276
282
|
WebMock.allow_net_connect!
|
|
277
283
|
|
|
278
284
|
capture_stdio
|
|
@@ -288,25 +294,25 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
288
294
|
$stdout = tmpout
|
|
289
295
|
$stderr = tmperr
|
|
290
296
|
|
|
291
|
-
$exited_abnormally =
|
|
297
|
+
$exited_abnormally = "#{cmd} #{args.join(' ')}"
|
|
298
|
+
|
|
299
|
+
MrMurano::HttpAuthed.instance.credentials_reset
|
|
292
300
|
|
|
293
301
|
# When Commander is loaded, it sets an at_exit hook, which we monkey
|
|
294
302
|
# patch in ReCommander. Since Config.validate_cmd is called before
|
|
295
303
|
# at_exit, it uses runner.command_exit to tell ReCommander's at_exit
|
|
296
304
|
# monkey patch not to call Commander.run!. Via rspec, we don't use the
|
|
297
305
|
# at_exit hook, or ReCommander.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
$cfg.load
|
|
301
|
-
end
|
|
306
|
+
$cfg = MrMurano::Config.new(::Commander::Runner.instance)
|
|
307
|
+
$cfg.load
|
|
302
308
|
$cfg['tool.no-progress'] = true
|
|
303
|
-
$cfg.validate_cmd
|
|
309
|
+
$cfg.validate_cmd
|
|
304
310
|
runner = ::Commander::Runner.instance
|
|
305
311
|
unless defined?(runner.command_exit) && runner.command_exit
|
|
306
|
-
# Commander's at_exit hook calls runner.run! which runs the
|
|
307
|
-
# that was determined with Commander was loaded. I
|
|
308
|
-
# different ways to reset Runner.instance, but nothing worked;
|
|
309
|
-
# best bet is to just call the command directly.
|
|
312
|
+
# (lb): Commander's at_exit hook calls runner.run! which runs the
|
|
313
|
+
# command that was determined with Commander was loaded. I tried a
|
|
314
|
+
# few different ways to reset Runner.instance, but nothing worked;
|
|
315
|
+
# our best bet is to just call the command directly.
|
|
310
316
|
the_cmd = command(cmd.to_sym)
|
|
311
317
|
when_called = the_cmd.peek_when_called.dup
|
|
312
318
|
|
|
@@ -342,6 +348,8 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
342
348
|
# $stdout, $stderr = STDOUT, STDERR
|
|
343
349
|
restore_stdio
|
|
344
350
|
|
|
351
|
+
WebMock.disable_net_connect! unless allow_net_conn
|
|
352
|
+
|
|
345
353
|
[strip_color(tmpout.string), strip_color(tmperr.string)]
|
|
346
354
|
end
|
|
347
355
|
|
|
@@ -376,11 +384,29 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
376
384
|
require 'byebug/settings/histfile'
|
|
377
385
|
_ignored = ::Byebug::HistfileSetting::DEFAULT
|
|
378
386
|
|
|
387
|
+
$exited_abnormally = ex.example.to_s
|
|
388
|
+
|
|
379
389
|
@testdir = Pathname.new(Dir.pwd).realpath
|
|
380
390
|
Dir.mktmpdir do |hdir|
|
|
391
|
+
saved_home = Dir.home
|
|
381
392
|
ENV['HOME'] = hdir
|
|
382
393
|
Dir.chdir(hdir) do
|
|
383
394
|
Dir.mkdir('.murano')
|
|
395
|
+
|
|
396
|
+
Dir.chdir('.murano') do
|
|
397
|
+
begin
|
|
398
|
+
FileUtils.ln_s(File.join(saved_home, '.murano', 'tokens'), 'tokens')
|
|
399
|
+
rescue NotImplementedError => err
|
|
400
|
+
require 'rbconfig'
|
|
401
|
+
unless OS.windows?
|
|
402
|
+
warn(
|
|
403
|
+
'Unexpected: ln_s failed on non-Windows machine / ' \
|
|
404
|
+
"host_os: #{RbConfig::CONFIG['host_os']} / err: #{err}"
|
|
405
|
+
)
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
384
410
|
@tmpdir = File.join(hdir, 'project')
|
|
385
411
|
Dir.mkdir(@tmpdir)
|
|
386
412
|
Dir.chdir(@tmpdir) do
|
|
@@ -392,7 +418,10 @@ RSpec.shared_context 'CI_CMD' do
|
|
|
392
418
|
rm_symlink
|
|
393
419
|
end
|
|
394
420
|
end
|
|
421
|
+
ENV['HOME'] = saved_home
|
|
395
422
|
end
|
|
423
|
+
|
|
424
|
+
$exited_abnormally = false
|
|
396
425
|
end
|
|
397
426
|
end
|
|
398
427
|
|
data/spec/cmd_content_spec.rb
CHANGED
|
@@ -15,19 +15,24 @@ RSpec.describe 'murano content', :cmd, :needs_password do
|
|
|
15
15
|
|
|
16
16
|
before(:example) do
|
|
17
17
|
@product_name = rname('contestTest')
|
|
18
|
-
out, err, status = Open3.capture3(
|
|
18
|
+
out, err, status = Open3.capture3(
|
|
19
|
+
capcmd('murano', 'product', 'create', @product_name, '--save')
|
|
20
|
+
)
|
|
19
21
|
expect(err).to eq('')
|
|
20
22
|
expect(out.chomp).to match(/^[a-zA-Z0-9]+$/)
|
|
21
23
|
expect(status.exitstatus).to eq(0)
|
|
22
24
|
end
|
|
25
|
+
|
|
23
26
|
after(:example) do
|
|
24
|
-
out, err, status = Open3.capture3(
|
|
27
|
+
out, err, status = Open3.capture3(
|
|
28
|
+
capcmd('murano', 'solution', 'delete', '--yes', @product_name)
|
|
29
|
+
)
|
|
25
30
|
expect(out).to eq('')
|
|
26
31
|
expect(err).to eq('')
|
|
27
32
|
expect(status.exitstatus).to eq(0)
|
|
28
33
|
end
|
|
29
34
|
|
|
30
|
-
it 'life cycle' do
|
|
35
|
+
it 'life cycle', :club_10s do
|
|
31
36
|
out, err, status = Open3.capture3(capcmd('murano', 'content', 'list'))
|
|
32
37
|
#expect(out.lines).to match(
|
|
33
38
|
# [
|
|
@@ -43,7 +48,9 @@ RSpec.describe 'murano content', :cmd, :needs_password do
|
|
|
43
48
|
expect(status.exitstatus).to eq(0)
|
|
44
49
|
|
|
45
50
|
FileUtils.copy(File.join(@testdir, 'spec/fixtures/dumped_config'), 'myFile')
|
|
46
|
-
out, err, status = Open3.capture3(
|
|
51
|
+
out, err, status = Open3.capture3(
|
|
52
|
+
capcmd('murano', 'content', 'upload', 'myFile', '--tags', 'random=junk')
|
|
53
|
+
)
|
|
47
54
|
expect(out).to eq('')
|
|
48
55
|
expect(err).to eq('')
|
|
49
56
|
expect(status.exitstatus).to eq(0)
|
|
@@ -75,7 +82,9 @@ RSpec.describe 'murano content', :cmd, :needs_password do
|
|
|
75
82
|
)
|
|
76
83
|
expect(status.exitstatus).to eq(0)
|
|
77
84
|
|
|
78
|
-
out, err, status = Open3.capture3(
|
|
85
|
+
out, err, status = Open3.capture3(
|
|
86
|
+
capcmd('murano', 'content', 'download', 'myFile', '-o', 'testDown')
|
|
87
|
+
)
|
|
79
88
|
expect(out).to eq('')
|
|
80
89
|
expect(err).to eq('')
|
|
81
90
|
expect(status.exitstatus).to eq(0)
|
|
@@ -84,7 +93,9 @@ RSpec.describe 'murano content', :cmd, :needs_password do
|
|
|
84
93
|
tdf = IO.read('testDown')
|
|
85
94
|
expect(tdf).to eq(dcf)
|
|
86
95
|
|
|
87
|
-
out, err, status = Open3.capture3(
|
|
96
|
+
out, err, status = Open3.capture3(
|
|
97
|
+
capcmd('murano', 'content', 'delete', 'myFile', '-y')
|
|
98
|
+
)
|
|
88
99
|
expect(out).to eq('')
|
|
89
100
|
expect(err).to eq('')
|
|
90
101
|
expect(status.exitstatus).to eq(0)
|
|
@@ -105,4 +116,3 @@ RSpec.describe 'murano content', :cmd, :needs_password do
|
|
|
105
116
|
end
|
|
106
117
|
end
|
|
107
118
|
|
|
108
|
-
# vim: set ai et sw=2 ts=2 :
|
data/spec/cmd_device_spec.rb
CHANGED
|
@@ -84,7 +84,7 @@ RSpec.describe 'murano device', :cmd, :needs_password do
|
|
|
84
84
|
expect(status.exitstatus).to eq(0)
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
it 'writes and reads' do
|
|
87
|
+
it 'writes and reads', :club_10s do
|
|
88
88
|
FileUtils.mkpath('specs')
|
|
89
89
|
FileUtils.copy(
|
|
90
90
|
File.join(@testdir, 'spec/fixtures/product_spec_files/lightbulb.yaml'),
|
data/spec/cmd_domain_spec.rb
CHANGED
|
@@ -35,7 +35,7 @@ RSpec.describe 'murano domain', :cmd, :needs_password do
|
|
|
35
35
|
expect(status.exitstatus).to eq(0)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
it 'show domain' do
|
|
38
|
+
it 'show domain', :club_20s, :club_10s do
|
|
39
39
|
out, err, status = Open3.capture3(capcmd('murano', 'domain'))
|
|
40
40
|
# 2017-05-31: Previously, the project could be named whatever and
|
|
41
41
|
# the URI would start with the same.
|
|
@@ -46,7 +46,7 @@ RSpec.describe 'murano domain', :cmd, :needs_password do
|
|
|
46
46
|
#expect(out.chomp).to end_with('m2.exosite.io')
|
|
47
47
|
out.lines.each do |line|
|
|
48
48
|
expect(line).to match(
|
|
49
|
-
%r{^(Product|Application): domain[Tt]est[a-z0-9]+ <[a-z0-9]+> https://[
|
|
49
|
+
%r{^(Product|Application): domain[Tt]est[a-z0-9]+ <[a-z0-9]+> https://[.\-a-z0-9]+$}
|
|
50
50
|
)
|
|
51
51
|
end
|
|
52
52
|
expect(err).to eq('')
|
|
@@ -0,0 +1,400 @@
|
|
|
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
|
+
# (lb): 2018-05-01: Whoa. Coverage at 303 of 306 lines! 99.02%!!
|
|
9
|
+
|
|
10
|
+
require 'fileutils'
|
|
11
|
+
require 'json'
|
|
12
|
+
require 'open3'
|
|
13
|
+
require 'pathname'
|
|
14
|
+
require 'tty-editor'
|
|
15
|
+
require 'yaml'
|
|
16
|
+
|
|
17
|
+
require 'cmd_common'
|
|
18
|
+
require 'MrMurano/Config'
|
|
19
|
+
|
|
20
|
+
RSpec.describe 'murano element', :cmd, :needs_password do
|
|
21
|
+
include_context 'CI_CMD'
|
|
22
|
+
|
|
23
|
+
context 'without project' do
|
|
24
|
+
it 'usage' do
|
|
25
|
+
cmd_verify_help('element')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def expect_exchange_element_table(stdout, stderr, num_cols: nil)
|
|
30
|
+
expect(stderr).to eq('')
|
|
31
|
+
lines = stdout.lines
|
|
32
|
+
# FIXME/2018-04-30: Is this too much detail??
|
|
33
|
+
# What about running test once, dumping output to file,
|
|
34
|
+
# and expecting same output next time?
|
|
35
|
+
# Outline of table. n columns. '+-----+-----+---...----+\n'
|
|
36
|
+
expect(lines[0]).to match(/^(\+-+){#{num_cols}}\+$/)
|
|
37
|
+
# Header. "... key | value ..."
|
|
38
|
+
expect(lines[1]).to match(/^\| key \+| value \+|$/)
|
|
39
|
+
# Separator.
|
|
40
|
+
expect(lines[2]).to match(/^(\+-+){#{num_cols}}\+$/)
|
|
41
|
+
# Content. Starts with nested.hash.key.
|
|
42
|
+
(3..(lines.length - 2)).to_a.each do |line|
|
|
43
|
+
expect(lines[line]).to match(/^\| [\.0-9a-zA-Z]* +\| /)
|
|
44
|
+
end
|
|
45
|
+
expect(lines[-1]).to match(/^(\+-+){#{num_cols}}\+$/)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'show' do
|
|
49
|
+
it '--help' do
|
|
50
|
+
stdout, stderr = murano_command_wont_parse('element show', '--help')
|
|
51
|
+
expect(stdout).to a_string_starting_with('Usage:')
|
|
52
|
+
expect(stderr).to eq('')
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'using ambiguous name' do
|
|
56
|
+
# MEH/2018-04-30: This test is dependent on the platform having
|
|
57
|
+
# more than one element with the term 'IoT' in its name!
|
|
58
|
+
# 59bc24836b12c505c98c5a51: ‘Twilio SMS Service’
|
|
59
|
+
# 5adedb7cdcd2dd1d04082fba: ‘Public application for the twilio’
|
|
60
|
+
#
|
|
61
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
62
|
+
stdout, stderr = murano_command_exits('element show', 'twilio')
|
|
63
|
+
expect(stdout).to eq('')
|
|
64
|
+
expect(stderr).to a_string_starting_with(
|
|
65
|
+
'Please be more specific: More than one matching element was found:'
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'as default-table' do
|
|
70
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
71
|
+
stdout, stderr = murano_command_run('element show', 'MUR-6407')
|
|
72
|
+
expect_exchange_element_table(stdout, stderr, num_cols: 2)
|
|
73
|
+
expect(stderr).to eq('')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'as table wrap' do
|
|
77
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
78
|
+
stdout, stderr = murano_command_run('element show', 'MUR-6407', '--wrap')
|
|
79
|
+
expect_exchange_element_table(stdout, stderr, num_cols: 2)
|
|
80
|
+
expect(stderr).to eq('')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'as table truncate' do
|
|
84
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
85
|
+
stdout, stderr = murano_command_run('element show', 'MUR-6407', '--truncate')
|
|
86
|
+
expect_exchange_element_table(stdout, stderr, num_cols: 2)
|
|
87
|
+
expect(stderr).to eq('')
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# (lb): NOTE: This does not add any additional coverage to element.rb:
|
|
91
|
+
it 'as json' do
|
|
92
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
93
|
+
stdout, stderr = murano_command_run('element show', '--json', 'MUR-6407')
|
|
94
|
+
expect { JSON.parse(stdout) }.to_not raise_error
|
|
95
|
+
expect(stderr).to eq('')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# (lb): NOTE: This does not add any additional coverage to element.rb:
|
|
99
|
+
it 'as yaml' do
|
|
100
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
101
|
+
stdout, stderr = murano_command_run('element show', 'MUR-6407', '--yaml')
|
|
102
|
+
expect { YAML.parse(stdout) }.to_not raise_error
|
|
103
|
+
expect(stderr).to eq('')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# (lb): This adds 1 line of coverage.
|
|
107
|
+
it 'as csv' do
|
|
108
|
+
# FIXME/2018-04-30: Make test-specific elements for this test!
|
|
109
|
+
stdout, stderr = murano_command_run('element show', 'MUR-6407', '--csv')
|
|
110
|
+
expect(stdout).to_not eq('')
|
|
111
|
+
expect(stderr).to eq('')
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'edit' do
|
|
116
|
+
before(:example) do
|
|
117
|
+
@json_input_file = 'element-show.json'
|
|
118
|
+
@spec_swagger_20k = 'swagger-mur-6407__20k.yaml'
|
|
119
|
+
@spec_swagger_10k = 'swagger-mur-6407__10k.yaml'
|
|
120
|
+
[
|
|
121
|
+
@json_input_file,
|
|
122
|
+
@spec_swagger_20k,
|
|
123
|
+
@spec_swagger_10k,
|
|
124
|
+
].each do |path|
|
|
125
|
+
FileUtils.copy(
|
|
126
|
+
File.join(@testdir, "spec/fixtures/exchange_element/#{path}"), path
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def element_editor_expect_edit_json_full
|
|
132
|
+
# Mock the $EDITOR session.
|
|
133
|
+
expect(TTY::Editor).to receive(:open) do |path|
|
|
134
|
+
edit_json_make_unique_contact(path)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def edit_json_make_unique_contact(path)
|
|
139
|
+
pname = path.is_a?(Pathname) && path || Pathname.new(path)
|
|
140
|
+
pname.write pname.read.gsub(
|
|
141
|
+
/\n "contact": "[a-f0-9]+",\n/,
|
|
142
|
+
%(\n "contact": "#{rname}",\n)
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def edit_specs_yaml_make_unique_contact(path)
|
|
147
|
+
pname = path.is_a?(Pathname) && path || Pathname.new(path)
|
|
148
|
+
rname7 = rname[0..6]
|
|
149
|
+
pname.write pname.read.gsub(
|
|
150
|
+
/\n name: Exosite Exosite Exosite Exosite\n/,
|
|
151
|
+
%(\n name: #{rname7} #{rname7} #{rname7} #{rname7}\n)
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def element_editor_expect_edit_plain_contact
|
|
156
|
+
# Mock the $EDITOR session.
|
|
157
|
+
expect(TTY::Editor).to receive(:open) do |path|
|
|
158
|
+
pname = path.is_a?(Pathname) && path || Pathname.new(path)
|
|
159
|
+
pname.write(rname)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# DEL:
|
|
164
|
+
def element_editor_expect_edit_json_from_string
|
|
165
|
+
expect(TTY::Editor).to receive(:open) do |path|
|
|
166
|
+
pname = path.is_a?(Pathname) && path || Pathname.new(path)
|
|
167
|
+
pname.write(
|
|
168
|
+
%({"tiers":[],"bizid":"55cop31gs89","access":"private","attachment":{},"contact":"#{rname}","description":"For testing Murano CLI element-edit.\\n\\nTEST2222\\n\\nTEST MORE","image":{"detail":{"color":"#224123","filename":"","url":""},"thumbnail":{"color":"#224655","filename":"xxx","url":""}},"markdown":"AxxxxAA2333BBBCCC\\n","name":"MUR-6407 Test Element","source":{"from":"service","name":"mur6407testelement","url":"https://testtesttest.apps.exosite-dev.io/swagger-mur-6407.yaml"},"specs":"","type":"service","tags":[],"active":true,"approval":"approved","elementId":"5ae3600e313d01708c2a6e0f"})
|
|
169
|
+
)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it '--help' do
|
|
174
|
+
stdout, stderr = murano_command_wont_parse('element edit', '--help')
|
|
175
|
+
expect(stdout).to a_string_starting_with('Usage:')
|
|
176
|
+
expect(stderr).to eq('')
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'as static field option' do
|
|
180
|
+
stdout, stderr = murano_command_run(
|
|
181
|
+
'element edit', '--contact', rname, 'MUR-6407'
|
|
182
|
+
)
|
|
183
|
+
expect(stdout).to eq('')
|
|
184
|
+
expect(stderr).to eq('')
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it 'as dynamic field option' do
|
|
188
|
+
stdout, stderr = murano_command_run(
|
|
189
|
+
'element edit', '-e', "contact=#{rname}", 'MUR-6407'
|
|
190
|
+
)
|
|
191
|
+
expect(stdout).to eq('')
|
|
192
|
+
expect(stderr).to eq('')
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'as dynamic edit empty string without update' do
|
|
196
|
+
# I.e., @edit_fields[''] = nil, meaning should bring up editor.
|
|
197
|
+
# FIXME: Requires (lb)'s fixed commander library.
|
|
198
|
+
|
|
199
|
+
# If we don't change the file, Murano CLI will not PUT to BizAPI.
|
|
200
|
+
expect(TTY::Editor).to receive(:open).once
|
|
201
|
+
stdout, stderr = murano_command_exits(
|
|
202
|
+
'element edit', '-e', '', 'MUR-6407'
|
|
203
|
+
)
|
|
204
|
+
expect(stdout).to eq('')
|
|
205
|
+
expect(stderr).to eq("No new field values specified to update.\n")
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it 'as dynamic edit empty string with update' do
|
|
209
|
+
element_editor_expect_edit_json_full
|
|
210
|
+
stdout, stderr = murano_command_run(
|
|
211
|
+
'element edit', '-e', '', 'MUR-6407'
|
|
212
|
+
)
|
|
213
|
+
expect(stdout).to eq('')
|
|
214
|
+
expect(stderr).to eq('')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'as dynamic edit no field with update' do
|
|
218
|
+
element_editor_expect_edit_json_full
|
|
219
|
+
stdout, stderr = murano_command_run(
|
|
220
|
+
'element edit', '-e', '--', 'MUR-6407'
|
|
221
|
+
)
|
|
222
|
+
expect(stdout).to eq('')
|
|
223
|
+
expect(stderr).to eq('')
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'as dynamic edit set empty string' do
|
|
227
|
+
# I.e., @edit_fields[''] = ''
|
|
228
|
+
stdout, stderr = murano_command_run(
|
|
229
|
+
#'element edit', '-e', "''=", 'MUR-6407'
|
|
230
|
+
'element edit', '-e', '=', 'MUR-6407'
|
|
231
|
+
)
|
|
232
|
+
expect(stdout).to eq('')
|
|
233
|
+
expect(stderr).to eq(
|
|
234
|
+
%(Request Failed: 400: [400] child "type" fails because ["type" is required]\n)
|
|
235
|
+
)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it 'as edit with too many fields specified' do
|
|
239
|
+
stdout, stderr = murano_command_exits(
|
|
240
|
+
'element edit', '-e', "contact=#{rname}", '-e', 'markdown', 'MUR-6407'
|
|
241
|
+
)
|
|
242
|
+
expect(stdout).to eq('')
|
|
243
|
+
expect(stderr).to eq(
|
|
244
|
+
%(Please specify at most one field when not specifing all field values.\n)
|
|
245
|
+
)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it 'as edit with no action specified' do
|
|
249
|
+
stdout, stderr = murano_command_exits(
|
|
250
|
+
'element edit', 'MUR-6407'
|
|
251
|
+
)
|
|
252
|
+
expect(stdout).to eq('')
|
|
253
|
+
expect(stderr).to eq(
|
|
254
|
+
%(Please specify one or more -e/--edit options, or an input file.\n)
|
|
255
|
+
)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it 'as edit with input file not found' do
|
|
259
|
+
bad_path = "/path/to/nowhere/#{rname}.json"
|
|
260
|
+
stdout, stderr = murano_command_exits(
|
|
261
|
+
'element edit', 'MUR-6407', bad_path
|
|
262
|
+
)
|
|
263
|
+
expect(stdout).to eq('')
|
|
264
|
+
expect(stderr).to eq(
|
|
265
|
+
%(Input file not found: #{bad_path}\n)
|
|
266
|
+
)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it 'as edit with input file found and valid' do
|
|
270
|
+
path = Pathname.new(@json_input_file)
|
|
271
|
+
path.write path.read.gsub(
|
|
272
|
+
/,"contact":"[a-f0-9]+",/,
|
|
273
|
+
%(,"contact":"#{rname}",)
|
|
274
|
+
)
|
|
275
|
+
stdout, stderr = murano_command_run(
|
|
276
|
+
'element edit', 'MUR-6407', @json_input_file
|
|
277
|
+
)
|
|
278
|
+
expect(stdout).to eq('')
|
|
279
|
+
expect(stderr).to eq('')
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it 'as edit with input file and too many fields specified' do
|
|
283
|
+
stdout, stderr = murano_command_exits(
|
|
284
|
+
'element edit', '-e', 'contact', '-e', 'markdown', 'MUR-6407', @spec_swagger_20k
|
|
285
|
+
)
|
|
286
|
+
expect(stdout).to eq('')
|
|
287
|
+
expect(stderr).to eq(
|
|
288
|
+
%(Please specify at most a single field when specifing an input file.\n)
|
|
289
|
+
)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it 'as edit with input file and value specified' do
|
|
293
|
+
stdout, stderr = murano_command_exits(
|
|
294
|
+
'element edit', '-e', 'contact=XYZ', 'MUR-6407', @spec_swagger_20k
|
|
295
|
+
)
|
|
296
|
+
expect(stdout).to eq('')
|
|
297
|
+
expect(stderr).to eq(
|
|
298
|
+
%(Please do not specify a value when specifing an input file.\n)
|
|
299
|
+
)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
it 'as edit with input file that is too large and unrecognized field' do
|
|
303
|
+
stdout, stderr = murano_command_run(
|
|
304
|
+
'element edit', '--edit', "spec=@#{@spec_swagger_20k}", 'MUR-6407'
|
|
305
|
+
)
|
|
306
|
+
expect(stdout).to eq('')
|
|
307
|
+
expect(stderr).to eq(
|
|
308
|
+
%(Request Failed: 400: [400] "spec" is not allowed\n)
|
|
309
|
+
)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it 'as edit with input file that should not be parsed' do
|
|
313
|
+
stdout, stderr = murano_command_run(
|
|
314
|
+
'element edit', '--edit', "specs=@#{@spec_swagger_20k}", 'MUR-6407'
|
|
315
|
+
)
|
|
316
|
+
expect(stdout).to eq('')
|
|
317
|
+
expect(stderr).to eq(
|
|
318
|
+
%(Request Failed: 400: [400] child "specs" fails because ["specs" must be a string]\n)
|
|
319
|
+
)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# FIXME/2018-05-01 00:10: How does Tilstra circumvent 20k limit?
|
|
323
|
+
it 'as edit with input file that is too large' do
|
|
324
|
+
stdout, stderr = murano_command_run(
|
|
325
|
+
'element edit', '--edit', 'specs', '--plain', '--', 'MUR-6407', @spec_swagger_20k
|
|
326
|
+
)
|
|
327
|
+
expect(stdout).to eq('')
|
|
328
|
+
expect(stderr).to eq(
|
|
329
|
+
%(Request Failed: 400: [400] child "specs" fails because ["specs" length must be less than or equal to 10000 characters long]\n)
|
|
330
|
+
)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
it 'as edit with input file that is just right' do
|
|
334
|
+
edit_specs_yaml_make_unique_contact(@spec_swagger_10k)
|
|
335
|
+
stdout, stderr = murano_command_run(
|
|
336
|
+
'element edit', '--edit', 'specs', '--plain', '--', 'MUR-6407', @spec_swagger_10k
|
|
337
|
+
)
|
|
338
|
+
expect(stdout).to eq('')
|
|
339
|
+
expect(stderr).to eq('')
|
|
340
|
+
|
|
341
|
+
# Send same file again.
|
|
342
|
+
stdout, stderr = murano_command_exits(
|
|
343
|
+
'element edit', '--edit', 'specs', '--plain', '--', 'MUR-6407', @spec_swagger_10k
|
|
344
|
+
)
|
|
345
|
+
expect(stdout).to eq('')
|
|
346
|
+
expect(stderr).to eq("No new field values specified to update.\n")
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it 'as dynamic edit single field no value uses EDITOR' do
|
|
350
|
+
element_editor_expect_edit_plain_contact
|
|
351
|
+
stdout, stderr = murano_command_run(
|
|
352
|
+
'element edit', '-e', 'contact', '--', 'MUR-6407'
|
|
353
|
+
)
|
|
354
|
+
expect(stdout).to eq('')
|
|
355
|
+
expect(stderr).to eq('')
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
it 'as dynamic edit nested field change value' do
|
|
359
|
+
stdout, stderr = murano_command_run(
|
|
360
|
+
'element edit', '-e', "image.detail.color=0x#{rname[0..5]}", 'MUR-6407'
|
|
361
|
+
)
|
|
362
|
+
expect(stdout).to eq('')
|
|
363
|
+
expect(stderr).to eq('')
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# (lb): Get 2 more lines of coverage.
|
|
367
|
+
it 'as dynamic edit no field with update from string' do
|
|
368
|
+
stdout, stderr = murano_command_run(
|
|
369
|
+
'element edit',
|
|
370
|
+
'-e',
|
|
371
|
+
%(={"bizid":"55cop31gs89","access":"private","attachment":{},"contact":"#{rname}","description":"For testing Murano CLI element-edit.\\n\\nTEST2222\\n\\nTEST MORE","image":{"detail":{"color":"#224123","filename":"","url":""},"thumbnail":{"color":"#224655","filename":"xxx","url":""}},"markdown":"AxxxxAA2333BBBCCC\\n","name":"MUR-6407 Test Element","source":{"from":"service","name":"mur6407testelement","url":"https://testtesttest.apps.exosite-dev.io/swagger-mur-6407.yaml"},"specs":"","type":"service","tags":[],"active":true,"elementId":"5ae3600e313d01708c2a6e0f"}),
|
|
372
|
+
'MUR-6407'
|
|
373
|
+
)
|
|
374
|
+
expect(stdout).to eq('')
|
|
375
|
+
expect(stderr).to eq('')
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# (lb): Get 2 more lines of coverage.
|
|
379
|
+
it 'as dynamic edit no field with update from string not valid Hash' do
|
|
380
|
+
stdout, stderr = murano_command_exits(
|
|
381
|
+
'element edit', '-e', %(={), 'MUR-6407'
|
|
382
|
+
)
|
|
383
|
+
expect(stdout).to eq('')
|
|
384
|
+
expect(stderr).to eq %(The document object is not a Hash: {\n765: unexpected token at '{'\n)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# (lb): No additional coverage, other than integration.
|
|
388
|
+
it 'as dynamic edit no field with update from string fields not allowed' do
|
|
389
|
+
stdout, stderr = murano_command_run(
|
|
390
|
+
'element edit',
|
|
391
|
+
'-e',
|
|
392
|
+
%(={"tiers":[],"bizid":"55cop31gs89","access":"private","attachment":{},"contact":"#{rname}","description":"For testing Murano CLI element-edit.\\n\\nTEST2222\\n\\nTEST MORE","image":{"detail":{"color":"#224123","filename":"","url":""},"thumbnail":{"color":"#224655","filename":"xxx","url":""}},"markdown":"AxxxxAA2333BBBCCC\\n","name":"MUR-6407 Test Element","source":{"from":"service","name":"mur6407testelement","url":"https://testtesttest.apps.exosite-dev.io/swagger-mur-6407.yaml"},"specs":"","type":"service","tags":[],"active":true,"approval":"approved","elementId":"5ae3600e313d01708c2a6e0f"}),
|
|
393
|
+
'MUR-6407'
|
|
394
|
+
)
|
|
395
|
+
expect(stdout).to eq('')
|
|
396
|
+
expect(stderr).to eq %(Request Failed: 400: [400] "tiers" is not allowed. "approval" is not allowed\n)
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
data/spec/cmd_exchange_spec.rb
CHANGED
|
@@ -39,7 +39,7 @@ RSpec.describe 'murano exchange', :cmd, :needs_password do
|
|
|
39
39
|
expect(lines[3]).to match(/^(\+-+){#{num_cols}}\+$/)
|
|
40
40
|
# Content. Starts with elementId.
|
|
41
41
|
(4..(lines.length - 2)).to_a.each do |line|
|
|
42
|
-
expect(lines[line]).to match(/^\| [0-9a-f]+
|
|
42
|
+
expect(lines[line]).to match(/^\| [0-9a-f]+ +\| /)
|
|
43
43
|
end
|
|
44
44
|
expect(lines[-1]).to match(/^(\+-+){#{num_cols}}\+$/)
|
|
45
45
|
end
|
|
@@ -51,7 +51,7 @@ RSpec.describe 'murano exchange', :cmd, :needs_password do
|
|
|
51
51
|
expect_exchange_element_table(stdout, stderr, num_cols: 4)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
it 'only ids' do
|
|
54
|
+
it 'only ids', :club_20s, :club_10s do
|
|
55
55
|
stdout, stderr = murano_command_run('exchange list', '--idonly')
|
|
56
56
|
expect(stderr).to eq('')
|
|
57
57
|
stdout.lines.each do |line|
|