UPDATED ---- For advanced use cases when defining resources e.g. a resource that delegates to one or more other resources it is of great value to be able to capture parameter key-values instead of having to wrap such in a Hash since that makes it impossible to use the new resource as a drop in replacement for what it delegates to without having to update all logic where the replacement should be used (see examples below in comments). (There are also other variations on this theme).
Add support for varargs/captures in user defined resources by allowing the same syntax that is used for functions to specify that extra parameters are captured into a Hash variable. For functions this is an {{Array}}, and for "args by name" calls, this is a {{Hash}}.
{code:puppet} define foo($a, $b, *$captured) { } {code} In the body the variable $capture is always a {{Hash}}, it may be empty, or contain any keys the user has given. To restrict the keys, the user can type the parameter with a {{Hash\[String, <wanted-data-type>, min, max]}}, or a {{Struct}}. When using a {{Struct}} the keys can be pattern based (as defined in PUP-5942) and it is thus possible to type different pattern based parameters to different types.
{code:puppet} define foo($a, $b, Struct[{Patter[/prefix_[a-z]+/] => Integer}], *$captured) { } {code} See PUP-5942 for how to constraint the number of keys (from min required to max allowed).
The above definition of {{foo}} allows this: {code:puppet} foo { 'example': prefix_abc => 1, prefix_bcd => 2, } {code}
* The same varargs support should also be added to EPP templates since they use "args by name". * This should *not* be added to classes (there is no way to do data binding, and parameters are part of the class' API and they are externally addressable).
A concern has been raised that adding "varargs" support is less declarative, but that is only a matter of perception - something that is defined by a pattern is just as specified as a concrete specification. What we cannot accept though is that the API of something changes depending on how it is used - this means that varargs support cannot be added to classes unless the varargs hash is made into a private variable in that class thus making it impossible to refer to its individual matching parameters from outside of the class body. The captured hash itself could be made public. Support for varargs in classes is therefore not included in this ticket. If wanted a new ticket should be opened, and that ticket should depend on the ability to have private variables in class scopes.
ORIGINAL ---- Through roles and profiles, a pattern started to emerge where we write a wrapper {{define}}, for convenience, for better naming, both, or other reasons.
Example:
{code} define http2https_vhost ( $servername = $name, $serveraliases = undef, ) { apache::vhost ( "http-${servername}": servername => $servername, serveraliases => $serveraliases, redirect_status => '301', redirect_dest => "https://{servername}/", }
apache::vhost ( "https-${servername}": servername => $servername, ssl_ca => "/etc/ssl/certs/${servername}s.ca.pem", ssl_cert => "/etc/ssl/certs/${servername}.crt.pem", ssl_key => "/etc/ssl/private/${servername}.key.pem", } } {code}
This is nice and convenient for the most simple of cases. If we need more options from apache::vhost, we have to extend our wrapper profile. Similarly, if apache::vhost changes, and new admins want to use those new options, we (or they!) have to touch our convenience wrappers.
We could do a gruesome hack, such as:
{code} define http2https_vhost ( $servername = $name, $serveraliases = undef, $options = {}, ) { apache::vhost ( "http-${servername}": servername => $servername, serveraliases => $serveraliases, redirect_status => '301', redirect_dest => "https://{servername}/", }
create_resources('apache::vhost', { "https-${servername}" => $options}, { servername => $servername, ssl_ca => "/etc/ssl/certs/${servername}s.ca.pem", ssl_cert => "/etc/ssl/certs/${servername}.crt.pem", ssl_key => "/etc/ssl/private/${servername}.key.pem", }) {code}
but the additional indirection through {{$options}} is hard to follow, and with more complex wrappers it's also hard to know where _our options_ start, and where _their options_ end… what is a default, what's being overwritten, etc…
I propose we introduce a syntax which helps us create such, or even more powerful wrappers, analogous to clojure's {{&rest}}:
{code} define http2https_vhost ( $servername = $name, $serveraliases = undef, &rest, ) { apache::vhost ( "http-${servername}": servername => $servername, serveraliases => $serveraliases, redirect_status => '301', redirect_dest => "https://{servername}/", }
apache::vhost ( "https-${servername}": servername => $servername, docroot => "/srv/web/${servername}/htdocs", ssl_ca => "/etc/ssl/certs/${servername}s.ca.pem", ssl_cert => "/etc/ssl/certs/${servername}.crt.pem", ssl_key => "/etc/ssl/private/${servername}.key.pem", &rest, } } {code}
Example use:
{code} http2https_vhost { 'blag.esotericsystems.at': fallbackresource => '/index.php' } {code}
This passes {{fallbackresource}} down to the second {{apache::vhost}}.
It might be useful to _filter_ for specific prefixes,
{code} define tc_and_apache_vhost ( $servername = $name, $port = 8080, &tomcat_, &apache_, ) {
apache::vhost ( "https-${servername}": servername => $servername, ssl_ca => "/etc/ssl/certs/${servername}s.ca.pem", ssl_cert => "/etc/ssl/certs/${servername}.crt.pem", ssl_key => "/etc/ssl/private/${servername}.key.pem", proxy_pass => '/', proxy_dest => "http://localhost:${port}/" &apache_, }
tomcat::instance ( "tc-${servername}": application => $servername, proxy => "https://servername:443/" &tomcat_, } } {code}
The idea here is that all parameters passed to a {{tc_and_apache_vhost}} that start with {{apache_}} would be routed into the {{apache::vhost}}, and all parameters that start with {{tomcat_}} would be routed to {{tomcat::instance}}.
I'm not sure yet, if they should be stripped of their prefix before being routed, or not.
|
|
|