Parameterized class development Ofavre analysis » History » Version 1
Olivier Favre, 06/27/2012 06:24 AM
ofavre: Thoughts on parameterized classes support
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 | But this will not be very practical: |
||
66 | * New mandatory parameters would need their smart-variable configured, or it will generate errors. |
||
67 | Hence we need to make this visible somehow. |
||
68 | * An old smart-variable, no longer attached to a valid {puppetclass, parameter} couple cannot easily be reassigned to a new, valid couple, without erasing an existing (automatically created) smart-variable. |
||
69 | This makes it __impractical__ for the user interface. __But note that it__ is __feasible.__ |
||
70 | * Note that puppetclass or parameter renames __cannot__, generally speaking, be detected. Hence we can only to add/delete. |
||
71 | |||
72 | So we would need to separate puppetclass parameters from the eventual smart-variables that will control them. |
||
73 | That way: |
||
74 | * We can show the obsolete smart-variables (no longer bound to a value {puppetclass, parameter} couple). |
||
75 | * We can show uncontrolled parameters: puppetclass parameters without a bound smart-variable. |
||
76 | We can visually separate mandatory uncontrolled parameters from optional ones (which have a default value, hence won't raise errors). |
||
77 | * Provide a way to rebind an obsolete smart-variable to a yet unbound {puppetclass, parameter} couple. |
||
78 | * Provide a way to create a smart-variable for an uncontrolled parameter, presenting a form for the necessary configuration. |
||
79 | * Additionally provide an easy way to automatically create a noop smart-variable for an optional parameter. |
||
80 | |||
81 | So we need to easily see the mapping between smart-variables and puppetclasses parameters. |
||
82 | We can either: |
||
83 | * Store a serialized hash into a new parameters column of the puppetclasses table. |
||
84 | But this would mean parsing them all to see which are not controlled by a smart-variable. |
||
85 | * Create an entry in the parameters __table__ of type @PuppetClassParameter@, filling the name and value from the smart-proxy's output and binding it to the corresponding puppetclass. |
||
86 | |||
87 | I favor the second solution. Do you see any other? |
||
88 | |||
89 | h2. Supporting non uniform classes across environments |
||
90 | |||
91 | In puppet, classes are totally separate from an environment to another. |
||
92 | Hence it is possible that classes have the same name in two environments while having different parameters. |
||
93 | Currently puppetclasses are linked to environments with an __n-n__ relation. |
||
94 | This need to be changed to a __n-1__ relation (envs. having many classes, a class belonging to a single env.). |
||
95 | |||
96 | 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. |