MuranoCLI 3.0.1 → 3.0.2

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.agignore +1 -0
  3. data/.rubocop.yml +67 -5
  4. data/Gemfile +6 -3
  5. data/MuranoCLI.gemspec +14 -10
  6. data/README.markdown +299 -126
  7. data/Rakefile +6 -1
  8. data/bin/murano +2 -2
  9. data/docs/completions/murano_completion-bash +93 -0
  10. data/lib/MrMurano.rb +19 -2
  11. data/lib/MrMurano/Business.rb +22 -19
  12. data/lib/MrMurano/Config.rb +19 -9
  13. data/lib/MrMurano/Content.rb +4 -4
  14. data/lib/MrMurano/Exchange-Element.rb +99 -0
  15. data/lib/MrMurano/Exchange.rb +137 -0
  16. data/lib/MrMurano/Gateway.rb +9 -9
  17. data/lib/MrMurano/Keystore.rb +4 -2
  18. data/lib/MrMurano/ReCommander.rb +3 -5
  19. data/lib/MrMurano/Solution-ServiceConfig.rb +12 -12
  20. data/lib/MrMurano/Solution-Services.rb +15 -14
  21. data/lib/MrMurano/Solution-Users.rb +2 -2
  22. data/lib/MrMurano/Solution.rb +43 -49
  23. data/lib/MrMurano/SolutionId.rb +28 -28
  24. data/lib/MrMurano/SyncUpDown.rb +32 -22
  25. data/lib/MrMurano/Webservice-Endpoint.rb +2 -1
  26. data/lib/MrMurano/Webservice.rb +5 -5
  27. data/lib/MrMurano/commands.rb +2 -1
  28. data/lib/MrMurano/commands/business.rb +21 -19
  29. data/lib/MrMurano/commands/domain.rb +16 -2
  30. data/lib/MrMurano/commands/exchange.rb +272 -0
  31. data/lib/MrMurano/commands/globals.rb +17 -1
  32. data/lib/MrMurano/commands/init.rb +3 -3
  33. data/lib/MrMurano/commands/link.rb +16 -16
  34. data/lib/MrMurano/commands/postgresql.rb +2 -2
  35. data/lib/MrMurano/commands/show.rb +13 -7
  36. data/lib/MrMurano/commands/solution.rb +23 -17
  37. data/lib/MrMurano/commands/solution_picker.rb +49 -44
  38. data/lib/MrMurano/commands/sync.rb +2 -1
  39. data/lib/MrMurano/commands/timeseries.rb +2 -2
  40. data/lib/MrMurano/commands/tsdb.rb +2 -2
  41. data/lib/MrMurano/hash.rb +19 -7
  42. data/lib/MrMurano/http.rb +12 -2
  43. data/lib/MrMurano/orderedhash.rb +200 -0
  44. data/lib/MrMurano/spec_commander.rb +98 -0
  45. data/lib/MrMurano/verbosing.rb +2 -2
  46. data/lib/MrMurano/version.rb +2 -2
  47. data/spec/Business_spec.rb +8 -6
  48. data/spec/Solution-ServiceConfig_spec.rb +1 -1
  49. data/spec/SyncUpDown_spec.rb +6 -6
  50. data/spec/_workspace.rb +9 -4
  51. data/spec/cmd_business_spec.rb +8 -2
  52. data/spec/cmd_common.rb +266 -25
  53. data/spec/cmd_exchange_spec.rb +118 -0
  54. data/spec/cmd_help_spec.rb +54 -13
  55. data/spec/cmd_init_spec.rb +1 -12
  56. data/spec/cmd_link_spec.rb +94 -72
  57. data/spec/spec_helper.rb +11 -16
  58. metadata +23 -17
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.15 /coding: utf-8
1
+ # Last Modified: 2017.08.29 /coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -48,6 +48,11 @@ task :echo do
48
48
  puts built_gem
49
49
  end
50
50
 
51
+ desc 'Tail the CI build file and the curl file'
52
+ task :tail do
53
+ sh %(tail -F .rake_build.out curldebug.out)
54
+ end
55
+
51
56
  desc 'display remind of how to release'
52
57
  task :release_reminder do
53
58
  reminder = %(
data/bin/murano CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # Last Modified: 2017.08.23 /coding: utf-8
2
+ # Last Modified: 2017.08.30 /coding: utf-8
3
3
  # frozen_string_literal: true
4
4
 
5
5
  # Copyright © 2016-2017 Exosite LLC.
@@ -43,7 +43,7 @@ program :description, %(
43
43
  # VAR=$(murano command ...)
44
44
  # etc., then do not do progress.
45
45
  # TEST/2017-08-23: Does this work on Windows?
46
- ARGV.push('--no-progress') unless $stdout.tty?
46
+ ARGV.push('--no-progress') unless $stdout.tty? || ARGV.include?('--no-progress')
47
47
 
48
48
  default_command :help
49
49
 
@@ -10,6 +10,10 @@ __app_switches=(
10
10
  --configfile
11
11
  --curl
12
12
  --dry
13
+ --csv
14
+ --json
15
+ --yaml
16
+ --pp
13
17
  --exclude-scopes
14
18
  --no-page
15
19
  --no-plugins
@@ -78,6 +82,7 @@ function _murano () {
78
82
  devices
79
83
  diff
80
84
  domain
85
+ exchange
81
86
  find
82
87
  gwe
83
88
  help
@@ -163,6 +168,9 @@ function _murano () {
163
168
  (domain)
164
169
  __murano-domain "$cmd1" "$cmd2" "${used_switches[@]}"
165
170
  ;;
171
+ (exchange)
172
+ __murano-exchange "$cmd1" "$cmd2" "${used_switches[@]}"
173
+ ;;
166
174
  (find)
167
175
  __murano-find "$cmd1" "$cmd2" "${used_switches[@]}"
168
176
  ;;
@@ -1398,6 +1406,91 @@ function __murano-domain () {
1398
1406
  COMPREPLY=($(compgen -W '${comp_list[@]}' -- "${last}"))
1399
1407
  }
1400
1408
 
1409
+ # Completion for subcommand: "exchange".
1410
+ function __murano-exchange () {
1411
+ local subcmd1="$1"
1412
+ local subcmd2="$2"
1413
+ #local subcmdn="$3"
1414
+ local used_switches="${@:3}"
1415
+ local last="${COMP_WORDS[COMP_CWORD]}"
1416
+ local len=$(($COMP_CWORD - 1))
1417
+
1418
+ local -a more_switches
1419
+
1420
+ local -a comp_list
1421
+
1422
+ #>&2 echo -e "\nsubcmd1=$subcmd1 / subcmd2=$subcmd2 / last=$last / len=$len"
1423
+ #>&2 echo "used_switches=$used_switches"
1424
+ #>&2 echo "more_switches=$more_switches"
1425
+
1426
+ # NOTE: Not doing anything special for ${subcmd2}.
1427
+ # Are there sub-sub-commands we shoud list?
1428
+ if [[ -z ${subcmd1} || ${len} -eq 1 ]]; then
1429
+ comp_list=(
1430
+ add
1431
+ buy
1432
+ list
1433
+ purchase
1434
+ )
1435
+ else
1436
+ case $subcmd1 in
1437
+ (add)
1438
+ more_switches=(
1439
+ {--trace}
1440
+ )
1441
+ ;;
1442
+ (buy)
1443
+ more_switches=(
1444
+ {--trace}
1445
+ )
1446
+ ;;
1447
+ (list)
1448
+ more_switches=(
1449
+ {--trace}
1450
+ )
1451
+ ;;
1452
+ (purchase)
1453
+ more_switches=(
1454
+ {--trace}
1455
+ )
1456
+ ;;
1457
+ esac
1458
+ fi
1459
+
1460
+ # Add unused application-wide flags.
1461
+ local idx
1462
+ for ((idx = 0; idx < ${#__app_switches[@]}; idx++)); do
1463
+ local switch=${__app_switches[$idx]}
1464
+ if ! contains_element "$switch" "${used_switches[@]}"; then
1465
+ comp_list+=("$switch")
1466
+ fi
1467
+ done
1468
+ # Add unused subcommand flags.
1469
+ for ((idx = 0; idx < ${#more_switches[@]}; idx++)); do
1470
+ local switch=${more_switches[$idx]}
1471
+ comp_list+=("$switch")
1472
+ done
1473
+
1474
+ # If there are only --flags, <TAB> will put the common prefix,
1475
+ # "--", but maybe the user doesn't want to add a flag after all.
1476
+ if [[ -z ${last} ]]; then
1477
+ local flags_only=true
1478
+ for ((idx = 0; idx < ${#comp_list[@]}; idx++)); do
1479
+ local switch=${comp_list[$idx]}
1480
+ if [[ ${switch} != --* ]]; then
1481
+ flags_only=false
1482
+ break
1483
+ fi
1484
+ done
1485
+ if ${flags_only}; then
1486
+ # Use two Unicode en spaces to prevent compgen from prefixing "--".
1487
+ comp_list+=("  ")
1488
+ fi
1489
+ fi
1490
+
1491
+ COMPREPLY=($(compgen -W '${comp_list[@]}' -- "${last}"))
1492
+ }
1493
+
1401
1494
  # Completion for subcommand: "find".
1402
1495
  function __murano-find () {
1403
1496
  local subcmd1="$1"
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.16 /coding: utf-8
1
+ # Last Modified: 2017.08.29 /coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -9,27 +9,44 @@
9
9
  # individual files include all the files they need.
10
10
 
11
11
  require 'MrMurano/version'
12
- require 'MrMurano/verbosing'
12
+
13
13
  require 'MrMurano/hash'
14
14
  require 'MrMurano/http'
15
+ require 'MrMurano/makePretty'
16
+ #require 'MrMurano/optparse'
17
+ require 'MrMurano/progress'
18
+ require 'MrMurano/verbosing'
15
19
 
16
20
  require 'MrMurano/Config'
21
+ require 'MrMurano/Config-Migrate'
17
22
  require 'MrMurano/ProjectFile'
18
23
 
19
24
  require 'MrMurano/Account'
20
25
  require 'MrMurano/Business'
26
+ require 'MrMurano/Exchange'
27
+ require 'MrMurano/Exchange-Element'
28
+ require 'MrMurano/Passwords'
21
29
 
22
30
  require 'MrMurano/Content'
23
31
  require 'MrMurano/Gateway'
32
+ require 'MrMurano/Keystore'
33
+ require 'MrMurano/Mock'
24
34
  require 'MrMurano/Setting'
35
+ require 'MrMurano/SolutionId'
25
36
  require 'MrMurano/Solution'
26
37
  require 'MrMurano/Solution-Services'
27
38
  require 'MrMurano/Solution-ServiceConfig'
28
39
  require 'MrMurano/Solution-Users'
40
+ require 'MrMurano/Webservice'
29
41
  require 'MrMurano/Webservice-Cors'
30
42
  require 'MrMurano/Webservice-Endpoint'
31
43
  require 'MrMurano/Webservice-File'
32
44
 
45
+ require 'MrMurano/SyncAllowed'
46
+ require 'MrMurano/SyncRoot'
47
+ require 'MrMurano/SyncUpDown'
48
+
49
+ require 'MrMurano/SubCmdGroupContext'
33
50
  require 'MrMurano/ReCommander'
34
51
  require 'MrMurano/commands'
35
52
 
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.23 /coding: utf-8
1
+ # Last Modified: 2017.09.11 /coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -26,12 +26,11 @@ module MrMurano
26
26
  include Http
27
27
  include Verbose
28
28
 
29
- #attr_accessor :bid
30
- #attr_accessor :name
31
- attr_accessor :role
32
- attr_reader :meta
33
29
  attr_writer :bid
34
30
  attr_writer :name
31
+ attr_accessor :role
32
+ attr_reader :meta
33
+ attr_reader :ometa
35
34
 
36
35
  def initialize(data=nil)
37
36
  @bid = nil
@@ -39,6 +38,7 @@ module MrMurano
39
38
  @valid = false
40
39
  @user_bizes = {}
41
40
  self.meta = data unless data.nil?
41
+ @ometa = nil
42
42
  end
43
43
 
44
44
  def valid?
@@ -155,7 +155,7 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
155
155
  whirly_stop
156
156
  @valid = !data.nil?
157
157
  @name = data[:name] if @valid
158
- @valid
158
+ @ometa = data
159
159
  end
160
160
 
161
161
  # ---------------------------------------------------------------------
@@ -166,7 +166,7 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
166
166
  #ALLOWED_TYPES = [:domain, :onepApi, :dataApi, :application, :product,].freeze
167
167
  ALLOWED_TYPES = %i[application product].freeze
168
168
 
169
- def solutions(type: :all, sid: nil, name: nil, fuzzy: nil, invalidate: false)
169
+ def solutions(type: :all, api_id: nil, name: nil, fuzzy: nil, invalidate: false)
170
170
  debug "Getting all solutions of type #{type}"
171
171
  must_business_id!
172
172
 
@@ -201,16 +201,17 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
201
201
 
202
202
  solz = @user_bizes[type].dup
203
203
 
204
- match_sid = ensure_array(sid)
204
+ match_api_id = ensure_array(api_id)
205
205
  match_name = ensure_array(name)
206
206
  match_fuzzy = ensure_array(fuzzy)
207
- if match_sid.any? || match_name.any? || match_fuzzy.any?
207
+ if match_api_id.any? || match_name.any? || match_fuzzy.any?
208
208
  solz.select! do |sol|
209
209
  (
210
- match_sid.include?(sol[:apiId]) ||
210
+ match_api_id.include?(sol[:apiId]) ||
211
211
  match_name.include?(sol[:name]) ||
212
212
  match_fuzzy.any? do |term|
213
- sol[:name] =~ /#{Regexp.escape(term)}/i || sol[:apiId] =~ /#{Regexp.escape(term)}/i
213
+ sol[:name] =~ /#{Regexp.escape(term)}/i || \
214
+ sol[:apiId] =~ /#{Regexp.escape(term)}/i
214
215
  end
215
216
  )
216
217
  end
@@ -224,7 +225,9 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
224
225
  MrMurano::Product.new(meta)
225
226
  else
226
227
  warning("Unexpected solution type: #{meta[:type]}")
227
- warning('* Please enable Murano for this business') if meta[:type].to_sym == :dataApi
228
+ if meta[:type].to_sym == :dataApi
229
+ warning('* Please enable Murano for this business')
230
+ end
228
231
  MrMurano::Solution.new(meta)
229
232
  end
230
233
  end
@@ -241,14 +244,14 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
241
244
  def solution_from_type!(type)
242
245
  type = type.to_s.to_sym
243
246
  raise "Unknown type(#{type})" unless type.to_s.empty? || ALLOWED_TYPES.include?(type)
244
- sid = MrMurano::Solution::INVALID_SID
247
+ api_id = MrMurano::Solution::INVALID_API_ID
245
248
  if type == :application
246
- sol = MrMurano::Application.new(sid)
249
+ sol = MrMurano::Application.new(api_id)
247
250
  elsif type == :product
248
- sol = MrMurano::Product.new(sid)
251
+ sol = MrMurano::Product.new(api_id)
249
252
  else
250
253
  #raise "Unexpected path: Unrecognized type #{fancy_ticks(type)}"
251
- sol = MrMurano::Solution.new(sid)
254
+ sol = MrMurano::Solution.new(api_id)
252
255
  end
253
256
  sol.biz = self
254
257
  sol
@@ -312,7 +315,7 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
312
315
  error("Unexpected: Solution ID not returned: #{resp}")
313
316
  exit 1
314
317
  end
315
- sol.sid = resp[:id]
318
+ sol.api_id = resp[:id]
316
319
  sol.affirm_valid
317
320
  # 2017-06-29: The code used to hunt for the solution ID, because
318
321
  # POST business/<bizid>/solution/ used to not return anything,
@@ -333,11 +336,11 @@ or set it interactively using \`#{MrMurano::EXE_NAME} init\`
333
336
  # exit 3
334
337
  # end
335
338
  # sol.meta = ret.first
336
- # if sol.sid.to_s.empty? then
339
+ # if sol.api_id.to_s.empty? then
337
340
  # error("New solution created for #{fancy_ticks(sol.name)} missing ID?: #{ret}")
338
341
  # exit 3
339
342
  # end
340
- # sol.sid = sid
343
+ # sol.api_id = api_id
341
344
  #end
342
345
  sol
343
346
  end
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.23 /coding: utf-8
1
+ # Last Modified: 2017.08.31 /coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -280,23 +280,33 @@ module MrMurano
280
280
  true
281
281
  end
282
282
 
283
- def validate_cmd
283
+ INVALID_PROJECT_HINT = %(
284
+ Please change to a project directory, or run `murano init` to create a new project.
285
+ ).strip
286
+
287
+ def validate_cmd(cmd=nil)
288
+ return unless validate_cmd_business_and_project(cmd)
289
+ migrate_old_config(@project_dir)
290
+ migrate_old_config(Pathname.new(Dir.home))
291
+ end
292
+
293
+ def validate_cmd_business_and_project(cmd)
284
294
  # Most commands should be run from within a Murano project (sub-)directory.
285
295
  # If user is running a project command not within a project directory,
286
296
  # we'll print a message now and exit the app from run_active_command later.
287
297
  unless @runner.nil?
288
- the_cmd = @runner.active_command
289
- unless the_cmd.name == 'help' || the_cmd.project_not_required || @project_exists
298
+ the_cmd = @runner.active_command if cmd.nil?
299
+ the_cmd = command(cmd) if the_cmd.nil?
300
+ the_cmd.project_not_required = false unless defined?(the_cmd.project_not_required)
301
+ if the_cmd.name != 'help' && !the_cmd.project_not_required && !@project_exists
290
302
  error %(The "#{the_cmd.name}" command only works in a Murano project.)
291
- say %(Please change to a project directory, or run `murano init` to create a new project.)
303
+ say INVALID_PROJECT_HINT
292
304
  # Note that commnander-rb uses an at_exit hook, which we hack around.
293
305
  @runner.command_exit = 1
294
- return
306
+ false
295
307
  end
296
308
  end
297
-
298
- migrate_old_config(@project_dir)
299
- migrate_old_config(Pathname.new(Dir.home))
309
+ true
300
310
  end
301
311
 
302
312
  def self.fix_modes(path)
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.23 /coding: utf-8
1
+ # Last Modified: 2017.09.11 /coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -29,9 +29,9 @@ module MrMurano
29
29
 
30
30
  def initialize
31
31
  @solntype = 'product.id'
32
- @uriparts_sidex = 1
33
- init_sid!
34
- @uriparts = [:service, @sid, :content, :item]
32
+ @uriparts_apidex = 1
33
+ init_api_id!
34
+ @uriparts = [:service, @api_id, :content, :item]
35
35
  @itemkey = :id
36
36
  #@locationbase = $cfg['location.base']
37
37
  @location = nil
@@ -0,0 +1,99 @@
1
+ # Last Modified: 2017.08.31 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
8
+ module MrMurano
9
+ class ExchangeElement
10
+ include HashInit
11
+
12
+ # The meta is the element hash returned from the platform,
13
+ # i.e., all of the other attrs in a Hash.
14
+ attr_reader :meta
15
+
16
+ # The Exchange Element's Business ID context.
17
+ attr_accessor :bizid
18
+
19
+ # The Exchange Element's Element ID.
20
+ attr_accessor :elementId
21
+ #attr_accessor :element_id
22
+
23
+ # The Purchase ID is nil unless the user has added/purchased this element.
24
+ attr_accessor :purchaseId
25
+ #attr_accessor :purchase_id
26
+
27
+ # The <bizId>/exchange/ endpoint returns a list of flat dictionaries.
28
+ # The <bizId>/purchase/ endpoint, on the other hand, puts the remaining
29
+ # items in an object under an "element" key.
30
+
31
+ # The type is one of: download
32
+ attr_accessor :type
33
+ #attr_accessor :action_type
34
+
35
+ # The friendly, descriptive name of the Exchange Element.
36
+ attr_accessor :name
37
+
38
+ # FIXME/EXPLAIN: Is this what the Lua code calls the service?
39
+ attr_accessor :apiServiceName
40
+
41
+ # The image associated with the Exchange Element; not used by the CLI.
42
+ attr_accessor :image
43
+
44
+ # The short description describing the Exchange Element.
45
+ attr_accessor :description
46
+
47
+ # The long description describing the Exchange Element.
48
+ attr_accessor :markdown
49
+
50
+ # The Murano business tiers to which this element applies.
51
+ # One or more of: ["free", "developer", "professional", "enterprise"]
52
+ attr_accessor :tiers
53
+
54
+ # Tags used to describe the Exchange Element.
55
+ attr_accessor :tags
56
+
57
+ # Actions associated with the Exchange Element.
58
+ attr_accessor :actions
59
+ # The actions is an array with one dict element with:
60
+ # 'url', 'type' (e.g., 'download), and 'primary' (bool).
61
+
62
+ # MurCLI-only: Based on purchaseId and tiers, state of Element in Business.
63
+ attr_accessor :statusable
64
+
65
+ ELEM_KEY_TRANSLATE = {
66
+ #type: :action_type,
67
+ #elementId: :element_id,
68
+ }.freeze
69
+
70
+ def initialize(*hash)
71
+ hash = [hash] unless hash.is_a? Array
72
+ camel_cased = {}
73
+ hash.first.each do |key, val|
74
+ if ELEM_KEY_TRANSLATE[key].nil?
75
+ camel_cased[key] = val
76
+ else
77
+ camel_cased[ELEM_KEY_TRANSLATE[key]] = val
78
+ end
79
+ end
80
+ super camel_cased
81
+ @meta = hash.first
82
+ #@meta = camel_cased
83
+ end
84
+
85
+ def status
86
+ case statusable
87
+ when :available
88
+ 'available'
89
+ when :upgrade
90
+ 'available*'
91
+ when :added
92
+ 'added'
93
+ else
94
+ statusable.to_s
95
+ end
96
+ end
97
+ end
98
+ end
99
+