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,13 +1,23 @@
1
+ # Last Modified: 2017.08.16 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
1
8
  require 'date'
9
+ require 'MrMurano/ReCommander'
2
10
  require 'MrMurano/Solution-ServiceConfig'
3
11
  require 'MrMurano/SubCmdGroupContext'
4
12
 
5
13
  module MrMurano
6
14
  module ServiceConfigs
7
15
  class Tsdb < ServiceConfig
8
- def initialize
16
+ def initialize(sid=nil)
17
+ # FIXME/2017-07-03: What soln types have TSDBs?
18
+ @solntype = 'application.id'
9
19
  super
10
- @serviceName = 'tsdb'
20
+ @service_name = 'tsdb'
11
21
  end
12
22
 
13
23
  def write(data)
@@ -18,6 +28,8 @@ module MrMurano
18
28
  call(:query, :post, query)
19
29
  end
20
30
 
31
+ # FIXME/2017-08-16: Convert to snake_case. Or is this method name magical?
32
+ # rubocop:disable Style/MethodName: Use snake_case for method names.
21
33
  def listTags
22
34
  call(:listTags)
23
35
  end
@@ -26,34 +38,54 @@ module MrMurano
26
38
  call(:listMetrics)
27
39
  end
28
40
 
29
-
30
41
  def str_to_timestamp(str)
31
- if str =~ /^\d+(u|ms|s)?$/ then
42
+ if str =~ /^\d+(u|ms|s)?$/
32
43
  str
33
44
  else
34
45
  dt = DateTime.parse(str)
35
- (dt.to_time.to_f * 1000000).to_i
46
+ (dt.to_time.to_f * 1_000_000).to_i
36
47
  end
37
48
  end
38
49
  end
39
50
  end
40
51
  end
41
52
 
53
+ command :tsdb do |c|
54
+ c.syntax = %(murano tsdb)
55
+ c.summary = %(Show list of TSDB commands)
56
+ c.description = %(
57
+ The tsdb sub-commands let you interact directly with the TSDB instance in a
58
+ solution. This allows for easier debugging, being able to quickly try out
59
+ different queries or write test data.
60
+ ).strip
61
+ c.project_not_required = true
62
+
63
+ c.action do |_args, _options|
64
+ ::Commander::UI.enable_paging
65
+ say MrMurano::SubCmdGroupHelp.new(c).get_help
66
+ end
67
+ end
68
+
42
69
  command 'tsdb write' do |c|
43
- c.syntax = %{murano tsdb write [options] <metric=value>|@<tag=value> … }
44
- c.summary = %{write data}
45
- c.description = %{Write data
70
+ c.syntax = %(murano tsdb write [--options] <metric=value>|@<tag=value> … )
71
+ c.summary = %(Write data to the TSDB)
72
+ c.description = %(
73
+ Write data to the time series database (TSDB).
46
74
 
47
75
  TIMESTAMP is microseconds since unix epoch, or can be suffixed with units.
48
76
  Units are u (microseconds), ms (milliseconds), s (seconds)
49
77
 
50
78
  Also, many date-time formats can be parsed and will be converted to microseconds
51
- }
52
- c.option '--when TIMESTAMP', %{When this data happened. (defaults to now)}
79
+ ).strip
80
+
81
+ c.option '--when TIMESTAMP', %(When this data happened (default: now))
53
82
  # TODO: add option to take data from STDIN.
54
- c.example 'murano tsdb write hum=45 lux=12765 @sn=44', %{Write two metrics (hum and lux) with a tag (sn)}
83
+
84
+ c.example 'murano tsdb write hum=45 lux=12765 @sn=44', %(Write two metrics (hum and lux) with a tag (sn))
55
85
 
56
86
  c.action do |args, options|
87
+ # SKIP: c.verify_arg_count!(args)
88
+
57
89
  sol = MrMurano::ServiceConfigs::Tsdb.new
58
90
 
59
91
  # we have hash of tags, hash of metrics, optional timestamp.
@@ -61,32 +93,31 @@ Also, many date-time formats can be parsed and will be converted to microseconds
61
93
  tags = {}
62
94
  args.each do |item|
63
95
  key, value = item.split('=', 2)
64
- if key[0] == '@' then
65
- tags[key[1..-1]] = value.to_s #tags are always strings.
96
+ if key[0] == '@'
97
+ tags[key[1..-1]] = value.to_s # tags are always strings.
66
98
  else
67
99
  value = value.to_i if value == value.to_i.to_s
68
100
  metrics[key] = value
69
101
  end
70
102
  end
71
103
 
72
- data = {:tags=>tags, :metrics=>metrics}
73
- if not options.when.nil? and options.when != 'now' then
104
+ data = { tags: tags, metrics: metrics }
105
+ if !options.when.nil? && options.when != 'now'
74
106
  data[:ts] = sol.str_to_timestamp(options.when)
75
107
  end
76
108
 
77
109
  ret = sol.write(data)
78
- if ret != {} then
79
- sol.error ret
80
- end
110
+ sol.error ret if ret != {}
81
111
  end
82
112
  end
83
113
 
84
114
  command 'tsdb query' do |c|
85
- c.syntax = %{murano tsdb query [options] <metric>|@<tag=value> …}
86
- c.summary = %{query data}
87
- c.description =%{Query data from the TSDB.
115
+ c.syntax = %(murano tsdb query [--options] <metric>|@<tag=value> …)
116
+ c.summary = %(Query data from the TSDB)
117
+ c.description = %(
118
+ Query data from the time series database (TSDB).
88
119
 
89
- FUNCS is a comma seperated list of the aggregate functions.
120
+ FUNCS is a comma separated list of the aggregate functions.
90
121
  Currently: avg, min, max, count, sum. For string metrics, only count.
91
122
 
92
123
  FILL is null, none, any integer, previous
@@ -99,20 +130,21 @@ TIMESTAMP is microseconds since unix epoch, or can be suffixed with units.
99
130
  Units are u (microseconds), ms (milliseconds), s (seconds)
100
131
 
101
132
  Also, many date-time formats can be parsed and will be converted to microseconds
102
- }
103
- c.option '--start_time TIMESTAMP', %{Start time range}
104
- c.option '--end_time TIMESTAMP', %{End time range; defaults to now}
105
- c.option '--relative_start DURATION', %{Start time relative from now}
106
- c.option '--relative_end DURATION', %{End time relative from now}
107
- c.option '--sampling_size DURATION', %{The size of time slots used for downsampling}
108
- c.option '--limit NUM', Integer, %{Limit number of data points returned}
109
- c.option '--epoch UNIT', ['u','ms','s'], %{Set size of returned timestamps}
110
- c.option '--mode MODE', ['merge','split'], %{Merge or split each returned metric}
111
- c.option '--fill FILL', %{Value to fill for time slots with no data points exist in merge mode}
112
- c.option '--order_by ORDER', ['desc','asc'], %{Return results in ascending or descending time order}
113
- c.option '--aggregate FUNCS', %{Aggregation functions to apply}
114
-
115
- c.option '-o', '--output FILE', %{Download to file instead of STDOUT}
133
+ ).strip
134
+
135
+ c.option '--start_time TIMESTAMP', %(Start time range)
136
+ c.option '--end_time TIMESTAMP', %(End time range; defaults to now)
137
+ c.option '--relative_start DURATION', %(Start time relative from now)
138
+ c.option '--relative_end DURATION', %(End time relative from now)
139
+ c.option '--sampling_size DURATION', %(The size of time slots used for downsampling)
140
+ c.option '--limit NUM', Integer, %(Limit number of data points returned)
141
+ c.option '--epoch UNIT', %w[u ms s], %(Set size of returned timestamps)
142
+ c.option '--mode MODE', %w[merge split], %(Merge or split each returned metric)
143
+ c.option '--fill FILL', %(Value to fill for time slots with no data points exist in merge mode)
144
+ c.option '--order_by ORDER', %w[desc asc], %(Return results in ascending or descending time order)
145
+ c.option '--aggregate FUNCS', %(Aggregation functions to apply)
146
+
147
+ c.option '-o', '--output FILE', %(Download to file instead of STDOUT)
116
148
 
117
149
  c.example 'murano tsdb query hum', 'Get all hum metric entries'
118
150
  c.example 'murano tsdb query hum @sn=45', 'Get all hum metric entries for tag sn=45'
@@ -123,17 +155,18 @@ Also, many date-time formats can be parsed and will be converted to microseconds
123
155
  c.example 'murano tsdb query hum --sampling_size 30m', 'Get one hum entry from each 30 minute chunk of time'
124
156
  c.example 'murano tsdb query hum --sampling_size 30m --aggregate avg', 'Get average hum entry from each 30 minute chunk of time'
125
157
 
126
-
127
158
  c.action do |args, options|
159
+ # SKIP: c.verify_arg_count!(args)
160
+
128
161
  sol = MrMurano::ServiceConfigs::Tsdb.new
129
162
 
130
163
  query = {}
131
164
  tags = {}
132
165
  metrics = []
133
166
  args.each do |arg|
134
- if arg =~ /=/ then
167
+ if arg =~ /=/
135
168
  # a tag.
136
- k,v = arg.split('=', 2)
169
+ k, v = arg.split('=', 2)
137
170
  k = k[1..-1] if k[0] == '@'
138
171
  tags[k] = v
139
172
  else
@@ -145,24 +178,24 @@ Also, many date-time formats can be parsed and will be converted to microseconds
145
178
 
146
179
  # A query without any metrics is invalid. So if the user didn't provide any,
147
180
  # look up all of them (well, frist however many) and use that list.
148
- if query[:metrics].nil? or query[:metrics].empty? then
181
+ if query[:metrics].to_s.empty?
149
182
  ret = sol.listMetrics
150
183
  query[:metrics] = ret[:metrics]
151
184
  end
152
185
 
153
- unless options.start_time.nil? then
186
+ unless options.start_time.nil?
154
187
  query[:start_time] = sol.str_to_timestamp(options.start_time)
155
188
  end
156
- unless options.end_time.nil? then
189
+ unless options.end_time.nil?
157
190
  query[:end_time] = sol.str_to_timestamp(options.end_time)
158
191
  end
159
192
 
160
- unless options.relative_start.nil? then
193
+ unless options.relative_start.nil?
161
194
  o = options.relative_start
162
195
  o = "-#{o}" unless o[0] == '-'
163
196
  query[:relative_start] = o
164
197
  end
165
- unless options.relative_end.nil? then
198
+ unless options.relative_end.nil?
166
199
  o = options.relative_end
167
200
  o = "-#{o}" unless o[0] == '-'
168
201
  query[:relative_end] = o
@@ -175,79 +208,86 @@ Also, many date-time formats can be parsed and will be converted to microseconds
175
208
  query[:order_by] = options.order_by unless options.order_by.nil?
176
209
 
177
210
  query[:fill] = options.fill unless options.fill.nil?
178
- unless options.aggregate.nil? then
211
+ unless options.aggregate.nil?
179
212
  query[:aggregate] = options.aggregate.split(',')
180
213
  end
181
214
 
182
- io=nil
183
- if options.output then
184
- io = File.open(options.output, 'w')
185
- end
215
+ io = File.open(options.output, 'w') if options.output
186
216
  sol.outf sol.query(query) do |dd, ios|
187
217
  # If aggregated, then we need to break up the columns. since each is now a
188
218
  # hash of the aggregated functions
189
- unless options.aggregate.nil? then
219
+ unless options.aggregate.nil?
190
220
  dd[:values].map! do |row|
191
221
  row.map do |value|
192
- if value.kind_of? Hash then
193
- query[:aggregate].map{|qa| value[qa.to_sym]}
222
+ if value.is_a? Hash
223
+ query[:aggregate].map { |qa| value[qa.to_sym] }
194
224
  else
195
225
  value
196
226
  end
197
227
  end.flatten
198
228
  end
199
229
  dd[:columns].map! do |col|
200
- if col == 'time' then
230
+ if col == 'time'
201
231
  col
202
232
  else
203
- query[:aggregate].map{|qa| "#{col}.#{qa.to_s}"}
233
+ query[:aggregate].map { |qa| "#{col}.#{qa}" }
204
234
  end
205
235
  end.flatten!
206
236
  end
207
- sol.tabularize({
208
- :headers=>dd[:columns],
209
- :rows=>dd[:values]
210
- }, ios)
237
+ sol.tabularize(
238
+ {
239
+ headers: dd[:columns],
240
+ rows: dd[:values],
241
+ },
242
+ ios
243
+ )
211
244
  end
212
245
  io.close unless io.nil?
213
246
  end
214
247
  end
215
248
 
216
249
  command 'tsdb list tags' do |c|
217
- c.syntax = %{murano tsdb list tags [options]}
218
- c.summary = %{List tags}
219
- c.option '--values', %{Also return the known tag values}
250
+ c.syntax = %(murano tsdb list tags [--options])
251
+ c.summary = %(List tags)
252
+ c.description = %(
253
+ List tags.
254
+ ).strip
255
+
256
+ c.option '--values', %(Include the known tag values)
220
257
 
221
258
  c.action do |args, options|
222
- options.default :values=>false
259
+ c.verify_arg_count!(args)
260
+ options.default(values: false)
223
261
 
224
262
  sol = MrMurano::ServiceConfigs::Tsdb.new
225
263
  ret = sol.listTags
226
264
  # TODO: handle looping if :next != nil
227
265
 
228
- if options.values then
266
+ if options.values
229
267
  sol.outf(ret[:tags]) do |dd, ios|
230
- data={}
268
+ data = {}
231
269
  data[:headers] = dd.keys
232
- data[:rows] = dd.keys.map{|k| dd[k]}
233
- len = data[:rows].map{|i| i.length}.max
234
- data[:rows].each{|r| r.fill(nil, r.length, len - r.length)}
270
+ data[:rows] = dd.keys.map { |k| dd[k] }
271
+ len = data[:rows].map(&:length).max
272
+ data[:rows].each { |r| r.fill(nil, r.length, len - r.length) }
235
273
  data[:rows] = data[:rows].transpose
236
274
  sol.tabularize(data, ios)
237
275
  end
238
276
  else
239
277
  sol.outf ret[:tags].keys
240
278
  end
241
-
242
-
243
279
  end
244
280
  end
245
281
 
246
282
  command 'tsdb list metrics' do |c|
247
- c.syntax = %{murano tsdb list metrics}
248
- c.summary = %{List metrics}
249
-
250
- c.action do |args, options|
283
+ c.syntax = %(murano tsdb list metrics)
284
+ c.summary = %(List metrics)
285
+ c.description = %(
286
+ List metrics.
287
+ ).strip
288
+
289
+ c.action do |args, _options|
290
+ c.verify_arg_count!(args)
251
291
  sol = MrMurano::ServiceConfigs::Tsdb.new
252
292
  ret = sol.listMetrics
253
293
  # TODO: handle looping if :next != nil
@@ -255,17 +295,3 @@ command 'tsdb list metrics' do |c|
255
295
  end
256
296
  end
257
297
 
258
- command :tsdb do |c|
259
- c.syntax = %{murano tsdb}
260
- c.summary = %{About TSDB}
261
- c.description = %{The tsdb sub-commands let you interact directly with the TSDB instance in a
262
- solution. This allows for easier debugging, being able to quickly try out
263
- different queries or write test data.}
264
-
265
- c.action do |args, options|
266
- ::Commander::UI.enable_paging
267
- say MrMurano::SubCmdGroupHelp.new(c).get_help
268
- end
269
- end
270
-
271
- # vim: set ai et sw=2 ts=2 :
@@ -1,23 +1,65 @@
1
+ # Last Modified: 2017.08.16 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
8
+ require 'MrMurano/ReCommander'
1
9
  require 'MrMurano/Solution'
2
10
 
3
11
  command :usage do |c|
4
- c.syntax = %{murano usage}
5
- c.summary = %{Get usage info for project}
6
- c.description = %{Get usage info for project}
7
-
8
- c.action do |args,options|
9
- sol = MrMurano::Solution.new
10
- sol.outf(sol.usage) do |dd,ios|
11
- headers = ['', :Quota, :Daily, :Monthly, :Total]
12
- rows = []
13
- dd.each_pair do |key,value|
14
- quota = value[:quota] or {}
15
- usage = value[:usage] or {}
16
- rows << [key, quota[:daily], usage[:calls_daily], usage[:calls_monthly], usage[:calls_total]]
12
+ c.syntax = %(murano usage)
13
+ c.summary = %(Get usage info for solution(s))
14
+ c.description = %(
15
+ Get usage info for solution(s).
16
+ ).strip
17
+
18
+ # Add flag: --type [application|product|all].
19
+ cmd_add_solntype_pickers(c)
20
+
21
+ c.option '--[no-]all', 'Show usage for all Solutions in Business, not just Project'
22
+ c.option(
23
+ '--[no-]header', %(Output solution descriptions (default: true))
24
+ )
25
+
26
+ c.action do |args, options|
27
+ c.verify_arg_count!(args)
28
+ options.default(all: false, header: true)
29
+ cmd_defaults_solntype_pickers(options)
30
+
31
+ solz = must_fetch_solutions!(options)
32
+
33
+ solsages = []
34
+ MrMurano::Verbose.whirly_start('Fetching usage...')
35
+ solz.each do |sol|
36
+ solsages += [[sol, sol.usage]]
37
+ end
38
+ MrMurano::Verbose.whirly_stop
39
+
40
+ solsages.each do |sol, usage|
41
+ sol.outf(usage) do |dd, ios|
42
+ ios.puts(sol.pretty_desc(add_type: true)) if options.header
43
+ headers = ['', :Quota, :Daily, :Monthly, :Total]
44
+ rows = []
45
+ dd.each_pair do |key, value|
46
+ quota = value[:quota] || {}
47
+ usage = value[:usage] || {}
48
+ rows << [
49
+ key,
50
+ quota[:daily],
51
+ usage[:calls_daily],
52
+ usage[:calls_monthly],
53
+ usage[:calls_total],
54
+ ]
55
+ end
56
+ sol.tabularize({ headers: headers, rows: rows }, ios)
17
57
  end
18
- sol.tabularize({:headers=>headers,:rows=>rows}, ios)
19
58
  end
20
59
  end
21
60
  end
61
+ alias_command 'usage application', 'usage', '--type', 'application'
62
+ alias_command 'usage product', 'usage', '--type', 'product'
63
+ alias_command 'application usage', 'usage', '--type', 'application'
64
+ alias_command 'product usage', 'usage', '--type', 'product'
22
65
 
23
- # vim: set ai et sw=2 ts=2 :
@@ -1,20 +1,110 @@
1
+ # Last Modified: 2017.08.16 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
8
+ require 'orderedhash'
1
9
 
2
- # from: http://www.any-where.de/blog/ruby-hash-convert-string-keys-to-symbols/
3
10
  class Hash
4
- #take keys of hash and transform those to a symbols
11
+ # From:
12
+ # http://www.any-where.de/blog/ruby-hash-convert-string-keys-to-symbols/
13
+ #
14
+ # Take keys of hash and transform those to symbols.
5
15
  def self.transform_keys_to_symbols(value)
6
- return value.map{|v| Hash.transform_keys_to_symbols(v)} if value.is_a?(Array)
16
+ return value.map { |v| Hash.transform_keys_to_symbols(v) } if value.is_a?(Array)
7
17
  return value if not value.is_a?(Hash)
8
- hash = value.inject({}){|memo,(k,v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo}
9
- return hash
18
+ value.inject({}) { |memo, (k,v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo }
10
19
  end
11
- #take keys of hash and transform those to strings
20
+
21
+ # From:
22
+ # http://www.any-where.de/blog/ruby-hash-convert-string-keys-to-symbols/
23
+ #
24
+ # Take keys of hash and transform those to strings.
12
25
  def self.transform_keys_to_strings(value)
13
- return value.map{|v| Hash.transform_keys_to_strings(v)} if value.is_a?(Array)
26
+ return value.map { |v| Hash.transform_keys_to_strings(v) } if value.is_a?(Array)
14
27
  return value if not value.is_a?(Hash)
15
- hash = value.inject({}){|memo,(k,v)| memo[k.to_s] = Hash.transform_keys_to_strings(v); memo}
16
- return hash
28
+ value.inject({}) { |memo, (k,v)| memo[k.to_s] = Hash.transform_keys_to_strings(v); memo }
29
+ end
30
+
31
+ # From Rails.
32
+ def deep_merge!(other_hash, &block)
33
+ other_hash.each_pair do |current_key, other_value|
34
+ this_value = self[current_key]
35
+ if this_value.is_a?(Hash) && other_value.is_a?(Hash)
36
+ self[current_key] = this_value.deep_merge(other_value, &block)
37
+ elsif block_given? && key?(current_key)
38
+ self[current_key] = block.call(current_key, this_value, other_value)
39
+ else
40
+ self[current_key] = other_value
41
+ end
42
+ end
43
+ self
44
+ end
45
+ end
46
+
47
+ def ordered_hash(dict)
48
+ ohash = OrderedHash.new
49
+ dict.keys.sort.each do |key|
50
+ value = dict[key]
51
+ if value.is_a? Hash
52
+ ohash[key] = ordered_hash(value)
53
+ else
54
+ ohash[key] = value
55
+ end
56
+ end
57
+ ohash
58
+ end
59
+
60
+ ##
61
+ # Take a hash or something (a Commander::Command::Options) and return a hash
62
+ #
63
+ # @param hsh [Hash, Commander::Command::Options] Thing we want to be a Hash
64
+ # @return [Hash] an actual Hash with default value of false
65
+ def elevate_hash(hsh)
66
+ # Commander::Command::Options stripped all of the methods from parent
67
+ # objects. I have not nice thoughts about that.
68
+ begin
69
+ hsh = hsh.__hash__
70
+ # rubocop:disable Lint/HandleExceptions: Do not suppress exceptions.
71
+ rescue NoMethodError
72
+ # swallow this.
73
+ end
74
+ # build a hash where the default is 'false' instead of 'nil'
75
+ Hash.new(false).merge(Hash.transform_keys_to_symbols(hsh))
76
+ # 2017-08-16: Weird: [lb] seeing the Hash behave differently
77
+ # after feeding through this function. Unknown keys would
78
+ # return nil before, but after, return false.
79
+ #
80
+ # (byeebug) options
81
+ # {:delete=>false, :create=>true, :update=>false}
82
+ # (byeebug) options[:fff]
83
+ # false
84
+ # (byeebug) options[:fff] = nil
85
+ # nil
86
+ # (byeebug) options[:fff]
87
+ # nil
88
+ # (byeebug) options[:fffd]
89
+ # false
90
+ # (byeebug) options
91
+ # {:delete=>false, :create=>true, :update=>false, :fff=>nil}
92
+ #
93
+ # Work around is to test with hash.key?
94
+ end
95
+
96
+ ##
97
+ # Array-ify the given item, if not already an array.
98
+ #
99
+ # NOTE/2017-08-15: This fcn. is not hash-related, but this file is the
100
+ # closest we've got to a generic utility method dumping ground.
101
+ def ensure_array(item)
102
+ if item.nil?
103
+ []
104
+ elsif !item.is_a?(Array)
105
+ [item]
106
+ else
107
+ item
17
108
  end
18
109
  end
19
110
 
20
- # vim: set ai et sw=2 ts=2 :