MrMurano 1.2.1 → 1.3.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 +4 -4
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/MrMurano.gemspec +2 -2
- data/README.markdown +25 -3
- data/Rakefile +5 -1
- data/TODO.taskpaper +15 -3
- data/bin/mr +1 -1
- data/lib/MrMurano.rb +4 -0
- data/lib/MrMurano/Account.rb +18 -11
- data/lib/MrMurano/Solution-Endpoint.rb +5 -5
- data/lib/MrMurano/Solution-ServiceConfig.rb +20 -10
- data/lib/MrMurano/Solution-Services.rb +8 -8
- data/lib/MrMurano/Solution.rb +8 -17
- data/lib/MrMurano/cors.rb +57 -0
- data/lib/MrMurano/keystore.rb +105 -0
- data/lib/MrMurano/logs.rb +2 -3
- data/lib/MrMurano/timeseries.rb +84 -0
- data/lib/MrMurano/version.rb +1 -1
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64252dab4d9f4551bfffef5723875d8aab4c2964
|
4
|
+
data.tar.gz: a24ed29a6a1726b9b54d75e9b34cdd6e5ef596f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85dfd850d6f21f917350de746cb94e57674346fa3d06ac21ef96243491fd7e59cec4e789809a2b8834c0b4549cd71a1802a8d0d143f12fa9b366fad9944fcd20
|
7
|
+
data.tar.gz: 5021da7e66050a1bed213c504bf7405632e5b2a3f5238b1810fb43104c66b7f658d81c42eafcfd3a52fd459dd9bc7a40bd77f9486a72c37469b7d3e67429f56a
|
data/Gemfile
CHANGED
data/MrMurano.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
3
|
-
|
3
|
+
require_relative 'lib/MrMurano/version.rb'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'MrMurano'
|
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
|
33
33
|
s.add_development_dependency('bundler', '~> 1.7.6')
|
34
34
|
s.add_development_dependency('rspec', '~> 3.2')
|
35
|
-
s.add_development_dependency('rake')
|
35
|
+
s.add_development_dependency('rake', '~> 10.1.1')
|
36
36
|
end
|
37
37
|
|
38
38
|
|
data/README.markdown
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# MrMurano
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/MrMurano)
|
4
|
+
[](https://travis-ci.org/tadpol/MrMurano)
|
4
5
|
|
5
6
|
Do more from the command line with [Murano](https://exosite.com/platform/)
|
6
7
|
|
@@ -11,15 +12,13 @@ To start from an existing project in Murano
|
|
11
12
|
mkdir myproject
|
12
13
|
cd myproject
|
13
14
|
mr config solution.id XXXXXX
|
14
|
-
mr syncdown
|
15
|
+
mr syncdown -V
|
15
16
|
```
|
16
17
|
|
17
18
|
Do stuff, see what changed: `mr status` or `mr diff`.
|
18
19
|
Then deploy with `mr syncup`
|
19
20
|
|
20
21
|
|
21
|
-
|
22
|
-
|
23
22
|
## Install
|
24
23
|
|
25
24
|
```
|
@@ -32,6 +31,29 @@ Or
|
|
32
31
|
|
33
32
|
## Features
|
34
33
|
|
34
|
+
### Logs
|
35
|
+
|
36
|
+
You can monitor the log messages from your solution with the `mr logs --follow`.
|
37
|
+
Or quickly get the last few with `mr logs`
|
38
|
+
|
39
|
+
MrMurano does a few things to make your log output easier to follow.
|
40
|
+
- Adds color to easily see where each log message starts.
|
41
|
+
- Reformats the timestamps to be in local time.
|
42
|
+
- Finds JSON blobs and pretty prints them.
|
43
|
+
|
44
|
+
All of these can be toggled with command line options.
|
45
|
+
|
46
|
+
### Keystore
|
47
|
+
|
48
|
+
To aid with debugging, MrMurano has direct access to a solution's Keystore service.
|
49
|
+
|
50
|
+
To see all of the keys in the current solution: `mr keystore`
|
51
|
+
|
52
|
+
### Timeseries
|
53
|
+
|
54
|
+
To aid with debugging, MrMurano has direct access to a solution's Timeseries service.
|
55
|
+
|
56
|
+
|
35
57
|
### Sub-directories
|
36
58
|
|
37
59
|
For the endpoints, modules, and eventhandlers directories. The can contain both
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
|
3
|
-
|
3
|
+
task :default => [:test]
|
4
4
|
|
5
5
|
# TODO: figure out better way to test.
|
6
6
|
desc "Install gem in user dir"
|
@@ -21,5 +21,9 @@ task :run do
|
|
21
21
|
sh %{ruby -Ilib bin/mr }
|
22
22
|
end
|
23
23
|
|
24
|
+
|
25
|
+
task :test do
|
26
|
+
end
|
27
|
+
|
24
28
|
# vim: set sw=4 ts=4 :
|
25
29
|
|
data/TODO.taskpaper
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
Readme:
|
2
|
+
- Add more walk-thrus of common actions. (create new solution, …)
|
1
3
|
|
2
4
|
Commands:
|
3
5
|
- Status will show things have changes when they don’t.
|
@@ -11,28 +13,38 @@ Account:
|
|
11
13
|
Endpoints:
|
12
14
|
- Add support for multiple endpoints in one file (maybe)
|
13
15
|
- Add directory support like in modules @done(2016-07-26)
|
14
|
-
|
16
|
+
|
15
17
|
Files:
|
18
|
+
- Add ignore patterns to config
|
16
19
|
- Switch to mime-types v3
|
17
20
|
- Fix upload. @done(2016-08-01)
|
18
21
|
- Files won't update, they always delete then add. @done(2016-07-28)
|
19
22
|
|
20
|
-
Users:
|
23
|
+
Users and Roles:
|
21
24
|
Much of this is stuck until we get more docs on the User/Role management
|
22
25
|
- Figure out how to upload (create and update) user info.
|
23
26
|
- Figure out how to add Roles to Users in the local data and upload it.
|
24
27
|
- Fix diff for Users and Roles.
|
25
28
|
- Have hash keys in the yaml be strings not symbols. (don't start with colon) @done(2016-07-27)
|
26
29
|
|
30
|
+
CORS:
|
31
|
+
- Get working with sync up/down.
|
32
|
+
- GET&PUT /cors data @done(2016-09-08)
|
33
|
+
|
27
34
|
Product:
|
28
35
|
- Need to add way to set the product ID on a device eventhandler. @done(2016-08-01)
|
29
36
|
|
30
37
|
Config:
|
31
38
|
- Think about adding dev,staging,prod system; how would that work?
|
32
39
|
Would it work ok to just use the --configfile option?
|
40
|
+
I'm thinking so. To the point of dropping the :private scope.
|
41
|
+
- Add ENV support for some (or all?) options.
|
42
|
+
At least the --configfile option. (and --config option)
|
43
|
+
- Maybe add dotenv support.
|
33
44
|
|
34
45
|
SolutionBase:
|
35
46
|
- All network traffic is serialized. Make some parallel.
|
47
|
+
- JSON parse should use symbols for keys. @done(2016-09-01)
|
36
48
|
- Add the --curl verbose option. @done(2016-08-12)
|
37
49
|
- Rebuild how local names and paths are computed from remote items. @done(2016-07-27)
|
38
50
|
|
@@ -41,7 +53,7 @@ Bundles:
|
|
41
53
|
- Work on design @done(2016-08-09)
|
42
54
|
Thinking of something like VIM bundles. A directory of directories. Each with a
|
43
55
|
manafest file? (maybe) A Bundle is a group of modules, endpoints, static files
|
44
|
-
and the other things.
|
56
|
+
and the other things.
|
45
57
|
|
46
58
|
There needs to be some layering logic added, where the bundles are stacked and
|
47
59
|
then the top-level files are stack on top of that. This builds the final map of
|
data/bin/mr
CHANGED
@@ -40,7 +40,7 @@ $cfg.load
|
|
40
40
|
# Basic command support is:
|
41
41
|
# - read/write config file in [Project, User, System] (all are optional)
|
42
42
|
# - Introspection for tab completion.
|
43
|
-
# - Look for tools in PATH that are +x and "mr-foo..."
|
43
|
+
# - Look for tools in PATH that are +x and "mr-foo..."
|
44
44
|
|
45
45
|
|
46
46
|
# Look for plug-ins
|
data/lib/MrMurano.rb
CHANGED
@@ -8,7 +8,11 @@ require 'MrMurano/Solution-File.rb'
|
|
8
8
|
require 'MrMurano/Solution-Services.rb'
|
9
9
|
require 'MrMurano/Solution-Users.rb'
|
10
10
|
require 'MrMurano/Solution-ServiceConfig.rb'
|
11
|
+
|
12
|
+
require 'MrMurano/cors'
|
13
|
+
require 'MrMurano/keystore.rb'
|
11
14
|
require 'MrMurano/logs.rb'
|
12
15
|
require 'MrMurano/sync.rb'
|
13
16
|
require 'MrMurano/status.rb'
|
17
|
+
require 'MrMurano/timeseries.rb'
|
14
18
|
#require 'MrMurano/shelledCommand'
|
data/lib/MrMurano/Account.rb
CHANGED
@@ -51,6 +51,13 @@ module MrMurano
|
|
51
51
|
end
|
52
52
|
|
53
53
|
class Account
|
54
|
+
def initialize
|
55
|
+
@json_opts = {
|
56
|
+
:allow_nan => true,
|
57
|
+
:symbolize_names => true,
|
58
|
+
:create_additions => false
|
59
|
+
}
|
60
|
+
end
|
54
61
|
|
55
62
|
|
56
63
|
def endPoint(path)
|
@@ -91,8 +98,8 @@ module MrMurano
|
|
91
98
|
response = http.request(request)
|
92
99
|
case response
|
93
100
|
when Net::HTTPSuccess
|
94
|
-
token = JSON.parse(response.body)
|
95
|
-
@token = token[
|
101
|
+
token = JSON.parse(response.body, @json_opts)
|
102
|
+
@token = token[:token]
|
96
103
|
else
|
97
104
|
say_error "No token! because: #{response}"
|
98
105
|
@token = nil
|
@@ -113,7 +120,7 @@ module MrMurano
|
|
113
120
|
response = http.request(request)
|
114
121
|
case response
|
115
122
|
when Net::HTTPSuccess
|
116
|
-
busy = JSON.parse(response.body)
|
123
|
+
busy = JSON.parse(response.body, @json_opts)
|
117
124
|
return busy
|
118
125
|
else
|
119
126
|
raise response
|
@@ -132,7 +139,7 @@ module MrMurano
|
|
132
139
|
response = http.request(request)
|
133
140
|
case response
|
134
141
|
when Net::HTTPSuccess
|
135
|
-
busy = JSON.parse(response.body)
|
142
|
+
busy = JSON.parse(response.body, @json_opts)
|
136
143
|
return busy
|
137
144
|
else
|
138
145
|
raise response
|
@@ -151,7 +158,7 @@ module MrMurano
|
|
151
158
|
response = http.request(request)
|
152
159
|
case response
|
153
160
|
when Net::HTTPSuccess
|
154
|
-
busy = JSON.parse(response.body)
|
161
|
+
busy = JSON.parse(response.body, @json_opts)
|
155
162
|
return busy
|
156
163
|
else
|
157
164
|
raise response
|
@@ -180,9 +187,9 @@ command :account do |c|
|
|
180
187
|
if options.businesses then
|
181
188
|
data = acc.businesses
|
182
189
|
if options.idonly then
|
183
|
-
say data.map{|row| row[
|
190
|
+
say data.map{|row| row[:bizid]}.join(' ')
|
184
191
|
else
|
185
|
-
busy = data.map{|row| [row[
|
192
|
+
busy = data.map{|row| [row[:bizid], row[:role], row[:name]]}
|
186
193
|
table = Terminal::Table.new :rows => busy, :headings => ['Biz ID', 'Role', 'Name']
|
187
194
|
say table
|
188
195
|
end
|
@@ -190,9 +197,9 @@ command :account do |c|
|
|
190
197
|
elsif options.products then
|
191
198
|
data = acc.products
|
192
199
|
if options.idonly then
|
193
|
-
say data.map{|row| row[
|
200
|
+
say data.map{|row| row[:pid]}.join(' ')
|
194
201
|
else
|
195
|
-
busy = data.map{|r| [r[
|
202
|
+
busy = data.map{|r| [r[:label], r[:type], r[:pid], r[:modelId]]}
|
196
203
|
table = Terminal::Table.new :rows => busy, :headings => ['Label', 'Type', 'PID', 'ModelID']
|
197
204
|
say table
|
198
205
|
end
|
@@ -200,9 +207,9 @@ command :account do |c|
|
|
200
207
|
elsif options.solutions then
|
201
208
|
data = acc.solutions
|
202
209
|
if options.idonly then
|
203
|
-
say data.map{|row| row[
|
210
|
+
say data.map{|row| row[:apiId]}.join(' ')
|
204
211
|
else
|
205
|
-
busy = data.map{|r| [r[
|
212
|
+
busy = data.map{|r| [r[:apiId], r[:domain], r[:type], r[:sid]]}
|
206
213
|
table = Terminal::Table.new :rows => busy, :headings => ['API ID', 'Domain', 'Type', 'SID']
|
207
214
|
say table
|
208
215
|
end
|
@@ -20,16 +20,16 @@ module MrMurano
|
|
20
20
|
|
21
21
|
def fetch(id)
|
22
22
|
ret = get('/' + id.to_s)
|
23
|
-
aheader = ret[
|
24
|
-
dheader = /^--#ENDPOINT (?i:#{ret[
|
25
|
-
rheader = %{--#ENDPOINT #{ret[
|
23
|
+
aheader = ret[:script].lines.first.chomp
|
24
|
+
dheader = /^--#ENDPOINT (?i:#{ret[:method]}) #{ret[:path]}$/
|
25
|
+
rheader = %{--#ENDPOINT #{ret[:method]} #{ret[:path]}\n}
|
26
26
|
if block_given? then
|
27
27
|
yield rheader unless dheader =~ aheader
|
28
|
-
yield ret[
|
28
|
+
yield ret[:script]
|
29
29
|
else
|
30
30
|
res = ''
|
31
31
|
res << rheader unless dheader =~ aheader
|
32
|
-
res << ret[
|
32
|
+
res << ret[:script]
|
33
33
|
res
|
34
34
|
end
|
35
35
|
end
|
@@ -9,30 +9,40 @@ module MrMurano
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def list
|
12
|
-
get()[
|
12
|
+
get()[:items]
|
13
13
|
end
|
14
14
|
def fetch(id)
|
15
15
|
get('/' + id.to_s)
|
16
16
|
end
|
17
17
|
|
18
|
+
def scid_for_name(name)
|
19
|
+
name = name.to_s unless name.kind_of? String
|
20
|
+
scr = list().select{|i| i[:service] == name}.first
|
21
|
+
scid = scr[:id]
|
22
|
+
end
|
23
|
+
|
24
|
+
def scid
|
25
|
+
return @scid unless @scid.nil?
|
26
|
+
@scid = scid_for_name(@serviceName)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Below is Device ServiceConfig Specific. Should it be in its own class?
|
18
30
|
|
19
31
|
def assignTriggers(products)
|
20
|
-
|
21
|
-
scid = scr['id'] or scr[:id]
|
32
|
+
scid = scid_for_name('device')
|
22
33
|
|
23
|
-
details =
|
34
|
+
details = fetch(scid)
|
24
35
|
products = [products] unless products.kind_of? Array
|
25
36
|
details[:triggers] = {:pid=>products}
|
26
37
|
|
27
38
|
put('/'+scid, details)
|
28
|
-
|
39
|
+
|
29
40
|
end
|
30
41
|
|
31
42
|
def showTriggers
|
32
|
-
|
33
|
-
scid = scr['id'] or scr[:id]
|
43
|
+
scid = scid_for_name('device')
|
34
44
|
|
35
|
-
details =
|
45
|
+
details = fetch(scid)
|
36
46
|
|
37
47
|
return [] if details[:triggers].nil?
|
38
48
|
details[:triggers][:pid]
|
@@ -57,7 +67,7 @@ command :assign do |c|
|
|
57
67
|
say trigs.join(' ')
|
58
68
|
else
|
59
69
|
acc = MrMurano::Account.new
|
60
|
-
products = acc.products
|
70
|
+
products = acc.products
|
61
71
|
products.select!{|p| trigs.include? p[:pid] }
|
62
72
|
busy = products.map{|r| [r[:label], r[:type], r[:pid], r[:modelId]]}
|
63
73
|
table = Terminal::Table.new :rows => busy, :headings => ['Label', 'Type', 'PID', 'ModelID']
|
@@ -70,7 +80,7 @@ command :assign do |c|
|
|
70
80
|
prid = $cfg['product.id']
|
71
81
|
else
|
72
82
|
acc = MrMurano::Account.new
|
73
|
-
products = acc.products
|
83
|
+
products = acc.products
|
74
84
|
products.select!{|p| p[:label] == prname or p[:pid] == prname }
|
75
85
|
prid = products.map{|p| p[:pid]}
|
76
86
|
end
|
@@ -27,15 +27,15 @@ module MrMurano
|
|
27
27
|
|
28
28
|
def list
|
29
29
|
ret = get()
|
30
|
-
ret[
|
30
|
+
ret[:items]
|
31
31
|
end
|
32
32
|
|
33
33
|
def fetch(name)
|
34
34
|
ret = get('/'+name)
|
35
35
|
if block_given? then
|
36
|
-
yield ret[
|
36
|
+
yield ret[:script]
|
37
37
|
else
|
38
|
-
ret[
|
38
|
+
ret[:script]
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -127,20 +127,20 @@ module MrMurano
|
|
127
127
|
def list
|
128
128
|
ret = get()
|
129
129
|
skiplist = ($cfg['eventhandler.skiplist'] or '').split
|
130
|
-
ret[
|
130
|
+
ret[:items].reject{|i| i.has_key?(:service) and skiplist.include? i[:service] }
|
131
131
|
end
|
132
132
|
|
133
133
|
def fetch(name)
|
134
134
|
ret = get('/'+name)
|
135
|
-
aheader = (ret[
|
136
|
-
dheader = "--#EVENT #{ret[
|
135
|
+
aheader = (ret[:script].lines.first or "").chomp
|
136
|
+
dheader = "--#EVENT #{ret[:service]} #{ret[:event]}"
|
137
137
|
if block_given? then
|
138
138
|
yield dheader + "\n" if aheader != dheader
|
139
|
-
yield ret[
|
139
|
+
yield ret[:script]
|
140
140
|
else
|
141
141
|
res = ''
|
142
142
|
res << dheader + "\n" if aheader != dheader
|
143
|
-
res << ret[
|
143
|
+
res << ret[:script]
|
144
144
|
res
|
145
145
|
end
|
146
146
|
end
|
data/lib/MrMurano/Solution.rb
CHANGED
@@ -10,12 +10,18 @@ module MrMurano
|
|
10
10
|
# This might also be a valid ProductBase.
|
11
11
|
def initialize
|
12
12
|
@token = Account.new.token
|
13
|
+
raise "Not logged in!" if @token.nil?
|
13
14
|
@sid = $cfg['solution.id']
|
14
15
|
raise "No solution!" if @sid.nil?
|
15
16
|
@uriparts = [:solution, @sid]
|
16
17
|
@itemkey = :id
|
17
18
|
@locationbase = $cfg['location.base']
|
18
19
|
@location = nil
|
20
|
+
@json_opts = {
|
21
|
+
:allow_nan => true,
|
22
|
+
:symbolize_names => true,
|
23
|
+
:create_additions => false
|
24
|
+
}
|
19
25
|
end
|
20
26
|
|
21
27
|
def verbose(msg)
|
@@ -70,7 +76,7 @@ module MrMurano
|
|
70
76
|
when Net::HTTPSuccess
|
71
77
|
return {} if response.body.nil?
|
72
78
|
begin
|
73
|
-
return JSON.parse(response.body)
|
79
|
+
return JSON.parse(response.body, @json_opts)
|
74
80
|
rescue
|
75
81
|
return response.body
|
76
82
|
end
|
@@ -276,7 +282,7 @@ module MrMurano
|
|
276
282
|
def syncdown(options=Commander::Command::Options.new)
|
277
283
|
options.asdown = true
|
278
284
|
dt = status(options)
|
279
|
-
into = @locationbase + @location
|
285
|
+
into = @locationbase + @location ###
|
280
286
|
toadd = dt[:toadd]
|
281
287
|
todel = dt[:todel]
|
282
288
|
tomod = dt[:tomod]
|
@@ -396,21 +402,6 @@ module MrMurano
|
|
396
402
|
|
397
403
|
end
|
398
404
|
|
399
|
-
# …/serviceconfig
|
400
|
-
class ServiceConfig < SolutionBase
|
401
|
-
def initialize
|
402
|
-
super
|
403
|
-
@uriparts << 'serviceconfig'
|
404
|
-
end
|
405
|
-
|
406
|
-
def list
|
407
|
-
get()['items']
|
408
|
-
end
|
409
|
-
def fetch(id)
|
410
|
-
get('/' + id.to_s)
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
405
|
end
|
415
406
|
|
416
407
|
# vim: set ai et sw=2 ts=2 :
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
module MrMurano
|
3
|
+
class Cors < SolutionBase
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
@uriparts << 'cors'
|
7
|
+
@location = $cfg['location.cors']
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch()
|
11
|
+
ret = get()
|
12
|
+
ret[:cors]
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: fill out other metheds so this could be part of sync up/down.
|
16
|
+
|
17
|
+
##
|
18
|
+
# Upload CORS
|
19
|
+
# :local path to file to push
|
20
|
+
# :remote hash of method and endpoint path (ignored for now)
|
21
|
+
def upload(local, remote)
|
22
|
+
local = Pathname.new(local) unless local.kind_of? Pathname
|
23
|
+
raise "no file" unless local.exist?
|
24
|
+
|
25
|
+
local.open do |io|
|
26
|
+
data = YAML.load(io)
|
27
|
+
put('', data)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def tolocalpath(into, item)
|
32
|
+
into
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
command :cors do |c|
|
38
|
+
c.syntax = %{mr cors [options]}
|
39
|
+
c.description = %{Get or set the CORS for the solution.}
|
40
|
+
c.option '-f','--file FILE', String, %{File to set CORS from}
|
41
|
+
|
42
|
+
c.action do |args,options|
|
43
|
+
sol = MrMurano::Cors.new
|
44
|
+
|
45
|
+
if options.file then
|
46
|
+
#set
|
47
|
+
pp sol.upload(options.file, {})
|
48
|
+
else
|
49
|
+
# get
|
50
|
+
ret = sol.fetch()
|
51
|
+
puts ret
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# vim: set ai et sw=2 ts=2 :
|
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
module MrMurano
|
3
|
+
class Keystore < ServiceConfig
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
@serviceName = 'keystore'
|
7
|
+
end
|
8
|
+
|
9
|
+
def keyinfo
|
10
|
+
ret = get("/#{scid}/call/info")
|
11
|
+
end
|
12
|
+
|
13
|
+
def listkeys
|
14
|
+
ret = get("/#{scid}/call/list")
|
15
|
+
ret[:keys]
|
16
|
+
end
|
17
|
+
|
18
|
+
def getkey(key)
|
19
|
+
ret = post("/#{scid}/call/get", {:key=>key})
|
20
|
+
ret[:value]
|
21
|
+
end
|
22
|
+
|
23
|
+
def setkey(key, value)
|
24
|
+
post("/#{scid}/call/set", { :key=>key, :value=>value })
|
25
|
+
end
|
26
|
+
|
27
|
+
def delkey(key)
|
28
|
+
post("/#{scid}/call/delete", { :key=>key})
|
29
|
+
end
|
30
|
+
|
31
|
+
def command(key, cmd, args)
|
32
|
+
post("/#{scid}/call/command", {:key=>key, :command=>cmd, :args=>args})
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
command 'keystore info' do |c|
|
39
|
+
c.syntax = %{mr keystore info}
|
40
|
+
c.description = %{Show info about the Keystore}
|
41
|
+
c.action do |args,options|
|
42
|
+
sol = MrMurano::Keystore.new
|
43
|
+
pp sol.keyinfo
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
command 'keystore list' do |c|
|
48
|
+
c.syntax = %{mr keystore list}
|
49
|
+
c.description = %{List all of the keys in the Keystore}
|
50
|
+
c.action do |args,options|
|
51
|
+
sol = MrMurano::Keystore.new
|
52
|
+
sol.listkeys.each do |key|
|
53
|
+
puts key
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
alias_command :keystore, 'keystore list'
|
58
|
+
|
59
|
+
command 'keystore get' do |c|
|
60
|
+
c.syntax = %{mr keystore get <key>}
|
61
|
+
c.description = %{Get the value of a key in the Keystore}
|
62
|
+
c.action do |args,options|
|
63
|
+
sol = MrMurano::Keystore.new
|
64
|
+
ret = sol.getkey(args[0])
|
65
|
+
puts ret
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
command 'keystore set' do |c|
|
70
|
+
c.syntax = %{mr keystore set <key> <value...>}
|
71
|
+
c.description = %{Set teh value of a key in the Keystore}
|
72
|
+
c.action do |args,options|
|
73
|
+
sol = MrMurano::Keystore.new
|
74
|
+
sol.setkey(args[0], args[1..-1].join(' '))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
command 'keystore delete' do |c|
|
79
|
+
c.syntax = %{mr keystore delete <key>}
|
80
|
+
c.description = %{Delete a key from the Keystore}
|
81
|
+
c.action do |args,options|
|
82
|
+
sol = MrMurano::Keystore.new
|
83
|
+
sol.delkey(args[0])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
alias_command 'keystore rm', 'keystore delete'
|
87
|
+
|
88
|
+
command 'keystore command' do |c|
|
89
|
+
c.syntax = %{mr keystore command <key> <command> <args...>}
|
90
|
+
c.description = %{Call some Redis commands in the Keystore.
|
91
|
+
|
92
|
+
Only a subset of all Redis commands is supported.
|
93
|
+
See http://docs.exosite.com/murano/services/keystore/#command for current list.
|
94
|
+
}
|
95
|
+
c.example %{mr keystore command mykey lpush myvalue}, %{Push a value onto list}
|
96
|
+
c.example %{mr keystore command mykey lpush A B C}, %{Push three values onto list}
|
97
|
+
c.example %{mr keystore command mykey lrem 0 B}, %{Remove all B values from list}
|
98
|
+
c.action do |args,options|
|
99
|
+
sol = MrMurano::Keystore.new
|
100
|
+
pp sol.command(args[0], args[1], args[2..-1])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
alias_command 'keystore cmd', 'keystore command'
|
104
|
+
|
105
|
+
# vim: set ai et sw=2 ts=2 :
|
data/lib/MrMurano/logs.rb
CHANGED
@@ -22,8 +22,8 @@ command :logs do |c|
|
|
22
22
|
begin
|
23
23
|
ret = sol.get('/logs') # TODO: ('/logs?polling=true') Currently ignored.
|
24
24
|
|
25
|
-
if ret.kind_of?(Hash) and ret.has_key?(
|
26
|
-
ret[
|
25
|
+
if ret.kind_of?(Hash) and ret.has_key?(:items) then
|
26
|
+
ret[:items].reverse.each do |line|
|
27
27
|
curtime = ""
|
28
28
|
if line.kind_of?(String) then
|
29
29
|
|
@@ -53,7 +53,6 @@ command :logs do |c|
|
|
53
53
|
out = line
|
54
54
|
|
55
55
|
elsif line.kind_of?(Hash) then
|
56
|
-
line = Hash.transform_keys_to_symbols(line)
|
57
56
|
out=""
|
58
57
|
|
59
58
|
out << "[#{line[:subject]}]".color(:red).background(:aliceblue)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
module MrMurano
|
3
|
+
class Timeseries < ServiceConfig
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
@serviceName = 'timeseries'
|
7
|
+
end
|
8
|
+
|
9
|
+
def query(query)
|
10
|
+
post("/#{scid}/call/query", {:q=>query})
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(writestr)
|
14
|
+
post("/#{scid}/call/write", { :q=>writestr })
|
15
|
+
end
|
16
|
+
|
17
|
+
def command(cmd)
|
18
|
+
post("/#{scid}/call/command", { :q=>cmd})
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
command 'timeseries query' do |c|
|
25
|
+
c.syntax = %{mr timeseries query <query string>}
|
26
|
+
c.description = %{Query the timeseries database}
|
27
|
+
c.option '--[no-]json', %{Display results as raw json}
|
28
|
+
#c.option '--csv', %{Display results as csv}
|
29
|
+
# Should get a CSV formatter to make sure cells are properly escapped.
|
30
|
+
c.action do |args,options|
|
31
|
+
options.defalts :json=>false
|
32
|
+
sol = MrMurano::Timeseries.new
|
33
|
+
ret = sol.query args.join(' ')
|
34
|
+
if options.json then
|
35
|
+
puts ret.to_json
|
36
|
+
else
|
37
|
+
(ret[:results] or []).each do |res|
|
38
|
+
(res[:series] or []).each do |ser|
|
39
|
+
cols = ser[:columns]
|
40
|
+
table = Terminal::Table.new :title=>ser[:name], :headings=>cols, :rows=>ser[:values]
|
41
|
+
puts table
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# If nothing displayed, Format wasn't what we expected, so do what?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
alias_command :tsq, 'timeseries query'
|
49
|
+
|
50
|
+
command 'timeseries write' do |c|
|
51
|
+
c.syntax = %{mr timeseries <write string>}
|
52
|
+
c.description = %{Write data into the timeseries database}
|
53
|
+
c.option '--[no-]json', %{Display results as raw json}
|
54
|
+
c.action do |args,options|
|
55
|
+
options.defalts :json=>false
|
56
|
+
sol = MrMurano::Timeseries.new
|
57
|
+
ret = sol.write args.join(' ')
|
58
|
+
if options.json then
|
59
|
+
puts ret.to_json
|
60
|
+
else
|
61
|
+
pp ret
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
alias_command :tsw, 'timeseries write'
|
66
|
+
|
67
|
+
command 'timeseries command' do |c|
|
68
|
+
c.syntax = %{mr timeseries command <db command>}
|
69
|
+
c.description = %{Execute a non-query command in the database}
|
70
|
+
c.option '--[no-]json', %{Display results as raw json}
|
71
|
+
c.action do |args,options|
|
72
|
+
options.defalts :json=>false
|
73
|
+
sol = MrMurano::Timeseries.new
|
74
|
+
ret = sol.command args.join(' ')
|
75
|
+
if options.json then
|
76
|
+
puts ret.to_json
|
77
|
+
else
|
78
|
+
pp ret
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# vim: set ai et sw=2 ts=2 :
|
data/lib/MrMurano/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: MrMurano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Conrad Tadpol Tilstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: commander
|
@@ -140,16 +140,16 @@ dependencies:
|
|
140
140
|
name: rake
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ~>
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 10.1.1
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ~>
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 10.1.1
|
153
153
|
description: "Do more from the command line with Murano\n\n Push and pull data from
|
154
154
|
Murano.\n Get status on what things have changed.\n See a diff of the changes
|
155
155
|
before you push.\n "
|
@@ -161,6 +161,7 @@ extensions: []
|
|
161
161
|
extra_rdoc_files: []
|
162
162
|
files:
|
163
163
|
- .gitignore
|
164
|
+
- .travis.yml
|
164
165
|
- Gemfile
|
165
166
|
- MrMurano.gemspec
|
166
167
|
- README.markdown
|
@@ -176,11 +177,14 @@ files:
|
|
176
177
|
- lib/MrMurano/Solution-Users.rb
|
177
178
|
- lib/MrMurano/Solution.rb
|
178
179
|
- lib/MrMurano/configFile.rb
|
180
|
+
- lib/MrMurano/cors.rb
|
179
181
|
- lib/MrMurano/hash.rb
|
182
|
+
- lib/MrMurano/keystore.rb
|
180
183
|
- lib/MrMurano/logs.rb
|
181
184
|
- lib/MrMurano/shelledCommand.rb
|
182
185
|
- lib/MrMurano/status.rb
|
183
186
|
- lib/MrMurano/sync.rb
|
187
|
+
- lib/MrMurano/timeseries.rb
|
184
188
|
- lib/MrMurano/version.rb
|
185
189
|
homepage: https://github.com/tadpol/MrMurano
|
186
190
|
licenses:
|