ruby-grafana-reporter 0.2.2 → 0.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/README.md +28 -23
- data/bin/ruby-grafana-reporter +5 -5
- data/lib/VERSION.rb +2 -2
- data/lib/grafana/grafana.rb +27 -24
- data/lib/grafana_reporter/application/application.rb +20 -270
- data/lib/grafana_reporter/application/webservice.rb +2 -3
- data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +4 -7
- data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +4 -7
- data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +1 -1
- data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +6 -4
- data/lib/grafana_reporter/asciidoctor/help.rb +4 -4
- data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +4 -2
- data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +6 -4
- data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +4 -2
- data/lib/grafana_reporter/asciidoctor/query_mixin.rb +15 -4
- data/lib/grafana_reporter/asciidoctor/report.rb +1 -2
- data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +8 -8
- data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +9 -9
- data/lib/grafana_reporter/configuration.rb +40 -51
- data/lib/grafana_reporter/console_configuration_wizard.rb +269 -0
- data/lib/ruby-grafana-reporter.rb +3 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '00728deba4250ed327170393bbeaac1b1d6d1002463a5a243285ac570f09231f'
|
4
|
+
data.tar.gz: 2985a11f6404e622ff279dbe3e328b38e4202bf665b2fef9e23746bbfd6c3459
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92de552918a451f9bac1196dfbb05dc1ad64e0059f4c90fe06c079e5e181fee96a07858ae0c5815e3dbf37358c4aa271fcd8d129bb6721f3c8a53f285325fc25
|
7
|
+
data.tar.gz: aff95df6e4b5a8636905ec498433d1fcdae6d7b9aa2d26640815a68160c2f74c39078adfbe32a67c9115855ddd97683c6844ea0347e18cf010586e2bd036faed
|
data/README.md
CHANGED
@@ -12,6 +12,7 @@ Reporting Service for Grafana
|
|
12
12
|
* [Getting started](#getting-started)
|
13
13
|
* [Grafana integration](#grafana-integration)
|
14
14
|
* [Webservice overview](#webservice-overview)
|
15
|
+
* [Documentation](#documentation)
|
15
16
|
* [Features](#features)
|
16
17
|
* [Roadmap](#roadmap)
|
17
18
|
* [Contributing](#contributing)
|
@@ -38,28 +39,28 @@ integrate without further dependencies with the asciidoctor docker image.
|
|
38
39
|
Can't wait to see, what functions the reporter provides within the asciidoctor
|
39
40
|
templates? Have a look at the [function documentation](FUNCTION_CALLS.md).
|
40
41
|
|
41
|
-
The complete
|
42
|
-
[API documentation](https://rubydoc.info/gems/ruby-grafana-reporter) can be
|
43
|
-
found here.
|
44
|
-
|
45
42
|
## Getting started
|
46
43
|
|
47
|
-
There exist several ways of installing the reporter.
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
There exist several ways of installing the reporter. If you need further
|
45
|
+
installation help, or want to use a "baremetal" ruby setup or a docker
|
46
|
+
integration, please have a look at the more extended
|
47
|
+
[installation documentation](INSTALL.md).
|
51
48
|
|
52
|
-
|
49
|
+
Windows users may directly use the provided executable.
|
53
50
|
|
51
|
+
Following these steps sets up the reporter on a fresh Raspberry Pi installation:
|
52
|
+
|
53
|
+
sudo apt-get install ruby
|
54
54
|
gem install ruby-grafana-reporter
|
55
55
|
|
56
|
-
|
57
|
-
wizard, which leads you through all necessary steps:
|
56
|
+
That's it. Let's now configure a grafana setup with the configuration wizard:
|
58
57
|
|
59
58
|
ruby-grafana-reporter -w
|
60
59
|
|
61
60
|
It is strongly recommended, to also create the demo PDF file, as stated at the end
|
62
61
|
of the procedure, to get a detailed documentation of all the reporter capabilities.
|
62
|
+
The whole [function documentation](FUNCTION_CALLS.md) is also available at the
|
63
|
+
previous link.
|
63
64
|
|
64
65
|
To run the reporter as a service, you only need to call it like this:
|
65
66
|
|
@@ -112,39 +113,43 @@ Running the reporter as a webservice provides the following URLs
|
|
112
113
|
/view_report - for viewing the status or receving the result of a specific rendering, is automatically called after a successfull /render call
|
113
114
|
/cancel_report - for cancelling the rendering of a specific report, normally not called manually, but on user interaction in the /view_report or /overview URL
|
114
115
|
|
116
|
+
The main endpoint to call for report generation is configured in the previous chapter [Grafana integration](#grafana-integration).
|
117
|
+
|
118
|
+
However, if you would like to see, currently running report generations and previously generated reports, you may want to call the endpoint `/overview`.
|
119
|
+
|
120
|
+
## Documentation
|
121
|
+
|
122
|
+
The [function documentation](FUNCTION_CALLS.md) contains a complete overview of
|
123
|
+
all possible grafana calls, to generate dynamic report templates.
|
124
|
+
|
125
|
+
The [API documentation](https://rubydoc.info/gems/ruby-grafana-reporter) can be
|
126
|
+
found here.
|
127
|
+
|
115
128
|
## Features
|
116
129
|
|
117
130
|
* Build report template including all imaginable grafana content:
|
118
131
|
* panels as images
|
119
132
|
* panel table query or custom query results as real document tables (not images!)
|
120
133
|
* single panel value or custom query single value result integrated in texts
|
121
|
-
* Solid as a rock, also in case of template errors
|
122
|
-
*
|
134
|
+
* Solid as a rock, also in case of template errors and whatever else may happen
|
135
|
+
* Fully controllable as command line application or as a webservice
|
123
136
|
* Seamlessly integrates with asciidoctor docker container
|
124
|
-
* Developed
|
137
|
+
* Developed to support other tools than asciidoctor as well
|
125
138
|
|
126
139
|
## Roadmap
|
127
140
|
|
128
141
|
This is just a collection of things, I am heading for in future, without a schedule.
|
129
142
|
|
130
|
-
* Add documentation of possible asciidoctor calls to grafana
|
131
143
|
* Add a simple plugin system to support specific asciidoctor modifications
|
132
144
|
* Solve code TODOs
|
133
145
|
* Become [rubocop](https://rubocop.org/) ready
|
146
|
+
* Clean and properly setup test cases
|
134
147
|
|
135
148
|
## Contributing
|
136
149
|
|
137
150
|
If you'd like to contribute, please fork the repository and use a feature
|
138
151
|
branch. Pull requests are warmly welcome.
|
139
152
|
|
140
|
-
Though not yet valid for my code, I'd like to see the project become
|
141
|
-
[rubocop](https://rubocop.org/) ready :-)
|
142
|
-
|
143
|
-
Definitely open spots from my side are:
|
144
|
-
|
145
|
-
* This README
|
146
|
-
* Clean and properly setup test cases
|
147
|
-
|
148
153
|
## Licensing
|
149
154
|
|
150
155
|
The code in this project is licensed under MIT license.
|
data/bin/ruby-grafana-reporter
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative '../lib/ruby-grafana-reporter'
|
5
|
-
GrafanaReporter::Application::Application.new.configure_and_run(ARGV)
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/ruby-grafana-reporter'
|
5
|
+
GrafanaReporter::Application::Application.new.configure_and_run(ARGV) unless defined?(Ocra)
|
data/lib/VERSION.rb
CHANGED
data/lib/grafana/grafana.rb
CHANGED
@@ -13,16 +13,15 @@ module Grafana
|
|
13
13
|
# trailing slash, e.g. +https://localhost:3000+.
|
14
14
|
# @param key [String] API key for the grafana instance, if required
|
15
15
|
# @param opts [Hash] additional options.
|
16
|
-
# Currently supporting +:logger+ and +:
|
17
|
-
# +:datasources+ need to be an Hash with datasource name as key and datasource id as value.
|
18
|
-
# If not specified, the datasources will be queried from the grafana interface.
|
19
|
-
# Specifying +:datasources+> here can be used, so that the interface can be used without grafana Admin privileges.
|
16
|
+
# Currently supporting +:logger+ and +:ssl_cert+.
|
20
17
|
def initialize(base_uri, key = nil, opts = {})
|
21
18
|
@base_uri = base_uri
|
22
19
|
@key = key
|
23
20
|
@dashboards = {}
|
21
|
+
@ssl_cert = opts[:ssl_cert]
|
24
22
|
@logger = opts[:logger] || ::Logger.new(nil)
|
25
|
-
|
23
|
+
|
24
|
+
initialize_datasources unless @base_uri.empty?
|
26
25
|
end
|
27
26
|
|
28
27
|
# Used to test a connection to the grafana instance.
|
@@ -34,14 +33,13 @@ module Grafana
|
|
34
33
|
def test_connection
|
35
34
|
if execute_http_request('/api/datasources').is_a?(Net::HTTPOK)
|
36
35
|
# we have admin rights
|
37
|
-
@logger.
|
36
|
+
@logger.warn('Reporter is running with Admin privileges on grafana. This is a potential security risk.')
|
38
37
|
return 'Admin'
|
39
38
|
end
|
40
39
|
# check if we have lower rights
|
41
40
|
return 'Failed' unless execute_http_request('/api/dashboards/home').is_a?(Net::HTTPOK)
|
42
41
|
|
43
|
-
@logger.info('Reporter is running with NON-Admin privileges on grafana.
|
44
|
-
'datasources are specified in CONFIG_FILE, otherwise operation will fail')
|
42
|
+
@logger.info('Reporter is running with NON-Admin privileges on grafana.')
|
45
43
|
'NON-Admin'
|
46
44
|
end
|
47
45
|
|
@@ -49,17 +47,17 @@ module Grafana
|
|
49
47
|
#
|
50
48
|
# @return [Integer] ID for the specified datasource name
|
51
49
|
def datasource_id(datasource_name)
|
52
|
-
|
53
|
-
|
50
|
+
datasource_name ||= 'default'
|
51
|
+
return @datasources[datasource_name] if @datasources[datasource_name]
|
54
52
|
|
55
|
-
|
53
|
+
raise DatasourceDoesNotExistError.new('name', datasource_name)
|
56
54
|
end
|
57
55
|
|
58
56
|
# Returns if the given datasource ID exists for the grafana instance.
|
59
57
|
#
|
60
58
|
# @return [Boolean] true if exists, false otherwise
|
61
59
|
def datasource_id_exists?(datasource_id)
|
62
|
-
datasources.value?(datasource_id)
|
60
|
+
@datasources.value?(datasource_id)
|
63
61
|
end
|
64
62
|
|
65
63
|
# @param dashboard_uid [String] UID of the searched {Dashboard}
|
@@ -97,6 +95,13 @@ module Grafana
|
|
97
95
|
if @base_uri =~ /^https/
|
98
96
|
http.use_ssl = true
|
99
97
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
98
|
+
if @ssl_cert && !File.exist?(@ssl_cert)
|
99
|
+
@logger.warn('SSL certificate file does not exist.')
|
100
|
+
elsif @ssl_cert
|
101
|
+
http.cert_store = OpenSSL::X509::Store.new
|
102
|
+
http.cert_store.set_default_paths
|
103
|
+
http.cert_store.add_file(@ssl_cert)
|
104
|
+
end
|
100
105
|
end
|
101
106
|
http.read_timeout = timeout.to_i if timeout
|
102
107
|
|
@@ -112,19 +117,17 @@ module Grafana
|
|
112
117
|
|
113
118
|
private
|
114
119
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
@datasources = {}
|
125
|
-
end
|
120
|
+
def initialize_datasources
|
121
|
+
@datasources = {}
|
122
|
+
|
123
|
+
settings = execute_http_request('/api/frontend/settings')
|
124
|
+
return unless settings.is_a?(Net::HTTPOK)
|
125
|
+
|
126
|
+
json = JSON.parse(settings.body)
|
127
|
+
json['datasources'].select { |_k, v| v['id'].to_i.positive? }.each do |ds_name, ds_value|
|
128
|
+
@datasources[ds_name] = ds_value['id'].to_i
|
126
129
|
end
|
127
|
-
@datasources
|
130
|
+
@datasources['default'] = @datasources[json['defaultDatasource']]
|
128
131
|
end
|
129
132
|
end
|
130
133
|
end
|
@@ -33,7 +33,11 @@ module GrafanaReporter
|
|
33
33
|
action_wizard = false
|
34
34
|
|
35
35
|
parser = OptionParser.new do |opts|
|
36
|
-
|
36
|
+
if ENV['OCRA_EXECUTABLE']
|
37
|
+
opts.banner = "Usage: #{ENV['OCRA_EXECUTABLE'].gsub("#{Dir.pwd}/".gsub('/', '\\'), '')} [options]"
|
38
|
+
else
|
39
|
+
opts.banner = "Usage: #{Gem.ruby} #{$PROGRAM_NAME} [options]"
|
40
|
+
end
|
37
41
|
|
38
42
|
opts.on('-c', '--config CONFIG_FILE_NAME', 'Specify custom configuration file,'\
|
39
43
|
" instead of #{CONFIG_FILE}.") do |file_name|
|
@@ -48,11 +52,22 @@ module GrafanaReporter
|
|
48
52
|
tmp_config.set_param('to_file', file)
|
49
53
|
end
|
50
54
|
|
51
|
-
opts.on('-s', '--set VARIABLE,VALUE', Array, 'Set a variable value, which will be passed to the
|
52
|
-
|
55
|
+
opts.on('-s', '--set VARIABLE,VALUE', Array, 'Set a variable value, which will be passed to the '\
|
56
|
+
'rendering') do |list|
|
57
|
+
raise ParameterValueError, list.length unless list.length == 2
|
58
|
+
|
53
59
|
tmp_config.set_param("default-document-attributes:#{list[0]}", list[1])
|
54
60
|
end
|
55
61
|
|
62
|
+
opts.on('--ssl-cert FILE', 'Manually specify a SSL cert file for HTTPS connection to grafana. Only '\
|
63
|
+
'needed if not working properly otherwise.') do |file|
|
64
|
+
if File.exist?(file)
|
65
|
+
tmp_config.set_param('grafana-reporter:ssl-cert', file)
|
66
|
+
else
|
67
|
+
config.logger.warn("SSL certificate file #{file} does not exist. Setting will be ignored.")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
56
71
|
opts.on('--test GRAFANA_INSTANCE', 'test current configuration against given GRAFANA_INSTANCE') do |instance|
|
57
72
|
tmp_config.set_param('grafana-reporter:run-mode', 'test')
|
58
73
|
tmp_config.set_param('grafana-reporter:test-instance', instance)
|
@@ -80,7 +95,7 @@ module GrafanaReporter
|
|
80
95
|
|
81
96
|
begin
|
82
97
|
parser.parse!(params)
|
83
|
-
return
|
98
|
+
return ConsoleConfigurationWizard.new.start_wizard(config_file, tmp_config) if action_wizard
|
84
99
|
rescue ApplicationError => e
|
85
100
|
puts e.message
|
86
101
|
return -1
|
@@ -122,7 +137,7 @@ module GrafanaReporter
|
|
122
137
|
when Configuration::MODE_CONNECTION_TEST
|
123
138
|
res = Grafana::Grafana.new(config.grafana_host(config.test_instance),
|
124
139
|
config.grafana_api_key(config.test_instance),
|
125
|
-
logger: config.logger).test_connection
|
140
|
+
logger: config.logger, ssl_cert: config.ssl_cert).test_connection
|
126
141
|
puts res
|
127
142
|
|
128
143
|
when Configuration::MODE_SINGLE_RENDER
|
@@ -138,271 +153,6 @@ module GrafanaReporter
|
|
138
153
|
|
139
154
|
0
|
140
155
|
end
|
141
|
-
|
142
|
-
private
|
143
|
-
|
144
|
-
# Provides a command line configuration wizard for setting up the necessary configuration
|
145
|
-
# file.
|
146
|
-
def config_wizard(config_file)
|
147
|
-
if File.exist?(config_file)
|
148
|
-
input = nil
|
149
|
-
until input
|
150
|
-
input = user_input("Configuration file '#{config_file}' already exists. Do you want to overwrite it?", 'yN')
|
151
|
-
return if input =~ /^(?:n|N|yN)$/
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
puts 'This wizard will guide you through an initial configuration for'\
|
156
|
-
' the ruby-grafana-reporter. The configuration file will be created'\
|
157
|
-
' in the current folder. Please make sure to specify necessary paths'\
|
158
|
-
' either with a relative or an absolute path properly.'
|
159
|
-
puts
|
160
|
-
puts "Wizard is creating configuration file '#{config_file}'."
|
161
|
-
puts
|
162
|
-
port = ui_config_port
|
163
|
-
grafana = ui_config_grafana
|
164
|
-
templates = ui_config_templates_folder
|
165
|
-
reports = ui_config_reports_folder
|
166
|
-
images = ui_config_images_folder(templates)
|
167
|
-
retention = ui_config_retention
|
168
|
-
|
169
|
-
config_yaml = %(# This configuration has been built with the configuration wizard.
|
170
|
-
|
171
|
-
#{grafana}
|
172
|
-
|
173
|
-
grafana-reporter:
|
174
|
-
report-class: GrafanaReporter::Asciidoctor::Report
|
175
|
-
templates-folder: #{templates}
|
176
|
-
reports-folder: #{reports}
|
177
|
-
report-retention: #{retention}
|
178
|
-
webservice-port: #{port}
|
179
|
-
|
180
|
-
default-document-attributes:
|
181
|
-
imagesdir: #{images}
|
182
|
-
# feel free to add here additional asciidoctor document attributes which are applied to all your templates
|
183
|
-
)
|
184
|
-
|
185
|
-
begin
|
186
|
-
File.write(config_file, config_yaml, mode: 'w')
|
187
|
-
puts 'Configuration file successfully created.'
|
188
|
-
rescue StandardError => e
|
189
|
-
raise e
|
190
|
-
end
|
191
|
-
|
192
|
-
config = Configuration.new
|
193
|
-
begin
|
194
|
-
config.config = YAML.load_file(config_file)
|
195
|
-
puts 'Configuration file validated successfully.'
|
196
|
-
rescue StandardError => e
|
197
|
-
raise ConfigurationError, "Could not read config file '#{config_file}' (Error: #{e.message})\n"\
|
198
|
-
"Source:\n#{File.read(config_file)}"
|
199
|
-
end
|
200
|
-
|
201
|
-
# create a demo report
|
202
|
-
unless Dir.exist?(config.templates_folder)
|
203
|
-
puts "Skip creation of DEMO template, as folder '#{config.templates_folder}' does not exist."
|
204
|
-
return
|
205
|
-
end
|
206
|
-
demo_report = %(= First Grafana Report Template
|
207
|
-
|
208
|
-
include::grafana_help[]
|
209
|
-
|
210
|
-
include::grafana_environment[])
|
211
|
-
|
212
|
-
demo_report_file = "#{config.templates_folder}demo_report.adoc"
|
213
|
-
if File.exist?(demo_report_file)
|
214
|
-
puts "Skip creation of DEMO template, as file '#{demo_report_file}' already exists."
|
215
|
-
else
|
216
|
-
begin
|
217
|
-
File.write(demo_report_file, demo_report, mode: 'w')
|
218
|
-
puts "DEMO template '#{demo_report_file}' successfully created."
|
219
|
-
rescue StandardError => e
|
220
|
-
raise e
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
puts
|
225
|
-
puts 'Now everything is setup properly. To create an initial report including a manual of all reporter '\
|
226
|
-
'capabilities with the newly created configuration, call the following command:'
|
227
|
-
puts
|
228
|
-
puts " ruby-grafana-reporter -c #{config_file} -t #{demo_report_file} -o demo_report_with_help.pdf"
|
229
|
-
puts
|
230
|
-
puts 'To start the reporter as a service, call the following command:'
|
231
|
-
puts
|
232
|
-
puts " ruby-grafana-reporter -c #{config_file}"
|
233
|
-
puts
|
234
|
-
puts "Open 'http://localhost:#{config.webserver_port}/render?var-template=demo_report' in a webbrowser to"
|
235
|
-
puts 'verify your configuration.'
|
236
|
-
end
|
237
|
-
|
238
|
-
def ui_config_grafana
|
239
|
-
valid = false
|
240
|
-
url = nil
|
241
|
-
api_key = nil
|
242
|
-
datasources = ''
|
243
|
-
until valid
|
244
|
-
url ||= user_input('Specify grafana host', 'http://localhost:3000')
|
245
|
-
print "Testing connection to '#{url}' #{api_key ? '_with_' : '_without_'} API key..."
|
246
|
-
begin
|
247
|
-
res = Grafana::Grafana.new(url,
|
248
|
-
api_key,
|
249
|
-
logger: config.logger).test_connection
|
250
|
-
rescue StandardError => e
|
251
|
-
puts
|
252
|
-
puts e.message
|
253
|
-
end
|
254
|
-
puts 'done.'
|
255
|
-
|
256
|
-
case res
|
257
|
-
when 'Admin'
|
258
|
-
valid = true
|
259
|
-
|
260
|
-
when 'NON-Admin'
|
261
|
-
print 'Access to grafana is permitted as NON-Admin. Do you want to use an [a]pi key,'\
|
262
|
-
' configure [d]atasource manually, [r]e-enter api key or [i]gnore? [adRi]: '
|
263
|
-
|
264
|
-
case gets
|
265
|
-
when /(?:i|I)$/
|
266
|
-
valid = true
|
267
|
-
|
268
|
-
when /(?:a|A)$/
|
269
|
-
print 'Enter API key: '
|
270
|
-
api_key = gets.sub(/\n$/, '')
|
271
|
-
|
272
|
-
when /(?:r|R|adRi)$/
|
273
|
-
api_key = nil
|
274
|
-
|
275
|
-
when /(?:d|D)$/
|
276
|
-
valid = true
|
277
|
-
datasources = ui_config_datasources
|
278
|
-
|
279
|
-
end
|
280
|
-
|
281
|
-
else
|
282
|
-
print "Grafana could not be accessed at '#{url}'. Do you want do [r]e-enter url, or"\
|
283
|
-
' [i]gnore and proceed? [Ri]: '
|
284
|
-
|
285
|
-
case gets
|
286
|
-
when /(?:i|I)$/
|
287
|
-
valid = true
|
288
|
-
|
289
|
-
else
|
290
|
-
url = nil
|
291
|
-
api_key = nil
|
292
|
-
|
293
|
-
end
|
294
|
-
|
295
|
-
end
|
296
|
-
end
|
297
|
-
%(grafana:
|
298
|
-
default:
|
299
|
-
host: #{url}#{api_key ? "\n api_key: #{api_key}" : ''}#{datasources ? "\n#{datasources}" : ''}
|
300
|
-
)
|
301
|
-
end
|
302
|
-
|
303
|
-
def ui_config_datasources
|
304
|
-
finished = false
|
305
|
-
datasources = []
|
306
|
-
until finished
|
307
|
-
item = {}
|
308
|
-
print "Datasource ###{datasources.length + 1}) Enter datasource name as configured in grafana: "
|
309
|
-
item[:ds_name] = gets.sub(/\n$/, '')
|
310
|
-
print "Datasource ###{datasources.length + 1}) Enter datasource id: "
|
311
|
-
item[:ds_id] = gets.sub(/\n$/, '')
|
312
|
-
|
313
|
-
puts
|
314
|
-
selection = user_input("Datasource name: '#{item[:ds_name]}', Datasource id: '#{item[:ds_id]}'."\
|
315
|
-
' [A]ccept, [r]etry or [c]ancel?', 'Arc')
|
316
|
-
|
317
|
-
case selection
|
318
|
-
when /(?:Arc|A|a)$/
|
319
|
-
datasources << item
|
320
|
-
another = user_input('Add [a]nother datasource or [d]one?', 'aD')
|
321
|
-
finished = true if another =~ /(?:d|D)$/
|
322
|
-
|
323
|
-
when /(?:c|C)$/
|
324
|
-
finished = true
|
325
|
-
|
326
|
-
end
|
327
|
-
end
|
328
|
-
" datasources:\n#{datasources.collect { |el| " #{el[:ds_name]}: #{el[:ds_id]}" }.join('\n')}"
|
329
|
-
end
|
330
|
-
|
331
|
-
def ui_config_port
|
332
|
-
input = nil
|
333
|
-
until input
|
334
|
-
input = user_input('Specify port on which reporter shall run', '8815')
|
335
|
-
input = nil unless input =~ /[0-9]+/
|
336
|
-
end
|
337
|
-
input
|
338
|
-
end
|
339
|
-
|
340
|
-
def ui_config_templates_folder
|
341
|
-
input = nil
|
342
|
-
until input
|
343
|
-
input = user_input('Specify path where templates shall be stored', './templates')
|
344
|
-
input = nil unless validate_config_folder(input)
|
345
|
-
end
|
346
|
-
input
|
347
|
-
end
|
348
|
-
|
349
|
-
def ui_config_reports_folder
|
350
|
-
input = nil
|
351
|
-
until input
|
352
|
-
input = user_input('Specify path where created reports shall be stored', './reports')
|
353
|
-
input = nil unless validate_config_folder(input)
|
354
|
-
end
|
355
|
-
input
|
356
|
-
end
|
357
|
-
|
358
|
-
def ui_config_images_folder(parent)
|
359
|
-
input = nil
|
360
|
-
until input
|
361
|
-
input = user_input('Specify path where rendered images shall be stored (relative to templates folder)',
|
362
|
-
'./images')
|
363
|
-
input = nil unless validate_config_folder(File.join(parent, input))
|
364
|
-
end
|
365
|
-
input
|
366
|
-
end
|
367
|
-
|
368
|
-
def ui_config_retention
|
369
|
-
input = nil
|
370
|
-
until input
|
371
|
-
input = user_input('Specify report retention duration in hours', '24')
|
372
|
-
input = nil unless input =~ /[0-9]+/
|
373
|
-
end
|
374
|
-
input
|
375
|
-
end
|
376
|
-
|
377
|
-
def user_input(text, default)
|
378
|
-
print "#{text} [#{default}]: "
|
379
|
-
input = gets.gsub(/\n$/, '')
|
380
|
-
input = default if input.empty?
|
381
|
-
input
|
382
|
-
end
|
383
|
-
|
384
|
-
def validate_config_folder(folder)
|
385
|
-
return true if Dir.exist?(folder)
|
386
|
-
|
387
|
-
print "Directory '#{folder} does not exist: [c]reate, [r]e-enter path or [i]gnore? [cRi]: "
|
388
|
-
case gets
|
389
|
-
when /^(?:c|C)$/
|
390
|
-
begin
|
391
|
-
Dir.mkdir(folder)
|
392
|
-
puts "Directory '#{folder}' successfully created."
|
393
|
-
return true
|
394
|
-
rescue StandardError => e
|
395
|
-
puts "WARN: Directory '#{folder}' could not be created. Please create it manually."
|
396
|
-
puts e.message
|
397
|
-
end
|
398
|
-
|
399
|
-
when /^(?:i|I)$/
|
400
|
-
puts "WARN: Directory '#{folder}' does not exist. Please create manually."
|
401
|
-
return true
|
402
|
-
end
|
403
|
-
|
404
|
-
false
|
405
|
-
end
|
406
156
|
end
|
407
157
|
end
|
408
158
|
end
|