Parameterized class development Ofavre analysis » History » Version 3
Olivier Favre, 06/28/2012 10:24 AM
Forget about parameters, use solely smart-variables, it's even simpler (to understand) when we don't use the import feature
1 | 1 | Olivier Favre | h1. Parameterized class development - Ofavre's analysis |
---|---|---|---|
2 | |||
3 | h2. Puppet classes parameters and smart variables |
||
4 | |||
5 | h3. Making the smart-proxy return the parameters |
||
6 | |||
7 | Puppet classes parameters are given by the smart-proxy: |
||
8 | The current answer of smart-proxies are: |
||
9 | <pre> |
||
10 | [ |
||
11 | { |
||
12 | "amodule::aclass" : |
||
13 | { |
||
14 | "module" : "amodule", |
||
15 | "name" : "aclass" |
||
16 | } |
||
17 | }, |
||
18 | ... |
||
19 | ] |
||
20 | </pre> |
||
21 | I've extended it to give the extracted parameters, using the "@Puppet::Parser@":https://github.com/puppetlabs/puppet/blob/master/lib/puppet/parser: |
||
22 | <pre> |
||
23 | [ |
||
24 | { |
||
25 | "amodule::aclass" : |
||
26 | { |
||
27 | "module" : "amodule", |
||
28 | "name" : "aclass", |
||
29 | "params" : {} # no parameters |
||
30 | } |
||
31 | }, |
||
32 | { |
||
33 | "amodule::aparameterizedclass" : |
||
34 | { |
||
35 | "module" : "amodule", |
||
36 | "name" : "aparameterizedclass", |
||
37 | "params" : { |
||
38 | "mandatoryParam" : null, |
||
39 | "optionalNumericParam" : "42", |
||
40 | "optionalStringParam" : "\"foo\"" |
||
41 | "optionalConcatParam" : "company@$::hostname" |
||
42 | } |
||
43 | } |
||
44 | }, |
||
45 | ... |
||
46 | ] |
||
47 | </pre> |
||
48 | The values of the parameters are either @null@ if there is none, or the string representation of the @AST::Leaf@ (see "lib/puppet/parser/ast/leaf.rb":https://github.com/puppetlabs/puppet/blob/master/lib/puppet/parser/ast/leaf.rb). |
||
49 | Its likely not perfect yet. |
||
50 | |||
51 | h3. Storing the parameters in the db |
||
52 | |||
53 | We can do multiple things to represent the parameters in the database, but we need to know what we want to do with them before choosing the right representation. |
||
54 | We want to: |
||
55 | * Be able to sync the db when importing puppet classes. |
||
56 | This means addition, deletion of puppet classes __and__ parameters. |
||
57 | * Control the value of the parameter using a smart-variable, with a potentially complex set of matchers. |
||
58 | We never want to loose this complex configuration. |
||
59 | |||
60 | So we can directly: |
||
61 | * Create a new smart-variable for each new {puppetclass, parameter} couple on importing |
||
62 | * But we need not to delete a smart-variable for an obsolete {puppetclass, parameter} couple. |
||
63 | (We could do it automatically if and only if the description and default value were left intact, and there is no matchers). |
||
64 | |||
65 | 3 | Olivier Favre | But this will not be very practical in a few cases: |
66 | 1 | Olivier Favre | * New mandatory parameters would need their smart-variable configured, or it will generate errors. |
67 | Hence we need to make this visible somehow. |
||
68 | 3 | Olivier Favre | * An old smart-variable, no longer attached to a valid {puppetclass, parameter} couple cannot be reassigned to a new, valid couple, without erasing an existing (automatically created) smart-variable. |
69 | We would need a conflict resolution, or a mere "confirm overwrite". |
||
70 | * Note that puppetclass or parameter renames __cannot__, generally speaking, be detected. Hence we can only add/delete. |
||
71 | * As one can use foreman forms to create each environment, puppetclass and parameter, instead of using the import feature, there is no way to warn the user he has deleted a smart-variable for a parameter and left a possibly mandatory parameter with no values. |
||
72 | 1 | Olivier Favre | |
73 | 3 | Olivier Favre | So we need to easily see the mapping between smart-variables and puppetclasses parameters, as opposed to a global scope smart-variable attached to a puppetclass. |
74 | We need to: |
||
75 | * Use a special prefix like: @puppetmodule::puppetclass/parametername@. |
||
76 | 1 | Olivier Favre | |
77 | h2. Mandatory parameters |
||
78 | |||
79 | First we'll have to make smart-variables explicitly either optional or mandatory. |
||
80 | A mandatory smart-variable has no default value and should raise an error if its matchers yield no value during evaluation. |
||
81 | 3 | Olivier Favre | |
82 | How could we represent a smart-variable without default value (ie. mandatory)? |
||
83 | * Be close to the code: @"strings"@ are quoted, digits are not, @[lists]@ have brackets, @{:hash=>"es"}@ have braces, and a blank value means no default value. |
||
84 | * Forget about typed values and use a checkbox: string and digits are not quoted, lists and hashes need to be @eval()@ed, and a blank value means an empty string. |
||
85 | 2 | Olivier Favre | |
86 | What should we do when creating a new host with a class without a smart-variable controlling a mandatory parameter? |
||
87 | * Raise an error "please contact your sysadmin"? |
||
88 | * Provide a text field to provide a value? |
||
89 | Where should the value be stored? (as a HostParameter, with a @"puppetclass::"@ prefix?) |
||
90 | * Create a smart-variable with a @order:fqdn@ and a matcher on the @fqdn@ for the host to build? |
||
91 | |||
92 | 1 | Olivier Favre | h2. Supporting non uniform classes across environments |
93 | |||
94 | In puppet, classes are totally separate from an environment to another. |
||
95 | Hence it is possible that classes have the same name in two environments while having different parameters. |
||
96 | Currently puppetclasses are linked to environments with an __n-n__ relation. |
||
97 | This need to be changed to a __n-1__ relation (envs. having many classes, a class belonging to a single env.). |
||
98 | |||
99 | However, in order to reduce redundancy in the configuration, we may need to bind a smart-variable to multiple environments, ie. to same-named puppet classes across different environments. |