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.
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrafanaReporter
4
+ class ConsoleConfigurationWizard
5
+ # Provides a command line configuration wizard for setting up the necessary configuration
6
+ # file.
7
+ # TODO: refactor class
8
+ def start_wizard(config_file, console_config)
9
+ config = Configuration.new
10
+
11
+ return unless overwrite_file(config_file)
12
+
13
+ puts 'This wizard will guide you through an initial configuration for'\
14
+ ' the ruby-grafana-reporter. The configuration file will be created'\
15
+ ' in the current folder. Please make sure to specify necessary paths'\
16
+ ' either with a relative or an absolute path properly.'
17
+ puts
18
+ puts "Wizard is creating configuration file '#{config_file}'."
19
+ puts
20
+ port = ui_config_port
21
+ grafana = ui_config_grafana(console_config)
22
+ templates = ui_config_templates_folder
23
+ reports = ui_config_reports_folder
24
+ images = ui_config_images_folder(templates)
25
+ retention = ui_config_retention
26
+
27
+ config_yaml = %(# This configuration has been built with the configuration wizard.
28
+
29
+ #{grafana}
30
+
31
+ grafana-reporter:
32
+ report-class: GrafanaReporter::Asciidoctor::Report
33
+ templates-folder: #{templates}
34
+ reports-folder: #{reports}
35
+ report-retention: #{retention}
36
+ webservice-port: #{port}
37
+
38
+ default-document-attributes:
39
+ imagesdir: #{images}
40
+ # feel free to add here additional asciidoctor document attributes which are applied to all your templates
41
+ )
42
+
43
+ begin
44
+ File.write(config_file, config_yaml, mode: 'w')
45
+ puts 'Configuration file successfully created.'
46
+ rescue StandardError => e
47
+ raise e
48
+ end
49
+
50
+ begin
51
+ config.config = YAML.load_file(config_file)
52
+ rescue StandardError => e
53
+ raise ConfigurationError, "Could not read config file '#{config_file}' (Error: #{e.message})\n"\
54
+ "Source:\n#{File.read(config_file)}"
55
+ end
56
+
57
+ begin
58
+ config.validate(true)
59
+ puts 'Configuration file validated successfully.'
60
+ rescue ConfigurationError => e
61
+ raise e
62
+ end
63
+
64
+ demo_report = create_demo_report(config)
65
+
66
+ demo_report ||= '<<your_report_name>>'
67
+ config_param = config_file == Application::Application::CONFIG_FILE ? '' : " -c #{config_file}"
68
+ program_call = "#{Gem.ruby} #{$PROGRAM_NAME}"
69
+ program_call = ENV['OCRA_EXECUTABLE'].gsub("#{Dir.pwd}/".gsub('/', '\\'), '') if ENV['OCRA_EXECUTABLE']
70
+
71
+ puts
72
+ puts 'Now everything is setup properly. Create your reports as required in the templates '\
73
+ 'folder and run the reporter either standalone with e.g. the following command:'
74
+ puts
75
+ puts " #{program_call}#{config_param} -t #{demo_report} -o demo_report_with_help.pdf"
76
+ puts
77
+ puts 'or run it as a service using the following command:'
78
+ puts
79
+ puts " #{program_call}#{config_param}"
80
+ puts
81
+ puts "Open 'http://localhost:#{config.webserver_port}/render?var-template=#{demo_report}' in a webbrowser to"\
82
+ ' test your configuration.'
83
+ end
84
+
85
+ private
86
+
87
+ def create_demo_report(config)
88
+ unless Dir.exist?(config.templates_folder)
89
+ puts "Skip creation of DEMO template, as folder '#{config.templates_folder}' does not exist."
90
+ return nil
91
+ end
92
+
93
+ demo_report = 'demo_report'
94
+ demo_report_file = "#{config.templates_folder}#{demo_report}.adoc"
95
+
96
+ # TODO: add question to overwrite file
97
+ if File.exist?(demo_report_file)
98
+ puts "Skip creation of DEMO template, as file '#{demo_report_file}' already exists."
99
+ return demo_report
100
+ end
101
+
102
+ demo_report = %(= First Grafana Report Template
103
+
104
+ include::grafana_help[]
105
+
106
+ include::grafana_environment[])
107
+ begin
108
+ File.write(demo_report_file, demo_report, mode: 'w')
109
+ puts "DEMO template '#{demo_report_file}' successfully created."
110
+ rescue StandardError => e
111
+ puts e.message
112
+ return nil
113
+ end
114
+
115
+ demo_report
116
+ end
117
+
118
+ def ui_config_grafana(config)
119
+ valid = false
120
+ url = nil
121
+ api_key = nil
122
+ until valid
123
+ url ||= user_input('Specify grafana host', 'http://localhost:3000')
124
+ print "Testing connection to '#{url}' #{api_key ? '_with_' : '_without_'} API key..."
125
+ begin
126
+ # TODO: how to handle if ssl access if not working properly?
127
+ res = Grafana::Grafana.new(url,
128
+ api_key,
129
+ logger: config.logger, ssl_cert: config.ssl_cert).test_connection
130
+ rescue StandardError => e
131
+ puts
132
+ puts e.message
133
+ end
134
+ puts 'done.'
135
+
136
+ case res
137
+ when 'Admin'
138
+ valid = true
139
+
140
+ when 'NON-Admin'
141
+ print 'Access to grafana is permitted as NON-Admin. Do you want to use an [a]pi key,'\
142
+ ' [r]e-enter api key or [i]gnore? [aRi]: '
143
+
144
+ case gets
145
+ when /(?:i|I)$/
146
+ valid = true
147
+
148
+ # TODO: what is difference between 'a' and 'r'?
149
+ when /(?:a|A)$/
150
+ print 'Enter API key: '
151
+ api_key = gets.sub(/\n$/, '')
152
+
153
+ when /(?:r|R|adRi)$/
154
+ api_key = nil
155
+
156
+ end
157
+
158
+ # TODO: ask to enter API key, if grafana cannot be accessed without that
159
+ else
160
+ print "Grafana could not be accessed at '#{url}'. Do you want do [r]e-enter url, or"\
161
+ ' [i]gnore and proceed? [Ri]: '
162
+
163
+ case gets
164
+ when /(?:i|I)$/
165
+ valid = true
166
+
167
+ else
168
+ url = nil
169
+ api_key = nil
170
+
171
+ end
172
+
173
+ end
174
+ end
175
+ %(grafana:
176
+ default:
177
+ host: #{url}#{api_key ? "\n api_key: #{api_key}" : ''}}
178
+ )
179
+ end
180
+
181
+ def ui_config_port
182
+ input = nil
183
+ until input
184
+ input = user_input('Specify port on which reporter shall run', '8815')
185
+ input = nil unless input =~ /[0-9]+/
186
+ end
187
+ input
188
+ end
189
+
190
+ def ui_config_templates_folder
191
+ input = nil
192
+ until input
193
+ input = user_input('Specify path where templates shall be stored', './templates')
194
+ input = nil unless validate_config_folder(input)
195
+ end
196
+ input
197
+ end
198
+
199
+ def ui_config_reports_folder
200
+ input = nil
201
+ until input
202
+ input = user_input('Specify path where created reports shall be stored', './reports')
203
+ input = nil unless validate_config_folder(input)
204
+ end
205
+ input
206
+ end
207
+
208
+ def ui_config_images_folder(parent)
209
+ input = nil
210
+ until input
211
+ input = user_input('Specify path where rendered images shall be stored (relative to templates folder)',
212
+ './images')
213
+ input = nil unless validate_config_folder(File.join(parent, input))
214
+ end
215
+ input
216
+ end
217
+
218
+ def ui_config_retention
219
+ input = nil
220
+ until input
221
+ input = user_input('Specify report retention duration in hours', '24')
222
+ input = nil unless input =~ /[0-9]+/
223
+ end
224
+ input
225
+ end
226
+
227
+ def user_input(text, default)
228
+ print "#{text} [#{default}]: "
229
+ input = gets.gsub(/\n$/, '')
230
+ input = default if input.empty?
231
+ input
232
+ end
233
+
234
+ def validate_config_folder(folder)
235
+ return true if Dir.exist?(folder)
236
+
237
+ print "Directory '#{folder} does not exist: [c]reate, [r]e-enter path or [i]gnore? [cRi]: "
238
+ case gets
239
+ when /^(?:c|C)$/
240
+ begin
241
+ Dir.mkdir(folder)
242
+ puts "Directory '#{folder}' successfully created."
243
+ return true
244
+ rescue StandardError => e
245
+ puts "WARN: Directory '#{folder}' could not be created. Please create it manually."
246
+ puts e.message
247
+ end
248
+
249
+ when /^(?:i|I)$/
250
+ puts "WARN: Directory '#{folder}' does not exist. Please create manually."
251
+ return true
252
+ end
253
+
254
+ false
255
+ end
256
+
257
+ def overwrite_file(config_file)
258
+ return true unless File.exist?(config_file)
259
+
260
+ input = nil
261
+ until input
262
+ input = user_input("Configuration file '#{config_file}' already exists. Do you want to overwrite it?", 'yN')
263
+ return false if input =~ /^(?:n|N|yN)$/
264
+ end
265
+
266
+ true
267
+ end
268
+ end
269
+ end
@@ -18,6 +18,9 @@ require 'asciidoctor-pdf'
18
18
  require 'zip'
19
19
  require_relative 'VERSION'
20
20
 
21
+ # TODO: automatically build a template based on configured grafana dashboard
22
+ # TODO: add an sample report to github from grafana play (if permitted)
23
+
21
24
  folders = [
22
25
  %w[grafana],
23
26
  %w[grafana_reporter logger],
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-grafana-reporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Kohlmeyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-30 00:00:00.000000000 Z
11
+ date: 2021-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -152,6 +152,7 @@ files:
152
152
  - "./lib/grafana_reporter/asciidoctor/sql_first_value_query.rb"
153
153
  - "./lib/grafana_reporter/asciidoctor/sql_table_query.rb"
154
154
  - "./lib/grafana_reporter/configuration.rb"
155
+ - "./lib/grafana_reporter/console_configuration_wizard.rb"
155
156
  - "./lib/grafana_reporter/errors.rb"
156
157
  - "./lib/grafana_reporter/logger/two_way_logger.rb"
157
158
  - "./lib/ruby-grafana-reporter.rb"