MuranoCLI 2.2.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.agignore +3 -0
  3. data/.gitignore +18 -1
  4. data/.rubocop.yml +222 -0
  5. data/.trustme.sh +185 -0
  6. data/.trustme.vim +24 -0
  7. data/Gemfile +23 -4
  8. data/LICENSE.txt +1 -1
  9. data/MuranoCLI.gemspec +43 -8
  10. data/README.markdown +9 -11
  11. data/Rakefile +187 -143
  12. data/TODO.taskpaper +2 -2
  13. data/bin/murano +51 -52
  14. data/docs/basic_example.rst +436 -0
  15. data/docs/completions/murano_completion-bash +3484 -0
  16. data/docs/demo.md +32 -32
  17. data/docs/develop.rst +391 -0
  18. data/lib/MrMurano.rb +21 -7
  19. data/lib/MrMurano/Account.rb +159 -174
  20. data/lib/MrMurano/Business.rb +381 -0
  21. data/lib/MrMurano/Config-Migrate.rb +32 -26
  22. data/lib/MrMurano/Config.rb +407 -128
  23. data/lib/MrMurano/Content.rb +191 -0
  24. data/lib/MrMurano/Gateway.rb +489 -0
  25. data/lib/MrMurano/Keystore.rb +48 -0
  26. data/lib/MrMurano/Passwords.rb +103 -0
  27. data/lib/MrMurano/ProjectFile.rb +121 -79
  28. data/lib/MrMurano/ReCommander.rb +114 -10
  29. data/lib/MrMurano/Setting.rb +90 -0
  30. data/lib/MrMurano/Solution-ServiceConfig.rb +89 -45
  31. data/lib/MrMurano/Solution-Services.rb +461 -166
  32. data/lib/MrMurano/Solution-Users.rb +70 -31
  33. data/lib/MrMurano/Solution.rb +372 -13
  34. data/lib/MrMurano/SolutionId.rb +73 -0
  35. data/lib/MrMurano/SyncRoot.rb +137 -0
  36. data/lib/MrMurano/SyncUpDown.rb +594 -284
  37. data/lib/MrMurano/Webservice-Cors.rb +71 -0
  38. data/lib/MrMurano/Webservice-Endpoint.rb +234 -0
  39. data/lib/MrMurano/Webservice-File.rb +193 -0
  40. data/lib/MrMurano/Webservice.rb +51 -0
  41. data/lib/MrMurano/commands.rb +18 -15
  42. data/lib/MrMurano/commands/business.rb +300 -6
  43. data/lib/MrMurano/commands/completion-bash.erb +166 -0
  44. data/lib/MrMurano/commands/{zshcomplete.erb → completion-zsh.erb} +0 -0
  45. data/lib/MrMurano/commands/completion.rb +76 -39
  46. data/lib/MrMurano/commands/config.rb +108 -44
  47. data/lib/MrMurano/commands/content.rb +115 -72
  48. data/lib/MrMurano/commands/cors.rb +29 -14
  49. data/lib/MrMurano/commands/devices.rb +286 -0
  50. data/lib/MrMurano/commands/domain.rb +52 -12
  51. data/lib/MrMurano/commands/gb.rb +24 -9
  52. data/lib/MrMurano/commands/globals.rb +64 -0
  53. data/lib/MrMurano/commands/init.rb +377 -155
  54. data/lib/MrMurano/commands/keystore.rb +92 -82
  55. data/lib/MrMurano/commands/link.rb +300 -0
  56. data/lib/MrMurano/commands/login.rb +74 -11
  57. data/lib/MrMurano/commands/logs.rb +63 -32
  58. data/lib/MrMurano/commands/mock.rb +57 -29
  59. data/lib/MrMurano/commands/password.rb +57 -39
  60. data/lib/MrMurano/commands/postgresql.rb +127 -94
  61. data/lib/MrMurano/commands/settings.rb +203 -0
  62. data/lib/MrMurano/commands/show.rb +79 -38
  63. data/lib/MrMurano/commands/solution.rb +423 -5
  64. data/lib/MrMurano/commands/solution_picker.rb +547 -0
  65. data/lib/MrMurano/commands/status.rb +195 -61
  66. data/lib/MrMurano/commands/sync.rb +78 -39
  67. data/lib/MrMurano/commands/timeseries.rb +71 -55
  68. data/lib/MrMurano/commands/tsdb.rb +113 -87
  69. data/lib/MrMurano/commands/usage.rb +57 -15
  70. data/lib/MrMurano/hash.rb +100 -10
  71. data/lib/MrMurano/http.rb +187 -43
  72. data/lib/MrMurano/makePretty.rb +16 -14
  73. data/lib/MrMurano/optparse.rb +2178 -0
  74. data/lib/MrMurano/progress.rb +138 -0
  75. data/lib/MrMurano/schema/resource-v1.0.0.yaml +32 -0
  76. data/lib/MrMurano/template/projectFile.murano.erb +16 -13
  77. data/lib/MrMurano/verbosing.rb +166 -29
  78. data/lib/MrMurano/version.rb +30 -1
  79. data/spec/Account-Passwords_spec.rb +21 -4
  80. data/spec/Account_spec.rb +69 -146
  81. data/spec/Business_spec.rb +290 -0
  82. data/spec/ConfigFile_spec.rb +1 -0
  83. data/spec/ConfigMigrate_spec.rb +12 -8
  84. data/spec/Config_spec.rb +40 -34
  85. data/spec/Content_spec.rb +363 -0
  86. data/spec/GatewayBase_spec.rb +54 -0
  87. data/spec/GatewayDevice_spec.rb +321 -0
  88. data/spec/GatewayResource_spec.rb +266 -0
  89. data/spec/GatewaySettings_spec.rb +120 -0
  90. data/spec/Http_spec.rb +18 -8
  91. data/spec/Mock_spec.rb +2 -2
  92. data/spec/ProjectFile_spec.rb +25 -14
  93. data/spec/Setting_spec.rb +110 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +44 -5
  95. data/spec/Solution-ServiceEventHandler_spec.rb +23 -14
  96. data/spec/Solution-ServiceModules_spec.rb +47 -37
  97. data/spec/Solution-UsersRoles_spec.rb +10 -8
  98. data/spec/Solution_spec.rb +17 -8
  99. data/spec/SyncRoot_spec.rb +46 -20
  100. data/spec/SyncUpDown_spec.rb +437 -201
  101. data/spec/Verbosing_spec.rb +12 -4
  102. data/spec/{Solution-Cors_spec.rb → Webservice-Cors_spec.rb} +23 -20
  103. data/spec/{Solution-Endpoint_spec.rb → Webservice-Endpoint_spec.rb} +43 -41
  104. data/spec/{Solution-File_spec.rb → Webservice-File_spec.rb} +44 -33
  105. data/spec/Webservice-Setting_spec.rb +89 -0
  106. data/spec/_workspace.rb +4 -4
  107. data/spec/cmd_business_spec.rb +9 -4
  108. data/spec/cmd_common.rb +44 -1
  109. data/spec/cmd_content_spec.rb +43 -17
  110. data/spec/cmd_cors_spec.rb +4 -4
  111. data/spec/cmd_device_spec.rb +61 -16
  112. data/spec/cmd_domain_spec.rb +29 -6
  113. data/spec/cmd_init_spec.rb +281 -126
  114. data/spec/cmd_keystore_spec.rb +3 -3
  115. data/spec/cmd_link_spec.rb +98 -0
  116. data/spec/cmd_password_spec.rb +1 -1
  117. data/spec/cmd_setting_application_spec.rb +260 -0
  118. data/spec/cmd_setting_product_spec.rb +220 -0
  119. data/spec/cmd_status_spec.rb +223 -114
  120. data/spec/cmd_syncdown_spec.rb +115 -35
  121. data/spec/cmd_syncup_spec.rb +68 -15
  122. data/spec/cmd_usage_spec.rb +35 -8
  123. data/spec/fixtures/dumped_config +6 -4
  124. data/spec/fixtures/gateway_resource_files/resources.notyaml +12 -0
  125. data/spec/fixtures/gateway_resource_files/resources.yaml +13 -0
  126. data/spec/fixtures/gateway_resource_files/resources_invalid.yaml +13 -0
  127. data/spec/fixtures/mrmuranorc_deleted_bob +0 -2
  128. data/spec/fixtures/product_spec_files/lightbulb.yaml +20 -13
  129. data/spec/fixtures/{syncable_content → syncable_conflict}/services/devdata.lua +1 -1
  130. data/spec/fixtures/{syncable_content → syncable_conflict}/services/timers.lua +0 -0
  131. data/spec/spec_helper.rb +5 -0
  132. metadata +262 -171
  133. data/bin/mr +0 -8
  134. data/lib/MrMurano/Product-1P-Device.rb +0 -145
  135. data/lib/MrMurano/Product-Resources.rb +0 -205
  136. data/lib/MrMurano/Product.rb +0 -358
  137. data/lib/MrMurano/Solution-Cors.rb +0 -47
  138. data/lib/MrMurano/Solution-Endpoint.rb +0 -191
  139. data/lib/MrMurano/Solution-File.rb +0 -166
  140. data/lib/MrMurano/commands/assign.rb +0 -57
  141. data/lib/MrMurano/commands/businessList.rb +0 -45
  142. data/lib/MrMurano/commands/product.rb +0 -14
  143. data/lib/MrMurano/commands/productCreate.rb +0 -39
  144. data/lib/MrMurano/commands/productDelete.rb +0 -33
  145. data/lib/MrMurano/commands/productDevice.rb +0 -87
  146. data/lib/MrMurano/commands/productDeviceIdCmds.rb +0 -89
  147. data/lib/MrMurano/commands/productList.rb +0 -45
  148. data/lib/MrMurano/commands/productWrite.rb +0 -27
  149. data/lib/MrMurano/commands/solutionCreate.rb +0 -41
  150. data/lib/MrMurano/commands/solutionDelete.rb +0 -34
  151. data/lib/MrMurano/commands/solutionList.rb +0 -45
  152. data/spec/ProductBase_spec.rb +0 -113
  153. data/spec/ProductContent_spec.rb +0 -162
  154. data/spec/ProductResources_spec.rb +0 -329
  155. data/spec/Product_1P_Device_spec.rb +0 -202
  156. data/spec/Product_1P_RPC_spec.rb +0 -175
  157. data/spec/Product_spec.rb +0 -153
  158. data/spec/Solution-ServiceDevice_spec.rb +0 -176
  159. data/spec/cmd_assign_spec.rb +0 -51
data/bin/mr DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'highline'
3
-
4
- puts HighLine.color("!"*80, :yellow)
5
- puts HighLine.color("The command 'mr' is deprecated. Use 'murano' instead.", :yellow)
6
- puts HighLine.color("!"*80, :yellow)
7
-
8
- exec 'murano', *ARGV
@@ -1,145 +0,0 @@
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 :
@@ -1,205 +0,0 @@
1
- require 'MrMurano/Product'
2
- require 'MrMurano/SyncUpDown'
3
-
4
- module MrMurano
5
-
6
- ## Manage the resources on a Product
7
- #
8
- # There isn't an okami-shim for most of this, it maps right over to 1P-RPC.
9
- # Or better stated, that's all okami-shim is.
10
- class ProductResources < ProductBase
11
- include SyncUpDown
12
- include ProductOnePlatformRpcShim
13
-
14
- # Resource Specific details on an Item
15
- class ResourceItem < Item
16
- # @return [String] Reasource Identifier, internal use only.
17
- attr_accessor :rid
18
- # @return [String] The name of this resource
19
- attr_accessor :alias
20
- # @return [String] The format of thie resource.
21
- attr_accessor :format
22
- end
23
-
24
- def initialize
25
- super
26
- @uriparts << :proxy
27
- @uriparts << 'onep:v1'
28
- @uriparts << :rpc
29
- @uriparts << :process
30
- @model_rid = nil
31
-
32
- @itemkey = :rid # this is the key that is the identifier used by murano
33
- end
34
-
35
- ## Get 1P info about the prodcut
36
- def info
37
- do_rpc({:id=>1,
38
- :procedure=>:info,
39
- :arguments=>[model_rid, {}]
40
- })
41
- end
42
-
43
- ## Return a list of the product resources as items
44
- def list()
45
- data = info()
46
- ret = []
47
- data[:aliases].each do |rid, aliases|
48
- aliases.each do |al|
49
- ret << {
50
- :alias => al,
51
- :rid => rid
52
- }
53
- end
54
- end
55
-
56
- ret
57
- end
58
-
59
- ## Fetch data from one resource
60
- def fetch(rid)
61
- do_rpc({:id=>1,
62
- :procedure=>:info,
63
- :arguments=>[rid, {}],
64
- })
65
- end
66
-
67
- ## Remove a resource by RID
68
- def remove(rid)
69
- do_rpc({:id=>1,
70
- :procedure=>:drop,
71
- :arguments=>[rid]
72
- })
73
- end
74
-
75
- ## Create a new resource in the prodcut
76
- def create(alias_id, format=:string)
77
- raise "Alias cannot be nil" if alias_id.nil?
78
- # create then map.
79
- rid = do_rpc({:id=>1,
80
- :procedure=>:create,
81
- :arguments=>[:dataport,
82
- {:format=>format,
83
- :name=>alias_id,
84
- :retention=>{:count=>1,:duration=>:infinity}
85
- }
86
- ]
87
- })
88
- return rid unless not rid.kind_of?(String) or rid.match(/\p{XDigit}{40}/)
89
-
90
- do_rpc({:id=>1,
91
- :procedure=>:map,
92
- :arguments=>[:alias, rid, alias_id]
93
- })
94
- end
95
-
96
- ## Upload a resource.
97
- # this is for SyncUpDown
98
- # @param modify Bool: True if item exists already and this is changing it
99
- def upload(src, item, modify)
100
- if modify then
101
- # this is usually a format change, which can only be set on create.
102
- # So delete then create.
103
- remove(item[:rid])
104
- end
105
- r = create(item[:alias], item[:format])
106
- raise "Create Failed: #{r}" unless r.nil?
107
- end
108
-
109
- ## Use alias for doing sync compares
110
- # (The RID will change if destroyed and recreated.)
111
- def synckey(item)
112
- item[:alias]
113
- end
114
-
115
- ##
116
- #
117
- def tolocalpath(into, item)
118
- into
119
- end
120
-
121
- ## Get a local list of items from the single file
122
- def localitems(from)
123
- from = Pathname.new(from) unless from.kind_of? Pathname
124
- debug "#{self.class.to_s}: Getting local items from: #{from}"
125
- if not from.exist? then
126
- warning "Skipping missing #{from.to_s}"
127
- return []
128
- end
129
- unless from.file? then
130
- warning "Cannot read from #{from.to_s}"
131
- return []
132
- end
133
-
134
- here = []
135
- from.open {|io| here = YAML.load(io) }
136
- return [] if here == false
137
-
138
- if here.kind_of?(Hash) and here.has_key?('resources') then
139
- here['resources'].map{|i| Hash.transform_keys_to_symbols(i)}
140
- else
141
- warning "Unexpected data in #{from.to_s}"
142
- []
143
- end
144
- end
145
-
146
- def download(local, item)
147
- # needs to append/merge with file
148
- # for now, we'll read, modify, write
149
- data = fetch(item[:rid])
150
- item[:format] = data[:description][:format]
151
-
152
- here = []
153
- if local.exist? then
154
- local.open('rb') {|io| here = YAML.load(io)}
155
- here = [] if here == false
156
- if here.kind_of?(Hash) and here.has_key?('resources') then
157
- here = here['resources'].map{|i| Hash.transform_keys_to_symbols(i)}
158
- else
159
- here = []
160
- end
161
- end
162
- here.delete_if do |i|
163
- i[:alias] == item[:alias]
164
- end
165
- here << item.reject{|k,v| k==:synckey or k==:rid}
166
- here.map!{|i| Hash.transform_keys_to_strings(i)}
167
- local.dirname.mkpath
168
- local.open('wb') do |io|
169
- io << {'resources'=>here}.to_yaml
170
- end
171
- end
172
-
173
- def removelocal(dest, item)
174
- # needs to append/merge with file
175
- # for now, we'll read, modify, write
176
- here = []
177
- if dest.exist? then
178
- dest.open('rb') {|io| here = YAML.load(io)}
179
- here = [] if here == false
180
- if here.kind_of?(Hash) and here.has_key?('resources') then
181
- here = here['resources'].map{|i| Hash.transform_keys_to_symbols(i)}
182
- else
183
- here = []
184
- end
185
- end
186
- here.delete_if do |it|
187
- it[:alias] == item[:alias]
188
- end
189
- here.map!{|i| Hash.transform_keys_to_strings(i)}
190
- dest.open('wb') do|io|
191
- io << {'resources'=>here}.to_yaml
192
- end
193
- end
194
-
195
- ##
196
- # True if itemA and itemB are different
197
- def docmp(itemA, itemB)
198
- itemA[:alias] != itemB[:alias] or itemA[:format] != itemB[:format]
199
- end
200
-
201
- end
202
- SyncRoot.add('specs', ProductResources, 'P', %{Product Specification})
203
-
204
- end
205
- # vim: set ai et sw=2 ts=2 :
@@ -1,358 +0,0 @@
1
- require 'uri'
2
- require 'mime/types'
3
- require 'csv'
4
- require 'pp'
5
- require 'MrMurano/http'
6
- require 'MrMurano/verbosing'
7
-
8
- module MrMurano
9
- class ProductBase
10
- def initialize
11
- @pid = $cfg['product.id']
12
- raise "No Product ID!" if @pid.nil?
13
- @uriparts = [:product, @pid]
14
- @project_section = :resources
15
- end
16
-
17
- include Http
18
- include Verbose
19
-
20
- ## Generate an endpoint in Murano
21
- # Uses the uriparts and path
22
- # @param path String: any additional parts for the URI
23
- # @return URI: The full URI for this enpoint.
24
- def endPoint(path='')
25
- parts = ['https:/', $cfg['net.host'], 'api:1'] + @uriparts
26
- s = parts.map{|v| v.to_s}.join('/')
27
- URI(s + path.to_s)
28
- end
29
- end
30
-
31
- module ProductOnePlatformRpcShim
32
- ## The model RID for this product.
33
- def model_rid
34
- return @model_rid unless @model_rid.nil?
35
- prd = Product.new
36
- data = prd.info
37
- if data.kind_of?(Hash) and data.has_key?(:modelrid) then
38
- @model_rid = data[:modelrid]
39
- else
40
- raise "Bad info; #{data}"
41
- end
42
- @model_rid
43
- end
44
-
45
- ## Do a 1P RPC call
46
- #
47
- # While this will take an array of calls, don't. Only pass one.
48
- # This only returns the result of the first call. Results from other calls are
49
- # dropped.
50
- def do_rpc(calls, cid=model_rid)
51
- calls = [calls] unless calls.kind_of?(Array)
52
- r = do_mrpc(calls, cid)
53
- return r if not r.kind_of?(Array) or r.count < 1
54
- r = r[0]
55
- return r if not r.kind_of?(Hash) or r[:status] != 'ok'
56
- r[:result]
57
- end
58
- private :do_rpc
59
-
60
- ## Do many 1P RPC calls
61
- def do_mrpc(calls, cid=model_rid)
62
- calls = [calls] unless calls.kind_of?(Array)
63
- maxid = ((calls.max_by{|c| c[:id] or 0 }[:id]) or 0)
64
- calls.map!{|c| c[:id] = (maxid += 1) unless c.has_key?(:id); c}
65
- post('', {
66
- :auth=>(cid ? {:client_id=>cid} : {}),
67
- :calls=>calls
68
- })
69
- end
70
- private :do_mrpc
71
-
72
- end
73
-
74
- class Product < ProductBase
75
- ## Get info about the product
76
- def info
77
- get('/info')
78
- end
79
-
80
- ## List enabled devices
81
- def list(offset=0, limit=50)
82
- get("/device/?offset=#{offset}&limit=#{limit}")
83
- end
84
-
85
- ## Enable a serial number
86
- # This creates the device and opens the activation window.
87
- def enable(sn)
88
- post("/device/#{sn.to_s}")
89
- end
90
-
91
- ## Upload a spec file.
92
- #
93
- # Note that this will fail if any of the resources already exist.
94
- def update(specFile)
95
- specFile = Pathname.new(specFile) unless specFile.kind_of? Pathname
96
-
97
- uri = endPoint('/definition')
98
- request = Net::HTTP::Post.new(uri)
99
- ret = nil
100
-
101
- specFile.open do |io|
102
- request.body_stream = io
103
- request.content_length = specFile.size
104
- set_def_headers(request)
105
- request.content_type = 'text/yaml'
106
- ret = workit(request)
107
- end
108
- ret
109
- end
110
-
111
- ## Write a value to an alias on a device
112
- def write(sn, values)
113
- post("/write/#{sn}", values) unless $cfg['tool.dry']
114
- end
115
-
116
- ## Converts an exoline style spec file into a Murano style one
117
- # @param fin IO: IO Stream to read from
118
- # @return String: Converted yaml data
119
- def convertit(fin)
120
- specOut = {'resources'=>[]}
121
- spec = YAML.load(fin)
122
- if spec.has_key?('dataports') and spec['dataports'].kind_of?(Array) then
123
- dps = spec['dataports'].map do |dp|
124
- dp.delete_if{|k,v| k != 'alias' and k != 'format' and k != 'initial'}
125
- dp['format'] = 'string' if (dp['format']||'')[0..5] == 'string'
126
- dp
127
- end
128
- specOut['resources'] = dps
129
- else
130
- raise "No dataports section found, or not an array"
131
- end
132
- specOut
133
- end
134
-
135
- ## Converts an exoline style spec file into a Murano style one
136
- # @param specFile String: Path to file or '-' for stdin
137
- # @return String: Converted yaml data
138
- def convert(specFile)
139
- if specFile == '-' then
140
- convertit($stdin).to_yaml
141
- else
142
- specFile = Pathname.new(specFile) unless specFile.kind_of? Pathname
143
- out = ''
144
- specFile.open() do |fin|
145
- out = convertit(fin).to_yaml
146
- end
147
- out
148
- end
149
- end
150
- end
151
-
152
- ##
153
- # Manage the uploadable content for products.
154
- class ProductContent < ProductBase
155
- def initialize
156
- super
157
- @uriparts << :proxy
158
- @uriparts << :provision
159
- @uriparts << :manage
160
- @uriparts << :content
161
- @uriparts << @pid
162
- end
163
-
164
- ## List all things in content area
165
- def list
166
- ret = get('/')
167
- return [] if ret.kind_of?(Hash)
168
- ret.lines.map{|i|i.chomp}
169
- end
170
-
171
- ## List all contents allowed for sn
172
- def list_for(sn)
173
- ret = get("/?sn=#{sn}")
174
- return [] if ret.kind_of?(Hash)
175
- ret.lines.map{|i|i.chomp}
176
- end
177
-
178
- ## Create a new content item
179
- def create(id, meta='', protect=false)
180
- http_reset
181
- data = {:id=>id, :meta=>meta}
182
- data[:protected] = true if protect
183
- postf('/', data)
184
- end
185
-
186
- ## Remove Content item
187
- def remove(id)
188
- postf('/', {:id=>id, :delete=>true})
189
- end
190
-
191
- ## Get info for content item
192
- def info(id)
193
- get("/#{id}") do |request, http|
194
- http.request(request) do |resp|
195
- case resp
196
- when Net::HTTPSuccess
197
- return CSV.parse(resp.body)
198
- else
199
- return nil
200
- end
201
- end
202
- end
203
- end
204
-
205
- ## Download data for content item
206
- def download(id, &block)
207
- get("/#{id}?download=true") do |request, http|
208
- http.request(request) do |resp|
209
- case resp
210
- when Net::HTTPSuccess
211
- if block_given? then
212
- resp.read_body(&block)
213
- else
214
- resp.read_body do |chunk|
215
- $stdout.write chunk
216
- end
217
- end
218
- else
219
- showHttpError(request, resp)
220
- end
221
- end
222
- nil
223
- end
224
- end
225
-
226
- ## Upload data for content item
227
- # TODO: add support for passing in IOStream
228
- # @param modify Bool: True if item exists already and this is changing it
229
- def upload(id, path, modify=false)
230
- path = Pathname.new(path) unless path.kind_of? Pathname
231
-
232
- mime = MIME::Types.type_for(path.to_s)[0] || MIME::Types["application/octet-stream"][0]
233
- uri = endPoint("/#{id}")
234
- request = Net::HTTP::Post.new(uri)
235
- ret = nil
236
-
237
- path.open do |io|
238
- request.body_stream = io
239
- set_def_headers(request)
240
- request.content_length = path.size
241
- request.content_type = mime.simplified
242
- ret = workit(request)
243
- end
244
- ret
245
- end
246
-
247
- ## Delete data for content item
248
- # Note that the content item is still present and listed.
249
- def remove_content(id)
250
- delete("/#{id}")
251
- end
252
-
253
- end
254
-
255
- ##
256
- # This is not applicable to Murano. Remove?
257
- # :nocov:
258
- class ProductModel < ProductBase
259
- def initialize
260
- super
261
- @uriparts << :proxy
262
- @uriparts << :provision
263
- @uriparts << :manage
264
- @uriparts << :model
265
- end
266
-
267
- # In Murano, there should only ever be one.
268
- # AND it should be @pid
269
- def list
270
- get('/')
271
- end
272
-
273
- def info(modelID=@pid)
274
- get("/#{modelID}")
275
- end
276
-
277
- def list_sn(modelID=@pid)
278
- get("/#{modelID}/")
279
- end
280
- end
281
-
282
- class ProductSerialNumber < ProductBase
283
- def initialize
284
- super
285
- @uriparts << :proxy
286
- @uriparts << :provision
287
- @uriparts << :manage
288
- @uriparts << :model
289
- @uriparts << @pid
290
- end
291
-
292
- def list(offset=0, limit=1000)
293
- ret = get("/?offset=#{offset}&limit=#{limit}&status=true")
294
- return [] if ret.kind_of?(Hash)
295
- CSV.parse(ret)
296
- end
297
-
298
- def logs(sn)
299
- get("/#{sn}?show=log") # results are empty
300
- end
301
-
302
- def regen(sn)
303
- postf("/#{sn}", {:enable=>true})
304
- end
305
-
306
- def disable(sn)
307
- postf("/#{sn}", {:disable=>true})
308
- end
309
-
310
- def activate(sn)
311
- uri = URI("https://#{@pid}.m2.exosite.com/provision/activate")
312
- http = Net::HTTP.new(uri.host, uri.port)
313
- http.use_ssl = true
314
- http.start
315
- request = Net::HTTP::Post.new(uri)
316
- request.form_data = {
317
- :vendor => @pid,
318
- :model => @pid,
319
- :sn => sn
320
- }
321
- request['User-Agent'] = "MrMurano/#{MrMurano::VERSION}"
322
- request['Authorization'] = nil
323
- request.content_type = 'application/x-www-form-urlencoded; charset=utf-8'
324
- curldebug(request)
325
- response = http.request(request)
326
- case response
327
- when Net::HTTPSuccess
328
- return response.body
329
- else
330
- showHttpError(request, response)
331
- end
332
- end
333
-
334
- def add_sn(sn, extra='')
335
- # this does add, but what does that mean?
336
- # Still need to call …/device/<sn> to enable.
337
- # How long is the activation window?
338
- postf('/', {:sn=>sn,:extra=>extra})
339
- end
340
-
341
- def remove_sn(sn)
342
- #postf('/', {:sn=>sn, :delete=>true})
343
- delete("/#{sn}")
344
- end
345
-
346
- def ranges
347
- get('/?show=ranges')
348
- end
349
-
350
- def add_range()
351
- post('/', {:ranges=>[ ]})
352
- end
353
-
354
- end
355
- # :nocov:
356
-
357
- end
358
- # vim: set ai et sw=2 ts=2 :