kafo 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kafo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +192 -0
- data/bin/kafo-configure +1 -4
- data/bin/kafo-export-params +92 -68
- data/bin/kafofy +1 -1
- data/lib/kafo/condition.rb +25 -0
- data/lib/kafo/configuration.rb +104 -102
- data/lib/kafo/doc_parser.rb +129 -0
- data/lib/kafo/exceptions.rb +14 -3
- data/lib/kafo/help_builder.rb +3 -0
- data/lib/kafo/help_builders/advanced.rb +19 -0
- data/lib/kafo/help_builders/base.rb +82 -0
- data/lib/kafo/help_builders/basic.rb +12 -0
- data/lib/kafo/hooking.rb +37 -0
- data/lib/kafo/kafo_configure.rb +270 -243
- data/lib/kafo/logger.rb +54 -52
- data/lib/kafo/param.rb +83 -60
- data/lib/kafo/param_builder.rb +69 -45
- data/lib/kafo/param_group.rb +27 -0
- data/lib/kafo/params/array.rb +14 -12
- data/lib/kafo/params/boolean.rb +17 -15
- data/lib/kafo/params/integer.rb +11 -9
- data/lib/kafo/params/password.rb +44 -38
- data/lib/kafo/params/string.rb +8 -2
- data/lib/kafo/password_manager.rb +34 -32
- data/lib/kafo/progress_bar.rb +51 -48
- data/lib/kafo/progress_bars/black_white.rb +11 -9
- data/lib/kafo/progress_bars/colored.rb +20 -18
- data/lib/kafo/puppet_command.rb +34 -36
- data/lib/kafo/puppet_module.rb +92 -68
- data/lib/kafo/puppet_module_parser.rb +63 -60
- data/lib/kafo/string_helper.rb +19 -15
- data/lib/kafo/system_checker.rb +20 -18
- data/lib/kafo/validator.rb +49 -47
- data/lib/kafo/version.rb +1 -1
- data/lib/kafo/wizard.rb +135 -95
- metadata +28 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7361c36d1938a0cb6e0aef8e7ba478e23f8f4af0
|
4
|
+
data.tar.gz: 828ffbb4779539427b3b40b1cb81db900e08820c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11cf281c119c97541a028f364681fc00f7d93b86cb53123cec742b6530412bdf417d5bfc0f9a433e1a0eaf4ecdda1f857752d913a8df40e3fb59cf4c4a9675de
|
7
|
+
data.tar.gz: 872579a93ddff382ce44d83973a6b0eb0971a5fd7adee80733b5b3284416246e00b17ec1907aa006557639e142f0484cac4cf4582b68df648986e02921b43e8e
|
data/README.md
CHANGED
@@ -168,6 +168,40 @@ class foreman (
|
|
168
168
|
}
|
169
169
|
```
|
170
170
|
|
171
|
+
You can separate your parameters into groups like this.
|
172
|
+
|
173
|
+
Example - separating parameters into groups:
|
174
|
+
```puppet
|
175
|
+
# Manage your foreman server
|
176
|
+
#
|
177
|
+
# === Parameters:
|
178
|
+
#
|
179
|
+
# $foreman_url:: URL on which foreman is going to run
|
180
|
+
#
|
181
|
+
# === Advanced parameters:
|
182
|
+
#
|
183
|
+
# $foreman_port:: Foreman listens on this port
|
184
|
+
#
|
185
|
+
# ==== MySQL:
|
186
|
+
#
|
187
|
+
# $mysql_host:: MySQL server address
|
188
|
+
```
|
189
|
+
|
190
|
+
When you run the installer with ```--help``` argument it displays only
|
191
|
+
parameters specified in ```=== Parameters:``` group. If you don't specify
|
192
|
+
any group all parameters will be considered as Basic and will be displayed.
|
193
|
+
|
194
|
+
If you run installer with ```--full-help``` you'll receive help of all
|
195
|
+
parameters divided into groups. Note that only headers that include word
|
196
|
+
parameters are considered as parameter groups. Other headers are ignored.
|
197
|
+
Also note that you can nest parameter groups and the child has precedence.
|
198
|
+
Help output does not take header level into account though.
|
199
|
+
|
200
|
+
So in previous example, each parameter would be printed in one group even
|
201
|
+
though MySQL is a child of Advanced parameter. All groups in help would be
|
202
|
+
prefixed with second level (==). The first level is always a module to which
|
203
|
+
particular parameter belongs.
|
204
|
+
|
171
205
|
## Argument types
|
172
206
|
|
173
207
|
By default all arguments that are parsed from puppet are treated as string.
|
@@ -237,6 +271,125 @@ bin/foreman-installer --puppetmaster-environments=development --puppetmaster-env
|
|
237
271
|
In interactive mode you'll be prompted for another value until you specify
|
238
272
|
blank line.
|
239
273
|
|
274
|
+
## Grouping in interactive mode
|
275
|
+
|
276
|
+
If your module has too much parameters you may find useful grouping. Every
|
277
|
+
block in your documentation (prefixed by header) forms a group. Unlike for
|
278
|
+
help, all block are used in interactive mode. Suppose you have following
|
279
|
+
example:
|
280
|
+
|
281
|
+
```puppet
|
282
|
+
# Testing class
|
283
|
+
#
|
284
|
+
# == Parameters:
|
285
|
+
#
|
286
|
+
# $one:: number one
|
287
|
+
#
|
288
|
+
# == Advanced parameters:
|
289
|
+
#
|
290
|
+
# $two:: number two
|
291
|
+
#
|
292
|
+
# === Advanced A:
|
293
|
+
#
|
294
|
+
# $two_a:: 2_a
|
295
|
+
#
|
296
|
+
# === Advanced 2_b
|
297
|
+
#
|
298
|
+
# $two_b:: 2_b
|
299
|
+
#
|
300
|
+
# == Extra parameters:
|
301
|
+
#
|
302
|
+
# $three:: number three
|
303
|
+
```
|
304
|
+
|
305
|
+
When you enter Testing class module in interactive mode you see parameters
|
306
|
+
from Basic group and options to configure parameters which belongs to rest
|
307
|
+
of groups on same level, in this case Advanced and Extra parameters.
|
308
|
+
|
309
|
+
```
|
310
|
+
Module foreman configuration
|
311
|
+
1. Enable/disable foreman module, current value: true
|
312
|
+
2. Set one, current value: '1'
|
313
|
+
3. Configure Advanced parameters
|
314
|
+
4. Configure Extra parameters
|
315
|
+
5. Back to main menu
|
316
|
+
```
|
317
|
+
|
318
|
+
When you enter Extra paramaters, you see only $three and option to get back
|
319
|
+
to parent. In Advanced you see $two and two more subgroups - Advanced A and
|
320
|
+
Advanced B. When you enter these subgroups, you see their parameters of
|
321
|
+
course. Nesting is unlimited. Also there's no naming rule. Just notice that
|
322
|
+
the main group must be called `Parameters` and it's parameters are always
|
323
|
+
displayed on first level of module configuration.
|
324
|
+
|
325
|
+
```
|
326
|
+
Group Extra parameters (of module foreman)
|
327
|
+
1. Set two_b, current value: '2b'
|
328
|
+
2. Back to parent menu
|
329
|
+
```
|
330
|
+
|
331
|
+
If there's no primary group a new one is created for you and it does not have
|
332
|
+
any parameter. This mean when user enters module configuration he or she will
|
333
|
+
see only subgroups in menu (no parameters until a particular subgroup is entered).
|
334
|
+
If there is no group in documentation a new primary group is created and it
|
335
|
+
holds all module parameters (there are no subgroups in module configuration).
|
336
|
+
|
337
|
+
## Conditional parameters in interactive mode
|
338
|
+
|
339
|
+
You can also define conditions to parameter and their groups. These conditions
|
340
|
+
are evaluated in interactive mode and based on the result they are displayed
|
341
|
+
to the user. You can use this for example to hide mysql_* parameters when
|
342
|
+
$db_type is not set 'mysql'. Let's look at following example
|
343
|
+
|
344
|
+
```puppet
|
345
|
+
# Testing class
|
346
|
+
#
|
347
|
+
# == Parameters:
|
348
|
+
#
|
349
|
+
# $use_db:: use database?
|
350
|
+
# type:boolean
|
351
|
+
#
|
352
|
+
# == Database parameters: condition: $use_db
|
353
|
+
#
|
354
|
+
# $database_type:: mysql/sqlite
|
355
|
+
#
|
356
|
+
# === MySQL: condition: $database_type == 'mysql'
|
357
|
+
#
|
358
|
+
# $remote:: use remote connection
|
359
|
+
# type:boolean
|
360
|
+
# $host server to connect to
|
361
|
+
# condition: $remote
|
362
|
+
# $socket server to connect to
|
363
|
+
# condition: !$remote
|
364
|
+
```
|
365
|
+
|
366
|
+
Here you can see we defined several conditions on group and parameter level.
|
367
|
+
You can write condition in ruby language. All dollar-prefixed words are be
|
368
|
+
substituted by value of a particular puppet parameter.
|
369
|
+
|
370
|
+
Note that conditions are combined using ```&&``` when you nest them. So these
|
371
|
+
are facts based on example:
|
372
|
+
|
373
|
+
* $database_type, $remote, $host, $socket are displayed only when $use_db is set to true
|
374
|
+
* $remote, $host, $socket are displayed only when $database_type is set to 'mysql'
|
375
|
+
* $host is displayed only if $remote is set to true, $socket is displayed otherwise
|
376
|
+
|
377
|
+
Here's explanation how conditions are constructed
|
378
|
+
|
379
|
+
```
|
380
|
+
-----------------------------------------------------------------------------
|
381
|
+
| parameter name | resulting condition |
|
382
|
+
-----------------------------------------------------------------------------
|
383
|
+
| $use_db | true |
|
384
|
+
| $database_type | true && $use_db |
|
385
|
+
| $remote | true && $use_db && $database_type == 'mysql' |
|
386
|
+
| $host | true && $use_db && $database_type == 'mysql' && $remote |
|
387
|
+
| $socket | true && $use_db && $database_type == 'mysql' && !$remote |
|
388
|
+
-----------------------------------------------------------------------------
|
389
|
+
```
|
390
|
+
As already said you can use whatever ruby code, so you could leverage e.g.
|
391
|
+
parentheses, &&, ||, !, and, or
|
392
|
+
|
240
393
|
## Custom modules and manifest names
|
241
394
|
|
242
395
|
By default Kafo expects a common module structure. For example if you add
|
@@ -290,6 +443,45 @@ bin/foreman-installer --foreman-db-password=UNDEF
|
|
290
443
|
|
291
444
|
It also works in interactive mode.
|
292
445
|
|
446
|
+
## Hooks
|
447
|
+
|
448
|
+
You may need to add new features to the installer. Kafo provides simple hook
|
449
|
+
mechanism that allows you to run custom code just before and after the puppet
|
450
|
+
is ran. Let's assume we want to add --reset-foreman-db option to our
|
451
|
+
foreman-installer. We add following lines to generated installer script
|
452
|
+
|
453
|
+
```ruby
|
454
|
+
require 'kafo/hooking'
|
455
|
+
|
456
|
+
# functions specific to foreman installer
|
457
|
+
KafoConfigure.app_option '--reset-foreman-db',
|
458
|
+
:flag, 'Drop foreman database first? You will lose all data!', :default => false
|
459
|
+
|
460
|
+
KafoConfigure.hooking.register_pre(:reset_db) do |kafo|
|
461
|
+
if kafo.config.app[:reset_foreman_db] && !kafo.config.app[:noop]
|
462
|
+
`which foreman-rake > /dev/null 2>&1`
|
463
|
+
if $?.success?
|
464
|
+
KafoConfigure.logger.info 'Dropping database!'
|
465
|
+
output = `foreman-rake db:drop 2>&1`
|
466
|
+
KafoConfigure.logger.debug output.to_s
|
467
|
+
unless $?.success?
|
468
|
+
KafoConfigure.logger.warn "Unable to drop DB, ignoring since it's not fatal, output was: '#{output}''"
|
469
|
+
end
|
470
|
+
else
|
471
|
+
KafoConfigure.logger.warn 'Foreman not installed yet, can not drop database!'
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
```
|
476
|
+
|
477
|
+
Note that we can access other installer options using ```kafo.config.app```. Since ```kafo``` is
|
478
|
+
KafoConfigure instance, you can even access puppet params values. Last but not least you have
|
479
|
+
access to logger.
|
480
|
+
|
481
|
+
You can register as many hooks as you need. They are executed in unspecified order. Every hook
|
482
|
+
must have a unique name. In a very similar way you can register :post hooks that are executed
|
483
|
+
right after puppet run is over.
|
484
|
+
|
293
485
|
## Custom paths
|
294
486
|
|
295
487
|
Usually when you package your installer you want to load files from specific
|
data/bin/kafo-configure
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# TODO cover with tests
|
4
|
-
# TODO validations: "puppet master --compile <fqdn>" compiles a catalog for a given host but it uses the global manifest/modules rather than stdin.. but by specifying --manifestdir you could get it to read a site.pp that contains the "include kafo_configure"
|
5
|
-
|
6
3
|
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'kafo'))
|
7
4
|
require 'kafo_configure'
|
8
|
-
result = KafoConfigure.run
|
5
|
+
result = Kafo::KafoConfigure.run
|
9
6
|
exit result.nil? ? 0 : result.exit_code
|
data/bin/kafo-export-params
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'ostruct'
|
2
4
|
require 'clamp'
|
3
5
|
require 'logging'
|
4
6
|
require 'kafo/string_helper'
|
@@ -8,97 +10,119 @@ require 'configuration'
|
|
8
10
|
|
9
11
|
KafoConfigure = OpenStruct.new
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
module Kafo
|
14
|
+
class KafoExportParams < Clamp::Command
|
15
|
+
TYPES = %w(md html asciidoc)
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
option ['-c', '--config'], 'FILE', 'Config file for which should we generate params',
|
18
|
+
:required => true
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
option ['-f', '--format'], 'FORMAT',
|
21
|
+
'Config file for which should we generate params', :default => 'md' do |format|
|
22
|
+
format = format.downcase
|
23
|
+
raise ArgumentError unless TYPES.include?(format)
|
24
|
+
format
|
25
|
+
end
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
def execute
|
28
|
+
c = Configuration.new(config, false)
|
29
|
+
KafoConfigure.config = c
|
30
|
+
KafoConfigure.root_dir = File.expand_path(c.app[:installer_dir])
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
exporter = self.class.const_get(format.capitalize).new(c)
|
33
|
+
exporter.print_out
|
34
|
+
end
|
32
35
|
|
33
|
-
|
34
|
-
|
36
|
+
class Html
|
37
|
+
include StringHelper
|
35
38
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
def initialize(config)
|
40
|
+
@config = config
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
def print_out
|
44
|
+
puts '<div id="installer-options">'
|
45
|
+
puts ' <table class="table table-bordered table-condensed">'
|
46
|
+
header
|
47
|
+
puts ' <tbody>'
|
48
|
+
|
49
|
+
@config.modules.sort.each do |mod|
|
50
|
+
mod.params.sort.each do |param|
|
51
|
+
puts ' <tr>'
|
52
|
+
puts " <td style='white-space:nowrap'>#{parametrize(param)}</td>"
|
53
|
+
puts " <td>#{param.doc.join(' ')}</td>"
|
54
|
+
puts ' </tr>'
|
55
|
+
end
|
52
56
|
end
|
57
|
+
|
58
|
+
puts ' </tbody>'
|
59
|
+
puts ' </table>'
|
60
|
+
puts '</div>'
|
53
61
|
end
|
54
62
|
|
55
|
-
|
56
|
-
|
57
|
-
|
63
|
+
private
|
64
|
+
|
65
|
+
def header
|
66
|
+
puts ' <thead>'
|
67
|
+
puts ' <tr>'
|
68
|
+
puts ' <th>Option</th>'
|
69
|
+
puts ' <th>Description</th>'
|
70
|
+
puts ' </tr>'
|
71
|
+
puts ' </thead>'
|
72
|
+
end
|
58
73
|
end
|
59
74
|
|
60
|
-
|
75
|
+
class Asciidoc
|
76
|
+
include StringHelper
|
77
|
+
|
78
|
+
def initialize(config)
|
79
|
+
@config = config
|
80
|
+
end
|
61
81
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
82
|
+
def print_out
|
83
|
+
@config.modules.sort.each do |mod|
|
84
|
+
puts "Parameters for '#{mod}'\n:"
|
85
|
+
mod.params.sort.each do |param|
|
86
|
+
puts "#{parametrize(param)}::"
|
87
|
+
puts param.doc.join("\n")
|
88
|
+
puts "\n"
|
89
|
+
end
|
90
|
+
puts "\n"
|
91
|
+
end
|
92
|
+
end
|
69
93
|
end
|
70
|
-
end
|
71
94
|
|
72
|
-
|
73
|
-
|
95
|
+
class Md
|
96
|
+
include StringHelper
|
74
97
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
98
|
+
def initialize(config)
|
99
|
+
@config = config
|
100
|
+
@max = max_description_length
|
101
|
+
end
|
79
102
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
103
|
+
def print_out
|
104
|
+
puts "| #{('Parameter name').ljust(40)} | #{'Description'.ljust(@max)} |"
|
105
|
+
puts "| #{'-'*40} | #{'-' * @max} |"
|
106
|
+
@config.modules.sort.each do |mod|
|
107
|
+
mod.params.sort.each do |param|
|
108
|
+
puts "| #{parametrize(param).ljust(40)} | #{param.doc.join(' ').ljust(@max)} |"
|
109
|
+
end
|
86
110
|
end
|
87
111
|
end
|
88
|
-
end
|
89
112
|
|
90
|
-
|
113
|
+
private
|
91
114
|
|
92
|
-
|
93
|
-
|
94
|
-
|
115
|
+
def header
|
116
|
+
@header ||= "| #{'-'*40} | #{'-' * @max} |"
|
117
|
+
end
|
95
118
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
119
|
+
def max_description_length
|
120
|
+
doc_lengths = @config.modules.map { |mod| mod.params.map { |param| param.doc.join(' ').length } }.flatten
|
121
|
+
doc_lengths << 52
|
122
|
+
doc_lengths.max
|
123
|
+
end
|
100
124
|
end
|
101
125
|
end
|
102
126
|
end
|
103
127
|
|
104
|
-
KafoExportParams.run
|
128
|
+
Kafo::KafoExportParams.run
|
data/bin/kafofy
CHANGED
@@ -24,7 +24,7 @@ if ARGV.size > 0
|
|
24
24
|
require 'rubygems'
|
25
25
|
require 'kafo'
|
26
26
|
CONFIG_FILE = "/etc/#{name}/#{name}.yaml"
|
27
|
-
result = KafoConfigure.run
|
27
|
+
result = Kafo::KafoConfigure.run
|
28
28
|
exit result.nil? ? 0 : result.exit_code
|
29
29
|
EOS
|
30
30
|
File.open(script_name, 'w') { |file| file.write(content) }
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Kafo
|
3
|
+
class Condition
|
4
|
+
VARIABLE_RE = /(\$\w+)/
|
5
|
+
|
6
|
+
def initialize(expression, context = [])
|
7
|
+
@expression = expression
|
8
|
+
@context = context
|
9
|
+
end
|
10
|
+
|
11
|
+
def evaluate
|
12
|
+
!!eval(substitute(@expression))
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def substitute(expression)
|
18
|
+
expression.gsub(VARIABLE_RE) do |variable|
|
19
|
+
param = @context.detect { |p| p.name == $1.tr('$','') }
|
20
|
+
raise ConditionError, "can't substitute #{$1}, unknown parameter with such name" if param.nil?
|
21
|
+
variable.gsub!($1, param.condition_value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|