MrMurano 1.11.3 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
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 :