ruby-grafana-reporter 0.1.6 → 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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +0 -0
  3. data/README.md +95 -173
  4. data/bin/ruby-grafana-reporter +5 -0
  5. data/lib/VERSION.rb +5 -3
  6. data/lib/grafana/abstract_panel_query.rb +22 -20
  7. data/lib/grafana/abstract_query.rb +132 -127
  8. data/lib/grafana/abstract_sql_query.rb +51 -42
  9. data/lib/grafana/dashboard.rb +77 -66
  10. data/lib/grafana/errors.rb +66 -61
  11. data/lib/grafana/grafana.rb +133 -131
  12. data/lib/grafana/panel.rb +41 -39
  13. data/lib/grafana/panel_image_query.rb +52 -49
  14. data/lib/grafana/variable.rb +217 -259
  15. data/lib/grafana_reporter/abstract_report.rb +112 -109
  16. data/lib/grafana_reporter/application/application.rb +158 -229
  17. data/lib/grafana_reporter/application/errors.rb +33 -30
  18. data/lib/grafana_reporter/application/webservice.rb +230 -0
  19. data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +101 -99
  20. data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +96 -96
  21. data/lib/grafana_reporter/asciidoctor/errors.rb +40 -37
  22. data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +92 -86
  23. data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +91 -86
  24. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +69 -67
  25. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +68 -65
  26. data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +61 -58
  27. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +78 -75
  28. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +73 -70
  29. data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +20 -18
  30. data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +43 -41
  31. data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +30 -202
  32. data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +70 -67
  33. data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +66 -65
  34. data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +88 -57
  35. data/lib/grafana_reporter/asciidoctor/help.rb +435 -0
  36. data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +36 -32
  37. data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +28 -23
  38. data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +44 -43
  39. data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +40 -36
  40. data/lib/grafana_reporter/asciidoctor/query_mixin.rb +312 -309
  41. data/lib/grafana_reporter/asciidoctor/report.rb +179 -159
  42. data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +42 -34
  43. data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +44 -32
  44. data/lib/grafana_reporter/configuration.rb +304 -326
  45. data/lib/grafana_reporter/console_configuration_wizard.rb +269 -0
  46. data/lib/grafana_reporter/errors.rb +48 -38
  47. data/lib/grafana_reporter/logger/two_way_logger.rb +58 -52
  48. data/lib/ruby-grafana-reporter.rb +32 -27
  49. metadata +116 -16
@@ -1,109 +1,112 @@
1
- module GrafanaReporter
2
- # @abstract Override {#create_report} and {#progress}.
3
- #
4
- # This class is used to build a report on basis of a given configuration and
5
- # template.
6
- #
7
- # Objects of this class are also stored in {Application::Application}, unless
8
- # the retention time is over.
9
- class AbstractReport
10
- # @return [String] path to the template
11
- attr_reader :template
12
-
13
- # @return [Time] time, when the report generation started
14
- attr_reader :start_time
15
-
16
- # @return [Time] time, when the report generation ended
17
- attr_reader :end_time
18
-
19
- # @return [Logger] logger object used during report generation
20
- attr_reader :logger
21
-
22
- # @return [Boolean] true, if the report is or shall be cancelled
23
- attr_reader :cancel
24
-
25
- # @return [Boolen] true, if the report generation is finished (successfull or not)
26
- attr_reader :done
27
-
28
- # @param config [Configuration] configuration object
29
- # @param template [String] path to the template to be used
30
- # @param destination_file_or_path [String or File] path to the destination report or file object to use
31
- # @param custom_attributes [Hash] custom attributes, which shall be merged with priority over the configuration
32
- def initialize(config, template, destination_file_or_path = nil, custom_attributes = {})
33
- @config = config
34
- @logger = Logger::TwoWayDelegateLogger.new
35
- @logger.additional_logger = @config.logger
36
- @done = false
37
- @template = template
38
- @destination_file_or_path = destination_file_or_path
39
- @custom_attributes = custom_attributes
40
- @start_time = nil
41
- @end_time = nil
42
- @cancel = false
43
- raise MissingTemplateError, @template.to_s unless File.exist?(@template.to_s)
44
- end
45
-
46
- # Call to request cancelling the report generation.
47
- # @return [void]
48
- def cancel!
49
- @cancel = true
50
- logger.info('Cancelling report generation invoked.')
51
- end
52
-
53
- # @return [String] path to the report destination file
54
- def path
55
- @destination_file_or_path.respond_to?(:path) ? @destination_file_or_path.path : @destination_file_or_path
56
- end
57
-
58
- # Deletes the report file object.
59
- # @return [void]
60
- def delete_file
61
- if @destination_file_or_path.is_a?(Tempfile)
62
- @destination_file_or_path.unlink
63
- elsif @destination_file_or_path.is_a?(File)
64
- @destination_file_or_path.delete
65
- end
66
- @destination_file_or_path = nil
67
- end
68
-
69
- # @return [Float] time in seconds, that the report generation took
70
- def execution_time
71
- return nil if start_time.nil?
72
- return end_time - start_time unless end_time.nil?
73
-
74
- Time.now - start_time
75
- end
76
-
77
- # @return [Array] error messages during report generation.
78
- def error
79
- @error || []
80
- end
81
-
82
- # @return [String] status of the report, one of 'in progress', 'cancelled', 'died' or 'finished'.
83
- def status
84
- return 'cancelled' if done && cancel
85
- return 'finished' if done && error.empty?
86
- return 'died' if done && !error.empty?
87
-
88
- 'in progress'
89
- end
90
-
91
- # @return [String] string containing all messages ([Logger::Severity::DEBUG]) of the logger during report generation.
92
- def full_log
93
- logger.internal_messages
94
- end
95
-
96
- # @abstract
97
- # Is being called to start the report generation.
98
- # @return [void]
99
- def create_report
100
- raise NotImplementedError
101
- end
102
-
103
- # @abstract
104
- # @return [Integer] number between 0 and 100, representing the current progress of the report creation.
105
- def progress
106
- raise NotImplementedError
107
- end
108
- end
109
- end
1
+ # frozen_string_literal: true
2
+
3
+ module GrafanaReporter
4
+ # @abstract Override {#create_report} and {#progress}.
5
+ #
6
+ # This class is used to build a report on basis of a given configuration and
7
+ # template.
8
+ #
9
+ # Objects of this class are also stored in {Application::Application}, unless
10
+ # the retention time is over.
11
+ class AbstractReport
12
+ # @return [String] path to the template
13
+ attr_reader :template
14
+
15
+ # @return [Time] time, when the report generation started
16
+ attr_reader :start_time
17
+
18
+ # @return [Time] time, when the report generation ended
19
+ attr_reader :end_time
20
+
21
+ # @return [Logger] logger object used during report generation
22
+ attr_reader :logger
23
+
24
+ # @return [Boolean] true, if the report is or shall be cancelled
25
+ attr_reader :cancel
26
+
27
+ # @return [Boolen] true, if the report generation is finished (successfull or not)
28
+ attr_reader :done
29
+
30
+ # @param config [Configuration] configuration object
31
+ # @param template [String] path to the template to be used
32
+ # @param destination_file_or_path [String or File] path to the destination report or file object to use
33
+ # @param custom_attributes [Hash] custom attributes, which shall be merged with priority over the configuration
34
+ def initialize(config, template, destination_file_or_path = nil, custom_attributes = {})
35
+ @config = config
36
+ @logger = Logger::TwoWayDelegateLogger.new
37
+ @logger.additional_logger = @config.logger
38
+ @done = false
39
+ @template = template
40
+ @destination_file_or_path = destination_file_or_path
41
+ @custom_attributes = custom_attributes
42
+ @start_time = nil
43
+ @end_time = nil
44
+ @cancel = false
45
+ raise MissingTemplateError, @template.to_s unless File.exist?(@template.to_s)
46
+ end
47
+
48
+ # Call to request cancelling the report generation.
49
+ # @return [void]
50
+ def cancel!
51
+ @cancel = true
52
+ logger.info('Cancelling report generation invoked.')
53
+ end
54
+
55
+ # @return [String] path to the report destination file
56
+ def path
57
+ @destination_file_or_path.respond_to?(:path) ? @destination_file_or_path.path : @destination_file_or_path
58
+ end
59
+
60
+ # Deletes the report file object.
61
+ # @return [void]
62
+ def delete_file
63
+ if @destination_file_or_path.is_a?(Tempfile)
64
+ @destination_file_or_path.unlink
65
+ elsif @destination_file_or_path.is_a?(File)
66
+ @destination_file_or_path.delete
67
+ end
68
+ @destination_file_or_path = nil
69
+ end
70
+
71
+ # @return [Float] time in seconds, that the report generation took
72
+ def execution_time
73
+ return nil if start_time.nil?
74
+ return end_time - start_time unless end_time.nil?
75
+
76
+ Time.now - start_time
77
+ end
78
+
79
+ # @return [Array] error messages during report generation.
80
+ def error
81
+ @error || []
82
+ end
83
+
84
+ # @return [String] status of the report, one of 'in progress', 'cancelled', 'died' or 'finished'.
85
+ def status
86
+ return 'cancelled' if done && cancel
87
+ return 'finished' if done && error.empty?
88
+ return 'died' if done && !error.empty?
89
+
90
+ 'in progress'
91
+ end
92
+
93
+ # @return [String] string containing all messages ([Logger::Severity::DEBUG]) of the logger during report
94
+ # generation.
95
+ def full_log
96
+ logger.internal_messages
97
+ end
98
+
99
+ # @abstract
100
+ # Is being called to start the report generation.
101
+ # @return [void]
102
+ def create_report
103
+ raise NotImplementedError
104
+ end
105
+
106
+ # @abstract
107
+ # @return [Integer] number between 0 and 100, representing the current progress of the report creation.
108
+ def progress
109
+ raise NotImplementedError
110
+ end
111
+ end
112
+ end
@@ -1,229 +1,158 @@
1
- module GrafanaReporter
2
- # This module contains all classes, which are used by the grafana reporter
3
- # application. The application is a set of classes, which allows to run the
4
- # reporter in several ways.
5
- #
6
- # If you intend to use the reporter functionality, without the application,
7
- # it might be helpful to not use the classes from here.
8
- module Application
9
- # This class contains the main application to run the grafana reporter.
10
- #
11
- # It can be run to test the grafana connection, render a single template
12
- # or run as a service.
13
- class Application
14
- def initialize
15
- @logger = ::Logger.new(STDERR, level: :unknown)
16
- @reports = []
17
- end
18
-
19
- # Can be used to set a {Configuration} object to the application.
20
- #
21
- # This is mainly helpful in testing the application or in an
22
- # integrated use.
23
- # @param config {Configuration} configuration to be used by the application
24
- # @return [void]
25
- def config=(config)
26
- @logger = config.logger || @logger
27
- @config = config
28
- end
29
-
30
- # This is the main method, which is called, if the application is
31
- # run in standalone mode.
32
- # @param params [Array] normally the ARGV command line parameters
33
- # @return [Integer] see {#run}
34
- def configure_and_run(params = [])
35
- config = GrafanaReporter::Configuration.new
36
- config.logger.level = ::Logger::Severity::INFO
37
- result = config.configure_by_command_line(params)
38
- return result if result != 0
39
-
40
- self.config = config
41
- run
42
- end
43
-
44
- # Runs the application with the current set {Configuration} object.
45
- # @return [Integer] value smaller than 0, if error. 0 if successfull
46
- def run
47
- begin
48
- @config.validate
49
- rescue ConfigurationError => e
50
- puts e.message
51
- return -2
52
- end
53
-
54
- case @config.mode
55
- when Configuration::MODE_CONNECTION_TEST
56
- res = Grafana::Grafana.new(@config.grafana_host(@config.test_instance), @config.grafana_api_key(@config.test_instance), logger: @logger).test_connection
57
- puts res
58
-
59
- when Configuration::MODE_SINGLE_RENDER
60
- @config.report_class.new(@config, @config.template, @config.to_file).create_report
61
-
62
- when Configuration::MODE_SERVICE
63
- run_webserver
64
- end
65
- 0
66
- end
67
-
68
- private
69
-
70
- def clean_outdated_temporary_reports
71
- clean_time = Time.now - 60 * 60 * @config.report_retention
72
- @reports.select { |report| report.done && clean_time > report.end_time }.each do |report|
73
- @reports.delete(report).delete_file
74
- end
75
- end
76
-
77
- def run_webserver
78
- # start webserver
79
- server = TCPServer.new(@config.webserver_port)
80
- @logger.info("Server listening on port #{@config.webserver_port}...")
81
-
82
- @progress_reporter = Thread.new {}
83
-
84
- loop do
85
- # step 1) accept incoming connection
86
- socket = server.accept
87
-
88
- # step 2) print the request headers (separated by a blank line e.g. \r\n)
89
- request = ''
90
- line = ''
91
- begin
92
- until line == "\r\n"
93
- line = socket.readline
94
- request += line
95
- end
96
- rescue EOFError => e
97
- @logger.debug("Webserver EOFError: #{e.message}")
98
- end
99
-
100
- begin
101
- response = handle_request(request)
102
- socket.write response
103
- rescue WebserviceUnknownPathError => e
104
- @logger.debug(e.message)
105
- socket.write http_response(404, '', e.message)
106
- rescue MissingTemplateError => e
107
- @logger.error(e.message)
108
- socket.write http_response(400, 'Bad Request', e.message)
109
- rescue WebserviceGeneralRenderingError => e
110
- @logger.fatal(e.message)
111
- socket.write http_response(400, 'Bad Request', e.message)
112
- rescue StandardError => e
113
- @logger.fatal(e.message)
114
- socket.write http_response(400, 'Bad Request', e.message)
115
- ensure
116
- socket.close
117
- end
118
-
119
- unless @progress_reporter.alive?
120
- @progress_reporter = Thread.new do
121
- running_reports = @reports.reject(&:done)
122
- until running_reports.empty?
123
- @logger.info("#{running_reports.length} report(s) in progress: #{running_reports.map { |report| (report.progress * 100).to_i.to_s + '% (running ' + report.execution_time.to_i.to_s + ' secs)' }.join(', ')}") unless running_reports.empty?
124
- sleep 5
125
- running_reports = @reports.reject(&:done)
126
- end
127
- # puts "no more running reports - stopping to report progress"
128
- end
129
- end
130
-
131
- clean_outdated_temporary_reports
132
- end
133
- end
134
-
135
- def handle_request(request)
136
- raise WebserviceUnknownPathError, request.split("\r\n")[0] if request.nil?
137
- raise WebserviceUnknownPathError, request.split("\r\n")[0] if request.split("\r\n")[0].nil?
138
-
139
- query_string = request.split("\r\n")[0].gsub(%r{(?:[^\?]+[\?])(.*)(?: HTTP/.*)$}, '\1')
140
- query_parameters = CGI.parse(query_string)
141
-
142
- @logger.debug("Received request: #{request.split("\r\n")[0]}")
143
- @logger.debug('query_parameters: ' + query_parameters.to_s)
144
-
145
- # read URL parameters
146
- attrs = {}
147
- query_parameters.each do |k, v|
148
- attrs[k] = v.length == 1 ? v[0] : v
149
- end
150
-
151
- if request.split("\r\n")[0] =~ %r{^GET /render[\? ]}
152
- # build report
153
- template_file = @config.templates_folder.to_s + attrs['var-template'].to_s + '.adoc'
154
-
155
- file = Tempfile.new('gf_pdf_', @config.reports_folder)
156
- begin
157
- FileUtils.chmod('+r', file.path)
158
- rescue StandardError => e
159
- @logger.debug("File permissions could not be set for #{file.path}: #{e.message}")
160
- end
161
-
162
- report = @config.report_class.new(@config, template_file, file, attrs)
163
- Thread.new do
164
- report.create_report
165
- end
166
- @reports << report
167
-
168
- return http_response(302, 'Found', nil, Location: "/view_report?report_id=#{report.object_id}")
169
-
170
- elsif request.split("\r\n")[0] =~ %r{^GET /overview[\? ]}
171
- # show overview for current reports
172
- return get_reports_status_as_html(@reports)
173
-
174
- elsif request.split("\r\n")[0] =~ %r{^GET /view_report[\? ]}
175
- # view report if already available, or show status view
176
- report = @reports.select { |r| r.object_id.to_s == attrs['report_id'].to_s }.first
177
- raise WebserviceGeneralRenderingError, 'view_report has been called without valid id' if report.nil?
178
-
179
- # show report status
180
- return get_reports_status_as_html([report]) if !report.done || !report.error.empty?
181
-
182
- # provide report
183
- @logger.debug("Returning PDF report at #{report.path}")
184
- content = File.read(report.path)
185
- return http_response(200, 'OK', content, "Content-Type": 'application/pdf') if content.start_with?("%PDF")
186
- # TODO properly provide file as zip
187
- return http_response(200, 'OK', content, "Content-Type": 'application/octet-stream', "Content-Disposition": "attachment; filename=report.zip")
188
-
189
- elsif request.split("\r\n")[0] =~ %r{^GET /cancel_report[\? ]}
190
- # view report if already available, or show status view
191
- report = @reports.select { |r| r.object_id.to_s == attrs['report_id'].to_s }.first
192
- raise WebserviceGeneralRenderingError, 'cancel_report has been called without valid id' if report.nil?
193
-
194
- report.cancel! unless report.done
195
-
196
- # redirect to view_report page
197
- return http_response(302, 'Found', nil, Location: "/view_report?report_id=#{report.object_id}")
198
-
199
- elsif request.split("\r\n")[0] =~ %r{^GET /view_log[\? ]}
200
- # view report if already available, or show status view
201
- report = @reports.select { |r| r.object_id.to_s == attrs['report_id'].to_s }.first
202
- raise WebserviceGeneralRenderingError, 'view_log has been called without valid id' if report.nil?
203
-
204
- content = report.full_log
205
-
206
- return http_response(200, 'OK', content, "Content-Type": 'text/plain')
207
- end
208
-
209
- raise WebserviceUnknownPathError, request.split("\r\n")[0]
210
- end
211
-
212
- def get_reports_status_as_html(reports)
213
- i = reports.length
214
-
215
- content = '<html><head></head><body><table><thead><th>#</th><th>Start Time</th><th>End Time</th><th>Template</th><th>Execution time</th><th>Status</th><th>Error</th><th>Action</th></thead>' +
216
- reports.reverse.map do |report|
217
- "<tr><td>#{(i -= 1)}</td><td>#{report.start_time}</td><td>#{report.end_time}</td><td>#{report.template}</td><td>#{report.execution_time.to_i} secs</td><td>#{report.status} (#{(report.progress * 100).to_i}%)</td><td>#{report.error.join('<br>')}</td><td>#{!report.done && !report.cancel ? "<a href=\"/cancel_report?report_id=#{report.object_id}\">Cancel</a>&nbsp;" : ''}#{(report.status == 'finished') || (report.status == 'cancelled') ? "<a href=\"/view_report?report_id=#{report.object_id}\">View</a>&nbsp;" : '&nbsp;'}<a href=\"/view_log?report_id=#{report.object_id}\">Log</a></td></tr>"
218
- end.join('') +
219
- '</table></body></html>'
220
-
221
- http_response(200, 'OK', content, "Content-Type": 'text/html')
222
- end
223
-
224
- def http_response(code, text, body, opts = {})
225
- "HTTP/1.1 #{code} #{text}\r\n#{opts.map { |k, v| "#{k}: #{v}" }.join("\r\n")}#{body ? "\r\nContent-Length: #{body.to_s.bytesize}" : ''}\r\n\r\n#{body}"
226
- end
227
- end
228
- end
229
- end
1
+ # frozen_string_literal: true
2
+
3
+ module GrafanaReporter
4
+ # This module contains all classes, which are used by the grafana reporter
5
+ # application. The application is a set of classes, which allows to run the
6
+ # reporter in several ways.
7
+ #
8
+ # If you intend to use the reporter functionality, without the application,
9
+ # it might be helpful to not use the classes from here.
10
+ module Application
11
+ # This class contains the main application to run the grafana reporter.
12
+ #
13
+ # It can be run to test the grafana connection, render a single template
14
+ # or run as a service.
15
+ class Application
16
+ # Default file name for grafana reporter configuration file
17
+ CONFIG_FILE = 'grafana_reporter.config'
18
+
19
+ # Contains the {Configuration} object of the application.
20
+ attr_accessor :config
21
+
22
+ def initialize
23
+ @config = Configuration.new
24
+ end
25
+
26
+ # This is the main method, which is called, if the application is
27
+ # run in standalone mode.
28
+ # @param params [Array<String>] command line parameters, mainly ARGV can be used.
29
+ # @return [Integer] 0 if everything is fine, -1 if execution aborted.
30
+ def configure_and_run(params = [])
31
+ config_file = CONFIG_FILE
32
+ tmp_config = Configuration.new
33
+ action_wizard = false
34
+
35
+ parser = OptionParser.new do |opts|
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
41
+
42
+ opts.on('-c', '--config CONFIG_FILE_NAME', 'Specify custom configuration file,'\
43
+ " instead of #{CONFIG_FILE}.") do |file_name|
44
+ config_file = file_name
45
+ end
46
+
47
+ opts.on('-d', '--debug LEVEL', 'Specify detail level: FATAL, ERROR, WARN, INFO, DEBUG.') do |level|
48
+ tmp_config.set_param('grafana-reporter:debug-level', level)
49
+ end
50
+
51
+ opts.on('-o', '--output FILE', 'Output filename if only a single file is rendered') do |file|
52
+ tmp_config.set_param('to_file', file)
53
+ end
54
+
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
+
59
+ tmp_config.set_param("default-document-attributes:#{list[0]}", list[1])
60
+ end
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
+
71
+ opts.on('--test GRAFANA_INSTANCE', 'test current configuration against given GRAFANA_INSTANCE') do |instance|
72
+ tmp_config.set_param('grafana-reporter:run-mode', 'test')
73
+ tmp_config.set_param('grafana-reporter:test-instance', instance)
74
+ end
75
+
76
+ opts.on('-t', '--template TEMPLATE', 'Render a single ASCIIDOC template to PDF and exit') do |template|
77
+ tmp_config.set_param('grafana-reporter:run-mode', 'single-render')
78
+ tmp_config.set_param('default-document-attributes:var-template', template)
79
+ end
80
+
81
+ opts.on('-w', '--wizard', 'Configuration wizard to prepare environment for the reporter.') do
82
+ action_wizard = true
83
+ end
84
+
85
+ opts.on('-v', '--version', 'Version information') do
86
+ puts GRAFANA_REPORTER_VERSION.join('.')
87
+ return -1
88
+ end
89
+
90
+ opts.on('-h', '--help', 'Show this message') do
91
+ puts opts
92
+ return -1
93
+ end
94
+ end
95
+
96
+ begin
97
+ parser.parse!(params)
98
+ return ConsoleConfigurationWizard.new.start_wizard(config_file, tmp_config) if action_wizard
99
+ rescue ApplicationError => e
100
+ puts e.message
101
+ return -1
102
+ end
103
+
104
+ # abort if config file does not exist
105
+ unless File.exist?(config_file)
106
+ puts "Config file '#{config_file}' does not exist. Consider calling the configuration wizard"\
107
+ ' with option \'-w\' or use \'-h\' to see help message. Aborting.'
108
+ return -1
109
+ end
110
+
111
+ # read config file
112
+ config_hash = nil
113
+ begin
114
+ config_hash = YAML.load_file(config_file)
115
+ rescue StandardError => e
116
+ raise ConfigurationError, "Could not read config file '#{config_file}' (Error: #{e.message})"
117
+ end
118
+
119
+ # merge command line configuration with read config file
120
+ @config.config = config_hash
121
+ @config.merge!(tmp_config)
122
+
123
+ run
124
+ end
125
+
126
+ # Runs the application with the current set {Configuration} object.
127
+ # @return [Integer] value smaller than 0, if error. 0 if successfull
128
+ def run
129
+ begin
130
+ config.validate
131
+ rescue ConfigurationError => e
132
+ puts e.message
133
+ return -2
134
+ end
135
+
136
+ case config.mode
137
+ when Configuration::MODE_CONNECTION_TEST
138
+ res = Grafana::Grafana.new(config.grafana_host(config.test_instance),
139
+ config.grafana_api_key(config.test_instance),
140
+ logger: config.logger, ssl_cert: config.ssl_cert).test_connection
141
+ puts res
142
+
143
+ when Configuration::MODE_SINGLE_RENDER
144
+ begin
145
+ config.report_class.new(config, config.template, config.to_file).create_report
146
+ rescue StandardError => e
147
+ puts e.message
148
+ end
149
+
150
+ when Configuration::MODE_SERVICE
151
+ Webservice.new(config).run
152
+ end
153
+
154
+ 0
155
+ end
156
+ end
157
+ end
158
+ end