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
@@ -1,47 +0,0 @@
1
- require 'yaml'
2
- require 'json'
3
- require 'MrMurano/hash'
4
- require 'MrMurano/Solution'
5
-
6
- module MrMurano
7
- class Cors < SolutionBase
8
- def initialize
9
- super
10
- @uriparts << 'cors'
11
- @project_section = :cors
12
- end
13
-
14
- def fetch(id=nil, &block)
15
- ret = get()
16
- return [] if ret.is_a? Hash and ret.has_key? :error
17
- if ret.kind_of?(Hash) and ret.has_key?(:cors) then
18
- # XXX cors is a JSON encoded string. That seems weird. keep an eye on this.
19
- data = JSON.parse(ret[:cors], @json_opts)
20
- else
21
- data = ret
22
- end
23
- if block_given? then
24
- yield Hash.transform_keys_to_strings(data).to_yaml
25
- else
26
- data
27
- end
28
- end
29
-
30
- ##
31
- # Upload CORS
32
- # @param file [String,Nil] File path to upload other than defaults
33
- def upload(file=nil)
34
- unless file.nil? then
35
- data = YAML.load_file(file)
36
- else
37
- data = $project['routes.cors']
38
- # If it is just a string, then is a file to load.
39
- data = YAML.load_file(data) if data.kind_of? String
40
- end
41
- put('', data)
42
- end
43
-
44
- end
45
- end
46
-
47
- # vim: set ai et sw=2 ts=2 :
@@ -1,191 +0,0 @@
1
- require 'uri'
2
- require 'net/http'
3
- require 'json'
4
- require 'pp'
5
- require 'MrMurano/Solution'
6
-
7
- module MrMurano
8
- # …/endpoint
9
- class Endpoint < SolutionBase
10
- # Route Specific details on an Item
11
- class RouteItem < Item
12
- # @return [String] HTTP method for this endpoint
13
- attr_accessor :method
14
- # @return [String] path for URL maps to this endpoint
15
- attr_accessor :path
16
- # @return [String] Acceptable Content-Type for this endpoint
17
- attr_accessor :content_type
18
- # ???? What is this?
19
- attr_accessor :use_basic_auth
20
- end
21
-
22
- def initialize
23
- super
24
- @uriparts << 'endpoint'
25
- @project_section = :routes
26
-
27
- @match_header = /--#ENDPOINT (?<method>\S+) (?<path>\S+)( (?<ctype>.*))?/
28
- end
29
-
30
- ##
31
- # This gets all data about all endpoints
32
- def list
33
- ret = get()
34
- return [] if ret.is_a? Hash and ret.has_key? :error
35
- ret.map do |item|
36
- if item[:content_type].nil? or item[:content_type].empty? then
37
- item[:content_type] = 'application/json'
38
- end
39
- # XXX should this update the script header?
40
- RouteItem.new(item)
41
- end
42
- end
43
-
44
- def fetch(id)
45
- ret = get('/' + id.to_s)
46
- ret[:content_type] = 'application/json' if ret[:content_type].empty?
47
-
48
- script = ret[:script].lines.map{|l|l.chomp}
49
-
50
- aheader = (script.first or "")
51
-
52
- rh = ['--#ENDPOINT', ret[:method].upcase, ret[:path]]
53
- rh << ret[:content_type] if ret[:content_type] != 'application/json'
54
- rheader = rh.join(' ')
55
-
56
- # if header is missing add it.
57
- # If header is wrong, replace it.
58
-
59
- md = @match_header.match(aheader)
60
- if md.nil? then
61
- # header missing.
62
- script.unshift rheader
63
- elsif md[:method] != ret[:method] or
64
- md[:path] != ret[:path] or
65
- md[:ctype] != ret[:content_type] then
66
- # header is wrong.
67
- script[0] = rheader
68
- end
69
- # otherwise current header is good.
70
-
71
- script = script.join("\n") + "\n"
72
- if block_given? then
73
- yield script
74
- else
75
- script
76
- end
77
- end
78
-
79
- ##
80
- # Upload endpoint
81
- # @param local [Pathname] path to file to push
82
- # @param remote [RouteItem] of method and endpoint path
83
- # @param modify [Boolean] True if item exists already and this is changing it
84
- def upload(local, remote, modify)
85
- local = Pathname.new(local) unless local.kind_of? Pathname
86
- raise "no file" unless local.exist?
87
-
88
- # we assume these are small enough to slurp.
89
- if remote.script.nil? then
90
- script = local.read
91
- remote[:script] = script
92
- end
93
- limitkeys = [:method, :path, :script, :content_type, @itemkey]
94
- remote = remote.to_h.select{|k,v| limitkeys.include? k }
95
- # post('', remote)
96
- if remote.has_key? @itemkey then
97
- put('/' + remote[@itemkey], remote) do |request, http|
98
- response = http.request(request)
99
- case response
100
- when Net::HTTPSuccess
101
- #return JSON.parse(response.body)
102
- when Net::HTTPNotFound
103
- verbose "\tDoesn't exist, creating"
104
- post('/', remote)
105
- else
106
- showHttpError(request, response)
107
- end
108
- end
109
- else
110
- verbose "\tNo itemkey, creating"
111
- post('/', remote)
112
- end
113
- end
114
-
115
- ##
116
- # Delete an endpoint
117
- def remove(id)
118
- delete('/' + id.to_s)
119
- end
120
-
121
- def tolocalname(item, key)
122
- name = ''
123
- name << item[:path].split('/').reject{|i|i.empty?}.join('-')
124
- name << '.'
125
- name << item[:method].downcase
126
- name << '.lua'
127
- end
128
-
129
- def toRemoteItem(from, path)
130
- # Path could be have multiple endpoints inside, so a loop.
131
- items = []
132
- path = Pathname.new(path) unless path.kind_of? Pathname
133
- cur = nil
134
- lineno=0
135
- path.readlines().each do |line|
136
- md = @match_header.match(line)
137
- if not md.nil? then
138
- # header line.
139
- cur[:line_end] = lineno unless cur.nil?
140
- items << cur unless cur.nil?
141
- cur = RouteItem.new(:method=>md[:method],
142
- :path=>md[:path],
143
- :content_type=> (md[:ctype] or 'application/json'),
144
- :local_path=>path,
145
- :line=>lineno,
146
- :script=>line)
147
- elsif not cur.nil? and not cur[:script].nil? then
148
- cur[:script] << line
149
- end
150
- lineno += 1
151
- end
152
- cur[:line_end] = lineno unless cur.nil?
153
- items << cur unless cur.nil?
154
- items
155
- end
156
-
157
- def match(item, pattern)
158
- # Pattern is: #{method}#{path glob}
159
- pattern_pattern = /^#(?<method>[^#]*)#(?<path>.*)/i
160
- md = pattern_pattern.match(pattern)
161
- return false if md.nil?
162
- debug "match pattern: '#{md[:method]}' '#{md[:path]}'"
163
-
164
- unless md[:method].empty? then
165
- return false unless item[:method].downcase == md[:method].downcase
166
- end
167
-
168
- return true if md[:path].empty?
169
-
170
- ::File.fnmatch(md[:path],item[:path])
171
- end
172
-
173
- def synckey(item)
174
- "#{item[:method].upcase}_#{item[:path]}"
175
- end
176
-
177
- def docmp(itemA, itemB)
178
- if itemA[:script].nil? and itemA[:local_path] then
179
- itemA[:script] = itemA[:local_path].read
180
- end
181
- if itemB[:script].nil? and itemB[:local_path] then
182
- itemB[:script] = itemB[:local_path].read
183
- end
184
- return (itemA[:script] != itemB[:script] or itemA[:content_type] != itemB[:content_type])
185
- end
186
-
187
- end
188
-
189
- SyncRoot.add('endpoints', Endpoint, 'A', %{Endpoints}, true)
190
- end
191
- # vim: set ai et sw=2 ts=2 :
@@ -1,166 +0,0 @@
1
- require 'uri'
2
- require 'net/http'
3
- require "http/form_data"
4
- require 'digest/sha1'
5
- require 'mime/types'
6
- require 'pp'
7
- require 'MrMurano/Solution'
8
-
9
- module MrMurano
10
- # …/file
11
- class File < SolutionBase
12
- # File Specific details on an Item
13
- class FileItem < Item
14
- # @return [String] path for URL maps to this static file
15
- attr_accessor :path
16
- # @return [String] The MIME-Type for this content
17
- attr_accessor :mime_type
18
- # @return [String] Checksum for the content.
19
- attr_accessor :checksum
20
- end
21
- def initialize
22
- super
23
- @uriparts << 'file'
24
- @itemkey = :path
25
- @project_section = :assets
26
- end
27
-
28
- ##
29
- # Get a list of all of the static content
30
- def list
31
- ret = get()
32
- return [] if ret.is_a? Hash and ret.has_key? :error
33
- ret.map{|i| FileItem.new(i)}
34
- end
35
-
36
- ##
37
- # Get one item of the static content.
38
- def fetch(path, &block)
39
- path = path[1..-1] if path[0] == '/'
40
- path = '/'+ URI.encode_www_form_component(path)
41
- get(path) do |request, http|
42
- http.request(request) do |resp|
43
- case resp
44
- when Net::HTTPSuccess
45
- if block_given? then
46
- resp.read_body(&block)
47
- else
48
- resp.read_body do |chunk|
49
- $stdout.write chunk
50
- end
51
- end
52
- else
53
- showHttpError(request, resp)
54
- end
55
- end
56
- nil
57
- end
58
- end
59
-
60
- ##
61
- # Delete a file
62
- def remove(path)
63
- path = path[1..-1] if path[0] == '/'
64
- delete('/'+ URI.encode_www_form_component(path))
65
- end
66
-
67
- def curldebug(request)
68
- # The upload will get printed out inside of upload.
69
- # Because we don't have the correct info here.
70
- if request.method != 'PUT' then
71
- super(request)
72
- end
73
- end
74
-
75
- ##
76
- # Upload a file
77
- # @param modify Bool: True if item exists already and this is changing it
78
- def upload(local, remote, modify)
79
- local = Pathname.new(local) unless local.kind_of? Pathname
80
-
81
- path = remote[:path]
82
- path = path[1..-1] if path[0] == '/'
83
- uri = endPoint('upload/' + URI.encode_www_form_component(path))
84
-
85
- # kludge past for a bit.
86
- #`curl -s -H 'Authorization: token #{@token}' '#{uri.to_s}' -F file=@#{local.to_s}`
87
-
88
- # http://stackoverflow.com/questions/184178/ruby-how-to-post-a-file-via-http-as-multipart-form-data
89
- #
90
- # Look at: https://github.com/httprb/http
91
- # If it works well, consider porting over to it.
92
- #
93
- # Or just: https://github.com/httprb/form_data.rb ?
94
- #
95
- # Most of these pull into ram. So maybe just go with that. Would guess that
96
- # truely large static content is rare, and we can optimize/fix that later.
97
-
98
- file = HTTP::FormData::File.new(local.to_s, {:content_type=>remote[:mime_type]})
99
- form = HTTP::FormData.create(:file=>file)
100
- req = Net::HTTP::Put.new(uri)
101
- set_def_headers(req)
102
- workit(req) do |request,http|
103
- request.content_type = form.content_type
104
- request.content_length = form.content_length
105
- request.body = form.to_s
106
-
107
- if $cfg['tool.curldebug'] then
108
- a = []
109
- a << %{curl -s -H 'Authorization: #{request['authorization']}'}
110
- a << %{-H 'User-Agent: #{request['User-Agent']}'}
111
- a << %{-X #{request.method}}
112
- a << %{'#{request.uri.to_s}'}
113
- a << %{-F file=@#{local.to_s}}
114
- puts a.join(' ')
115
- end
116
-
117
- response = http.request(request)
118
- case response
119
- when Net::HTTPSuccess
120
- else
121
- showHttpError(request, response)
122
- end
123
- end
124
- end
125
-
126
- def tolocalname(item, key)
127
- name = item[key]
128
- name = $cfg['files.default_page'] if name == '/'
129
- name
130
- end
131
-
132
- def toRemoteItem(from, path)
133
- item = super(from, path)
134
- name = item[:name]
135
- name = '/' if name == $cfg['files.default_page']
136
- name = "/#{name}" unless name.chars.first == '/'
137
-
138
- mime = MIME::Types.type_for(path.to_s)[0] || MIME::Types["application/octet-stream"][0]
139
-
140
- # It does not actually take the SHA1 of the file.
141
- # It first converts the file to hex, then takes the SHA1 of that string
142
- #sha1 = Digest::SHA1.file(path.to_s).hexdigest
143
- sha1 = Digest::SHA1.new
144
- path.open('rb:ASCII-8BIT') do |io|
145
- while chunk = io.read(1048576) do
146
- sha1 << Digest.hexencode(chunk)
147
- end
148
- end
149
- debug "Checking #{name} (#{mime.simplified} #{sha1.hexdigest})"
150
-
151
- FileItem.new(:path=>name, :mime_type=>mime.simplified, :checksum=>sha1.hexdigest)
152
- end
153
-
154
- def synckey(item)
155
- item[:path]
156
- end
157
-
158
- def docmp(itemA, itemB)
159
- return (itemA[:mime_type] != itemB[:mime_type] or
160
- itemA[:checksum] != itemB[:checksum])
161
- end
162
-
163
- end
164
- SyncRoot.add('files', File, 'S', %{Static Files}, true)
165
- end
166
- # vim: set ai et sw=2 ts=2 :
@@ -1,57 +0,0 @@
1
- require 'terminal-table'
2
-
3
- command 'assign list' do |c|
4
- c.syntax = 'murano assign list [options]'
5
- c.description = 'List the products that are assigned'
6
- c.option '--idonly', 'Only return the ids'
7
-
8
- c.action do |args, options|
9
- sol = MrMurano::SC_Device.new
10
-
11
- trigs = sol.showTriggers()
12
- options.idonly = true if $cfg['business.id'].nil?
13
-
14
- if options.idonly then
15
- say trigs.join(' ')
16
- else
17
- acc = MrMurano::Account.new
18
- products = acc.products
19
- products.select!{|p| trigs.include? p[:modelId] }
20
- if products.empty? then
21
- say trigs.join(' ')
22
- else
23
- busy = products.map{|r| [r[:label], r[:modelId]]}
24
- table = Terminal::Table.new :rows => busy, :headings => ['Label', 'ModelID']
25
- say table
26
- end
27
- end
28
- end
29
- end
30
- alias_command :assign, 'assign list'
31
-
32
- command 'assign set' do |c|
33
- c.syntax = 'murano assign set [product]'
34
- c.description = 'Assign a product to a eventhandler'
35
-
36
- c.action do |args, options|
37
- sol = MrMurano::SC_Device.new
38
-
39
- prname = args.shift
40
- if prname.nil? then
41
- prid = $cfg['product.id']
42
- else
43
- acc = MrMurano::Account.new
44
- products = acc.products
45
- products.select!{|p|
46
- p[:label] == prname or p[:modelId] == prname or p[:pid] == prname
47
- }
48
- prid = products.map{|p| p[:modelId]}
49
- end
50
- raise "No product ID!" if prid.nil?
51
- say "Assigning #{prid} to solution" if $cfg['tool.verbose']
52
- sol.assignTriggers(prid) unless $cfg['tool.dry']
53
- end
54
-
55
- end
56
-
57
- # vim: set ai et sw=2 ts=2 :