MrMurano 1.11.3 → 1.12.0

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +2 -0
  4. data/README.markdown +12 -14
  5. data/Rakefile +2 -2
  6. data/TODO.taskpaper +8 -6
  7. data/docs/demo.md +109 -0
  8. data/lib/MrMurano/Account.rb +6 -3
  9. data/lib/MrMurano/Config.rb +13 -37
  10. data/lib/MrMurano/Product-1P-Device.rb +2 -0
  11. data/lib/MrMurano/Product-Resources.rb +5 -4
  12. data/lib/MrMurano/Product.rb +3 -3
  13. data/lib/MrMurano/Solution-File.rb +1 -2
  14. data/lib/MrMurano/Solution-ServiceConfig.rb +11 -1
  15. data/lib/MrMurano/Solution-Services.rb +24 -7
  16. data/lib/MrMurano/Solution-Users.rb +6 -4
  17. data/lib/MrMurano/SyncUpDown.rb +67 -28
  18. data/lib/MrMurano/commands/config.rb +4 -1
  19. data/lib/MrMurano/commands/exportImport.rb +3 -0
  20. data/lib/MrMurano/hash.rb +2 -0
  21. data/lib/MrMurano/http.rb +3 -3
  22. data/lib/MrMurano/verbosing.rb +9 -3
  23. data/lib/MrMurano/version.rb +1 -1
  24. data/spec/Account_spec.rb +104 -0
  25. data/spec/Config_spec.rb +202 -57
  26. data/spec/Http_spec.rb +204 -0
  27. data/spec/MakePretties_spec.rb +35 -0
  28. data/spec/Mock_spec.rb +13 -20
  29. data/spec/ProductBase_spec.rb +2 -0
  30. data/spec/ProductContent_spec.rb +77 -12
  31. data/spec/ProductResources_spec.rb +235 -0
  32. data/spec/Product_1P_Device_spec.rb +62 -0
  33. data/spec/Product_1P_RPC_spec.rb +2 -0
  34. data/spec/Product_spec.rb +18 -8
  35. data/spec/Solution-Cors_spec.rb +28 -1
  36. data/spec/Solution-Endpoint_spec.rb +250 -33
  37. data/spec/Solution-File_spec.rb +210 -0
  38. data/spec/Solution-ServiceConfig_spec.rb +2 -0
  39. data/spec/Solution-ServiceDevice_spec.rb +174 -0
  40. data/spec/Solution-ServiceEventHandler_spec.rb +134 -1
  41. data/spec/Solution-ServiceModules_spec.rb +317 -64
  42. data/spec/Solution-UsersRoles_spec.rb +207 -0
  43. data/spec/Solution_spec.rb +90 -0
  44. data/spec/SyncRoot_spec.rb +52 -46
  45. data/spec/SyncUpDown_spec.rb +364 -0
  46. data/spec/Verbosing_spec.rb +279 -0
  47. data/spec/_workspace.rb +27 -0
  48. data/spec/fixtures/dumped_config +47 -0
  49. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  50. data/spec/fixtures/product_spec_files/lightbulb.yaml +2 -0
  51. data/spec/fixtures/roles-three.yaml +11 -0
  52. data/spec/spec_helper.rb +9 -0
  53. metadata +26 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3834a5056532662031cc184d66b913ff77d516f
4
- data.tar.gz: 4185017027496ed440bb23d0c84bf39ea44ecb9e
3
+ metadata.gz: 5435dfba3b558c2de067fc23c0f3dddce44b826f
4
+ data.tar.gz: 5472c934c6ab6920ea86a5a774f1790e04028d59
5
5
  SHA512:
6
- metadata.gz: 4587f4ee92cc776f1b7284a6a0da7992fc15ba180b48aa6178345eec23b6ff5843d153de20eade090d45be464f9c9d38daae28f8f2f4a9f3e9baafd23deb5d91
7
- data.tar.gz: 7420fae6e4e16eb99c122f05dd45efc6c49980c9dc346b97023d61603cdda7c7e7e28b628a733966d592d4aa919d3742b6e0ad267d79cc0877b00ef2a7ddc071
6
+ metadata.gz: 18b2a24e1703142195cdb729d58136e8a49bd1237ec209e272b7345d58e4d70001e14807b39b498f59f98b6fa9e159b5f76dc4ccc647aa223484351ecad26c0a
7
+ data.tar.gz: 7e754ef2e1b9de17d40f74837bc518da249ec65bdd29e63c041edf1da16fce9a26ccb9d27aa8e45b71c84e8d01332b8164fa044da523213b9045bb8e87d95cb6
data/.gitignore CHANGED
@@ -12,6 +12,7 @@ xcuserdata
12
12
  Pods/
13
13
  pkg/
14
14
  report/
15
+ coverage/
15
16
 
16
17
  .mrmurano/
17
18
  .mrmuranorc
data/Gemfile CHANGED
@@ -15,6 +15,8 @@ group :test do
15
15
  gem 'rake', '~> 10.1.1'
16
16
  gem 'rspec', '~> 3.5'
17
17
  gem 'webmock', '~> 2.1.0'
18
+ gem 'simplecov', :require => false
19
+ gem 'coderay', :require => false
18
20
  end
19
21
 
20
22
  group :windows do
data/README.markdown CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/MrMurano.svg)](https://badge.fury.io/rb/MrMurano)
4
4
  [![Build Status](https://travis-ci.org/tadpol/MrMurano.svg?branch=master)](https://travis-ci.org/tadpol/MrMurano)
5
+ [![Inline docs](http://inch-ci.org/github/exosite/MrMurano.svg?branch=master)](http://inch-ci.org/github/exosite/MrMurano)
5
6
 
6
7
  Do more from the command line with [Murano](https://exosite.com/platform/)
7
8
 
@@ -64,6 +65,16 @@ Your `PATH` may need to be updated to find the installed `mr` command. See the
64
65
  [Ruby Gem FAQ](http://guides.rubygems.org/faqs/#user-install). In short, you need
65
66
  to add the output of `ruby -rubygems -e 'puts Gem.user_dir'` to your `PATH`.
66
67
 
68
+ ### Windows Install
69
+
70
+ The MrMurano gem will install on Windows. There is also a single Windows binary
71
+ Setup installer availible in [releases](https://github.com/exosite/MrMurano/releases)
72
+
73
+ You can install Ruby on Windows with [RubyInstaller](http://rubyinstaller.org).
74
+ You might run into a [known SSL cert issue](http://guides.rubygems.org/ssl-certificate-update/).
75
+ If so follow the steps there to update the certs.
76
+
77
+
67
78
  ## Features
68
79
 
69
80
  ### Logs
@@ -105,7 +116,7 @@ cat >> .mrmurano.prod <<EOF
105
116
  id=CCCCCCCC
106
117
  EOF
107
118
 
108
- cat >> .env <<EOF
119
+ cat > .env <<EOF
109
120
  MR_CONFIGFILE=.mrmurano.dev
110
121
  EOF
111
122
  ```
@@ -156,10 +167,6 @@ following commands:
156
167
 
157
168
  Call them with `--help` for details.
158
169
 
159
- ### ZSH tab completion
160
-
161
- Basic completion support for zsh.
162
-
163
170
  ### Sub-directories
164
171
 
165
172
  For the endpoints, modules, and eventhandlers directories. The can contain both
@@ -214,12 +221,3 @@ MrMurano also uses [bundler](http://bundler.io).
214
221
 
215
222
  When submitting pull requests, please do them against the develop branch.
216
223
 
217
- ## Windows
218
-
219
- The MrMurano gem will install on Windows.
220
-
221
- You can install Ruby on Windows with [RubyInstaller](http://rubyinstaller.org).
222
- You might run into a [known SSL cert issue](http://guides.rubygems.org/ssl-certificate-update/).
223
- If so follow the steps there to update the certs.
224
-
225
-
data/Rakefile CHANGED
@@ -46,14 +46,14 @@ task :gemit do
46
46
  sh %{git checkout v#{mrt}}
47
47
  Rake::Task[:build].invoke
48
48
  Rake::Task[:bob].invoke
49
- Rake::Task['push::gem'].invoke
49
+ Rake::Task['push:gem'].invoke
50
50
  sh %{git checkout develop}
51
51
  end
52
52
 
53
53
  namespace :push do
54
54
  desc 'Push gem up to RubyGems'
55
55
  task :gem do
56
- sh %{gem push pkg/MrMurano-#{Bundler::GemHelper.gemspec.version}.gem}
56
+ sh %{gem push #{builtGem}}
57
57
  end
58
58
 
59
59
  namespace :github do
data/TODO.taskpaper CHANGED
@@ -28,8 +28,8 @@ Endpoints:
28
28
  - Add directory support like in modules @done(2016-07-26)
29
29
 
30
30
  Files:
31
- - Add ignore patterns to config @done(2016-12-20)
32
31
  - Switch to mime-types v3 @pri(low)
32
+ - Add ignore patterns to config @done(2016-12-20)
33
33
  - Figure out how to make the hexed-sha checksum faster. @done(2016-09-23)
34
34
  - Fix upload. @done(2016-08-01)
35
35
  - Files won't update, they always delete then add. @done(2016-07-28)
@@ -56,7 +56,8 @@ Timeseries:
56
56
 
57
57
  Product:
58
58
  - Add option for progress bar when uploading content files.
59
- - Support multiple products.
59
+ - Support multiple products. @done(2017-01-05)
60
+ Won't do. Future will be one-to-one.
60
61
  Think about how this would work. There is the syncing of the resoruces, and then
61
62
  some of the commands that use product.id.
62
63
  - Auto convert exoline spec files into murano spec files on upload? @done(2016-10-27)
@@ -68,8 +69,6 @@ Service Device:
68
69
  - When listing and business.id is missing, gracefully fall back to --idonly @done(2016-09-12)
69
70
 
70
71
  Config:
71
- - Add config tool.default_sync to set which things sync{up,down} by default
72
- It is internally hardcoded to be -s, -a, -m, -e right now.
73
72
  - Store passwords in system Keychain on system that have a Keychain.
74
73
  mac OS does, various Linux desktops have a couple differnet ones. Not sure about
75
74
  Windows.
@@ -80,6 +79,8 @@ Config:
80
79
 
81
80
  Plus things like 1Password, LastPass, KeePass, and others.
82
81
 
82
+ - Add config sync.bydefault to set which things sync{up,down} by default @done(2017-01-05)
83
+ It is internally hardcoded to be -s, -a, -m, -e right now.
83
84
  - Add ENV['MR_CONFIGFILE'] path to file to load like --configfile @done(2016-09-22)
84
85
  - Maybe add dotenv support. @done(2016-09-22)
85
86
  - Think about adding dev,staging,prod system; how would that work? @done(2016-09-16)
@@ -88,6 +89,7 @@ SyncUpDown:
88
89
  - Document the hash keys for an item. @pri(high)
89
90
  Also consider turning that hash into a Struct
90
91
  - Allow specifying local files to limit actions to.
92
+ This is one the command line. The idea being to sync just one file.
91
93
 
92
94
  SolutionBase:
93
95
  - All network traffic is serialized. Make some parallel.
@@ -98,8 +100,8 @@ SolutionBase:
98
100
  - Rebuild how local names and paths are computed from remote items. @done(2016-07-27)
99
101
 
100
102
  Windows:
101
- - Need to test with http://rubyinstaller.org on Windows. @pri(high)
102
- - Look into http://ocra.rubyforge.org for building an exec. @pri(high)
103
+ - Need to test with http://rubyinstaller.org on Windows. @pri(high) @done(2016-12-21)
104
+ - Look into http://ocra.rubyforge.org for building an exec. @pri(high) @done(2016-12-21)
103
105
 
104
106
  Bundles:
105
107
  - Revisit this idea. Its complexity may not be worth its value.
data/docs/demo.md ADDED
@@ -0,0 +1,109 @@
1
+
2
+
3
+ # Every sub-command will --help
4
+
5
+ # Start anew
6
+ - Clone project: `git clone https://github.com/tadpol/GWE-Multitool.git demo01`
7
+ - `cd demo01`
8
+
9
+ - Pick a bussiness: `mr business list`
10
+ - Set it: `mr config business.id ZZZZZZZZZ`
11
+
12
+ - Create a product: `mr product create myawesomeproduct`
13
+ - Save the result: `mr config product.id YYYYYYYYY`
14
+
15
+ - Set the product definition: `mr config product.spec gwe-multitool.yaml`
16
+ - Set the directory to look for specs. `mr config location.specs spec`
17
+ - Sync the product definition up: `mr syncup -V --specs`
18
+
19
+ - Create a solution: `mr solution create myawesomesolution`
20
+ - Save the result: `mr config solution.id XXXXXX`
21
+ - Assign the product to the solution: `mr assign set`
22
+
23
+ # What got configured?
24
+ `mr config --dump`
25
+
26
+
27
+
28
+
29
+
30
+
31
+ # <voice type='orc'>Work Work</voice>
32
+
33
+ - What is going to change? `mr status`
34
+ - Sync solution code up: `mr syncup -V`
35
+
36
+ - Change a file
37
+ - What is going to change? `mr status`
38
+ - Details of change: `mr diff`
39
+
40
+
41
+
42
+
43
+ # Devices
44
+ - Add a real device: `mr product device enable 42:42:42:42:42:42`
45
+ - !!!cheet and activate by hand: `mr product device activate 42:42:42:42:42:42`
46
+ - Which resources are there? `mr product spec pull`
47
+ - What did the device write to that one resource?
48
+ `mr product device read 42:42:42:42:42:42 update_interval`
49
+ - `mr product device write 42:42:42:42:42:42 update_interval 300`
50
+
51
+
52
+
53
+ # Multiple configs
54
+ Because Developing, Staging, Production.
55
+
56
+ Set addition config file to load with `MR_CONFIGFILE`
57
+
58
+ Also supports '.env'
59
+
60
+
61
+
62
+
63
+ # Device Content Area
64
+
65
+ See GWE.
66
+
67
+
68
+
69
+
70
+
71
+ # Debugging
72
+
73
+ ## Logs
74
+ - `mr logs`
75
+ - `mr logs --follow`
76
+
77
+
78
+
79
+
80
+
81
+
82
+ ## Keystore
83
+ ### What is in the Keystore?
84
+ `mr keystore list`
85
+
86
+ ### Write and Read a Key
87
+ - `mr keystore set test greebled`
88
+ - `mr keystore get test`
89
+
90
+ ### Write to a Set
91
+ - `mr keystore command sadd myset greebled`
92
+ Or any other supported Redis command.
93
+
94
+ ### Remove just the ones with 'socketmap'
95
+ `mr keystore list | grep socketmap | xargs -L1 mr keystore delete`
96
+
97
+
98
+
99
+
100
+ ## TSDB
101
+
102
+ - `mr tsdb list metrics`
103
+ - `mr tsdb list tags`
104
+ - `mr tsdb query @sn=1 temp0`
105
+ - `mr tsdb query @sn=1 temp0 --limit=4`
106
+ - `mr tsdb query @sn=1 --limit=10 -c outformat=csv --epoch ms`
107
+
108
+
109
+
@@ -65,7 +65,7 @@ module MrMurano
65
65
  host = $cfg['net.host']
66
66
  user = $cfg['user.name']
67
67
  if user.nil? then
68
- say_error("No Murano user account found; please login")
68
+ error("No Murano user account found; please login")
69
69
  user = ask("User name: ")
70
70
  $cfg.set('user.name', user, :user)
71
71
  end
@@ -74,7 +74,7 @@ module MrMurano
74
74
  pf.load
75
75
  pws = pf.get(host, user)
76
76
  if pws.nil? then
77
- say_error("Couldn't find password for #{user}")
77
+ error("Couldn't find password for #{user}")
78
78
  pws = ask("Password: ") { |q| q.echo = "*" }
79
79
  pf.set(host, user, pws)
80
80
  pf.save
@@ -108,12 +108,15 @@ module MrMurano
108
108
  showHttpError(request, response)
109
109
  error "Check to see if username and password are correct."
110
110
  @@token = nil
111
- raise response
112
111
  end
113
112
  end
114
113
  @@token
115
114
  end
116
115
 
116
+ def token_reset(value=nil)
117
+ @@token = value
118
+ end
119
+
117
120
  def businesses
118
121
  get('user/' + $cfg['user.name'] + '/membership/')
119
122
  end
@@ -9,7 +9,6 @@ module MrMurano
9
9
  # env from ENV['MR_CONFIGFILE']
10
10
  # project .mrmuranorc at project dir
11
11
  # user .mrmuranorc at $HOME
12
- # system .mrmuranorc at /etc
13
12
  # defaults Internal hardcoded defaults
14
13
  #
15
14
  ConfigFile = Struct.new(:kind, :path, :data) do
@@ -34,12 +33,10 @@ module MrMurano
34
33
  attr :paths
35
34
  attr_reader :projectDir
36
35
 
37
- CFG_SCOPES=%w{internal specified env project private user system defaults}.map{|i| i.to_sym}.freeze
36
+ CFG_SCOPES=%w{internal specified env project user defaults}.map{|i| i.to_sym}.freeze
38
37
  CFG_FILE_NAME = '.mrmuranorc'.freeze
39
- CFG_PRVT_NAME = '.mrmuranorc.private'.freeze # Going away.
40
38
  CFG_DIR_NAME = '.mrmurano'.freeze
41
39
  CFG_ALTRC_NAME = '.mrmurano/config'.freeze
42
- CFG_SYS_NAME = '/etc/mrmuranorc'.freeze # Going away.
43
40
 
44
41
  def initialize
45
42
  @paths = []
@@ -55,19 +52,13 @@ module MrMurano
55
52
  end
56
53
  @projectDir = findProjectDir()
57
54
  unless @projectDir.nil? then
58
- if (@projectDir + CFG_PRVT_NAME).exist? then
59
- say_warning "!!! Using .mrmuranorc.private is deprecated"
60
- end
61
- @paths << ConfigFile.new(:private, @projectDir + CFG_PRVT_NAME)
62
55
  @paths << ConfigFile.new(:project, @projectDir + CFG_FILE_NAME)
63
56
  fixModes(@projectDir + CFG_DIR_NAME)
57
+ else
58
+ @paths << ConfigFile.new(:project, Pathname.new(Dir.home) + CFG_FILE_NAME)
64
59
  end
65
60
  @paths << ConfigFile.new(:user, Pathname.new(Dir.home) + CFG_FILE_NAME)
66
61
  fixModes(Pathname.new(Dir.home) + CFG_DIR_NAME)
67
- if Pathname.new(CFG_SYS_NAME).exist? then
68
- say_warning "!!! Using #{CFG_SYS_NAME} is deprecated"
69
- @paths << ConfigFile.new(:system, Pathname.new(CFG_SYS_NAME))
70
- end
71
62
  @paths << ConfigFile.new(:defaults, nil, IniFile.new())
72
63
 
73
64
 
@@ -89,6 +80,8 @@ module MrMurano
89
80
  set('location.cors', 'cors.yaml', :defaults)
90
81
  set('location.specs', 'specs', :defaults)
91
82
 
83
+ set('sync.bydefault', SyncRoot.bydefault.join(' '), :defaults)
84
+
92
85
  set('files.default_page', 'index.html', :defaults)
93
86
  set('files.searchFor', '**/*', :defaults)
94
87
  set('files.ignoring', '', :defaults)
@@ -105,7 +98,11 @@ module MrMurano
105
98
 
106
99
  set('product.spec', 'resources.yaml', :defaults)
107
100
 
108
- set('diff.cmd', 'diff -u', :defaults)
101
+ if Gem.win_platform? then
102
+ set('diff.cmd', 'fc', :defaults)
103
+ else
104
+ set('diff.cmd', 'diff -u', :defaults)
105
+ end
109
106
  end
110
107
 
111
108
  ## Find the root of this project Directory.
@@ -119,10 +116,10 @@ module MrMurano
119
116
  # - .git/
120
117
  def findProjectDir()
121
118
  result=nil
122
- fileNames=[CFG_FILE_NAME, CFG_PRVT_NAME, CFG_ALTRC_NAME]
119
+ fileNames=[CFG_FILE_NAME, CFG_ALTRC_NAME]
123
120
  dirNames=[CFG_DIR_NAME]
124
- home = Pathname.new(Dir.home)
125
- pwd = Pathname.new(Dir.pwd)
121
+ home = Pathname.new(Dir.home).realpath
122
+ pwd = Pathname.new(Dir.pwd).realpath
126
123
  return nil if home == pwd
127
124
  pwd.dirname.ascend do |i|
128
125
  break unless result.nil?
@@ -174,8 +171,6 @@ module MrMurano
174
171
  root = @projectDir + CFG_DIR_NAME
175
172
  when :user
176
173
  root = Pathname.new(Dir.home) + CFG_DIR_NAME
177
- when :system
178
- root = nil
179
174
  when :defaults
180
175
  root = nil
181
176
  end
@@ -259,25 +254,6 @@ module MrMurano
259
254
 
260
255
  end
261
256
 
262
- ##
263
- # IF none of -same, then -same; else just the ones listed.
264
- def self.checkSAME(opt)
265
- unless opt.files or opt.endpoints or opt.modules or
266
- opt.eventhandlers or opt.roles or opt.users or opt.spec then
267
- opt.files = true
268
- opt.endpoints = true
269
- opt.modules = true
270
- opt.eventhandlers = true
271
- end
272
- if opt.all then
273
- opt.files = true
274
- opt.endpoints = true
275
- opt.modules = true
276
- opt.eventhandlers = true
277
- opt.roles = true
278
- opt.users = true
279
- end
280
- end
281
257
  end
282
258
 
283
259
  # vim: set ai et sw=2 ts=2 :
@@ -31,6 +31,8 @@ module MrMurano
31
31
  offset += 50
32
32
  end
33
33
 
34
+ raise "Identifier Not Found: #{sn}" if found.empty?
35
+
34
36
  @sn_rid = found.first[:rid]
35
37
  @sn_rid
36
38
  end
@@ -114,7 +114,7 @@ module MrMurano
114
114
  remove(item[:rid])
115
115
  end
116
116
  r = create(item[:alias], item[:format])
117
- raise "Create Failed: #{r}" unless r.nil?
117
+ raise "Create Failed: #{r}" unless r.empty?
118
118
  end
119
119
 
120
120
  ## Use alias for doing sync compares
@@ -134,11 +134,11 @@ module MrMurano
134
134
  from = Pathname.new(from) unless from.kind_of? Pathname
135
135
  debug "#{self.class.to_s}: Getting local items from: #{from}"
136
136
  if not from.exist? then
137
- say_warning "Skipping missing #{from.to_s}"
137
+ warning "Skipping missing #{from.to_s}"
138
138
  return []
139
139
  end
140
140
  unless from.file? then
141
- say_warning "Cannot read from #{from.to_s}"
141
+ warning "Cannot read from #{from.to_s}"
142
142
  return []
143
143
  end
144
144
 
@@ -149,6 +149,7 @@ module MrMurano
149
149
  if here.kind_of?(Hash) and here.has_key?('resources') then
150
150
  here['resources'].map{|i| Hash.transform_keys_to_symbols(i)}
151
151
  else
152
+ warning "Unexpected data in #{from.to_s}"
152
153
  []
153
154
  end
154
155
  end
@@ -205,7 +206,7 @@ module MrMurano
205
206
  ##
206
207
  # True if itemA and itemB are different
207
208
  def docmp(itemA, itemB)
208
- itemA[:alias] == itemB[:alias] and itemA[:format] == itemB[:format]
209
+ itemA[:alias] != itemB[:alias] or itemA[:format] != itemB[:format]
209
210
  end
210
211
 
211
212
  end
@@ -217,8 +217,7 @@ module MrMurano
217
217
  end
218
218
  end
219
219
  else
220
- showHttpError(request, response)
221
- raise resp
220
+ showHttpError(request, resp)
222
221
  end
223
222
  end
224
223
  nil
@@ -256,6 +255,7 @@ module MrMurano
256
255
 
257
256
  ##
258
257
  # This is not applicable to Murano. Remove?
258
+ # :nocov:
259
259
  class ProductModel < ProductBase
260
260
  def initialize
261
261
  super
@@ -329,7 +329,6 @@ module MrMurano
329
329
  return response.body
330
330
  else
331
331
  showHttpError(request, response)
332
- raise response
333
332
  end
334
333
  end
335
334
 
@@ -354,6 +353,7 @@ module MrMurano
354
353
  end
355
354
 
356
355
  end
356
+ # :nocov:
357
357
 
358
358
  end
359
359
  # vim: set ai et sw=2 ts=2 :
@@ -37,8 +37,7 @@ module MrMurano
37
37
  end
38
38
  end
39
39
  else
40
- showHttpError(request, response)
41
- raise resp
40
+ showHttpError(request, resp)
42
41
  end
43
42
  end
44
43
  nil
@@ -6,6 +6,7 @@ module MrMurano
6
6
  def initialize
7
7
  super
8
8
  @uriparts << 'serviceconfig'
9
+ @scid = nil
9
10
  end
10
11
 
11
12
  def list
@@ -57,6 +58,14 @@ module MrMurano
57
58
 
58
59
  end
59
60
 
61
+ ## This is only used for debugging and deciphering APIs.
62
+ #
63
+ # There was once a plan for using this to automagically map commands into
64
+ # services by reading their schema. That plan had too much magic and was too
65
+ # fragile for real use.
66
+ #
67
+ # A much better UI/UX happens with human intervention.
68
+ # :nocov:
60
69
  class Services < SolutionBase
61
70
  def initialize
62
71
  super
@@ -100,8 +109,9 @@ module MrMurano
100
109
  calls
101
110
  end
102
111
  end
112
+ # :nocov:
103
113
 
104
-
114
+ # Device config interface for the assign commands.
105
115
  class SC_Device < ServiceConfig
106
116
  def initialize
107
117
  super
@@ -12,11 +12,15 @@ module MrMurano
12
12
  class ServiceBase < SolutionBase
13
13
 
14
14
  def mkalias(remote)
15
+ # :nocov:
15
16
  raise "Needs to be implemented in child"
17
+ # :nocov:
16
18
  end
17
19
 
18
20
  def mkname(remote)
21
+ # :nocov:
19
22
  raise "Needs to be implemented in child"
23
+ # :nocov:
20
24
  end
21
25
 
22
26
  def list
@@ -106,6 +110,7 @@ module MrMurano
106
110
  if cacheFile.file? then
107
111
  cacheFile.open('r+') do |io|
108
112
  cache = YAML.load(io)
113
+ cache = {} unless cache
109
114
  io.rewind
110
115
  cache[local_path.to_s] = entry
111
116
  io << cache.to_yaml
@@ -127,6 +132,7 @@ module MrMurano
127
132
  ret = nil
128
133
  cacheFile.open('r') do |io|
129
134
  cache = YAML.load(io)
135
+ return nil unless cache
130
136
  if cache.has_key?(local_path.to_s) then
131
137
  entry = cache[local_path.to_s]
132
138
  debug("For #{local_path}:")
@@ -199,6 +205,7 @@ module MrMurano
199
205
  @uriparts << 'eventhandler'
200
206
  @itemkey = :alias
201
207
  @location = $cfg['location.eventhandlers']
208
+ @match_header = /--#EVENT (?<service>\S+) (?<event>\S+)/
202
209
  end
203
210
 
204
211
  def mkalias(remote)
@@ -259,14 +266,24 @@ module MrMurano
259
266
 
260
267
  def toRemoteItem(from, path)
261
268
  path = Pathname.new(path) unless path.kind_of? Pathname
262
- aheader = path.readlines().first
263
- md = /--#EVENT (\S+) (\S+)/.match(aheader)
264
- if md.nil? then
265
- rp = path.relative_path_from(Pathname.new(Dir.pwd))
266
- say_warning "Not an Event handler: #{rp}"
267
- return nil
269
+ cur = nil
270
+ lineno=0
271
+ path.readlines().each do |line|
272
+ md = @match_header.match(line)
273
+ if not md.nil? then
274
+ # header line.
275
+ cur = {:service=>md[:service],
276
+ :event=>md[:event],
277
+ :local_path=>path,
278
+ :line=>lineno,
279
+ :script=>line}
280
+ elsif not cur.nil? and not cur[:script].nil? then
281
+ cur[:script] << line
282
+ end
283
+ lineno += 1
268
284
  end
269
- {:service=>md[1], :event=>md[2]}
285
+ cur[:line_end] = lineno unless cur.nil?
286
+ cur
270
287
  end
271
288
 
272
289
  def synckey(item)
@@ -54,7 +54,7 @@ module MrMurano
54
54
  end
55
55
  end
56
56
 
57
- def removelocal(dest, item)
57
+ def removelocal(local, item)
58
58
  # needs to append/merge with file
59
59
  # for now, we'll read, modify, write
60
60
  here = []
@@ -78,11 +78,11 @@ module MrMurano
78
78
  def localitems(from)
79
79
  from = Pathname.new(from) unless from.kind_of? Pathname
80
80
  if not from.exist? then
81
- say_warning "Skipping missing #{from.to_s}"
81
+ warning "Skipping missing #{from.to_s}"
82
82
  return []
83
83
  end
84
84
  unless from.file? then
85
- say_warning "Cannot read from #{from.to_s}"
85
+ warning "Cannot read from #{from.to_s}"
86
86
  return []
87
87
  end
88
88
 
@@ -106,6 +106,7 @@ module MrMurano
106
106
  SyncRoot.add('roles', Role, 'R', %{Roles})
107
107
 
108
108
  # …/user
109
+ # :nocov:
109
110
  class User < UserBase
110
111
  def initialize
111
112
  super
@@ -116,7 +117,7 @@ module MrMurano
116
117
  # @param modify Bool: True if item exists already and this is changing it
117
118
  def upload(local, remote, modify)
118
119
  # TODO figure out APIs for updating users.
119
- say_warning "Updating Users isn't working currently."
120
+ warning "Updating Users isn't working currently."
120
121
  # post does work if the :password field is set.
121
122
  end
122
123
 
@@ -124,6 +125,7 @@ module MrMurano
124
125
  item[:email]
125
126
  end
126
127
  end
128
+ # :nocov:
127
129
  SyncRoot.add('users', User, 'U', %{Users})
128
130
  end
129
131
  # vim: set ai et sw=2 ts=2 :