MuranoCLI 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23b5f23df3ae26fa85d24b1350c090a7699c6b1a
4
- data.tar.gz: 2d7f68e4ff2edafc2272184b1b881ed52a89a0ff
3
+ metadata.gz: 06a751fa4b7c0b5cd5ee4c3ec8e5075d915b31bf
4
+ data.tar.gz: d3d7f35806143bdea0849b71b8117626dcf58727
5
5
  SHA512:
6
- metadata.gz: 7ab6a593fb7834cbc3ee696a1446f67ba0541812ede973f8dfd723603204375738438eff824942854d30e157eac340ed10667148a029cfa46933dfff07a55e42
7
- data.tar.gz: 9c04e653b85cac4070838993e4a13603e6afcc776db2bd1a11340ba3538e6b53ae3502b80b48dc39f21f47ef9059d17509c04b1ac5004883dfa836caad56ed28
6
+ metadata.gz: 26f18f7661d62fda5df06fad381f0c1a81286027bf91dcd1da991973cb43489947a257dcffd9d69a4454247ac6a095390147cc993c51d180255d9376c724a152
7
+ data.tar.gz: 03829cb88d7211ddab47e1c0dc9a9ceed6a8858cf0d320e409a97a1acda999c08548c4f8615768f30a24246532f6bc94d9ef232a4f3e1ba98df71d25fcfc2b84
data/.gitignore CHANGED
@@ -5,6 +5,7 @@ Icon
5
5
  *.sw[a-z]
6
6
  cookies
7
7
  .jiramulerc
8
+ .yardoc/
8
9
  tags
9
10
  mr.exe
10
11
 
@@ -13,10 +14,13 @@ Pods/
13
14
  pkg/
14
15
  report/
15
16
  coverage/
17
+ doc/
16
18
 
17
19
  .murano/
20
+ .rspec_examples.txt
18
21
 
19
22
  _testProject/
23
+ test.*
20
24
 
21
25
  # Thumbnails
22
26
  ._*
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'http://rubygems.org'
2
2
 
3
3
  #gemspec
4
4
 
5
- gem 'commander', '~> 4.4.0'
5
+ gem 'commander', '~> 4.4.3'
6
6
  gem 'certified', '1.0.0'
7
7
  gem 'dotenv', '~> 2.1.1'
8
8
  gem 'highline', '~> 1.7.8'
@@ -11,7 +11,7 @@ gem 'inifile', '~> 3.0'
11
11
  gem 'json-schema', '~> 2.7.0'
12
12
  gem 'mime-types', '~> 3.1'
13
13
  gem 'mime-types-data', '~> 3.2016.0521'
14
- gem 'terminal-table', '~> 1.4.5'
14
+ gem 'terminal-table', '~> 1.7.3'
15
15
 
16
16
  group :test do
17
17
  gem 'coderay', :require => false
@@ -19,6 +19,7 @@ group :test do
19
19
  gem 'rspec', '~> 3.5'
20
20
  gem 'simplecov', :require => false
21
21
  gem 'webmock', '~> 2.3.0'
22
+ gem 'yard'
22
23
  end
23
24
 
24
25
  group :windows do
data/MuranoCLI.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
28
28
  s.require_paths = ['lib']
29
29
 
30
- s.add_runtime_dependency('commander', '~> 4.4.0')
30
+ s.add_runtime_dependency('commander', '~> 4.4.3')
31
31
  s.add_runtime_dependency('certified', '1.0.0')
32
32
  s.add_runtime_dependency('dotenv', '~> 2.1.1')
33
33
  s.add_runtime_dependency('highline', '~> 1.7.8')
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
36
36
  s.add_runtime_dependency('json-schema', '~> 2.7.0')
37
37
  s.add_runtime_dependency('mime-types', '~> 3.1')
38
38
  s.add_runtime_dependency('mime-types-data', '~> 3.2016.0521')
39
- s.add_runtime_dependency('terminal-table', '~> 1.4.5')
39
+ s.add_runtime_dependency('terminal-table', '~> 1.7.3')
40
40
 
41
41
  s.add_development_dependency('bundler', '~> 1.7.6')
42
42
  s.add_development_dependency('ocra', '~> 1.3.8')
data/README.markdown CHANGED
@@ -1,11 +1,11 @@
1
- # MuranoCLI
1
+ # Murano Command Line Interface (CLI)
2
2
 
3
3
  [![Gem
4
4
  Version](https://badge.fury.io/rb/MuranoCLI.svg)](https://badge.fury.io/rb/MuranoCLI)
5
- [![Build Status](https://travis-ci.org/tadpol/MrMurano.svg?branch=master)](https://travis-ci.org/tadpol/MrMurano)
5
+ [![Build Status](https://travis-ci.org/exosite/MuranoCLI.svg?branch=master)](https://travis-ci.org/exosite/MuranoCLI)
6
6
  [![Inline docs](http://inch-ci.org/github/exosite/MuranoCLI.svg?branch=master)](http://inch-ci.org/github/exosite/MuranoCLI)
7
7
 
8
- Do more from the command line with [Murano](https://exosite.com/platform/)
8
+ Do more from the command line with [Murano](https://exosite.com/platform/).
9
9
 
10
10
  MuranoCLI is the command-line tool that interacts with Murano and makes different
11
11
  tasks easier. MuranoCLI makes it easy to deploy code to a solution, import many
@@ -17,18 +17,24 @@ directory are synced up (or down) from Murano.
17
17
 
18
18
  ## Usage
19
19
 
20
- ### To start from an existing project in Murano
21
20
  ```
22
21
  mkdir myproject
23
22
  cd myproject
24
- murano config solution.id XXXXXX
25
- murano syncdown -V
23
+ murano init
26
24
  ```
27
25
 
28
- Do stuff, see what changed: `murano status` or `murano diff`.
26
+ Update `myproject.murano` with the info about your project.
27
+
28
+ If this is a new project, you will also need to run `murano assign set` to connect
29
+ the product and solution.
30
+
31
+ If this is an existing project, you want to run `murano syncdown -V` after
32
+ running `murano init`.
33
+
34
+ Now do stuff, see what changed: `murano status` or `murano diff`.
29
35
  Then deploy with `murano syncup`
30
36
 
31
- ### To start a brand new project
37
+ ### To start a brand new project the hard way.
32
38
  There are a few steps and pieces to getting a solution with a product up and
33
39
  running in Murano. Here is the list.
34
40
 
@@ -53,7 +59,7 @@ Then deploy with `murano syncup`
53
59
  When upgrading from a 1.\* version to a 2.0, you should uninstall the old versions
54
60
  first.
55
61
  ```
56
- > gem uninstall MuranoCLI`
62
+ > gem uninstall MuranoCLI
57
63
  ```
58
64
 
59
65
  And then install:
@@ -91,6 +97,8 @@ installing the new version.
91
97
 
92
98
  ## Features
93
99
 
100
+ ### Project File
101
+
94
102
  ### Logs
95
103
 
96
104
  You can monitor the log messages from your solution with the `murano logs --follow`.
@@ -103,6 +111,95 @@ MuranoCLI does a few things to make your log output easier to follow.
103
111
 
104
112
  All of these can be toggled with command line options.
105
113
 
114
+ ### CORS
115
+
116
+ If you are developing you UI on seperate services and you need cross-origin
117
+ resource sharing, you will need to set the
118
+ [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) options.
119
+
120
+ The current CORS options can be fetched with `murano cors`
121
+
122
+ There are three opitons for setting, the first and preferred way is to put your CORS
123
+ opitons into a file named `cors.yaml`.
124
+
125
+ Second and third are to put the CORS opitons in your project file. In the `routes`
126
+ section, add a `cors` sub-section with either the name of the file to read, or the
127
+ CORS options inline.
128
+
129
+ ```yaml
130
+ routes:
131
+ cors: my_cors_file.json
132
+ ```
133
+ OR:
134
+ ```yaml
135
+ routes:
136
+ cors: {"origin": true}
137
+ ```
138
+
139
+ Then use `murano cors set` to push these options up to your solution.
140
+
141
+ ### Writing Routes (or endpoints)
142
+
143
+ All of the routes that you create in your solution are identified by their method
144
+ and path. You set this with the following line:
145
+
146
+ ```lua
147
+ --#ENDPOINT METHOD PATH
148
+ ```
149
+
150
+ Optionally, you can set what the expected content type is too. (If you don't set
151
+ this, the value is application/json)
152
+
153
+ ```lua
154
+ --#ENDPOINT METHOD PATH CONTENT_TYPE
155
+ ```
156
+
157
+ An example of a route that puts csv data:
158
+ ```lua
159
+ --#ENDPOINT PUT /api/upload text/csv
160
+ ```
161
+
162
+ After this header line, the script to handle the route follows. Since many routes
163
+ end up being a couple of lines or less, you can put multiple routes into a single
164
+ file.
165
+
166
+ Which looks like this:
167
+ ```lua
168
+ --#ENDPOINT GET /api/somedata
169
+ return Tsdb.query(…)
170
+
171
+ --#ENDPOINT PUT /api/somedata text/csv
172
+ return myimport_module.import(request)
173
+
174
+ --#ENDPOINT DELETE /api/startover
175
+ return Tsdb.deleteAll()
176
+ ```
177
+
178
+ ### Writing Service Event Handlers
179
+
180
+ All of the event handlers you add to your solution are identified by which service
181
+ they are watching and which event in that service triggers the script.
182
+
183
+ This is set with the following line:
184
+ ```lua
185
+ --#EVENT SERVICE EVENT
186
+ ```
187
+
188
+ For example, the event handler that processes all data coming from your devices
189
+ could be:
190
+ ```lua
191
+ --#EVENT device datapoint
192
+ local stamped = nil
193
+ if data.api == "record" then
194
+ stamped = tostring(data.value[1]) .. 's'
195
+ end
196
+ Tsdb.write{
197
+ tags = {sn=data.device_sn},
198
+ metrics = {[data.alias] = tonumber(data.value[2])},
199
+ ts = stamped
200
+ }
201
+ ```
202
+
106
203
  ### MURANO_CONFIGFILE environment and Dotenv
107
204
 
108
205
  The environment variable `MURANO_CONFIGFILE` is checked for an additional config to
@@ -199,7 +296,7 @@ tests work with the live Murano servers (`--tag needs_password`).
199
296
 
200
297
  To use the live tests, the following environment variables need to be set:
201
298
  - `MURANO_USER` : User name to log into Murano with
202
- - `MURNO_PASSWORD` : Password for that user
299
+ - `MURANO_PASSWORD` : Password for that user
203
300
  - `MURANO_BUSINESS` : Business id to run tests within.
204
301
 
205
302
  A free account on Murano is sufficient for these tests.
@@ -11,6 +11,16 @@ module MrMurano
11
11
  include SyncUpDown
12
12
  include ProductOnePlatformRpcShim
13
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
+
14
24
  def initialize
15
25
  super
16
26
  @uriparts << :proxy
@@ -12,6 +12,8 @@ module MrMurano
12
12
  class ProjectFile
13
13
  include Verbose
14
14
 
15
+ attr_reader :usingProjectfile, :usingSolutionfile
16
+
15
17
  # Methods that are common to various internal structs.
16
18
  module PrjStructCommonMethods
17
19
  ## Load data from Hash into self
@@ -85,6 +87,8 @@ module MrMurano
85
87
  end
86
88
 
87
89
  def initialize()
90
+ @usingProjectfile = false
91
+ @usingSolutionfile = false
88
92
  @prjFile = nil
89
93
  tname = $cfg['location.base'].basename.to_s.gsub(/[^A-Za-z0-9]/, '')
90
94
  @data = PrfFile.new(
@@ -259,6 +263,7 @@ module MrMurano
259
263
  schema = YAML.load_file(schemaPath.to_s)
260
264
  v = JSON::Validator.fully_validate(schema, data)
261
265
  return v unless v.empty?
266
+ @usingProjectfile = true
262
267
 
263
268
  @data.each_pair do |key, str|
264
269
  str.load(data[key]) if data.has_key? key
@@ -277,6 +282,7 @@ module MrMurano
277
282
  schema = YAML.load_file(schemaPath.to_s)
278
283
  v = JSON::Validator.fully_validate(schema, data)
279
284
  return v unless v.empty?
285
+ @usingSolutionfile = true
280
286
 
281
287
  ifset(data, :default_page, @data[:assets], :default_page)
282
288
  ifset(data, :file_dir, @data[:assets], :location)
@@ -318,6 +324,7 @@ module MrMurano
318
324
  schema = YAML.load_file(schemaPath.to_s)
319
325
  v = JSON::Validator.fully_validate(schema, data)
320
326
  return v unless v.empty?
327
+ @usingSolutionfile = true
321
328
 
322
329
  ifset(data, :default_page, @data[:assets], :default_page)
323
330
  ifset(data, :assets, @data[:assets], :location)
@@ -7,6 +7,18 @@ require 'MrMurano/Solution'
7
7
  module MrMurano
8
8
  # …/endpoint
9
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
+
10
22
  def initialize
11
23
  super
12
24
  @uriparts << 'endpoint'
@@ -23,7 +35,7 @@ module MrMurano
23
35
  item[:content_type] = 'application/json'
24
36
  end
25
37
  # XXX should this update the script header?
26
- item
38
+ RouteItem.new(item)
27
39
  end
28
40
  end
29
41
 
@@ -64,20 +76,20 @@ module MrMurano
64
76
 
65
77
  ##
66
78
  # Upload endpoint
67
- # :local path to file to push
68
- # :remote hash of method and endpoint path
69
- # @param modify Bool: True if item exists already and this is changing it
79
+ # @param local [Pathname] path to file to push
80
+ # @param remote [RouteItem] of method and endpoint path
81
+ # @param modify [Boolean] True if item exists already and this is changing it
70
82
  def upload(local, remote, modify)
71
83
  local = Pathname.new(local) unless local.kind_of? Pathname
72
84
  raise "no file" unless local.exist?
73
85
 
74
86
  # we assume these are small enough to slurp.
75
- unless remote.has_key? :script then
87
+ if remote.script.nil? then
76
88
  script = local.read
77
89
  remote[:script] = script
78
90
  end
79
91
  limitkeys = [:method, :path, :script, :content_type, @itemkey]
80
- remote = remote.select{|k,v| limitkeys.include? k }
92
+ remote = remote.to_h.select{|k,v| limitkeys.include? k }
81
93
  # post('', remote)
82
94
  if remote.has_key? @itemkey then
83
95
  put('/' + remote[@itemkey], remote) do |request, http|
@@ -124,12 +136,12 @@ module MrMurano
124
136
  # header line.
125
137
  cur[:line_end] = lineno unless cur.nil?
126
138
  items << cur unless cur.nil?
127
- cur = {:method=>md[:method],
128
- :path=>md[:path],
129
- :content_type=> (md[:ctype] or 'application/json'),
130
- :local_path=>path,
131
- :line=>lineno,
132
- :script=>line}
139
+ cur = RouteItem.new(:method=>md[:method],
140
+ :path=>md[:path],
141
+ :content_type=> (md[:ctype] or 'application/json'),
142
+ :local_path=>path,
143
+ :line=>lineno,
144
+ :script=>line)
133
145
  elsif not cur.nil? and not cur[:script].nil? then
134
146
  cur[:script] << line
135
147
  end
@@ -9,6 +9,15 @@ require 'MrMurano/Solution'
9
9
  module MrMurano
10
10
  # …/file
11
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
12
21
  def initialize
13
22
  super
14
23
  @uriparts << 'file'
@@ -19,7 +28,7 @@ module MrMurano
19
28
  ##
20
29
  # Get a list of all of the static content
21
30
  def list
22
- get()
31
+ get().map{|i| FileItem.new(i)}
23
32
  end
24
33
 
25
34
  ##
@@ -47,8 +56,8 @@ module MrMurano
47
56
  ##
48
57
  # Delete a file
49
58
  def remove(path)
50
- # TODO test
51
- delete('/'+path)
59
+ path = path[1..-1] if path[0] == '/'
60
+ delete('/'+ URI.encode_www_form_component(path))
52
61
  end
53
62
 
54
63
  def curldebug(request)
@@ -65,7 +74,10 @@ module MrMurano
65
74
  def upload(local, remote, modify)
66
75
  local = Pathname.new(local) unless local.kind_of? Pathname
67
76
 
68
- uri = endPoint('upload' + remote[:path])
77
+ path = remote[:path]
78
+ path = path[1..-1] if path[0] == '/'
79
+ uri = endPoint('upload/' + URI.encode_www_form_component(path))
80
+
69
81
  # kludge past for a bit.
70
82
  #`curl -s -H 'Authorization: token #{@token}' '#{uri.to_s}' -F file=@#{local.to_s}`
71
83
 
@@ -132,7 +144,7 @@ module MrMurano
132
144
  end
133
145
  debug "Checking #{name} (#{mime.simplified} #{sha1.hexdigest})"
134
146
 
135
- {:path=>name, :mime_type=>mime.simplified, :checksum=>sha1.hexdigest}
147
+ FileItem.new(:path=>name, :mime_type=>mime.simplified, :checksum=>sha1.hexdigest)
136
148
  end
137
149
 
138
150
  def synckey(item)
@@ -94,15 +94,17 @@ module MrMurano
94
94
  end
95
95
 
96
96
  ## Get list of call operations from a schema
97
- def callable(id=sid)
97
+ def callable(id=sid, all=false)
98
98
  scm = schema(id)
99
99
  calls = []
100
100
  scm[:paths].each do |path, methods|
101
101
  methods.each do |method, params|
102
- if params.kind_of?(Hash) and
103
- not params['x-internal-use'.to_sym] and
104
- params.has_key?(:operationId) then
105
- calls << [method, params[:operationId]]
102
+ if params.kind_of?(Hash) then
103
+ call = [method]
104
+ call << path.to_s if all
105
+ call << params[:operationId]
106
+ call << (params['x-internal-use'.to_sym] or false) if all
107
+ calls << call
106
108
  end
107
109
  end
108
110
  end