|
| 1 | +Settings |
| 2 | +======== |
| 3 | + |
| 4 | +<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc --> |
| 5 | +**Table of Contents** |
| 6 | + |
| 7 | +- [Definitions](#definitions) |
| 8 | +- [Sections](#sections) |
| 9 | +- [Initialization](#initialization) |
| 10 | +- [Dashes & Underscores](#dashes--underscores) |
| 11 | +- [Setting Types](#setting-types) |
| 12 | +- [Setting Values](#setting-values) |
| 13 | + - [Duration & TTL Settings](#duration--ttl-settings) |
| 14 | + - [File/Directory Settings](#filedirectory-settings) |
| 15 | +- [Hooks](#hooks) |
| 16 | +- [Run Mode](#run-mode) |
| 17 | + - [Preferred Run Mode](#preferred-run-mode) |
| 18 | +- [Precedence](#precedence) |
| 19 | +- [File Watcher](#file-watcher) |
| 20 | +- [RSpec](#rspec) |
| 21 | + |
| 22 | +<!-- markdown-toc end --> |
| 23 | + |
| 24 | +Puppet can be configured via settings. All settings are defined in |
| 25 | +`lib/puppet/defaults.rb`. All settings have a type, value, description, etc. |
| 26 | +Settings can come from multiple sources such as the command line, configuration |
| 27 | +file, programmatically, etc, and are looked up in a specific order, so that the |
| 28 | +command line takes precedence over what's specified in puppet.conf. |
| 29 | + |
| 30 | +Puppet settings can be looked up using `Puppet[:name]` and set using |
| 31 | +`Puppet[:name] = 'value'`. |
| 32 | + |
| 33 | +# Definitions |
| 34 | + |
| 35 | +Settings are defined using `Puppet::Settings#define_settings`. The method takes |
| 36 | +a section name, setting name and a hash describing the setting, e.g. its type, |
| 37 | +description, etc. |
| 38 | + |
| 39 | +# Sections |
| 40 | + |
| 41 | +Puppet settings can be specified in INI file format based on a section, for example: |
| 42 | + |
| 43 | +```inifile |
| 44 | +[main] |
| 45 | +strict=true |
| 46 | +``` |
| 47 | + |
| 48 | +Comments and whitespace are ignored. A setting may be configured in any section, |
| 49 | +even if it wasn't defined in that section. For example, the `strict` setting is |
| 50 | +defined in `main`: |
| 51 | + |
| 52 | +```ruby |
| 53 | +settings.define_setting(:main, strict: { ... }) |
| 54 | +``` |
| 55 | + |
| 56 | +But it can be configured in any section, so this is legal: |
| 57 | + |
| 58 | +```inifile |
| 59 | +[server] |
| 60 | +strict = true |
| 61 | +``` |
| 62 | + |
| 63 | +The purpose of the section name is when applying a settings catalog, see |
| 64 | +'File/Directory Settings' below. |
| 65 | + |
| 66 | +Puppet predefines section names like `main`, `user`, `agent` and `server`. Only |
| 67 | +these sections are allowed in `puppet.conf`. |
| 68 | + |
| 69 | +# Initialization |
| 70 | + |
| 71 | +The entry point for initializing settings is `Puppet.initialize_settings`. It is |
| 72 | +possible to pass in command line arguments, as well as inject dependencies, such |
| 73 | +as an alternate facter implementation. |
| 74 | + |
| 75 | +Puppet initializes its settings in three phases: global options, loading its |
| 76 | +`puppet.conf`, and application options. |
| 77 | + |
| 78 | +First, puppet parses command line arguments using our vendored trollop library. |
| 79 | +Any argument with the same name as a puppet setting is automatically set. The |
| 80 | +argument and its optional value are "consumed" and unknown arguments are |
| 81 | +ignored. Puppet handles boolean arguments specially, so it's possible to pass |
| 82 | +`--onetime` or `--no-onetime`, and puppet will set the value to `true` or |
| 83 | +`false`, respectively. |
| 84 | + |
| 85 | +Second, puppet loads `puppet.conf` from a predefined location depending on |
| 86 | +whether it's running privileged or not. See |
| 87 | +[https://github.com/puppetlabs/puppet-specifications/blob/master/file_paths.md](https://github.com/puppetlabs/puppet-specifications/blob/master/file_paths.md |
| 88 | +). Assuming puppet is running an application like `puppet agent`, then |
| 89 | +the application parses unconsumed arguments using Ruby's builtin |
| 90 | +`OptionParser`. |
| 91 | + |
| 92 | +Third, the application parses any application-specific options using the same |
| 93 | +`OptionParser` instance from above. If the application defines an option with |
| 94 | +the same name as a setting, the application's option handler will be called |
| 95 | +last, so it "wins". |
| 96 | + |
| 97 | +# Dashes & Underscores |
| 98 | + |
| 99 | +Puppet settings are always defined using underscores, but application options |
| 100 | +should always be defined using dashes, e.g. `option("--job-id ID")` |
| 101 | + |
| 102 | +As long as you're using Ruby 2.5 or above, `OptionParser` will automatically |
| 103 | +convert underscores to dashes, so your option handler will always be called |
| 104 | +even if the setting is specified using underscores in `puppet.conf` or on the |
| 105 | +command line. |
| 106 | + |
| 107 | +# Setting Types |
| 108 | + |
| 109 | +By default, settings are assumed to contain a string value. It is possible to |
| 110 | +specify another type when the setting is defined, such as `:type => :integer`. Each |
| 111 | +type maps to a subclass of `Puppet::Settings::BaseSetting`. In general, try to |
| 112 | +reuse an existing type instead of creating one subclass for every setting. |
| 113 | + |
| 114 | +When creating a new setting type, you may need to implement the `munge` method |
| 115 | +to convert the external representation (the string "42") to its internal |
| 116 | +representation (the integer 42). |
| 117 | + |
| 118 | +You may also want to implement the `print` method, which is invoked when running |
| 119 | +`puppet config print <name>`. |
| 120 | + |
| 121 | +# Setting Values |
| 122 | + |
| 123 | +Puppet defines several "root" settings that must be defined, such as `confdir`. |
| 124 | +These settings default to directories based on whether puppet is running as a |
| 125 | +privileged user and is running on Windows or not. |
| 126 | + |
| 127 | +Non-root settings may be defined in terms of other settings. For example, the |
| 128 | +`ssldir` setting's value is defined to be `"$confdir/ssl"`. So in order to |
| 129 | +resolve the value of the `ssldir`, puppet will recursively resolve `confdir`. |
| 130 | +Puppet supports multiple levels of recursion, but will raise if it detects a |
| 131 | +cycle. |
| 132 | + |
| 133 | +## Duration & TTL Settings |
| 134 | + |
| 135 | +Puppet's duration and ttl-based settings assume the value is specified in |
| 136 | +seconds unless units are specified, such as `5m`, `1h`, etc. |
| 137 | + |
| 138 | +## File/Directory Settings |
| 139 | + |
| 140 | +The `file` and `directory` settings are handled specially, because puppet will |
| 141 | +compile an internal "settings" catalog and apply it, to ensure they match the |
| 142 | +desired state. So whenever `Puppet.settings.use(:main, etc)` is called, then all |
| 143 | +file and directory-based settings in the `main`, etc sections will be added to |
| 144 | +the settings catalog. |
| 145 | + |
| 146 | +It is possible to specify the `owner` and/or `group` for these types of |
| 147 | +settings. The special `service` account means use whatever user/group puppet is |
| 148 | +configured to run under, as specified as `Puppet[:user]`/`Puppet[:group]`. For |
| 149 | +example, when puppet is a library within puppetserver, `Puppet[:user]` is set |
| 150 | +to the `puppet` user. This way puppetserver, not running as root, can access |
| 151 | +files that puppet creates. |
| 152 | + |
| 153 | +It is also possible for a user to specify `owner`, `group` or `mode` metadata in |
| 154 | +`puppet.conf` by appending a hash after the value: |
| 155 | + |
| 156 | +```inifile |
| 157 | +ssldir = "$confdir/ssl" { owner=root,group=root,mode=0750 } |
| 158 | +``` |
| 159 | + |
| 160 | +See also the `settings_catalog` and `manage_internal_file_permissions` settings, |
| 161 | +which can disable these behaviors. |
| 162 | + |
| 163 | +# Hooks |
| 164 | + |
| 165 | +It is possible to add a hook to a setting. The hook will be called at various |
| 166 | +times whenever the value is set. The hook may be called multiple times. Hook |
| 167 | +behavior is confusing and surprising! If you must define a new hook, use |
| 168 | +`on_initialize_and_write`. The other types of hooks won't be called if the |
| 169 | +setting is defined in a section that doesn't match the current run_mode. |
| 170 | + |
| 171 | +If a setting's default value interpolates another base setting, then the hook |
| 172 | +will **not** be called if the base setting changes. So try to avoid mixing hooks |
| 173 | +and interpolated default values. |
| 174 | + |
| 175 | +# Run Mode |
| 176 | + |
| 177 | +Puppet can be configured to run in different "modes". The default run mode is |
| 178 | +`:user`, but can be switched to `:agent` or `:server`. If the run mode is |
| 179 | +switched, then it changes how settings are resolved. For example, given |
| 180 | +`puppet.conf` containing: |
| 181 | + |
| 182 | +```inifile |
| 183 | +[server] |
| 184 | +node_terminus=exec |
| 185 | +``` |
| 186 | +Then calling `Puppet[:node_terminus]` will return either `nil` or `exec` |
| 187 | +depending on the current run mode. |
| 188 | + |
| 189 | +## Preferred Run Mode |
| 190 | + |
| 191 | +Settings and run mode have a circular dependency. We need to know the run mode |
| 192 | +in order to load settings. However, puppet applications are defined in modules. |
| 193 | +So we need to resolve the `modulepath` setting to find the application, and then |
| 194 | +the application can change the run mode. |
| 195 | + |
| 196 | +To break the dependency, puppet's preferred run mode is the mode it initially |
| 197 | +starts in, though it may change later on. |
| 198 | + |
| 199 | +# Precedence |
| 200 | + |
| 201 | +Puppet settings can be defined in multiple sources (command line, puppet.conf, |
| 202 | +etc). When looking up a value, puppet searches based on the precedence of each |
| 203 | +source, roughly in order of high to low: |
| 204 | + |
| 205 | +* memory |
| 206 | +* command line |
| 207 | +* current environment.conf |
| 208 | +* section for the current run mode |
| 209 | +* main section |
| 210 | +* defaults |
| 211 | + |
| 212 | +It is important to note that both the current environment and run mode change |
| 213 | +how the value is resolved. |
| 214 | + |
| 215 | +# File Watcher |
| 216 | + |
| 217 | +When running as a daemon, puppet will watch its `puppet.conf` and reload its |
| 218 | +configuration if it changes. |
| 219 | + |
| 220 | +# RSpec |
| 221 | + |
| 222 | +To avoid order-dependent test failures, puppet's rspec tests create unique |
| 223 | +"root" directories for each rspec example. For example, you can safely mutate |
| 224 | +settings in a test `Puppet[:strict] = true` or modify the contents of the |
| 225 | +`confdir` without affecting other tests. |
0 commit comments