MuranoCLI 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +27 -0
  6. data/LICENSE.txt +19 -0
  7. data/MuranoCLI.gemspec +50 -0
  8. data/MuranoCLI.iss +50 -0
  9. data/README.markdown +208 -0
  10. data/Rakefile +188 -0
  11. data/TODO.taskpaper +122 -0
  12. data/bin/mr +8 -0
  13. data/bin/murano +84 -0
  14. data/docs/demo.md +109 -0
  15. data/lib/MrMurano/Account.rb +211 -0
  16. data/lib/MrMurano/Config-Migrate.rb +47 -0
  17. data/lib/MrMurano/Config.rb +286 -0
  18. data/lib/MrMurano/Mock.rb +63 -0
  19. data/lib/MrMurano/Product-1P-Device.rb +145 -0
  20. data/lib/MrMurano/Product-Resources.rb +195 -0
  21. data/lib/MrMurano/Product.rb +358 -0
  22. data/lib/MrMurano/ProjectFile.rb +349 -0
  23. data/lib/MrMurano/Solution-Cors.rb +46 -0
  24. data/lib/MrMurano/Solution-Endpoint.rb +177 -0
  25. data/lib/MrMurano/Solution-File.rb +150 -0
  26. data/lib/MrMurano/Solution-ServiceConfig.rb +140 -0
  27. data/lib/MrMurano/Solution-Services.rb +326 -0
  28. data/lib/MrMurano/Solution-Users.rb +129 -0
  29. data/lib/MrMurano/Solution.rb +59 -0
  30. data/lib/MrMurano/SubCmdGroupContext.rb +49 -0
  31. data/lib/MrMurano/SyncUpDown.rb +565 -0
  32. data/lib/MrMurano/commands/assign.rb +57 -0
  33. data/lib/MrMurano/commands/businessList.rb +45 -0
  34. data/lib/MrMurano/commands/completion.rb +152 -0
  35. data/lib/MrMurano/commands/config.rb +67 -0
  36. data/lib/MrMurano/commands/content.rb +130 -0
  37. data/lib/MrMurano/commands/cors.rb +30 -0
  38. data/lib/MrMurano/commands/domain.rb +17 -0
  39. data/lib/MrMurano/commands/gb.rb +33 -0
  40. data/lib/MrMurano/commands/init.rb +138 -0
  41. data/lib/MrMurano/commands/keystore.rb +157 -0
  42. data/lib/MrMurano/commands/logs.rb +78 -0
  43. data/lib/MrMurano/commands/mock.rb +63 -0
  44. data/lib/MrMurano/commands/password.rb +88 -0
  45. data/lib/MrMurano/commands/postgresql.rb +41 -0
  46. data/lib/MrMurano/commands/product.rb +14 -0
  47. data/lib/MrMurano/commands/productCreate.rb +39 -0
  48. data/lib/MrMurano/commands/productDelete.rb +33 -0
  49. data/lib/MrMurano/commands/productDevice.rb +84 -0
  50. data/lib/MrMurano/commands/productDeviceIdCmds.rb +86 -0
  51. data/lib/MrMurano/commands/productList.rb +45 -0
  52. data/lib/MrMurano/commands/productWrite.rb +27 -0
  53. data/lib/MrMurano/commands/show.rb +80 -0
  54. data/lib/MrMurano/commands/solution.rb +14 -0
  55. data/lib/MrMurano/commands/solutionCreate.rb +39 -0
  56. data/lib/MrMurano/commands/solutionDelete.rb +34 -0
  57. data/lib/MrMurano/commands/solutionList.rb +45 -0
  58. data/lib/MrMurano/commands/status.rb +92 -0
  59. data/lib/MrMurano/commands/sync.rb +60 -0
  60. data/lib/MrMurano/commands/timeseries.rb +115 -0
  61. data/lib/MrMurano/commands/tsdb.rb +271 -0
  62. data/lib/MrMurano/commands/usage.rb +23 -0
  63. data/lib/MrMurano/commands/zshcomplete.erb +112 -0
  64. data/lib/MrMurano/commands.rb +32 -0
  65. data/lib/MrMurano/hash.rb +20 -0
  66. data/lib/MrMurano/http.rb +153 -0
  67. data/lib/MrMurano/makePretty.rb +75 -0
  68. data/lib/MrMurano/schema/pf-v1.0.0.yaml +114 -0
  69. data/lib/MrMurano/schema/sf-v0.2.0.yaml +77 -0
  70. data/lib/MrMurano/schema/sf-v0.3.0.yaml +78 -0
  71. data/lib/MrMurano/template/mock.erb +9 -0
  72. data/lib/MrMurano/template/projectFile.murano.erb +81 -0
  73. data/lib/MrMurano/verbosing.rb +99 -0
  74. data/lib/MrMurano/version.rb +4 -0
  75. data/lib/MrMurano.rb +20 -0
  76. data/spec/Account-Passwords_spec.rb +242 -0
  77. data/spec/Account_spec.rb +272 -0
  78. data/spec/ConfigFile_spec.rb +50 -0
  79. data/spec/ConfigMigrate_spec.rb +89 -0
  80. data/spec/Config_spec.rb +409 -0
  81. data/spec/Http_spec.rb +204 -0
  82. data/spec/MakePretties_spec.rb +118 -0
  83. data/spec/Mock_spec.rb +53 -0
  84. data/spec/ProductBase_spec.rb +113 -0
  85. data/spec/ProductContent_spec.rb +162 -0
  86. data/spec/ProductResources_spec.rb +329 -0
  87. data/spec/Product_1P_Device_spec.rb +202 -0
  88. data/spec/Product_1P_RPC_spec.rb +175 -0
  89. data/spec/Product_spec.rb +153 -0
  90. data/spec/ProjectFile_spec.rb +324 -0
  91. data/spec/Solution-Cors_spec.rb +164 -0
  92. data/spec/Solution-Endpoint_spec.rb +581 -0
  93. data/spec/Solution-File_spec.rb +212 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +202 -0
  95. data/spec/Solution-ServiceDevice_spec.rb +176 -0
  96. data/spec/Solution-ServiceEventHandler_spec.rb +385 -0
  97. data/spec/Solution-ServiceModules_spec.rb +465 -0
  98. data/spec/Solution-UsersRoles_spec.rb +207 -0
  99. data/spec/Solution_spec.rb +92 -0
  100. data/spec/SyncRoot_spec.rb +83 -0
  101. data/spec/SyncUpDown_spec.rb +495 -0
  102. data/spec/Verbosing_spec.rb +279 -0
  103. data/spec/_workspace.rb +27 -0
  104. data/spec/cmd_assign_spec.rb +51 -0
  105. data/spec/cmd_business_spec.rb +59 -0
  106. data/spec/cmd_common.rb +72 -0
  107. data/spec/cmd_config_spec.rb +68 -0
  108. data/spec/cmd_content_spec.rb +71 -0
  109. data/spec/cmd_cors_spec.rb +50 -0
  110. data/spec/cmd_device_spec.rb +96 -0
  111. data/spec/cmd_domain_spec.rb +32 -0
  112. data/spec/cmd_init_spec.rb +30 -0
  113. data/spec/cmd_keystore_spec.rb +97 -0
  114. data/spec/cmd_password_spec.rb +62 -0
  115. data/spec/cmd_status_spec.rb +239 -0
  116. data/spec/cmd_syncdown_spec.rb +86 -0
  117. data/spec/cmd_syncup_spec.rb +62 -0
  118. data/spec/cmd_usage_spec.rb +36 -0
  119. data/spec/fixtures/.mrmuranorc +9 -0
  120. data/spec/fixtures/ProjectFiles/invalid.yaml +9 -0
  121. data/spec/fixtures/ProjectFiles/only_meta.yaml +24 -0
  122. data/spec/fixtures/ProjectFiles/with_routes.yaml +27 -0
  123. data/spec/fixtures/SolutionFiles/0.2.0.json +20 -0
  124. data/spec/fixtures/SolutionFiles/0.2.0_invalid.json +18 -0
  125. data/spec/fixtures/SolutionFiles/0.2.json +21 -0
  126. data/spec/fixtures/SolutionFiles/0.3.0.json +20 -0
  127. data/spec/fixtures/SolutionFiles/0.3.0_invalid.json +19 -0
  128. data/spec/fixtures/SolutionFiles/0.3.json +20 -0
  129. data/spec/fixtures/SolutionFiles/basic.json +20 -0
  130. data/spec/fixtures/SolutionFiles/secret.json +6 -0
  131. data/spec/fixtures/configfile +9 -0
  132. data/spec/fixtures/dumped_config +42 -0
  133. data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
  134. data/spec/fixtures/mrmuranorc_tool_bob +3 -0
  135. data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
  136. data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
  137. data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
  138. data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
  139. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  140. data/spec/fixtures/product_spec_files/lightbulb.yaml +14 -0
  141. data/spec/fixtures/roles-three.yaml +11 -0
  142. data/spec/fixtures/syncable_content/assets/icon.png +0 -0
  143. data/spec/fixtures/syncable_content/assets/index.html +0 -0
  144. data/spec/fixtures/syncable_content/assets/js/script.js +0 -0
  145. data/spec/fixtures/syncable_content/modules/table_util.lua +58 -0
  146. data/spec/fixtures/syncable_content/routes/manyRoutes.lua +11 -0
  147. data/spec/fixtures/syncable_content/routes/singleRoute.lua +5 -0
  148. data/spec/fixtures/syncable_content/services/devdata.lua +18 -0
  149. data/spec/fixtures/syncable_content/services/timers.lua +4 -0
  150. data/spec/spec_helper.rb +119 -0
  151. metadata +498 -0
@@ -0,0 +1,30 @@
1
+ require 'yaml'
2
+ require 'MrMurano/Solution-Cors'
3
+
4
+ command :cors do |c|
5
+ c.syntax = %{murano cors}
6
+ c.summary = %{Get the CORS for the project.}
7
+ c.description = %{Get the CORS for the project.
8
+
9
+ Set the CORS with `murano cors set`
10
+ }
11
+
12
+ c.action do |args,options|
13
+ sol = MrMurano::Cors.new
14
+ ret = sol.fetch()
15
+ sol.outf ret
16
+ end
17
+ end
18
+
19
+ command 'cors set' do |c|
20
+ c.syntax = %{murano cors set [<file>]}
21
+ c.summary = %{Set the CORS for the project.}
22
+
23
+ c.action do |args,options|
24
+ crs = MrMurano::Cors.new
25
+ file = args.shift
26
+ crs.upload(file)
27
+ end
28
+ end
29
+
30
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,17 @@
1
+ require 'MrMurano/Solution'
2
+ command :domain do |c|
3
+ c.syntax = %{murano domain}
4
+ c.summary = %{Print the domain for this solution}
5
+ c.option '--[no-]raw', %{Don't add scheme}
6
+ c.action do |args,options|
7
+ options.default :raw=>true
8
+ sol = MrMurano::Solution.new
9
+ ret = sol.info()
10
+ if options.raw then
11
+ say ret[:domain]
12
+ else
13
+ say "https://#{ret[:domain]}"
14
+ end
15
+ end
16
+ end
17
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,33 @@
1
+ require 'pp'
2
+
3
+ # You don't need this.
4
+ # To use this:
5
+ # - mkdir -p ~/.mrmurano/plugins
6
+ # - ln gb.rb ~/.mrmurano/plugins
7
+
8
+ command :_gb do |c|
9
+ c.syntax = %{murano _gb <class> <method> (<args>)}
10
+ c.summary = %{Call internal class methods directly.}
11
+ c.description = %{Call internal class methods directly.}
12
+
13
+ c.action do |args, options|
14
+ cls = args[0]
15
+ meth = args[1].to_sym
16
+ args.shift(2)
17
+
18
+ begin
19
+ gb = Object::const_get("MrMurano::#{cls}").new
20
+ if gb.respond_to? meth then
21
+ pp gb.__send__(meth, *args)
22
+ else
23
+ say_error "'#{cls}' doesn't '#{meth}'"
24
+ end
25
+ rescue Exception => e
26
+ say_error e.message
27
+ pp e
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,138 @@
1
+ require 'MrMurano/Account'
2
+ require 'MrMurano/Config-Migrate'
3
+ require 'erb'
4
+
5
+
6
+ command :init do |c|
7
+ c.syntax = %{murano init}
8
+ c.summary = %{The easy way to start a project}
9
+ c.description = %{}
10
+
11
+ c.option '--force', %{Override existing business, solution, or product ids}
12
+ c.option '--[no-]mkdirs', %{Create default directories}
13
+
14
+ c.action do |args, options|
15
+ options.default :force=>false, :mkdirs=>true
16
+ acc = MrMurano::Account.new
17
+ puts ''
18
+
19
+ if Pathname.new(Dir.pwd).realpath == Pathname.new(Dir.home).realpath then
20
+ acc.error "Cannot init a project in your HOME directory."
21
+ exit 2
22
+ end
23
+
24
+ say "Found project base directory at #{$cfg['location.base'].to_s}"
25
+ puts ''
26
+
27
+ # Try to import a .Solutionfile.secret
28
+ MrMurano::ConfigMigrate.new.import_secret
29
+
30
+ # If they have never logged in, then asking for the business.id will also ask
31
+ # for their username and password.
32
+ say "Using account #{$cfg['user.name']}"
33
+ say ''
34
+
35
+ # 1. Get business id
36
+ if not options.force and not $cfg['business.id'].nil? then
37
+ say "Using Business ID already set to #{$cfg['business.id']}"
38
+ else
39
+ bizz = acc.businesses
40
+ if bizz.count == 1 then
41
+ bizid = bizz.first
42
+ say "You are only part of one business; using #{bizid[:name]}"
43
+ $cfg.set('businesses.id', bizid[:bizid], :project)
44
+
45
+ else
46
+ choose do |menu|
47
+ menu.prompt = "Select which Business to use:"
48
+ menu.flow = :columns_across
49
+ bizz.sort{|a,b| a[:name]<=>b[:name]}.each do |b|
50
+ menu.choice(b[:name]) do
51
+ $cfg.set('business.id', b[:bizid], :project)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ puts '' # blank line
58
+
59
+ # 2. Get Solution id
60
+ if not options.force and not $cfg['solution.id'].nil? then
61
+ say "Using Solution ID already set to #{$cfg['solution.id']}"
62
+ else
63
+ solz = acc.solutions
64
+ if solz.count == 1 then
65
+ sol = solz.first
66
+ say "You only have one solution; using #{sol[:domain]}"
67
+ $cfg.set('solution.id', sol[:apiId], :project)
68
+ else
69
+ choose do |menu|
70
+ menu.prompt = "Select which Solution to use:"
71
+ menu.flow = :columns_across
72
+ solz.sort{|a,b| a[:domain]<=>b[:domain]}.each do |s|
73
+ menu.choice(s[:domain].sub(/\..*$/,'')) do
74
+ $cfg.set('solution.id', s[:apiId], :project)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ puts '' # blank line
81
+
82
+ # 3. Get Product id
83
+ if not options.force and not $cfg['product.id'].nil? then
84
+ say "Using Product ID already set to #{$cfg['product.id']}"
85
+ else
86
+ podz = acc.products
87
+ if podz.count == 1 then
88
+ prd = podz.first
89
+ say "You only have one product; using #{prd[:label]}"
90
+ $cfg.set('product.id', prd[:modelId], :project)
91
+ else
92
+ choose do |menu|
93
+ menu.prompt = "Select which Product to use:"
94
+ menu.flow = :columns_across
95
+ podz.sort{|a,b| a[:label]<=>b[:label]}.each do |p|
96
+ menu.choice(p[:label]) do
97
+ $cfg.set('product.id', p[:modelId], :project)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ puts ''
105
+ say "Ok, In business ID: #{$cfg['business.id']} using Solution ID: #{$cfg['solution.id']} with Product ID: #{$cfg['product.id']}"
106
+
107
+ # If no ProjectFile or Solutionfile, then write a ProjectFile
108
+ if $project.project_file.nil? then
109
+ tmpl = File.read(File.join(File.dirname(__FILE__),'..','template','projectFile.murano.erb'))
110
+ tmpl = ERB.new(tmpl)
111
+ res = tmpl.result($project.data_binding)
112
+ prFile = $project['info.name'] + '.murano'
113
+ say "Writing an initial Project file: #{prFile}"
114
+ File.open(prFile, 'w') {|io| io << res}
115
+ end
116
+
117
+ if options.mkdirs then
118
+ base = $cfg['location.base']
119
+ base = Pathname.new(base) unless base.kind_of? Pathname
120
+ %w{
121
+ location.files
122
+ location.endpoints
123
+ location.modules
124
+ location.eventhandlers
125
+ location.specs
126
+ }.each do |cfgi|
127
+ path = $cfg[cfgi]
128
+ path = Pathname.new(path) unless path.kind_of? Pathname
129
+ path = base + path
130
+ path.mkpath unless path.exist?
131
+ end
132
+ say "Default directories created"
133
+ end
134
+
135
+ end
136
+ end
137
+
138
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,157 @@
1
+ require 'MrMurano/Solution-ServiceConfig'
2
+
3
+ module MrMurano
4
+ class Keystore < ServiceConfig
5
+ def initialize
6
+ super
7
+ @serviceName = 'keystore'
8
+ end
9
+
10
+ def keyinfo
11
+ call(:info)
12
+ end
13
+
14
+ def listkeys
15
+ ret = call(:list)
16
+ ret[:keys]
17
+ end
18
+
19
+ def getkey(key)
20
+ ret = call(:get, :post, {:key=>key})
21
+ ret[:value]
22
+ end
23
+
24
+ def setkey(key, value)
25
+ call(:set, :post, { :key=>key, :value=>value })
26
+ end
27
+
28
+ def delkey(key)
29
+ call(:delete, :post, {:key=>key})
30
+ end
31
+
32
+ def command(key, cmd, args)
33
+ call(:command, :post, {:key=>key, :command=>cmd, :args=>args})
34
+ end
35
+
36
+ def clearall()
37
+ call(:clear, :post, {})
38
+ end
39
+
40
+ end
41
+ end
42
+
43
+ command :keystore do |c|
44
+ c.syntax = %{murano keystore}
45
+ c.summary = %{About Keystore}
46
+ c.description = %{The Keystore sub-commands let you interact directly with the Keystore instance
47
+ in a solution. This allows for easier debugging, being able to quickly get and
48
+ set data. As well as calling any of the other supported REDIS commands.}
49
+ c.action do |args, options|
50
+ ::Commander::UI.enable_paging
51
+ say MrMurano::SubCmdGroupHelp.new(c).get_help
52
+ end
53
+ end
54
+
55
+ command 'keystore clearAll' do |c|
56
+ c.syntax = %{murano keystore clearAll}
57
+ c.description = %{Delete all keys in the keystore}
58
+ c.action do |args,options|
59
+ sol = MrMurano::Keystore.new
60
+ sol.clearall
61
+ end
62
+ end
63
+
64
+ command 'keystore info' do |c|
65
+ c.syntax = %{murano keystore info}
66
+ c.description = %{Show info about the Keystore}
67
+ c.action do |args,options|
68
+ sol = MrMurano::Keystore.new
69
+ sol.outf sol.keyinfo
70
+ end
71
+ end
72
+
73
+ command 'keystore list' do |c|
74
+ c.syntax = %{murano keystore list}
75
+ c.description = %{List all of the keys in the Keystore}
76
+ c.action do |args,options|
77
+ sol = MrMurano::Keystore.new
78
+ sol.outf sol.listkeys
79
+ end
80
+ end
81
+
82
+ command 'keystore get' do |c|
83
+ c.syntax = %{murano keystore get <key>}
84
+ c.description = %{Get the value of a key in the Keystore}
85
+ c.action do |args,options|
86
+ sol = MrMurano::Keystore.new
87
+ ret = sol.getkey(args[0])
88
+ sol.outf ret
89
+ end
90
+ end
91
+
92
+ command 'keystore set' do |c|
93
+ c.syntax = %{murano keystore set <key> <value...>}
94
+ c.description = %{Set the value of a key in the Keystore}
95
+ c.action do |args,options|
96
+ sol = MrMurano::Keystore.new
97
+ sol.setkey(args[0], args[1..-1].join(' '))
98
+ end
99
+ end
100
+
101
+ command 'keystore delete' do |c|
102
+ c.syntax = %{murano keystore delete <key>}
103
+ c.description = %{Delete a key from the Keystore}
104
+ c.action do |args,options|
105
+ sol = MrMurano::Keystore.new
106
+ sol.delkey(args[0])
107
+ end
108
+ end
109
+ alias_command 'keystore rm', 'keystore delete'
110
+ alias_command 'keystore del', 'keystore delete'
111
+
112
+ command 'keystore command' do |c|
113
+ c.syntax = %{murano keystore command <command> <key> <args...>}
114
+ c.summary = %{Call some Redis commands in the Keystore}
115
+ c.description = %{Call some Redis commands in the Keystore.
116
+
117
+ Only a subset of all Redis commands is supported.
118
+ See http://docs.exosite.com/murano/services/keystore/#command for current list.
119
+ }
120
+ c.example %{murano keystore command lpush mykey myvalue}, %{Push a value onto list}
121
+ c.example %{murano keystore command lpush mykey A B C}, %{Push three values onto list}
122
+ c.example %{murano keystore command lrem mykey 0 B}, %{Remove all B values from list}
123
+ c.action do |args,options|
124
+ sol = MrMurano::Keystore.new
125
+ if args.count < 2 then
126
+ sol.error "Not enough params"
127
+ else
128
+ ret = sol.command(args[1], args[0], args[2..-1])
129
+ if ret.has_key?(:value) then
130
+ sol.outf ret[:value]
131
+ else
132
+ sol.error "#{ret[:code]}: #{ret.message}"
133
+ sol.outf ret[:error] if ($cfg['tool.debug'] and ret.has_key?(:error))
134
+ end
135
+ end
136
+ end
137
+ end
138
+ alias_command 'keystore cmd', 'keystore command'
139
+
140
+ # A bunch of common REDIS commands that are suported in Murano
141
+ alias_command 'keystore lpush', 'keystore command', 'lpush'
142
+ alias_command 'keystore lindex', 'keystore command', 'lindex'
143
+ alias_command 'keystore llen', 'keystore command', 'llen'
144
+ alias_command 'keystore linsert', 'keystore command', 'linsert'
145
+ alias_command 'keystore lrange', 'keystore command', 'lrange'
146
+ alias_command 'keystore lrem', 'keystore command', 'lrem'
147
+ alias_command 'keystore lset', 'keystore command', 'lset'
148
+ alias_command 'keystore ltrim', 'keystore command', 'ltrim'
149
+ alias_command 'keystore rpop', 'keystore command', 'rpop'
150
+ alias_command 'keystore rpush', 'keystore command', 'rpush'
151
+ alias_command 'keystore sadd', 'keystore command', 'sadd'
152
+ alias_command 'keystore srem', 'keystore command', 'srem'
153
+ alias_command 'keystore scard', 'keystore command', 'scard'
154
+ alias_command 'keystore smembers', 'keystore command', 'smembers'
155
+ alias_command 'keystore spop', 'keystore command', 'spop'
156
+
157
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,78 @@
1
+ require 'MrMurano/Solution'
2
+ require 'MrMurano/makePretty'
3
+
4
+ command :logs do |c|
5
+ c.syntax = %{murano logs [options]}
6
+ c.description = %{Get the logs for a solution}
7
+ c.option '-f','--follow', %{Follow logs from server}
8
+ c.option('--[no-]color', %{Toggle colorizing of logs}) {
9
+ Rainbow.enabled = false
10
+ }
11
+ c.option '--[no-]pretty', %{Reformat JSON blobs in logs.}
12
+ c.option '--[no-]localtime', %{Adjust Timestamps to be in local time}
13
+ c.option '--raw', %{Don't do any formating of the log data}
14
+
15
+ c.action do |args,options|
16
+ options.default :pretty=>true, :localtime=>true, :raw => false
17
+
18
+ sol = MrMurano::Solution.new
19
+
20
+ if options.follow then
21
+ # open a lasting connection and continueally feed makePretty()
22
+ begin
23
+ sol.get('/logs?polling=true') do |request, http|
24
+ request["Accept-Encoding"] = "None"
25
+ http.request(request) do |response|
26
+ remainder=''
27
+ response.read_body do |chunk|
28
+ chunk = remainder + chunk unless remainder.empty?
29
+
30
+ # for all complete JSON blobs, make them pretty.
31
+ chunk.gsub!(/\{(?>[^}{]+|\g<0>)*\}/m) do |m|
32
+ if options.raw then
33
+ puts m
34
+ else
35
+ begin
36
+ js = JSON.parse(m, {:allow_nan=>true,
37
+ :symbolize_names => true,
38
+ :create_additions=>false})
39
+ puts MrMurano::Pretties::makePretty(js, options)
40
+ rescue
41
+ sol.error '=== JSON parse error, showing raw instead ==='
42
+ puts m
43
+ end
44
+ end
45
+ '' #remove (we're kinda abusing gsub here.)
46
+ end
47
+
48
+ # is there an incomplete one?
49
+ if chunk.match(/(\{.*$)/m) then
50
+ remainder = $1
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ rescue Interrupt => _
57
+ end
58
+
59
+ else
60
+ ret = sol.get('/logs')
61
+
62
+ if ret.kind_of?(Hash) and ret.has_key?(:items) then
63
+ ret[:items].reverse.each do |line|
64
+ if options.raw then
65
+ puts line
66
+ else
67
+ puts MrMurano::Pretties::makePretty(line, options)
68
+ end
69
+ end
70
+ else
71
+ sol.error "Couldn't get logs: #{ret}"
72
+ break
73
+ end
74
+
75
+ end
76
+ end
77
+ end
78
+ # vim: set ai et sw=2 ts=2 :