MuranoCLI 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +27 -0
  6. data/LICENSE.txt +19 -0
  7. data/MuranoCLI.gemspec +50 -0
  8. data/MuranoCLI.iss +50 -0
  9. data/README.markdown +208 -0
  10. data/Rakefile +188 -0
  11. data/TODO.taskpaper +122 -0
  12. data/bin/mr +8 -0
  13. data/bin/murano +84 -0
  14. data/docs/demo.md +109 -0
  15. data/lib/MrMurano/Account.rb +211 -0
  16. data/lib/MrMurano/Config-Migrate.rb +47 -0
  17. data/lib/MrMurano/Config.rb +286 -0
  18. data/lib/MrMurano/Mock.rb +63 -0
  19. data/lib/MrMurano/Product-1P-Device.rb +145 -0
  20. data/lib/MrMurano/Product-Resources.rb +195 -0
  21. data/lib/MrMurano/Product.rb +358 -0
  22. data/lib/MrMurano/ProjectFile.rb +349 -0
  23. data/lib/MrMurano/Solution-Cors.rb +46 -0
  24. data/lib/MrMurano/Solution-Endpoint.rb +177 -0
  25. data/lib/MrMurano/Solution-File.rb +150 -0
  26. data/lib/MrMurano/Solution-ServiceConfig.rb +140 -0
  27. data/lib/MrMurano/Solution-Services.rb +326 -0
  28. data/lib/MrMurano/Solution-Users.rb +129 -0
  29. data/lib/MrMurano/Solution.rb +59 -0
  30. data/lib/MrMurano/SubCmdGroupContext.rb +49 -0
  31. data/lib/MrMurano/SyncUpDown.rb +565 -0
  32. data/lib/MrMurano/commands/assign.rb +57 -0
  33. data/lib/MrMurano/commands/businessList.rb +45 -0
  34. data/lib/MrMurano/commands/completion.rb +152 -0
  35. data/lib/MrMurano/commands/config.rb +67 -0
  36. data/lib/MrMurano/commands/content.rb +130 -0
  37. data/lib/MrMurano/commands/cors.rb +30 -0
  38. data/lib/MrMurano/commands/domain.rb +17 -0
  39. data/lib/MrMurano/commands/gb.rb +33 -0
  40. data/lib/MrMurano/commands/init.rb +138 -0
  41. data/lib/MrMurano/commands/keystore.rb +157 -0
  42. data/lib/MrMurano/commands/logs.rb +78 -0
  43. data/lib/MrMurano/commands/mock.rb +63 -0
  44. data/lib/MrMurano/commands/password.rb +88 -0
  45. data/lib/MrMurano/commands/postgresql.rb +41 -0
  46. data/lib/MrMurano/commands/product.rb +14 -0
  47. data/lib/MrMurano/commands/productCreate.rb +39 -0
  48. data/lib/MrMurano/commands/productDelete.rb +33 -0
  49. data/lib/MrMurano/commands/productDevice.rb +84 -0
  50. data/lib/MrMurano/commands/productDeviceIdCmds.rb +86 -0
  51. data/lib/MrMurano/commands/productList.rb +45 -0
  52. data/lib/MrMurano/commands/productWrite.rb +27 -0
  53. data/lib/MrMurano/commands/show.rb +80 -0
  54. data/lib/MrMurano/commands/solution.rb +14 -0
  55. data/lib/MrMurano/commands/solutionCreate.rb +39 -0
  56. data/lib/MrMurano/commands/solutionDelete.rb +34 -0
  57. data/lib/MrMurano/commands/solutionList.rb +45 -0
  58. data/lib/MrMurano/commands/status.rb +92 -0
  59. data/lib/MrMurano/commands/sync.rb +60 -0
  60. data/lib/MrMurano/commands/timeseries.rb +115 -0
  61. data/lib/MrMurano/commands/tsdb.rb +271 -0
  62. data/lib/MrMurano/commands/usage.rb +23 -0
  63. data/lib/MrMurano/commands/zshcomplete.erb +112 -0
  64. data/lib/MrMurano/commands.rb +32 -0
  65. data/lib/MrMurano/hash.rb +20 -0
  66. data/lib/MrMurano/http.rb +153 -0
  67. data/lib/MrMurano/makePretty.rb +75 -0
  68. data/lib/MrMurano/schema/pf-v1.0.0.yaml +114 -0
  69. data/lib/MrMurano/schema/sf-v0.2.0.yaml +77 -0
  70. data/lib/MrMurano/schema/sf-v0.3.0.yaml +78 -0
  71. data/lib/MrMurano/template/mock.erb +9 -0
  72. data/lib/MrMurano/template/projectFile.murano.erb +81 -0
  73. data/lib/MrMurano/verbosing.rb +99 -0
  74. data/lib/MrMurano/version.rb +4 -0
  75. data/lib/MrMurano.rb +20 -0
  76. data/spec/Account-Passwords_spec.rb +242 -0
  77. data/spec/Account_spec.rb +272 -0
  78. data/spec/ConfigFile_spec.rb +50 -0
  79. data/spec/ConfigMigrate_spec.rb +89 -0
  80. data/spec/Config_spec.rb +409 -0
  81. data/spec/Http_spec.rb +204 -0
  82. data/spec/MakePretties_spec.rb +118 -0
  83. data/spec/Mock_spec.rb +53 -0
  84. data/spec/ProductBase_spec.rb +113 -0
  85. data/spec/ProductContent_spec.rb +162 -0
  86. data/spec/ProductResources_spec.rb +329 -0
  87. data/spec/Product_1P_Device_spec.rb +202 -0
  88. data/spec/Product_1P_RPC_spec.rb +175 -0
  89. data/spec/Product_spec.rb +153 -0
  90. data/spec/ProjectFile_spec.rb +324 -0
  91. data/spec/Solution-Cors_spec.rb +164 -0
  92. data/spec/Solution-Endpoint_spec.rb +581 -0
  93. data/spec/Solution-File_spec.rb +212 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +202 -0
  95. data/spec/Solution-ServiceDevice_spec.rb +176 -0
  96. data/spec/Solution-ServiceEventHandler_spec.rb +385 -0
  97. data/spec/Solution-ServiceModules_spec.rb +465 -0
  98. data/spec/Solution-UsersRoles_spec.rb +207 -0
  99. data/spec/Solution_spec.rb +92 -0
  100. data/spec/SyncRoot_spec.rb +83 -0
  101. data/spec/SyncUpDown_spec.rb +495 -0
  102. data/spec/Verbosing_spec.rb +279 -0
  103. data/spec/_workspace.rb +27 -0
  104. data/spec/cmd_assign_spec.rb +51 -0
  105. data/spec/cmd_business_spec.rb +59 -0
  106. data/spec/cmd_common.rb +72 -0
  107. data/spec/cmd_config_spec.rb +68 -0
  108. data/spec/cmd_content_spec.rb +71 -0
  109. data/spec/cmd_cors_spec.rb +50 -0
  110. data/spec/cmd_device_spec.rb +96 -0
  111. data/spec/cmd_domain_spec.rb +32 -0
  112. data/spec/cmd_init_spec.rb +30 -0
  113. data/spec/cmd_keystore_spec.rb +97 -0
  114. data/spec/cmd_password_spec.rb +62 -0
  115. data/spec/cmd_status_spec.rb +239 -0
  116. data/spec/cmd_syncdown_spec.rb +86 -0
  117. data/spec/cmd_syncup_spec.rb +62 -0
  118. data/spec/cmd_usage_spec.rb +36 -0
  119. data/spec/fixtures/.mrmuranorc +9 -0
  120. data/spec/fixtures/ProjectFiles/invalid.yaml +9 -0
  121. data/spec/fixtures/ProjectFiles/only_meta.yaml +24 -0
  122. data/spec/fixtures/ProjectFiles/with_routes.yaml +27 -0
  123. data/spec/fixtures/SolutionFiles/0.2.0.json +20 -0
  124. data/spec/fixtures/SolutionFiles/0.2.0_invalid.json +18 -0
  125. data/spec/fixtures/SolutionFiles/0.2.json +21 -0
  126. data/spec/fixtures/SolutionFiles/0.3.0.json +20 -0
  127. data/spec/fixtures/SolutionFiles/0.3.0_invalid.json +19 -0
  128. data/spec/fixtures/SolutionFiles/0.3.json +20 -0
  129. data/spec/fixtures/SolutionFiles/basic.json +20 -0
  130. data/spec/fixtures/SolutionFiles/secret.json +6 -0
  131. data/spec/fixtures/configfile +9 -0
  132. data/spec/fixtures/dumped_config +42 -0
  133. data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
  134. data/spec/fixtures/mrmuranorc_tool_bob +3 -0
  135. data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
  136. data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
  137. data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
  138. data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
  139. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  140. data/spec/fixtures/product_spec_files/lightbulb.yaml +14 -0
  141. data/spec/fixtures/roles-three.yaml +11 -0
  142. data/spec/fixtures/syncable_content/assets/icon.png +0 -0
  143. data/spec/fixtures/syncable_content/assets/index.html +0 -0
  144. data/spec/fixtures/syncable_content/assets/js/script.js +0 -0
  145. data/spec/fixtures/syncable_content/modules/table_util.lua +58 -0
  146. data/spec/fixtures/syncable_content/routes/manyRoutes.lua +11 -0
  147. data/spec/fixtures/syncable_content/routes/singleRoute.lua +5 -0
  148. data/spec/fixtures/syncable_content/services/devdata.lua +18 -0
  149. data/spec/fixtures/syncable_content/services/timers.lua +4 -0
  150. data/spec/spec_helper.rb +119 -0
  151. metadata +498 -0
@@ -0,0 +1,47 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+ require 'yaml'
4
+ require 'MrMurano/verbosing'
5
+ require 'MrMurano/Account'
6
+ require 'MrMurano/Config'
7
+
8
+
9
+ module MrMurano
10
+ class ConfigMigrate
11
+ include Verbose
12
+
13
+ def import_secret
14
+ solsecret = Pathname.new($cfg['location.base']) + '.Solutionfile.secret'
15
+ if solsecret.exist? then
16
+ # Is in JSON, which as a subset of YAML, so use YAML parser
17
+ solsecret.open do |io|
18
+ ss = YAML.load(io)
19
+
20
+ pff = $cfg.file_at('passwords', :user)
21
+ pwd = MrMurano::Passwords.new(pff)
22
+ pwd.load
23
+ ps = pwd.get($cfg['net.host'], ss['email'])
24
+ if ps.nil? then
25
+ pwd.set($cfg['net.host'], ss['email'], ss['password'])
26
+ pwd.save
27
+ elsif ps != ss['password'] then
28
+ y = ask("A different password for this account already exists. Overwrite? N/y")
29
+ if y =~ /^y/i then
30
+ pwd.set($cfg['net.host'], ss['email'], ss['password'])
31
+ pwd.save
32
+ end
33
+ else
34
+ # already set, nothing to do.
35
+ end
36
+
37
+ $cfg.set('user.name', ss['email'])
38
+ $cfg.set('solution.id', ss['solution_id']) if ss.has_key? 'solution_id'
39
+ $cfg.set('product.id', ss['product_id']) if ss.has_key? 'product_id'
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+
47
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,286 @@
1
+ require 'pathname'
2
+ require 'inifile'
3
+ require 'highline'
4
+
5
+ module MrMurano
6
+ class Config
7
+ #
8
+ # internal transient this-run-only things (also -c options)
9
+ # specified from --configfile
10
+ # env from ENV['MURANO_CONFIGFILE']
11
+ # project .murano/config at project dir
12
+ # user .murano/config at $HOME
13
+ # defaults Internal hardcoded defaults
14
+ #
15
+ ConfigFile = Struct.new(:kind, :path, :data) do
16
+ def load()
17
+ return if kind == :internal
18
+ return if kind == :defaults
19
+ self[:path] = Pathname.new(path) unless path.kind_of? Pathname
20
+ self[:data] = IniFile.new(:filename=>path.to_s) if self[:data].nil?
21
+ self[:data].restore
22
+ end
23
+
24
+ def write()
25
+ return if kind == :internal
26
+ return if kind == :defaults
27
+ self[:path] = Pathname.new(path) unless path.kind_of? Pathname
28
+ self[:data] = IniFile.new(:filename=>path.to_s) if self[:data].nil?
29
+ self[:data].save
30
+ path.chmod(0600)
31
+ end
32
+ end
33
+
34
+ attr :paths
35
+ attr_reader :projectDir
36
+
37
+ CFG_SCOPES=%w{internal specified env project user defaults}.map{|i| i.to_sym}.freeze
38
+
39
+ CFG_ENV_NAME=%{MURANO_CONFIGFILE}.freeze
40
+ CFG_FILE_NAME=%[.murano/config].freeze
41
+ CFG_DIR_NAME=%[.murano].freeze
42
+
43
+ CFG_OLD_ENV_NAME=%[MR_CONFIGFILE].freeze
44
+ CFG_OLD_DIR_NAME=%[.mrmurano].freeze
45
+ CFG_OLD_FILE_NAME=%[.mrmuranorc].freeze
46
+
47
+ def warning(msg)
48
+ $stderr.puts HighLine.color(msg, :yellow)
49
+ end
50
+ def error(msg)
51
+ $stderr.puts HighLine.color(msg, :red)
52
+ end
53
+
54
+ def migrateOldEnv
55
+ unless ENV[CFG_OLD_ENV_NAME].nil? then
56
+ warning %{ENV "#{CFG_OLD_ENV_NAME}" is no longer supported. Rename it to "#{CFG_ENV_NAME}"}
57
+ unless ENV[CFG_ENV_NAME].nil? then
58
+ error %{Both "#{CFG_ENV_NAME}" and "#{CFG_OLD_ENV_NAME}" defined, please remove "#{CFG_OLD_ENV_NAME}".}
59
+ end
60
+ ENV[CFG_ENV_NAME] = ENV[CFG_OLD_ENV_NAME]
61
+ end
62
+ end
63
+
64
+ def migrateOldConfig(where)
65
+ # Check for dir.
66
+ if (where + CFG_OLD_DIR_NAME).exist? then
67
+ warning %{Moving old directory "#{CFG_OLD_DIR_NAME}" to "#{CFG_DIR_NAME}" in "#{where}"}
68
+ (where + CFG_OLD_DIR_NAME).rename(where + CFG_DIR_NAME)
69
+ end
70
+
71
+ # check for cfg.
72
+ if (where + CFG_OLD_FILE_NAME).exist? then
73
+ warning %{Moving old config "#{CFG_OLD_FILE_NAME}" to "#{CFG_FILE_NAME}" in "#{where}"}
74
+ (where + CFG_DIR_NAME).mkpath
75
+ (where + CFG_OLD_FILE_NAME).rename(where + CFG_FILE_NAME)
76
+ end
77
+ end
78
+
79
+ def initialize
80
+ @paths = []
81
+ @paths << ConfigFile.new(:internal, nil, IniFile.new())
82
+ # :specified --configfile FILE goes here. (see load_specific)
83
+
84
+ migrateOldEnv
85
+ unless ENV[CFG_ENV_NAME].nil? then
86
+ # if it exists, must be a file
87
+ # if it doesn't exist, that's ok
88
+ ep = Pathname.new(ENV[CFG_ENV_NAME])
89
+ if ep.file? or not ep.exist? then
90
+ @paths << ConfigFile.new(:env, ep)
91
+ end
92
+ end
93
+
94
+ @projectDir = findProjectDir()
95
+ migrateOldConfig(@projectDir)
96
+ @paths << ConfigFile.new(:project, @projectDir + CFG_FILE_NAME)
97
+ (@projectDir + CFG_DIR_NAME).mkpath
98
+ fixModes(@projectDir + CFG_DIR_NAME)
99
+
100
+ migrateOldConfig(Pathname.new(Dir.home))
101
+ @paths << ConfigFile.new(:user, Pathname.new(Dir.home) + CFG_FILE_NAME)
102
+ (Pathname.new(Dir.home) + CFG_DIR_NAME).mkpath
103
+ fixModes(Pathname.new(Dir.home) + CFG_DIR_NAME)
104
+
105
+ @paths << ConfigFile.new(:defaults, nil, IniFile.new())
106
+
107
+
108
+ set('tool.verbose', false, :defaults)
109
+ set('tool.debug', false, :defaults)
110
+ set('tool.dry', false, :defaults)
111
+ set('tool.fullerror', false, :defaults)
112
+ set('tool.outformat', 'best', :defaults)
113
+
114
+ set('net.host', 'bizapi.hosted.exosite.io', :defaults)
115
+
116
+ set('location.base', @projectDir, :defaults) unless @projectDir.nil?
117
+ set('location.files', 'files', :defaults)
118
+ set('location.endpoints', 'routes', :defaults)
119
+ set('location.modules', 'modules', :defaults)
120
+ set('location.eventhandlers', 'services', :defaults)
121
+ set('location.specs', 'specs/resources.yaml', :defaults)
122
+ set('location.cors', 'cors.yaml', :defaults)
123
+
124
+ set('sync.bydefault', SyncRoot.bydefault.join(' '), :defaults) if defined? SyncRoot
125
+
126
+ set('files.default_page', 'index.html', :defaults)
127
+ set('files.searchFor', '**/*', :defaults)
128
+ set('files.ignoring', '', :defaults)
129
+
130
+ set('endpoints.searchFor', '{,../endpoints}/*.lua {,../endpoints}s/*/*.lua', :defaults)
131
+ set('endpoints.ignoring', '*_test.lua *_spec.lua .*', :defaults)
132
+
133
+ set('eventhandler.searchFor', '*.lua */*.lua {../eventhandlers,../event_handler}/*.lua {../eventhandlers,../event_handler}/*/*.lua', :defaults)
134
+ set('eventhandler.ignoring', '*_test.lua *_spec.lua .*', :defaults)
135
+ set('eventhandler.skiplist', 'websocket webservice device.service_call', :defaults)
136
+
137
+ set('modules.searchFor', '*.lua */*.lua', :defaults)
138
+ set('modules.ignoring', '*_test.lua *_spec.lua .*', :defaults)
139
+
140
+ if Gem.win_platform? then
141
+ set('diff.cmd', 'fc', :defaults)
142
+ else
143
+ set('diff.cmd', 'diff -u', :defaults)
144
+ end
145
+ end
146
+
147
+ ## Find the root of this project Directory.
148
+ #
149
+ # The Project dir is the directory between PWD and HOME that has one of (in
150
+ # order of preference):
151
+ # - .murano/config
152
+ # - .mrmuranorc
153
+ # - .murano/
154
+ # - .mrmurano/
155
+ def findProjectDir()
156
+ result=nil
157
+ fileNames=[CFG_FILE_NAME, CFG_OLD_FILE_NAME]
158
+ dirNames=[CFG_DIR_NAME, CFG_OLD_DIR_NAME]
159
+ home = Pathname.new(Dir.home).realpath
160
+ pwd = Pathname.new(Dir.pwd).realpath
161
+ return home if home == pwd
162
+ pwd.ascend do |i|
163
+ break unless result.nil?
164
+ break if i == home
165
+ fileNames.each do |f|
166
+ if (i + f).exist? then
167
+ result = i
168
+ end
169
+ end
170
+ dirNames.each do |f|
171
+ if (i + f).directory? then
172
+ result = i
173
+ end
174
+ end
175
+ end
176
+
177
+ # Now if nothing found, assume it will live in pwd.
178
+ result = Pathname.new(Dir.pwd) if result.nil?
179
+ return result
180
+ end
181
+ private :findProjectDir
182
+
183
+ def fixModes(path)
184
+ if path.directory? then
185
+ path.chmod(0700)
186
+ elsif path.file? then
187
+ path.chmod(0600)
188
+ end
189
+ end
190
+
191
+ def file_at(name, scope=:project)
192
+ case scope
193
+ when :internal
194
+ root = nil
195
+ when :specified
196
+ root = nil
197
+ when :project
198
+ root = @projectDir + CFG_DIR_NAME
199
+ when :user
200
+ root = Pathname.new(Dir.home) + CFG_DIR_NAME
201
+ when :defaults
202
+ root = nil
203
+ end
204
+ return nil if root.nil?
205
+ root.mkpath
206
+ root + name
207
+ end
208
+
209
+ ## Load all of the potential config files
210
+ def load()
211
+ # - read/write config file in [Project, User, System] (all are optional)
212
+ @paths.each { |cfg| cfg.load }
213
+ end
214
+
215
+ ## Load specified file into the config stack
216
+ # This can be called multiple times and each will get loaded into the config
217
+ def load_specific(file)
218
+ spc = ConfigFile.new(:specified, Pathname.new(file))
219
+ spc.load
220
+ @paths.insert(1, spc)
221
+ end
222
+
223
+ ## Get a value for key, looking at the specificed scopes
224
+ # key is <section>.<key>
225
+ def get(key, scope=CFG_SCOPES)
226
+ scope = [scope] unless scope.kind_of? Array
227
+ paths = @paths.select{|p| scope.include? p.kind}
228
+
229
+ section, ikey = key.split('.')
230
+ paths.each do |path|
231
+ if path.data.has_section?(section) then
232
+ sec = path.data[section]
233
+ return sec if ikey.nil?
234
+ if sec.has_key?(ikey) then
235
+ return sec[ikey]
236
+ end
237
+ end
238
+ end
239
+ return nil
240
+ end
241
+
242
+ ## Dump out a combined config
243
+ def dump()
244
+ # have a fake, merge all into it, then dump it.
245
+ base = IniFile.new()
246
+ @paths.reverse.each do |ini|
247
+ base.merge! ini.data
248
+ end
249
+ base.to_s
250
+ end
251
+
252
+ def set(key, value, scope=:project)
253
+ section, ikey = key.split('.', 2)
254
+ raise "Invalid key" if section.nil?
255
+ if not section.nil? and ikey.nil? then
256
+ # If key isn't dotted, then assume the tool section.
257
+ ikey = section
258
+ section = 'tool'
259
+ end
260
+
261
+ paths = @paths.select{|p| scope == p.kind}
262
+ raise "Unknown scope" if paths.empty?
263
+ cfg = paths.first
264
+ data = cfg.data
265
+ tomod = data[section]
266
+ tomod[ikey] = value unless value.nil?
267
+ tomod.delete(ikey) if value.nil?
268
+ data[section] = tomod
269
+ cfg.write
270
+ end
271
+
272
+ # key is <section>.<key>
273
+ def [](key)
274
+ get(key)
275
+ end
276
+
277
+ # For setting internal, this-run-only values
278
+ def []=(key, value)
279
+ set(key, value, :internal)
280
+ end
281
+
282
+ end
283
+
284
+ end
285
+
286
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,63 @@
1
+ require 'erb'
2
+ require 'securerandom'
3
+
4
+ module MrMurano
5
+ class Mock
6
+ attr_accessor :uuid, :testpoint_file
7
+
8
+ def initialize
9
+ end
10
+
11
+ def show
12
+ file = Pathname.new(get_testpoint_path)
13
+ if file.exist? then
14
+ authorization = %{if request.headers["authorization"] == "}
15
+ file.open('rb') do |io|
16
+ io.each_line do |line|
17
+ auth_line = line.include?(authorization)
18
+ if auth_line then
19
+ capture = /\=\= "(.*)"/.match(line)
20
+ return capture.captures[0]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ return false
26
+ end
27
+
28
+ def get_mock_template
29
+ path = get_mock_template_path()
30
+ return ::File.read(path)
31
+ end
32
+
33
+ def get_testpoint_path
34
+ file_name = 'testpoint.post.lua'
35
+ path = %{#{$cfg['location.endpoints']}/#{file_name}}
36
+ return path
37
+ end
38
+
39
+ def get_mock_template_path
40
+ return ::File.join(::File.dirname(__FILE__), 'template', 'mock.erb')
41
+ end
42
+
43
+ def create_testpoint
44
+ uuid = SecureRandom.uuid
45
+ template = ERB.new(get_mock_template)
46
+ endpoint = template.result(binding)
47
+
48
+ Pathname.new(get_testpoint_path).open('wb') do |io|
49
+ io << endpoint
50
+ end
51
+ return uuid
52
+ end
53
+
54
+ def remove_testpoint
55
+ file = Pathname.new(get_testpoint_path)
56
+ if file.exist? then
57
+ file.unlink
58
+ return true
59
+ end
60
+ return false
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,145 @@
1
+ require 'MrMurano/Product'
2
+
3
+ module MrMurano
4
+ class Product1PDevice < ProductBase
5
+ include ProductOnePlatformRpcShim
6
+
7
+ def initialize
8
+ super
9
+ @uriparts << :proxy
10
+ @uriparts << 'onep:v1'
11
+ @uriparts << :rpc
12
+ @uriparts << :process
13
+ @model_rid = nil
14
+ @sn_rid = nil
15
+ end
16
+
17
+ ## Get the internal protocol identifier for a device
18
+ # +sn+:: Identifier for a device
19
+ def sn_rid(sn)
20
+ return @sn_rid unless @sn_rid.nil?
21
+ prd = Product.new()
22
+ found = []
23
+
24
+ offset = 0
25
+ loop do
26
+ listing = prd.list(offset)
27
+ break if listing.empty?
28
+ found = listing.select{|item| item[:sn] == sn}
29
+ break unless found.empty?
30
+
31
+ offset += 50
32
+ end
33
+
34
+ raise "Identifier Not Found: #{sn}" if found.empty?
35
+
36
+ @sn_rid = found.first[:rid]
37
+ @sn_rid
38
+ end
39
+
40
+ ## Get information about a device
41
+ # +sn+:: Identifier for a device
42
+ def info(sn)
43
+ do_rpc({:id=>1,
44
+ :procedure=>:info,
45
+ :arguments=>[sn_rid(sn), {}]
46
+ }, sn_rid(sn))
47
+ end
48
+
49
+ ## List resources on a device
50
+ # +sn+:: Identifier for a device
51
+ def list(sn)
52
+ data = info(sn)
53
+ dt = {}
54
+ data[:aliases].each{|k,v| v.each{|a| dt[a] = k.to_s}}
55
+ dt
56
+ end
57
+
58
+ def listing(sn)
59
+ do_rpc({:id=>1,
60
+ :procedure=>:listing,
61
+ :arguments=>[sn_rid(sn), [:dataport], {}]
62
+ }, sn_rid(sn))
63
+ end
64
+
65
+ ## Read the last value for resources on a device
66
+ # +sn+:: Identifier for a device
67
+ # +aliases+:: Array of resource names
68
+ def read(sn, aliases)
69
+ aliases = [aliases] unless aliases.kind_of? Array
70
+ calls = aliases.map do |a|
71
+ {
72
+ :procedure=>:read,
73
+ :arguments=>[ {:alias=>a}, {} ]
74
+ }
75
+ end
76
+ do_mrpc(calls, sn_rid(sn)).map do |i|
77
+ if i.has_key?(:result) and i[:result].count > 0 and i[:result][0].count > 1 then
78
+ i[:result][0][1]
79
+ else
80
+ nil
81
+ end
82
+ end
83
+ end
84
+
85
+ ## Completely remove an identifier from the product
86
+ # +sn+:: Identifier for a device
87
+ def remove(sn)
88
+ # First drop it from the 1P database
89
+ do_rpc({:id=>1, :procedure=>:drop, :arguments=>[sn_rid(sn)]}, nil)
90
+ # Then remove it from the provisioning databases
91
+ psn = ProductSerialNumber.new
92
+ psn.remove_sn(sn)
93
+ end
94
+
95
+ ## Get a tree of info for a device and its resources.
96
+ # @param sn [String] Identifier for a device
97
+ # @return [Hash]
98
+ def twee(sn)
99
+ inf = info(sn)
100
+ return {} if inf.nil?
101
+ return {} unless inf.kind_of? Hash
102
+ return {} unless inf.has_key? :aliases
103
+ return {} unless inf[:aliases].kind_of? Hash
104
+ aliases = inf[:aliases].keys
105
+ # information for all
106
+ info_calls = aliases.map do |rid|
107
+ {:procedure=>:info, :arguments=>[rid, {}]}
108
+ end
109
+
110
+ limitkeys = [:basic, :description, :usage, :children, :storage]
111
+
112
+ isubs = do_mrpc(info_calls, sn_rid(sn))
113
+ children = isubs.map{|i| i[:result].select{|k,v| limitkeys.include? k} }
114
+
115
+ # most current value
116
+ read_calls = aliases.map do |rid|
117
+ {:procedure=>:read, :arguments=>[rid, {}]}
118
+ end
119
+ ivalues = do_mrpc(read_calls, sn_rid(sn))
120
+
121
+ rez = aliases.zip(children, ivalues).map do |d|
122
+ dinf = d[1]
123
+ dinf[:rid] = d[0]
124
+ dinf[:alias] = inf[:aliases][d[0]].first
125
+
126
+ iv = d[2]
127
+ if iv.has_key?(:result) and iv[:result].count > 0 and iv[:result][0].count > 1 then
128
+ dinf[:value] = iv[:result][0][1]
129
+ else
130
+ dinf[:value] = nil
131
+ end
132
+
133
+ dinf
134
+ end
135
+
136
+ inf[:children] = rez
137
+ inf.select!{|k,v| limitkeys.include? k }
138
+ inf
139
+ end
140
+
141
+ end
142
+
143
+ end
144
+
145
+ # vim: set ai et sw=2 ts=2 :