kafo 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +11 -0
  3. data/README.md +1149 -0
  4. data/Rakefile +19 -0
  5. data/lib/kafo/version.rb +1 -1
  6. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e997beadceb5307a50757065a9b0feb0fcd7d35
4
- data.tar.gz: a2460963b6539e91acecf021935e94bb329dcbab
3
+ metadata.gz: 8ec0d922a71854c5650b1080cacce16dc1f659e8
4
+ data.tar.gz: 5ed8c9e1403dcda982b385143299468ba3a6ef93
5
5
  SHA512:
6
- metadata.gz: bed514715b9f2913a85cdbeee6713f1f1d74d38a311014ebf38b2a3d42c9fc0bc0797656ad063e6346b1e62c4500d14e29ccb5bd3a32082ae63d5218627a2851
7
- data.tar.gz: da303a516a27fb37c9a339198ff0e62a1bc8b3ecfc1f4068d49ef7e93ba6a3c9a4907ad52da45d931b8bf1cda98195eba8fa36c7214fb2abeb119f47d1bb34f0
6
+ metadata.gz: 2f0be8a6c8f02036fc4c10fad23e454cae12f870d2d3e2a9c6338e2a12d0226eb87f6eba3ec30f6da27c5692b137672f97c93acddd81d308e1cbca7df05c7aa6
7
+ data.tar.gz: b42e392dc34a924389c1a9911a72e1a328f7bd29bb0d174e7255abd9b379e501112eb93830b799669d9a6a9abc9b6da09d63556b3d1ed7e7f6d7490e76670815
data/LICENSE.txt ADDED
@@ -0,0 +1,11 @@
1
+ This program and entire repository is free software: you can redistribute it
2
+ and/or modify it under the terms of the GNU General Public License as
3
+ published by the Free Software Foundation, either version 3 of the License,
4
+ or any later version.
5
+
6
+ This program is distributed in the hope that it will be useful, but WITHOUT
7
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9
+
10
+ You should have received a copy of the GNU General Public License along with
11
+ this program. If not, see http://www.gnu.org/licenses/.
data/README.md ADDED
@@ -0,0 +1,1149 @@
1
+ # Kafo
2
+
3
+ A puppet based installer and configurer (not-only) for Foreman and Katello
4
+ projects. Kafo is a ruby gem that allows you to create fancy user interfaces for
5
+ puppet modules. It's some kind of a nice frontend to a
6
+
7
+ ```bash
8
+ echo "include some_modules" | puppet apply
9
+ ```
10
+ ## Why should I care?
11
+
12
+ Suppose you work on software which you want to distribute to a machine in an
13
+ infrastructure managed by puppet. You write a puppet module for your app.
14
+ But now you also want to be able to distribute your app to a machine outside of
15
+ your puppet infrastructure (e.g. install it to your clients) or you want to install
16
+ it in order to create a puppet infrastructure itself (e.g. foreman or
17
+ foreman-proxy).
18
+
19
+ With kafo you can reuse your puppet modules for creating an installer.
20
+ Even better: After the installation you can easily modify your configuration.
21
+ All using the very same puppet modules.
22
+
23
+ With your installer you can also provide multiple configuration files defining
24
+ different installation scenarios.
25
+
26
+ ## What does it do, how does it work?
27
+
28
+ Kafo reads a config file to find out which modules it should use. Then it
29
+ loads parameters from puppet manifests and gives you different ways to customize them.
30
+
31
+ There are three options how you can set parameters. You can
32
+ * predefine them in the configuration file
33
+ * specify them as CLI arguments
34
+ * you can use the interactive mode which will ask you for all required parameters
35
+
36
+ Note that your answers (gathered from any mode) are automatically saved for the next run
37
+ so you don't have to specify them again. Kafo also supports default values for
38
+ parameters so you can set only those you want to change. You can also combine
39
+ all modes to create an answer file with default values easily
40
+ and then use it for unattended installations.
41
+
42
+ ## How do I use it?
43
+
44
+ First install the kafo gem.
45
+
46
+ Using bundler - add kafo gem to your Gemfile and run
47
+ ```bash
48
+ bundle install
49
+ ```
50
+
51
+ or without bundler
52
+ ```bash
53
+ gem install kafo
54
+ ```
55
+
56
+ Create a directory for your installer. Let's say we want to create a
57
+ foreman-installer.
58
+
59
+ ```bash
60
+ mkdir foreman-installer
61
+ cd foreman-installer
62
+ ```
63
+
64
+ Now we run ```kafofy``` script which will prepare the directory structure and
65
+ optionally create a bin script according to the first parameter.
66
+
67
+ ```bash
68
+ kafofy -n foreman-installer -s foreman
69
+ ```
70
+
71
+ You can see that it created a modules directory where your puppet modules
72
+ should live. It also created config and bin directories and the default installation
73
+ scenario config file. If you specify the argument ```--name``` (or -n for short,
74
+ foreman-installer in this case) a script in the "bin" directory with this name will be created.
75
+
76
+ It's the script you can use to run the installer. If you did not specify any
77
+ arguments you can run your installer by `kafo-configure` which is the default.
78
+ All configuration related files are to be found in the config directory.
79
+
80
+ You can supply custom location for your scenario configuration and answer files
81
+ and change configuration and answer files names using options:
82
+ ```
83
+ kafofy --help
84
+ Usage: kafofy [options]
85
+ -c, --config_dir DIR location of the scenarios configuration directory [./config/installer-scenarios.d/]
86
+ -s, --scenario SCENARIO scenario file name (without extension) [default]
87
+ -a, --answer_file ANSWERS answer file file name (without extension) [default-answers]
88
+ -n, --name NAME installer name [kafo-configure]
89
+ ```
90
+
91
+ The scenario configuration file will be created by a default template. It's the configuration
92
+ of your installer (so you can setup the log level, path to puppet modules etc).
93
+ On the other hand, the answer file must be created manually. Answer files define
94
+ which modules should be used and hold all values for the puppet class parameters.
95
+
96
+ To add another installation scenario just run kafofy again:
97
+ ```bash
98
+ kafofy -n foreman-installer -s foreman-proxy
99
+ ```
100
+ it will create new configuration template for you. You can check available scenarios with:
101
+ ```bash
102
+ $ bin/foreman-installer --list-scenarios
103
+ Available scenarios
104
+ foreman-proxy (use: --scenario foreman-proxy)
105
+ foreman (use: --scenario foreman)
106
+ ```
107
+
108
+ Let's see for example how to install foreman:
109
+ ```bash
110
+ cd foreman-installer/modules
111
+ git clone https://github.com/theforeman/puppet-foreman/ foreman
112
+ ```
113
+ You must also download any dependant modules.
114
+ Then you need to tell kafo it's going to use the foreman module.
115
+ ```bash
116
+ cd ..
117
+ echo "foreman: true" > config/installer-scenarios.d/foreman-answers.yaml
118
+ ```
119
+
120
+ Alternatively you can use the librarian-puppet project to manage all dependencies for you.
121
+ You just create a Puppetfile and call librarian to install your modules. See
122
+ https://github.com/rodjek/librarian-puppet for more details.
123
+
124
+ When you have your modules in-place, fire the installer with -h as argument
125
+ and specify the foreman scenario to let installer find the right modules
126
+ ```bash
127
+ bin/foreman-installer -S foreman -h
128
+ ```
129
+
130
+ This will show you all the possible arguments you can pass to kafo. Note that underscored
131
+ puppet parameters are automatically converted to dashed arguments. You can
132
+ also see a documentation extracted from the foreman puppet module and a default
133
+ value.
134
+
135
+ Now run it without the -h argument. It will print you the puppet apply command
136
+ to execute. This will be automatized later. Once the installer is run the scenario
137
+ is remembered and it is not necessary to specify it again.
138
+ Look at config/answers.yaml, it was populated with default values.
139
+ To change those options you can use arguments like this
140
+
141
+ ```bash
142
+ bin/foreman-installer --foreman-enc=false --foreman-db-type=sqlite
143
+ ```
144
+
145
+ or you can run it in interactive mode
146
+
147
+ ```bash
148
+ bin/foreman-installer --interactive
149
+ ```
150
+
151
+ Also every change made to the `config/installer-scenarios.d/foreman-answers.yaml` persists
152
+ and becomes the new default value for the next run.
153
+
154
+ As you may have noticed there are several ways how to specify arguments. Here's the list:
155
+ (the lower the item is in this list the higher precedence it has):
156
+ * default values from puppet modules
157
+ * values from answers.yaml
158
+ * values specified on CLI
159
+ * interactive mode arguments
160
+
161
+ ## Requirements
162
+
163
+ Kafo is supported with Puppet versions 3 and 4. Puppet 2 is no longer supported
164
+ in current versions, use an older version of Kafo or update Puppet.
165
+
166
+ Puppet may be installed as a gem (add it to Gemfile) or through a package,
167
+ including official AIO packages.
168
+
169
+ ## How do I report bugs or contribute?
170
+
171
+ You can find our redmine issue tracker [here](http://projects.theforeman.org/projects/kafo),
172
+ you can use your github account for logging in. When reporting new issues please
173
+ don't forget to specify your:
174
+ * puppet version
175
+ * installation options (GEM/RPM/DEB)
176
+ * error trace (if any) or log with debug level
177
+ * reproducing steps
178
+
179
+ Since Kafo is a side project of Foreman you can use its IRC channels to
180
+ contact us on freenode. #theforeman is the channel for generic discussions
181
+ and #theforeman-dev is reserved only for technical topics. Likewise you can use the Foreman
182
+ mailing lists on googlegroups. For more information see [this page](http://theforeman.org/support.html)
183
+
184
+ Patches are always welcome. You can use instructions for Foreman, just
185
+ substitute Foreman with Kafo. More details are [here](http://projects.theforeman.org/projects/foreman/wiki/Contribute#New-Way-github)
186
+
187
+ # Advanced topics
188
+
189
+ ## Testing aka noop etc
190
+
191
+ Since you'll probably want to tweak your installer before you run it, you may find the
192
+ ```--noop``` argument handy (-n for short). This will run puppet in
193
+ noop so no change will be done to your system. The default value here is set to
194
+ false!
195
+
196
+ Sometimes you may want kafo not to store answers from the current run. You can
197
+ disable saving answer by passing a ```--dont-save-answers``` argument (or -d for short).
198
+
199
+ Note that running ```--noop``` implies ```--dont-save-answers```.
200
+
201
+ ## Executing Puppet with multiple versions
202
+
203
+ Kafo calls the `puppet` binary during an installer run to both compute default
204
+ parameter values and perform the actual installer changes. This relies on
205
+ `puppet` being in the PATH environment variable or as fallback, in
206
+ `/opt/puppetlabs/bin`.
207
+
208
+ When using Puppet via a Gemfile, Bundler should set up PATH to point at the
209
+ gem version. If using a system/packaged version, it will typically find and
210
+ execute /usr/bin/puppet from the regular PATH.
211
+
212
+ When using an AIO/PC1 packaged version of Puppet, other versions of Puppet from
213
+ PATH will be preferred if they exist, so they should either be removed or PATH
214
+ set to prefer /opt/puppetlabs/bin, i.e. `export PATH=/opt/puppetlabs/bin:$PATH`.
215
+ Debug logs from Kafo should indicate the full path of the binary used.
216
+
217
+ Note that Kafo parsers supports specific versions of Puppet, and may require
218
+ extra modules (such as puppet-strings on Puppet 4+) to parse manifests.
219
+
220
+ ## Parameters prefixes
221
+
222
+ As a default every module parameter is prefixed by the module name.
223
+ If you use just one module it's probably not necessary and you
224
+ can disable this behavior in config/kafo.yaml. Just enable the following option
225
+ ```yaml
226
+ :no_prefix: true
227
+ ```
228
+ ## Scenarios
229
+
230
+ With your installer you can provide multiple configuration files aka. scenarios.
231
+ Every scenario has its own answer file to store the scenario settings.
232
+ The files are kept in `installer-scenarios.d/` directory.
233
+
234
+ ### Using scenarios
235
+
236
+ To list scenarios available on your system
237
+ ```bash
238
+ foreman-installer --list-scenarios
239
+ ```
240
+
241
+ The installer needs to know the configuration even for such a basic operation
242
+ as printing help is because it contains basic settings and defines where
243
+ to look for module parameters. There are multiple ways how the installer can select the scenario:
244
+ * from a command line argument `-S` or `--scenario`
245
+ ```bash
246
+ foreman-installer --scenario foreman -h
247
+ ...
248
+ ```
249
+ * by user selection in interractive mode (`-i` or `--interractive`)
250
+ ```bash
251
+ foreman-installer -i
252
+
253
+ Select installation scenario
254
+
255
+ Please select one of the pre-set installation scenarios. You can customize your installtion later during the installtion.
256
+
257
+ Available actions:
258
+ 1. Foreman: Basic and most generic installation of Foreman
259
+ 2. Foreman Proxy: Install Foreman proxy without Foreman
260
+ 3. Cancel Installation
261
+ Your choice:
262
+ ```
263
+ * automatically if there is only one scenario available
264
+ * automatically if installer was ran already with scenario selected
265
+
266
+ ### Re-installing with different scenario
267
+
268
+ Lets assume you have already completed installation with one scenario (e.g. smart-proxy).
269
+ Now you want to reinstall or upgrade with different scenario (e.g. foreman). This is tricky
270
+ situation and may end with unpredictable results so you should double check
271
+ if the scenario and the puppet modules used in it support such kind of change.
272
+
273
+ Installer tries to prevent unintentional change of a scenario and interrupts when such situation is detected:
274
+ ```bash
275
+ foreman-installer -S foreman-installer
276
+ ERROR: You are trying to replace existing installation with different scenario. This may lead to unpredictable states. Use --force to override. You can use --compare-scenarios to see the differences
277
+ ```
278
+
279
+ To avoid losing some configuration values installer can detect differences between answer files of the two scenarios.
280
+ To display them use either interactive mode (`-i`) or `--compare-scenarios` flag:
281
+ ```bash
282
+ foreman-installer --compare-scenarios --scenario foreman
283
+ Scenarios are being compared, that may take a while...
284
+
285
+ Values from previous installation that will be added by installer:
286
+ foreman_proxy::http_port: 8000 -> 8080
287
+
288
+ Values from previous installation that will be lost by scenario change:
289
+ foreman_proxy::plugin::abrt::enabled: true
290
+ ...
291
+ ```
292
+
293
+ It may take some time as the installer has to evaluate default values for both scenarios. As a result it prints two lists.
294
+ - __Values from previous installation that will be added by installer:__ - in this list are options present in both scenarios but having different default values.
295
+ The only item from the example says that the default value for the new scenario is '8000' while the value for currently intalled scenario is '8080'.
296
+ When the new scenario is used the installer tries to keep the customized values from current installation and thus will use the `8080` value
297
+ - __Values from previous installation that will be lost by scenario change:__ - this list contains options that are part of current installation
298
+ and are missing from the new scenario. Most of the items are options from puppet modules that are disabled in the new scenario by default but were enabled
299
+ in the old one.
300
+
301
+ If you are sure you want to proceed use `--force` to run the installation. Installer will replace
302
+ the default values with values from the previous installation where possible as was indicated in the `--compare-scenario` output.
303
+
304
+ ### Adding scenario
305
+
306
+ You can add new scenario using kafofy as it was explained earlier or by creating
307
+ config and answer file in the `installer-scenarios.d/` directory.
308
+ [Template](https://github.com/theforeman/kafo/blob/master/config/kafo.yaml.example)
309
+ provided by Kafo can be used and customized to satisfy your needs
310
+ ```bash
311
+ cp `gem content kafo|grep "kafo.yaml.example"` <config>/installer-scenarios.d/new-scenario.yaml
312
+ touch <config>/installer-scenarios.d/new-scenario-answers.yaml
313
+ ```
314
+
315
+ ### Scenario as an installer plugin
316
+
317
+ Scenarios were designed to make it possible to package them separately as optional installer extension.
318
+ Config files are located in separate directory which makes packaging of additional scenarios easy.
319
+ Configuration of paths to modules, checks and hooks accepts multiple directories
320
+ so it is possible to bundle your scenario with additional modules, hooks and checks.
321
+
322
+ ### Updating scenarios
323
+
324
+ As your project grows you may need to change your installer modules or add new ones. To make upgrades of existing installations easier
325
+ Kafo has support for scenario migrations. Migrations are ruby scripts similar to hooks and are located
326
+ in `<config>/installer-scenarios.d/your-scenario.migrations/` so each scenario has its own set of independent migrations.
327
+ During its initialization the installer checks for migrations that were not applied yet. It happens exactly between execution of `pre-migrations` and `boot` hooks.
328
+ The installer stores names of applied migrations in `<config>/installer-scenarios.d/your-scenario.migrations/.applied` to avoid runnig the migrations multiple times.
329
+ It is recommended to prefix the migration names with `date +%y%m%d%H%M%S` to avoid migration ordering issues.
330
+
331
+ In a migration you can modify the scenario configuration as well as the answer file. The changed configs are stored immediately after all the migrations were applied.
332
+ If you just want to apply the migrations you can use `--migrations-only` switch.
333
+ Note that `--noop` and `--dont-save-answers` has no effect on migrations.
334
+
335
+ Sample migration adding new module could look like as follows:
336
+
337
+ ```bash
338
+ cat <<EOF > "/etc/foreman/installer-scenarios.d/foreman-installer.migrations/`date +%y%m%d%H%M%S`-gutterball.rb"
339
+ scenario[:mapping]['katello::plugin::gutterball'] = {
340
+ :dir_name => 'katello',
341
+ :manifest_name => 'plugin/gutterball'
342
+ }
343
+ answers['katello::plugin::gutterball'] = true
344
+ EOF
345
+ ```
346
+
347
+ The migration can also call `facts`, which returns a hash of symbol fact names to values (from
348
+ Facter), to help determine new parameter values.
349
+
350
+ ```ruby
351
+ answers['module']['foo'] = 'bar' if facts[:osfamily] == 'Debian'
352
+ ```
353
+
354
+ ### Enabling/disabling scenarios
355
+
356
+ Scenarios that are deprecated or wanted to be hidden on the system can be disabled with:
357
+
358
+ ```bash
359
+ foreman-installer --disable-scenario deprecated-scenario
360
+ Scenario deprecated-scenario was disabled.
361
+ ```
362
+ The disabled scenario is not shown in the scenario list and is prevented from being installed.
363
+ It is not deleted from the file system however so the custom values in the answer file are preserved
364
+ and e.g. migration to new scenario is still possible.
365
+
366
+ Disabled scenario can be enabled back again with `foreman-installer --enable-scenario SCENARIO`.
367
+
368
+ ## Store
369
+
370
+ Kafo features simple key value store that can be used to ship data with the installer.
371
+
372
+ The data are loaded from yaml files located in `store.d` directory that is either specified in
373
+ the scenario config's `store_dir:` or on same directory
374
+ level as configuration directory containing the scenarios. The files are loaded in
375
+ alphabetical order and the data are merged in that order.
376
+
377
+ The store is read-only during the run and the content can be influenced only by adding
378
+ new files into the `store.d` directory (e.g. from installer plugins)
379
+
380
+ ## Documentation
381
+
382
+ Every parameter that can be set by kafo *must* be documented. This means that
383
+ you must add documentation to your puppet class in init.pp. It's basically a
384
+ rdoc formatted documentation that must be above the class definitions. There can
385
+ be no space between the doc block and the class definition.
386
+
387
+ In case of emergency, it's still possible to use
388
+ `--ignore-undocumented` option, but in general it's not recommended to override it.
389
+
390
+ Example:
391
+ ```puppet
392
+ # Manage your foreman server
393
+ #
394
+ # This class ...
395
+ # ... does what it does.
396
+ #
397
+ # === Parameters:
398
+ #
399
+ # $foreman_url:: URL on which foreman is going to run
400
+ #
401
+ # $enc:: Should foreman act as an external node classifier (manage puppet class
402
+ # assignments)
403
+ #
404
+ class foreman (
405
+ String $foreman_url = $foreman::params::foreman_url,
406
+ Boolean $enc = $foreman::params::enc
407
+ ) {
408
+ class { 'foreman::install': }
409
+ }
410
+ ```
411
+
412
+ You can separate your parameters into groups like this.
413
+
414
+ Example - separating parameters into groups:
415
+ ```puppet
416
+ # Manage your foreman server
417
+ #
418
+ # === Parameters:
419
+ #
420
+ # $foreman_url:: URL on which foreman is going to run
421
+ #
422
+ # === Advanced parameters:
423
+ #
424
+ # $foreman_port:: Foreman listens on this port
425
+ #
426
+ # ==== MySQL:
427
+ #
428
+ # $mysql_host:: MySQL server address
429
+ ```
430
+
431
+ When you run the installer with the ```--help``` argument it displays only
432
+ parameters specified in the ```=== Parameters:``` group. If you don't specify
433
+ any group all parameters will be considered as basic and will be displayed.
434
+
435
+ If you run the installer with ```--full-help``` you'll receive help for all
436
+ parameters divided into groups. Note that only headers that include word
437
+ parameters are considered as parameter groups. Other headers are ignored.
438
+ Also note that you can nest parameter groups and the child has precedence.
439
+ Help output does not take header level into account though.
440
+
441
+ So in the previous example, each parameter would be printed in one group even
442
+ though MySQL is a child of Advanced parameter. All groups in help would be
443
+ prefixed with a second level (==). The first level is always a module to which
444
+ the particular parameter belongs.
445
+
446
+ ## Argument types
447
+
448
+ When using Puppet 4 or newer, the data type will be read from the parameter
449
+ list and defaults to Puppet's [Any](https://docs.puppet.com/puppet/latest/reference/lang_data_abstract.html#any)
450
+ data type, which Kafo handles as a basic string with no validation.
451
+
452
+ If more specific data types, such as `Optional[Array[2]]` or similar are
453
+ given in the [parameter list](https://docs.puppet.com/puppet/4.5/reference/lang_data_type.html#usage)
454
+ then Kafo will parse and validate parameters values according to the
455
+ specification.
456
+
457
+ ```puppet
458
+ class example (
459
+ Boolean $param = false
460
+ ) {
461
+ ```
462
+
463
+ When using Puppet 3, data types can be specified in the manifest documentation
464
+ rather than the parameter list, like this:
465
+
466
+ ```puppet
467
+ # $param:: Some documentation for param
468
+ type:Array[String]
469
+ ```
470
+
471
+ For compatibility with older Kafo releases, additional types are supported:
472
+ string, boolean, integer, array, password, hash. These are equivalent to their
473
+ Puppet 4 namesakes, plus wrapped in `Optional[..]` to permit `undef`.
474
+
475
+ If the data type is given in both the manifest documentation and the parameter
476
+ list, then the manifest documentation will be preferred.
477
+
478
+ Note that all arguments that are nil (have no value in answers.yaml or you
479
+ set them UNDEF (see below)) are translated to ```undef``` in puppet.
480
+
481
+ If your module declares its own types, you can add new corresponding subclasses
482
+ of DataType which implement validation and typecasting. This can be added to a
483
+ `boot` hook by calling:
484
+
485
+ Kafo::DataType.register_type('YourType', Kafo::DataType::YourType)
486
+
487
+ ## Password arguments
488
+
489
+ Kafo supports password arguments. It's adding some level of protection for your
490
+ passwords. Usually people generate random strings for passwords. However all
491
+ values are stored in config/answers.yaml which may introduce a security risk.
492
+
493
+ If this is something to consider for you, you can use the password type (see
494
+ Argument types for more info how to define parameter type). It will
495
+ generate a secure (random) password with a length of 32 chars and encrypts
496
+ it using AES 256 in CBC mode. It uses a passphrase that is stored in
497
+ config/kafo.yaml so if anyone gets an access to this file, he can read all
498
+ the passwords from the answers.yaml, too. A random password is generated and stored
499
+ if there is none in kafo.yaml yet.
500
+
501
+ When Kafo runs puppet, puppet will read this password from config/kafo.yaml.
502
+ It runs under the same user so it should have read access by default. The Kafo
503
+ puppet module also provides a function that you can use to decrypt such
504
+ parameters. You can use it like this
505
+
506
+ ```erb
507
+ password: <%= scope.function_decrypt([scope.lookupvar("::foreman::db_password"))]) -%>
508
+ ```
509
+
510
+ Also you can take advantage of already encrypted passwords and store since it is
511
+ (encrypted). Your application can decrypt it as long as it knows the
512
+ passphrase. The passphrase can be obtained from $kafo_configure::password.
513
+
514
+ Note that we use a bit extraordinary form of encrypted passwords. All our
515
+ encrypted passwords look like "$1$base64encodeddata". As you can see we
516
+ use the $1$ as prefix by which we can detect that it is our specially encrypted password.
517
+ The form has nothing common with Modular Crypt Format. Also our AES output
518
+ is base64 encoded. To get a password from this format you can do something
519
+ like this in your application
520
+
521
+ ```ruby
522
+ require 'base64'
523
+ encrypted = "$1$base64encodeddata"
524
+ encrypted = encrypted[3..-1] # strip $1$ prefix
525
+ encrypted = Base64.decode64(encrypted) # decode base64 string
526
+ result = aes_decrypt(encrypted) # for example how to implement aes_decrypt see lib/kafo/password_manager.rb
527
+ ```
528
+
529
+ ## Array arguments
530
+
531
+ Some arguments may be Arrays. If you want to specify array values you can
532
+ specify CLI argument multiple times e.g.
533
+ ```bash
534
+ bin/foreman-installer --puppetmaster-environments=development --puppetmaster-environments=production
535
+ ```
536
+
537
+ In interactive mode you'll be prompted for another value until you specify
538
+ blank line.
539
+
540
+ ## Hash arguments
541
+
542
+ You can use a Hash value like an Array. It's also a multivalue type but
543
+ you have to specify a key:value pair like in the following example.
544
+ ```bash
545
+ bin/foreman-installer --puppet-server-git-branch-map=master:some --puppet-server-git-branch-map=development:another
546
+ ```
547
+
548
+ The same applies to the interactive mode, you enter each pair on separate lines
549
+ just like with an Array, the only difference is that the line must be formatted
550
+ as key:value.
551
+
552
+ When parsing the value, the first colon divides key and value. All other
553
+ colons are ignored.
554
+
555
+ ## Default values
556
+
557
+ Default values for parameters are read from the class definitions in the
558
+ manifests. If values are given inline then these will be stored by Kafo as the
559
+ initial value of the parameter (unless set in the answers file or later changed
560
+ by the user), e.g.
561
+
562
+ ```puppet
563
+ class foreman(
564
+ $foreman_url = 'https://example.com'
565
+ ) {
566
+ ```
567
+
568
+ If the "params" pattern is used, where the default parameter values are defined
569
+ in another class then Kafo will attempt to retrieve them by running Puppet,
570
+ using `include` on the params class and then getting the variable value. This
571
+ will retrieve default values set by conditionals correctly, e.g.
572
+
573
+ ```puppet
574
+ class foreman(
575
+ $foreman_url = $::foreman::params::foreman_url,
576
+ ) inherits foreman::params {
577
+ ```
578
+
579
+ ```puppet
580
+ class foreman::params {
581
+ $foreman_url = 'https://example.com'
582
+ }
583
+ ```
584
+
585
+ If no inline default is given in the manifest and on Puppet 4.5+, then Kafo will
586
+ attempt to look up a default value using [data stored in the module](https://docs.puppet.com/puppet/latest/lookup_quick_module.html). This can be specified with Hiera data files (or even a data function) in the
587
+ module under `data/`.
588
+
589
+ ## Resetting an argument
590
+
591
+ Existing stored parameters can be reset back to their default value from the
592
+ command line or interactive mode. This deletes the stored value in the answers
593
+ file and stores the default from the Puppet manifest in its place.
594
+
595
+ The default value is the value set in, or computed by the Puppet params
596
+ manifest. This will _not_ reset to any defaults specified in the answers file
597
+ before running the Kafo-based installer, they are not kept.
598
+
599
+ Using the CLI, a --reset option is available for every parameter, e.g.
600
+
601
+ ```bash
602
+ bin/foreman-installer --reset-puppet-server-git-branch-map
603
+ ```
604
+
605
+ The parameter can also be reset to the default in interactive mode, via the
606
+ reset parameters sub-menu under each module.
607
+
608
+ ## Grouping in interactive mode
609
+
610
+ If your module has too many parameters you may find the grouping feature useful.
611
+ Every block in your documentation (prefixed by header) forms a group. Unlike for
612
+ help, all blocks are used in interactive mode. Suppose you have the following
613
+ example:
614
+
615
+ ```puppet
616
+ # Testing class
617
+ #
618
+ # == Parameters:
619
+ #
620
+ # $one:: number one
621
+ #
622
+ # == Advanced parameters:
623
+ #
624
+ # $two:: number two
625
+ #
626
+ # === Advanced A:
627
+ #
628
+ # $two_a:: 2_a
629
+ #
630
+ # === Advanced 2_b
631
+ #
632
+ # $two_b:: 2_b
633
+ #
634
+ # == Extra parameters:
635
+ #
636
+ # $three:: number three
637
+ ```
638
+
639
+ When you enter the Testing class module in interactive mode you can see parameters
640
+ from the Basic group and options to configure parameters which belong to the rest
641
+ of groups on same level, in this case Advanced and Extra parameters.
642
+
643
+ ```
644
+ Module foreman configuration
645
+ 1. Enable/disable foreman module, current value: true
646
+ 2. Set one, current value: '1'
647
+ 3. Configure Advanced parameters
648
+ 4. Configure Extra parameters
649
+ 5. Back to main menu
650
+ ```
651
+
652
+ When you enter Extra parameters, you see only $three and an option to get back
653
+ to the parent. In Advanced you can see $two and two more subgroups - Advanced A and
654
+ Advanced B. When you enter these subgroups, you can again see their parameters.
655
+ Nesting is unlimited. Also there's no naming rule. Just notice that
656
+ the main group must be called `Parameters` and it's parameters are always
657
+ displayed on first level of the module configuration.
658
+
659
+ ```
660
+ Group Extra parameters (of module foreman)
661
+ 1. Set two_b, current value: '2b'
662
+ 2. Back to parent menu
663
+ ```
664
+
665
+ If there's no primary group a new one is created for you and it does not have
666
+ any parameter. This means when a user enters the module configuration he or she will
667
+ see only subgroups in the menu (no parameters until a particular subgroup is entered).
668
+ If there is no group in the documentation a new primary group is created and it
669
+ holds all module parameters (there are no subgroups in the module configuration).
670
+
671
+ ## Conditional parameters in interactive mode
672
+
673
+ You can also define conditions to parameters and their groups. These conditions
674
+ are evaluated in interactive mode and are based on the results which are then displayed
675
+ to the user. You can use this for example to hide mysql_* parameters when
676
+ $db_type is not set 'mysql'. Let's look at following example
677
+
678
+ ```puppet
679
+ # Testing class
680
+ #
681
+ # == Parameters:
682
+ #
683
+ # $use_db:: use database?
684
+ # type:boolean
685
+ #
686
+ # == Database parameters: condition: $use_db
687
+ #
688
+ # $database_type:: mysql/sqlite
689
+ #
690
+ # === MySQL: condition: $database_type == 'mysql'
691
+ #
692
+ # $remote:: use remote connection
693
+ # type:boolean
694
+ # $host server to connect to
695
+ # condition: $remote
696
+ # $socket server to connect to
697
+ # condition: !$remote
698
+ ```
699
+
700
+ Here you can see we defined several conditions on the group and parameter level.
701
+ You can write a condition in ruby. All dollar-prefixed words will be
702
+ substituted with the value of the particular puppet parameter.
703
+
704
+ Note that conditions are combined using ```&&``` when you nest them. So these
705
+ are facts based on example:
706
+
707
+ * $database_type, $remote, $host, $socket are displayed only when $use_db is set to true
708
+ * $remote, $host, $socket are displayed only when $database_type is set to 'mysql'
709
+ * $host is displayed only if $remote is set to true, $socket is displayed otherwise
710
+
711
+ Here's explanation how conditions are constructed
712
+
713
+ ```
714
+ -----------------------------------------------------------------------------
715
+ | parameter name | resulting condition |
716
+ -----------------------------------------------------------------------------
717
+ | $use_db | true |
718
+ | $database_type | true && $use_db |
719
+ | $remote | true && $use_db && $database_type == 'mysql' |
720
+ | $host | true && $use_db && $database_type == 'mysql' && $remote |
721
+ | $socket | true && $use_db && $database_type == 'mysql' && !$remote |
722
+ -----------------------------------------------------------------------------
723
+ ```
724
+ As already said you can use whatever ruby code, so you could leverage e.g.
725
+ parentheses, &&, ||, !, and, or
726
+
727
+ ## Custom modules and manifest names
728
+
729
+ By default Kafo expects a common module structure. For example if you add
730
+ ```yaml
731
+ foreman: true
732
+ ```
733
+ to you answer file, Kafo expects a ```foreman``` subdirectory in ```modules/```. Also
734
+ it expects that there will be init.pp which it will instantiate. If you need
735
+ to change this behavior you can via ```mapping``` option in ```config/kafo.yaml```.
736
+
737
+ Suppose we have a puppet module and we want to use a puppet/server.pp as our init
738
+ file. Also we want to name our module puppetmaster. To do so we add the following mapping
739
+ to kafo.yaml
740
+
741
+ ```yaml
742
+ :mapping:
743
+ :puppetmaster: # a module name, so we'll have puppetmaster: true in answer file
744
+ :dir_name: 'puppet' # the subdirectory in modules/
745
+ :manifest_name: 'server' # manifest filename without .pp extension
746
+ :params_path: ... # params manifest full path, overriding params_name, must be with .pp extension
747
+ :params_name: 'params' # name of manifest holding the params class without .pp extension
748
+ ```
749
+
750
+ Note that if you add a mapping you must enter both the dir_name and manifest_name even
751
+ if one of them is already the default. The arguments params_path and params_name are optional.
752
+ You can use just "params_name" or override not just the file name but also complete paths using "params_path".
753
+ If you use "params_path" for this purpose, "params_name" is ignored.
754
+
755
+ ## Validations
756
+
757
+ If you specify validations of parameters in your init.pp manifest they
758
+ will be replaced with your values even before Puppet is run. In order to do this
759
+ you must follow a few rules however:
760
+
761
+ * you must use standard validation functions (e.g. validate_array, validate_re, ...)
762
+
763
+ These functions are re-implemented in Kafo from common stdlib functions, so please
764
+ contribute any missing ones.
765
+
766
+ If class parameters are declared with Puppet 4 data types then Kafo will
767
+ validate user inputs against Puppet's type validation rules, which should
768
+ replace the use of separate validation functions.
769
+
770
+ ## Enabling or disabling module
771
+
772
+ You can enable or disable a module specified in the answers.yaml file. Every module
773
+ automatically adds two options to the foreman-installer script. For the module "foreman"
774
+ you have two flag options ```--enable-foreman``` and ```--no-enable-foreman```.
775
+
776
+ When you disable a module all its answers will be removed and "module" will be
777
+ set to false. When you reenable the module you'll end up with the default values.
778
+
779
+ ## Special values for arguments
780
+
781
+ Sometimes you may want to enforce ```undef``` value for a particular parameter.
782
+ You can set this value by specifying an UNDEF string e.g.
783
+
784
+ ```bash
785
+ bin/foreman-installer --foreman-db-password=UNDEF
786
+ ```
787
+
788
+ It also works in interactive mode.
789
+
790
+ You may also need to override array parameters with empty array values. For this
791
+ purpose you can use `EMPTY_ARRAY` string as a value. Similarly you can use
792
+ `EMPTY_HASH` for hash parameters.
793
+
794
+ ## Hooks
795
+
796
+ You may need to add new features to the installer. Kafo provides a simple hook
797
+ mechanism that allows you to run custom code at several different occasions.
798
+ We currently support the following hooks.
799
+
800
+ * pre_migrations - just after kafo reads its configuration - useful for config file updates. Only in this stage it is posible to request config reload (`Kafo.request_config_reload`) to get in our changes
801
+ * boot - before kafo is ready to work, useful for adding new installer arguments, but logger won't work yet
802
+ * init - just after hooking is initialized and kafo is configured, parameters have no values yet
803
+ * pre_values - just before value from CLI is set to parameters (they already have default values)
804
+ * pre_validations - just after system checks and before validations are executed (and before interactive wizard is started), at this point all parameter values are already set but not yet stored in answer file
805
+ * pre_commit - after validations or interactive wizard have completed, all parameter values are set but not yet stored in the answer file
806
+ * pre - just before puppet is executed to converge system, after parameter values are stored in the answer file
807
+ * post - just after puppet is executed to converge system
808
+
809
+ For better understanding when the hooks are executed see the [diagram](doc/kafo_run.png).
810
+
811
+ Let's assume we want to add the ```--reset-foreman-db``` option to our
812
+ foreman-installer. We could add the following lines to the generated
813
+ installer script.
814
+
815
+ ```ruby
816
+ require 'kafo/hooking'
817
+
818
+ # first hook that creates new app option --reset-foreman-db
819
+ KafoConfigure.hooking.register_boot(:add_reset_option) do
820
+ app_option '--reset-foreman-db',
821
+ :flag, 'Drop foreman database first? You will lose all data!', :default => false
822
+ end
823
+
824
+ # second hook which resets the db if value was set to true
825
+ KafoConfigure.hooking.register_pre(:reset_db) do
826
+ if app_value(:reset_foreman_db) && !app_value(:noop)
827
+ `which foreman-rake > /dev/null 2>&1`
828
+ if $?.success?
829
+ logger.info 'Dropping database!'
830
+ output = `foreman-rake db:drop 2>&1`
831
+ logger.debug output.to_s
832
+ unless $?.success?
833
+ logger.warn "Unable to drop DB, ignoring since it's not fatal, output was: '#{output}''"
834
+ end
835
+ else
836
+ logger.warn 'Foreman not installed yet, can not drop database!'
837
+ end
838
+ end
839
+ end
840
+ ```
841
+
842
+ Note that the hook is evaluated in HookContext object which provides a DSL:
843
+
844
+ * ```app_option``` creates a new installer option
845
+ * ```app_value(:reset_foreman_db)``` accesses values of installer options
846
+ * ```param('module name', 'parameter name')``` accessor allows parameters to be modified if already
847
+ defined
848
+ * ```add_module``` registers your own module not specified in the answer file (custom mapping is also
849
+ supported), useful if you need to add some module to the existing installer based on kafo but you
850
+ don't have control over its source code
851
+ * ```module_enabled?('module_name')``` indicates whether a module is currently enabled
852
+ * ```get_custom_config``` and ```store_custom_config``` access custom config storage which persists
853
+ among kafo runs
854
+ * ```logger``` is also available for writing log messages
855
+
856
+ For more details, see
857
+ [hook_context.rb](https://github.com/theforeman/kafo/blob/master/lib/kafo/hook_context.rb).
858
+
859
+ If you don't want to modify your installer script you can place your hooks into the
860
+ hooks directory. By default the hooks dir is searched for ruby files in subdirectories
861
+ based on hook type. For example pre hooks are searched for in ```$installer_dir/hooks/pre/*.rb```
862
+ The hooks from the previous example would look like this. The only change to the code is
863
+ that you don't explicitely register hooks, it's done automatically for you.
864
+
865
+ ```ruby
866
+ # hooks/boot/10-add_reset_option.rb
867
+ app_option '--reset-foreman-db', :flag, 'Drop foreman database first? You will lose all data!', :default => false
868
+ ```
869
+
870
+ ```ruby
871
+ # hooks/pre/10-reset_option_feature.rb
872
+ if app_value(:reset_foreman_db) && !app_value(:noop)
873
+ `which foreman-rake > /dev/null 2>&1`
874
+ if $?.success?
875
+ logger.info 'Dropping database!'
876
+ output = `foreman-rake db:drop 2>&1`
877
+ logger.debug output.to_s
878
+ unless $?.success?
879
+ logger.warn "Unable to drop DB, ignoring since it's not fatal, output was: '#{output}''"
880
+ end
881
+ else
882
+ logger.warn 'Foreman not installed yet, can not drop database!'
883
+ end
884
+ end
885
+ ```
886
+
887
+
888
+ If you want to add more directories to be search you can use the "hook_dirs" option
889
+ in the installer configuration file.
890
+
891
+ ```yaml
892
+ :hook_dirs:
893
+ - /opt/hooks
894
+ - /my/plugin/hooks
895
+ ```
896
+
897
+ You can register as many hooks as you need. The order of execution for a particular hook type
898
+ is based on hook file name.
899
+
900
+ If you want to cancel the installation you can use the ```exit``` method and specify an exit code.
901
+
902
+ ## Colors
903
+
904
+ Everybody loves colors right? In case you don't you can disable them using the ```--no-colors```
905
+ argument or disallow them in the installer config file (search for ```colors:``` key and set
906
+ it to false). If you don't touch this setting, kafo will try to detect whether colors
907
+ are supported and will enable/disable it accordingly.
908
+
909
+ Kafo supports two sets of colors, one for terminals with bright and one for dark backround.
910
+ You can specify your installer default scheme in installer config file (```color_of_background```
911
+ key). Alternatively the user can override this default setting with the ```--color-of-background``` argument.
912
+ Possible values are ```dark``` and ```bright```.
913
+
914
+ You can reuse the kafo color schema in your custom hooks (so you can reuse dark/bright logic).
915
+ Look at this example in bin/foreman-installer
916
+ ```ruby
917
+ #!/usr/bin/env ruby
918
+
919
+ # Run the install
920
+ @result = Kafo::KafoConfigure.run
921
+ exit 0 if @result.nil? # --help invocation
922
+
923
+ # Puppet status codes say 0 for unchanged, 2 for changed succesfully
924
+ if [0,2].include?(@result.exit_code)
925
+ say " <%= color('Success!', :good) %>"
926
+
927
+ if module_enabled? 'foreman'
928
+ say " * <%= color('Foreman', :info) %> is running at <%= color('#{get_param('foreman','foreman_url')}', :info) %>"
929
+ say " Default credentials are '<%= color('admin:changeme', :info) %>'"e
930
+ end
931
+ end
932
+ ```
933
+
934
+ As you can see you can use HighLine helpers (e.g. say) with colors. Look at kafo/color_schema.rb for
935
+ supported color identifiers. We can guarantee that there will always be at least :good, :bad, :info.
936
+
937
+ Methods like module_enabled? and get_param are just helpers defined in the same file. If you find
938
+ them useful, here's the definition
939
+
940
+ ```ruby
941
+ def module_enabled?(name)
942
+ mod = @result.module(name)
943
+ return false if mod.nil?
944
+ mod.enabled?
945
+ end
946
+
947
+ def get_param(mod, name)
948
+ @result.param(mod, name).value
949
+ end
950
+ ```
951
+
952
+ ## Custom paths
953
+
954
+ Usually when you package your installer you want to load files from specific
955
+ paths. In order to do that you can use following configuration options:
956
+
957
+ * :answer_file: /etc/kafo/kafo.yaml
958
+ * :installer_dir: /usr/share/kafo/
959
+ * :module_dirs: /usr/share/foreman-installer/modules
960
+ * :hook_dirs: /user/share/foreman-installer/hooks
961
+ * :check_dirs: /user/share/foreman-installer/checks
962
+ * :kafo_modules_dir: /usr/share/kafo/modules
963
+ * :store_dir: /etc/foreman-installer/store.d
964
+
965
+ Answer file is obvious. The "installer_dir" is the place where your installer is
966
+ located. E.g. system checks will be loaded from here (under checks
967
+ subdirectory) if not set elsewhere by `check_dirs`. You can optionally change foreman-installer modules dir
968
+ using `module_dirs` option and hooks dir using `hook_dirs` option. `module_dirs`, `hook_dirs` and `check_dirs`
969
+ can hold multiple directories where to look for the resources.
970
+
971
+ On debian systems you may want to specify kafo modules dir
972
+ independent on your installer location. If you specify this option kafo's
973
+ internal-installer puppet-modules will be loaded from here.
974
+
975
+ ## Order of puppet modules execution
976
+
977
+ When you have more than one module you may end up in the situation where you need a
978
+ specific order of execution. It seems as a puppet antipattern to me however
979
+ there may be cases where it's needed. You can set order in config/kafo.yaml
980
+ like this
981
+
982
+ ```yaml
983
+ order:
984
+ - foreman
985
+ - foreman_proxy
986
+ ```
987
+
988
+ If you have other modules in your answer file they will be executed after
989
+ those that have explicit order. Their order is not be specified.
990
+
991
+ ## Changing the order of module appearance in interactive mode
992
+
993
+ We sort our modules alphabetically. Sometimes you may want to reorder
994
+ modules, e.g. a display plugin modules as last module.
995
+ For this you can use the ```low_priority_modules```
996
+ configuration option. It accepts an array of patterns considering the
997
+ first to have the lowest priority. So in follwing example
998
+
999
+ ```yaml
1000
+ low_priority_modules:
1001
+ - compute
1002
+ - plugin
1003
+ ```
1004
+
1005
+ all modules containing a word compute in their name would be listed
1006
+ at the end. If there are two modules containing compute, their order
1007
+ is alphabetical on suffix after compute word. If there are some modules
1008
+ containing word plugin, they will be above compute modules as they
1009
+ were mentioned later.
1010
+
1011
+ ## Changing of log directory and user/group
1012
+
1013
+ By default kafo logs every run to a separate file in /var/log/kafo.
1014
+ You probably want to put your installation logs alongside with other logs of
1015
+ your application. That's why kafo has its own configuration file in which you
1016
+ can tune details like these.
1017
+
1018
+ In order to do that, create a configuration file under config/kafo.yaml. You can
1019
+ use config/kafo.yaml.example as a template. If config/kafo.yaml does not exist
1020
+ default values will be used.
1021
+
1022
+ As a developer you can appreciate more verbose log. You can set a debug level
1023
+ in config/kafo.yml. Also you can change a user or group that will own the
1024
+ log file. This is usefull if your installer requires to be run as root
1025
+ but you want the logs to be readable by specific users.
1026
+
1027
+ ## System checks
1028
+
1029
+ When you want to make sure that a user has a certain software installed or has the
1030
+ right version you can write a simple script and put it into the checks directory.
1031
+ All files found there will be executed and if any of these exits with an non-zero
1032
+ exit code, kafo won't execute puppet but only print an error message
1033
+ `Your system does not meet configuration criteria.`
1034
+
1035
+ Everything on STDOUT and STDERR is logged in error level.
1036
+
1037
+ Example shell script which checks java version
1038
+
1039
+ ```bash
1040
+ #!/bin/sh
1041
+ java -version 2>&1 | grep OpenJDK
1042
+ exit $?
1043
+ ```
1044
+
1045
+ If you want to ignore results of the check scripts, you can use the builtin
1046
+ parameter `--skip-checks-i-know-better` (or `-s`). This will completely
1047
+ disable running all system check scripts. Note that this option is
1048
+ not persisted between runs.
1049
+
1050
+ ## Parser cache
1051
+
1052
+ One or more caches of parsed Puppet modules and manifests can be created to skip the use
1053
+ of kafo_parsers at runtime. This is useful when kafo_parsers doesn't support the
1054
+ version of Puppet in use, and may also provide a small performance benefit. When multiple
1055
+ cache files are used, they are being loaded in order they are specified in the config
1056
+ file. If their files overlap, the later cache fully replaces the previous cache for each
1057
+ file/manifest.
1058
+
1059
+ Create the cache with `kafo-export-params -f parsercache --no-parser-cache` and
1060
+ configure it in config/kafo.yaml with:
1061
+
1062
+ ```yaml
1063
+ # single cache
1064
+ :parser_cache_path: ./parser_cache.yaml
1065
+
1066
+ # multiple caches
1067
+ :parser_cache_path:
1068
+ - ./parser_cache.yaml
1069
+ - ./another_parser_cache.yaml
1070
+ ```
1071
+
1072
+ The cache will be skipped if the file modification time of the manifest is
1073
+ greater than the mtime recorded in the cache. Using `--parser-cache` will force
1074
+ the use of an outdated cache, but this should be used with caution.
1075
+
1076
+ ## Configuring Hiera
1077
+
1078
+ Kafo uses Hiera to include classes and pass parameters to classes using data
1079
+ binding, but this can be extended so parameters can be set for classes not
1080
+ being managed by Kafo. Set a custom Hiera config file in Kafo's config with:
1081
+
1082
+ ```yaml
1083
+ :hiera_config: /usr/share/kafo/hiera.yaml
1084
+ ```
1085
+
1086
+ The contents of this file are as per the [hiera.yaml docs](https://docs.puppet.com/hiera/latest/configuring.html),
1087
+ but hierarchy should contain the item `kafo_answers` and the `yaml` backend
1088
+ should be enabled. Kafo will add these if they're missing.
1089
+
1090
+ When running Puppet, Kafo will copy the Hiera config and YAML data directory to
1091
+ a temporary location to include its data. The file `kafo_answers.yaml` will be
1092
+ generated containing _all_ default and overriden values for parameters managed
1093
+ by Kafo. This may change in the future to allow a more complex hierarchy. As an
1094
+ example, a hierarchy could be set up with:
1095
+
1096
+ ```yaml
1097
+ :hierarchy:
1098
+ - kafo_answers
1099
+ - "%{::osfamily}"
1100
+ - common
1101
+ ```
1102
+
1103
+ This would give precedence to all Kafo-managed parameter values, but for any
1104
+ others, would check for values per OS family, followed by a `common.yaml` file.
1105
+
1106
+ ## Exit code
1107
+
1108
+ Kafo can terminate either before or after puppet is run. If it is run with
1109
+ ```--detailed-exitcodes``` Kafo returns the same exit code as puppet does. If
1110
+ kafo terminates after puppet run exit codes are like the following:
1111
+ * '1' means there were parser/validation errors
1112
+ * '2' means there were changes,
1113
+ * '4' means there were failures during the transaction,
1114
+ * '6' means there were both changes and failures.
1115
+
1116
+ Other exit codes that can be returned:
1117
+ * '0' means everything went fine no changes were made
1118
+ * '20' means your system does not meet configuration criteria (system checks failed)
1119
+ * '21' means your answer file contains invalid values
1120
+ * '22' means that puppet modules contains some error (e.g. missing documentation)
1121
+ * '23' means that you have no answer file
1122
+ * '24' means that your answer file asks for puppet module that you did not provide
1123
+ * '25' means that kafo could not get default values from puppet
1124
+ * '26' means that kafo could not find the specified scenario
1125
+ * '27' means that kafo found found scenario configuration error that prevents installation from continuing
1126
+ * '28' means that a value is missing for a parameter given on the command line
1127
+ * '29' means that effective user that ran the installer does not have permission to update the answer file
1128
+ * '130' user interrupt (^C)
1129
+
1130
+ ## Running Puppet Profiling
1131
+
1132
+ As of Puppet 3.2, performance data can be gathered during a puppet run by adding the `--profile` option. See [Tune Puppet for Performance with Profiler](https://puppetlabs.com/blog/tune-puppet-performance-profiler) for more information from the Puppet team. Users who wish to perform a Kafo run and gather this type of profiling data to analyze can pass the same option to their installer. The profiling data will then be present in the normal Kafo logs.
1133
+
1134
+ ## Issue tracker
1135
+
1136
+ Issues are tracked in Redmine, see:
1137
+
1138
+ * [Open Kafo issues](http://projects.theforeman.org/projects/kafo/issues/)
1139
+ * [File new issue](http://projects.theforeman.org/projects/kafo/issues/new)
1140
+
1141
+ ## Related projects
1142
+
1143
+ * [kafo_module_lint](https://github.com/domcleal/kafo_module_lint) will lint Puppet modules to ensure data types are specified correctly etc.
1144
+ * [kafo_parsers](https://github.com/theforeman/kafo_parsers) parses Puppet manifests for class documentation and parameter data
1145
+ * [puppet-lint-param-docs](https://github.com/voxpupuli/puppet-lint-param-docs) will lint Puppet modules to ensure all parameters are documented
1146
+
1147
+ # License
1148
+
1149
+ This project is licensed under the GPLv3+.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'rake/testtask'
2
+ require "bundler/gem_tasks"
3
+ load 'tasks/jenkins.rake'
4
+
5
+ Rake::TestTask.new('test:unit') do |t|
6
+ t.libs << 'lib' << 'test'
7
+ t.test_files = FileList['test/kafo/**/*_test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ Rake::TestTask.new('test:acceptance') do |t|
12
+ t.libs << 'lib' << 'test'
13
+ t.test_files = FileList['test/acceptance/*_test.rb']
14
+ t.verbose = true
15
+ end
16
+
17
+ CLEAN.include 'test/tmp'
18
+
19
+ task :test => ['test:unit', 'test:acceptance']
data/lib/kafo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
  module Kafo
3
3
  PARSER_CACHE_VERSION = 1
4
- VERSION = "1.0.7"
4
+ VERSION = "1.0.8"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kafo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marek Hulan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-15 00:00:00.000000000 Z
11
+ date: 2017-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -194,6 +194,9 @@ executables:
194
194
  extensions: []
195
195
  extra_rdoc_files: []
196
196
  files:
197
+ - LICENSE.txt
198
+ - README.md
199
+ - Rakefile
197
200
  - bin/kafo-configure
198
201
  - bin/kafo-export-params
199
202
  - bin/kafofy