MuranoCLI 2.0.0 → 2.1.0

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