MuranoCLI 3.2.2.beta.2 → 3.2.2.beta.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12d344b05fe0a8a403f5d166b1ac75b5b111a476111612b4ba45134e307d5df3
4
- data.tar.gz: d53c7a3d60aac2088cf707616e0bcfdcef62d96a722bd1f438221b962866f5b8
3
+ metadata.gz: 873b8cb25d9f921b8f7d516d3af89f9a8c00c0fca3563185c20e8f309e399e66
4
+ data.tar.gz: ce2ebb53424b1630afdc8792e55f557f4a16106ae52a309b6de895f6795269bb
5
5
  SHA512:
6
- metadata.gz: 7e79ea5d8fd3e7cdb3f947f801523d6c8c663ea2d2cd59ac97ef2c328052215660986f0698ba7f1351f039c9af9106a0cf54fa144ad930b8e6da6eb469870e88
7
- data.tar.gz: 58c1a02f8df8d9f4d9cf868d70e8280b7f2b763a3627471dcf8d91b6fc28dab7ed7be2f1ed1b190aed20a7a4b0b54a7bacb9f2756988a7b3e27529b23e31b72f
6
+ metadata.gz: 1c745b425de12f64871b71c930b6caf3d57d5000e2b5971f199b2e40a47a90d4bcee6508a145bb05d219f76f73f4487ab06c1408a2ac24d1841b6fcce2001370
7
+ data.tar.gz: 396c7e304790dcc1dd8f0d4e5e9be70abf212e687a0396c74a7d7874c4fbb107c262af9ddef9a55217863f85b7097bffb731b815a2e3c33dda92fc34ba58cbb4
@@ -0,0 +1,60 @@
1
+ ### Issue Reference
2
+
3
+ *Please fill in the Issue number.*
4
+
5
+ https://jira.exosite.com/browse/MUR-XXXX
6
+
7
+ ### Additional Notes
8
+
9
+ *Please add optional, supplementary information for the reviewer.*
10
+
11
+ ### Git and GitHub Etiquette
12
+
13
+ Please follow the guidelines documented in [Git Best Practices](https://github.com/exosite/MuranoCLI/blob/develop/docs/gitflow.md).
14
+
15
+ ### Readiness Checklist
16
+
17
+ *Please complete this checklist before asking for a review.*
18
+
19
+ - [ ] Linting checked with `rake lint`
20
+
21
+ - [ ] New unit tests added (if applicable)
22
+
23
+ - [ ] All unit tests pass with `rake rspec`
24
+ *(2018-09-07: Should be >= 537 active tests)*
25
+
26
+ - [ ] New unit tests provide coverage of new code
27
+ (peruse `report/index-*.html` to verify)
28
+
29
+ - [ ] New commands and all options tested using CLI
30
+
31
+ - [ ] All inline `--help` updated and verified using CLI
32
+
33
+ - [ ] Full walkthrough of current Epic performed (if applicable)
34
+
35
+ - [ ] New features and bugfixes tested against the appropriate
36
+ environments (`dev`, `staging`, and/or `production`)
37
+
38
+ - [ ] Developer documentation updated and compiles (if applicable)
39
+
40
+ ### When you Merge
41
+
42
+ *Follow these steps after your PR has been approved by a coworker.*
43
+
44
+ 1. Click the 'Merge pull request' button.
45
+
46
+ - Do not squash; we want to preserve your beautiful commit history
47
+ in the codebase.
48
+
49
+ 2. Edit the title of the merge message.
50
+
51
+ - Message format: **<JIRA_Ticket_Title> (<ticket_nums>) (PR_num)**
52
+
53
+ - For example: **Foo Bar Bug (MUR-1234) (#666)**
54
+
55
+ 3. Clear out the body text of the merge message.
56
+
57
+ 4. Click the 'Confirm merge' button.
58
+
59
+ 5. Delete your old branch.
60
+
data/.rubocop.yml CHANGED
@@ -261,6 +261,7 @@ Style/TrailingCommaInLiteral:
261
261
  EnforcedStyleForMultiline: "consistent_comma"
262
262
 
263
263
  AllCops:
264
+ TargetRubyVersion: 2.3.7
264
265
  Include:
265
266
  - 'bin/murano'
266
267
  # These are included by default:
@@ -285,7 +286,4 @@ AllCops:
285
286
  #
286
287
  # The spec_helper is a generated file; don't care.
287
288
  - 'spec/spec_helper.rb'
288
- # The unit test for syncdown has a ton of copy-paste curl output,
289
- # which would be super duper tedious to clean up for the linter.
290
- - 'spec/cmd_syncdown_unit_spec.rb'
291
289
 
data/Gemfile CHANGED
@@ -20,6 +20,7 @@ gem 'inflecto'
20
20
  gem 'inifile', '~> 3.0'
21
21
  gem 'json', '~> 2.1.0'
22
22
  gem 'json-schema', '~> 2.7.0'
23
+ gem 'launchy', '~> 2.4.3'
23
24
  gem 'mime-types', '~> 3.1'
24
25
  gem 'mime-types-data', '~> 3.2016.0521'
25
26
  # We forked commander to fix empty-string --args issue.
@@ -35,6 +36,7 @@ gem 'paint', '~> 2.0.0'
35
36
  # It's included by json, so make sure it's the old one.
36
37
  gem 'public_suffix', '~> 2.0.5'
37
38
  gem 'rainbow', '~> 2.2.2'
39
+ gem 'redcarpet', '~> 3.4.0'
38
40
  # LATER/2017-09-12: See MRMUR-160 and MRMUR-161:
39
41
  # Windows build fails unless `rake` is packaged.
40
42
  gem 'rake', '~> 12.1.0'
data/HISTORY.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  ---------------------------------------------------------------------------
4
4
 
5
+ ## Murano CLI v3.2.2.beta.3 (2018-09-06)
6
+
7
+ ### New
8
+
9
+ - Expose ``device2.event`` event handler. (Issue: [MUR-4543](https://i.exosite.com/jira/browse/MUR-4543))
10
+
11
+ ### Improved
12
+
13
+ - Fail early on ``content upload`` if file size exceeds maximum allowed (users may specify ``--no-limit`` to skip check and force upload). (Issue: [MUR-898](https://i.exosite.com/jira/browse/MUR-898))
14
+
15
+ - Do not crash on corrupt cache. Show warning instead, and ask user to email the corrupt cache file to the Murano Exchange team. (Issue: [MUR-4669](https://i.exosite.com/jira/browse/MUR-4669))
16
+
17
+ ### Fixed
18
+
19
+ - Fix ``migrate up`` and ``migrate down`` to sort and order migration scripts numerically, not alphabetically. (E.g., migrating from version ``9`` to ``10`` was broken.) (Issue: [MUR-7570](https://i.exosite.com/jira/browse/MUR-7570))
20
+
21
+ - Display platform error when ``postgresql`` or ``tsdb`` commands file, rather than crashing. (Issue: [MUR-7878](https://i.exosite.com/jira/browse/MUR-7878))
22
+
23
+ - Read keystore value from STDIN if not specified in command arguments. (Issue: [MUR-4410](https://i.exosite.com/jira/browse/MUR-4410))
24
+
25
+ - Prevent external HighLine library from crashing on "Error: Infinity" during ``murano init``. (Issue: [MUR-6474](https://i.exosite.com/jira/browse/MUR-6474))
26
+
27
+ ### Developer improvements
28
+
29
+ - Update developer documentation and add ``rake`` tasks for macOS development. (Issue: [MUR-8114](https://i.exosite.com/jira/browse/MUR-8114))
30
+
31
+ ---------------------------------------------------------------------------
32
+
5
33
  ## Murano CLI v3.2.2.beta.2 (2018-08-30)
6
34
 
7
35
  ### Improved
data/MuranoCLI.gemspec CHANGED
@@ -101,6 +101,7 @@ And so much more.
101
101
  s.add_runtime_dependency('rainbow', '~> 2.2.2')
102
102
  # 2017-09-12: MRMUR-160/MRMUR-161: (lb): Windows build fails without `rake`.
103
103
  s.add_runtime_dependency('rake', '~> 12.1.0')
104
+ s.add_runtime_dependency('redcarpet', '~> 3.4.0')
104
105
  s.add_runtime_dependency('terminal-table', '~> 1.8.0')
105
106
  s.add_runtime_dependency('tty-editor', '~> 0.4.0')
106
107
  s.add_runtime_dependency('vine', '~> 0.4')
data/Rakefile CHANGED
@@ -10,10 +10,15 @@ require 'open3'
10
10
  require 'shellwords'
11
11
  require 'tmpdir'
12
12
 
13
- task default: %i[test]
13
+ task default: %i[tasks]
14
14
 
15
15
  # ***
16
16
 
17
+ desc 'Show list of tasks'
18
+ task :tasks do
19
+ sh %(rake --tasks)
20
+ end
21
+
17
22
  def current_ver
18
23
  Bundler::GemHelper.gemspec.version.version
19
24
  end
@@ -65,6 +70,16 @@ task :'install:user' do
65
70
  build_gem_install_user
66
71
  end
67
72
 
73
+ def build_gem_install_user_mac(gem_ver=nil)
74
+ Rake::Task['install'].invoke
75
+ sh %(gem install #{built_gem(gem_ver)})
76
+ end
77
+
78
+ desc 'Build and install into user gems directory on mac using rvm'
79
+ task :'install:user:mac' do
80
+ build_gem_install_user_mac
81
+ end
82
+
68
83
  desc 'Uninstall gem from user gems directory'
69
84
  task :'uninstall:user' do
70
85
  # HINT: Replace #{built_gem} with any version to uninstall a specific version.
@@ -347,6 +362,18 @@ end
347
362
 
348
363
  # ***
349
364
 
365
+ # (lb): Shadow bundler's release task, which we don't use.
366
+ # The task looks like this:
367
+ # (byebug) Rake::Task['release']
368
+ # <Rake::Task release => [
369
+ # build, release:guard_clean, release:source_control_push, release:rubygem_push
370
+ # ]>
371
+ task :release do
372
+ shamings = ['Nope!', 'Wrong!!', 'Think again!!!']
373
+ $stdout.puts shamings[Random.rand(shamings.length)]
374
+ exit 1
375
+ end
376
+
350
377
  namespace :package do
351
378
  GH_OWNER = 'exosite'
352
379
  GH_REPO = 'MuranoCLI'
@@ -418,22 +445,6 @@ Here's some light reading if you need help:
418
445
  exit 1
419
446
  end
420
447
 
421
- def api_gh_fetch_releases
422
- # If the GitHub project was public, we could just `wget https://....gem`,
423
- # but the project is private, so we gotta use the GitHub API to fetch it.
424
- _out, _err, _status = Open3.capture3(
425
- %(
426
- curl --header "Authorization: token #{ENV['GITHUB_TOKEN']}" \
427
- --header "Accept: application/json" \
428
- --remote-name \
429
- --location \
430
- https://api.github.com/repos/#{GH_OWNER}/#{GH_REPO}/releases
431
- )
432
- )
433
- sh %(cat releases | head -n 14)
434
- $stdout.puts %(...\n\n)
435
- end
436
-
437
448
  def api_gh_fetch_asset_id
438
449
  _out, _err, _status = Open3.capture3(
439
450
  %(
@@ -444,12 +455,15 @@ Here's some light reading if you need help:
444
455
  https://api.github.com/repos/#{GH_OWNER}/#{GH_REPO}/releases/tags/v#{current_ver}
445
456
  )
446
457
  )
447
- sh %(cat v#{current_ver} | head -n 14)
448
- $stdout.puts %(...\n\n)
449
-
450
- asset_id, _err, _status = Open3.capture3(%(cat v#{current_ver} | jq '.assets[0].id'))
451
- $stdout.puts %(asset_id: #{asset_id}\n)
452
- asset_id
458
+ # If there's no such release, you'll see, e.g.,
459
+ # { "message": "Not Found", "documentation_url": "..." }
460
+ # Otherwise, you'll find an assets array in the JSON.
461
+ # NOTE: Use -M to disable output coloring.
462
+ asset_id, _err, _status = Open3.capture3(
463
+ %(cat v#{current_ver} | jq -M '.assets[0].id')
464
+ )
465
+ asset_id.chomp!
466
+ (asset_id != 'null') && asset_id || nil
453
467
  end
454
468
 
455
469
  def api_gh_fetch_asset(asset_id)
@@ -524,7 +538,6 @@ Now, smoke test!
524
538
  must_env_github_token!
525
539
  Dir.mktmpdir do |tmpdir|
526
540
  Dir.chdir(tmpdir)
527
- api_gh_fetch_releases
528
541
  asset_id = api_gh_fetch_asset_id
529
542
  gem_name = api_gh_fetch_asset(asset_id)
530
543
  must_gem_downloaded!(gem_name)
@@ -537,6 +550,18 @@ Now, smoke test!
537
550
  # it (and we might need it to troubleshoot!).
538
551
  end
539
552
  end
553
+
554
+ # rake package:pushed?
555
+ desc 'Check if the Gem has been built and pushed to GitHub'
556
+ task :pushed? do
557
+ must_env_github_token!
558
+ Dir.mktmpdir do |tmpdir|
559
+ Dir.chdir(tmpdir)
560
+ asset_id = api_gh_fetch_asset_id
561
+ $stdout.puts(asset_id.to_s.empty? && 'no' || 'yes')
562
+ exit asset_id.to_s.empty? && 1 || 0
563
+ end
564
+ end
540
565
  end
541
566
 
542
567
  # *** Push tasks (used by Jenkins CI release job).
@@ -20,29 +20,45 @@ module MrMurano
20
20
  # Is in JSON, which as a subset of YAML, so use YAML parser
21
21
  solsecret.open do |io|
22
22
  ss = YAML.load(io)
23
-
24
23
  pff = $cfg.file_at('passwords', :user)
25
24
  pwd = MrMurano::Passwords.new(pff)
26
- pwd.load
27
- ps = pwd.get($cfg['net.host'], ss['email'])
28
- if ps.nil?
25
+ ps = load_passwords_maybe(pwd, pff, ss)
26
+ update_passwords_maybe(pwd, ps, ss)
27
+ update_config_from_secrets(ss)
28
+ end
29
+ end
30
+
31
+ def load_passwords_maybe(pwd, pff, ss)
32
+ # 2018-09-05: (lb): I added a new warning for when the passwords file
33
+ # is not present, which is uncommon for normal users, but for tests,
34
+ # it's all too common. So do not expect the passwords file to be there.
35
+ return nil unless pff.exist?
36
+ pwd.load
37
+ pwd.get($cfg['net.host'], ss['email'])
38
+ end
39
+
40
+ def update_passwords_maybe(pwd, ps, ss)
41
+ if ps.nil?
42
+ pwd.set($cfg['net.host'], ss['email'], ss['password'])
43
+ pwd.save
44
+ elsif ps != ss['password']
45
+ okay = ask(
46
+ 'A different password for this account already exists. Overwrite? N/y'
47
+ )
48
+ if okay =~ /^y/i
29
49
  pwd.set($cfg['net.host'], ss['email'], ss['password'])
30
50
  pwd.save
31
- elsif ps != ss['password']
32
- y = ask('A different password for this account already exists. Overwrite? N/y')
33
- if y =~ /^y/i
34
- pwd.set($cfg['net.host'], ss['email'], ss['password'])
35
- pwd.save
36
- end
37
- # else, already set, nothing to do.
38
51
  end
52
+ # else, already set, nothing to do.
53
+ end
54
+ end
39
55
 
40
- $cfg.set('user.name', ss['email'])
41
- $project.refresh_user_name
56
+ def update_config_from_secrets(ss)
57
+ $cfg.set('user.name', ss['email'])
58
+ $project.refresh_user_name
42
59
 
43
- $cfg.set('application.id', ss['solution_id']) if ss.key? 'solution_id'
44
- $cfg.set('product.id', ss['product_id']) if ss.key? 'product_id'
45
- end
60
+ $cfg.set('application.id', ss['solution_id']) if ss.key? 'solution_id'
61
+ $cfg.set('product.id', ss['product_id']) if ss.key? 'product_id'
46
62
  end
47
63
  end
48
64
  end
@@ -284,7 +284,6 @@ module MrMurano
284
284
  # that we don't want to touch.
285
285
  set('eventhandler.skiplist', %w[
286
286
  device.service_call
287
- device2.event
288
287
  interface
289
288
  webservice
290
289
  websocket
@@ -344,6 +343,13 @@ module MrMurano
344
343
  set('business.name', nil, :defaults)
345
344
  set('application.name', nil, :defaults)
346
345
  set('product.name', nil, :defaults)
346
+ # (lb): The maximum allowed size the platform indicates is different
347
+ # between deployed environments. As measured on 2018-09-05:
348
+ # 134_219_813 # dev
349
+ # 134_219_804 # staging
350
+ # 134_219_808 # prod
351
+ # Let's just use the least common value, otherwise we'll be here all day.
352
+ set('content.size_limit', 134_219_804, :defaults) # Content service upload limit from Pegasus
347
353
  end
348
354
 
349
355
  ## Find the root of this project Directory.
@@ -65,7 +65,8 @@ module MrMurano
65
65
  return @pass_file unless @pass_file.nil?
66
66
  pwd_path = $cfg.file_at(MrMurano::Passwords::FILENAME, :user)
67
67
  @pass_file = MrMurano::Passwords.new(pwd_path)
68
- @pass_file.load
68
+ # Check password file exists to avoid not-found warning.
69
+ @pass_file.load if pwd_path.exist?
69
70
  @pass_file
70
71
  end
71
72
 
@@ -27,30 +27,75 @@ module MrMurano
27
27
  @data = nil
28
28
  end
29
29
 
30
+ def trace_type
31
+ fancy_ticks(@val_type || self.class)
32
+ end
33
+
30
34
  def load
31
- return unless @path.exist?
35
+ return if clear_data_unless_storage_file_exists
36
+ fix_permissions_storage_file
37
+ load_data_from_storage_file
38
+ end
39
+
40
+ def clear_data_unless_storage_file_exists
41
+ return false if @path.exist?
42
+ warning %(Could not load #{trace_type} file at: #{@path})
43
+ @data = {}
44
+ true
45
+ end
46
+
47
+ def fix_permissions_storage_file
48
+ # (lb): This acts like SSH would, and makes file read-write only to
49
+ # owner, just in case.
32
50
  @path.chmod(0o600)
51
+ rescue StandardError => err
52
+ warning %(Could not chmod #{trace_type} file at: #{@path})
53
+ error err.message
54
+ exit 1
55
+ end
56
+
57
+ def load_data_from_storage_file
33
58
  @path.open('rb') do |io|
34
59
  @data = YAML.load(io)
35
60
  # The @data is, e.g., false, if the file exists but is empty.
36
61
  @data = {} unless @data.is_a?(Hash)
37
62
  end
38
63
  rescue StandardError => err
39
- warning %(Could not load #{fancy_ticks(@val_type)} file at: #{@path})
64
+ warning %(Could not load #{trace_type} file at: #{@path})
40
65
  error err.message
41
66
  exit 1
42
67
  end
43
68
 
44
69
  def save
45
- if $cfg['tool.dry']
46
- say '--dry: Not saving config'
47
- return
48
- end
70
+ return if say_if_dry_run
71
+ ensure_dirpath!
72
+ store_data!
73
+ end
74
+
75
+ def say_if_dry_run
76
+ return false unless $cfg['tool.dry']
77
+ say '--dry: Not saving config'
78
+ true
79
+ end
80
+
81
+ def ensure_dirpath!
49
82
  @path.dirname.mkpath unless @path.dirname.exist?
83
+ rescue StandardError => err
84
+ # E.g., Errno::EACCES.
85
+ warning %(Could not create path to #{trace_type} file at: #{@path.dirname})
86
+ error err.message
87
+ exit 1
88
+ end
89
+
90
+ def store_data!
50
91
  @path.open('wb') do |io|
51
92
  io << @data.to_yaml
52
93
  end
53
94
  @path.chmod(0o600)
95
+ rescue StandardError => err
96
+ warning %(Could not store #{trace_type} file at: #{@path})
97
+ error err.message
98
+ exit 1
54
99
  end
55
100
 
56
101
  def get(key1, key2)
@@ -85,7 +130,7 @@ module MrMurano
85
130
  return unless !hd.nil? && hd.is_a?(Hash)
86
131
  if $cfg['tool.dry']
87
132
  MrMurano::Verbose.whirly_interject do
88
- say(%(--dry: Not removing #{@val_type} for #{fancy_ticks("#{key2}@#{host}")}))
133
+ say(%(--dry: Not removing #{trace_type} for #{fancy_ticks("#{key2}@#{host}")}))
89
134
  end
90
135
  return
91
136
  end
@@ -38,7 +38,11 @@ module MrMurano
38
38
 
39
39
  def must_id!(id)
40
40
  return unless id.nil?
41
- raise "ID not set, or Service '#{@service_name}' not enabled for this Solution"
41
+ service_missing_msg = %(
42
+ The #{fancy_ticks(@service_name)} service is not enabled for this Solution
43
+ ).strip
44
+ warning "#{service_missing_msg}, or the Solution ID is missing."
45
+ exit 1
42
46
  end
43
47
 
44
48
  def scid_for_name(name)
@@ -194,5 +198,34 @@ module MrMurano
194
198
  super
195
199
  end
196
200
  end
201
+
202
+ class PlatformService < ServiceConfig
203
+ def call_platform(query_or_queries, aqr)
204
+ # Send a block to call so that the response or error is returned
205
+ # and no post-processing is done (without the block, http.workit
206
+ # only returns success JSON; on failure, workit prints a generic
207
+ # error (the HTTP code) and returns nil).
208
+ call(query_or_queries, :post, aqr) do |request, http|
209
+ response = http.request(request)
210
+ json = workit_response(response)
211
+ return nil if json.empty?
212
+ json
213
+ end
214
+ end
215
+
216
+ def self.must_return_nonnil_nonerror!(ret)
217
+ # (lb): 2018-08-27: This behavior is old, but feels weird:
218
+ # If ret.nil?, silently exit on error; but if ret[:error],
219
+ # print the error, then exit on error. My question: why
220
+ # not print a generic error message when ret.nil? Or, maybe
221
+ # I need to know first, when and why would ret be nil anyway?
222
+ exit 1 if ret.nil?
223
+ return if ret[:error].nil?
224
+ MrMurano::Verbose.error(
225
+ "ERROR: #{MrMurano::Verbose.fancy_ticks(ret[:error])}"
226
+ )
227
+ exit 1
228
+ end
229
+ end
197
230
  end
198
231