On 2014-25-07 22:43, John Bollinger wrote:
On Thursday, July 24, 2014 7:32:13 PM UTC-5, Andy Parker wrote:
Howdy,
Henrik, David, Erik, John, and others have been having some pretty
epic conversations around resource expressions, precedence, order of
evaluation, and several other topics. What kicked all of that off
was us looking for some feedback on decisions we were making for the
Puppet 4 language about how resource overrides, defaults, and so on
actually work (or don't in some cases). I think we've finally
reached some decisions!
Henrik took all of the ideas and started trying to work out what we
could do and what we couldn't. Those are in a writeup at
https://docs.google.com/a/puppetlabs.com/document/d/1mlwyaEeZqCfbF2oI1F-95cochxfe9gubjfc_BXjkOjA/edit#
<https://docs.google.com/a/puppetlabs.com/document/d/1mlwyaEeZqCfbF2oI1F-95cochxfe9gubjfc_BXjkOjA/edit#>
Lots of information in there, so here is the summary.
The principles behind the decisions:
1. Only make changes that have a high likelihood of *not* needing
to be backed out later.
2. Strict or explicit is better than lax or implicit. It uncovers
issues and keeps you from lying to yourself.
3. Puppet 3 has already stacked up a lot of changes. Do not break
manifests unless we really have to.
4. Let's not break manifests and then have to break them in
almost the same way once we start working on a new catalog system.
Great principles.
There are three kinds of resource expression that we have to deal with:
1. Resource instantiation
2. Resource defaults
3. Resource overrides
Looking forward, I think it is highly likely that the catalog system
that we'll be working on during puppet 4 will be some sort of
production (rules) system. In that kind of a world, resource
instantiation likely remains as is, but defaults and overrides will
end up having to change quite a bit, if not in syntax, at least in
semantics.
DECISION ONE
Resource defaults and Resource overrides will be left untouched.
Decision one follows from principles 3 and 4. In the discussions it
became clear that changing when defaults or overrides are applied,
the scope of defaults, or anything else about them was going to
cause a lot of problems. Puppet's master branch changed resource
defaults to follow the same scoping rules as variables. That change
will be reverted.
I take it you mean that the current syntax for overrides and defaults
will continue to be supported and will continue to have the traditional
semantics.
yes, no new capabilities, and the same semantics - even keeping the
dynamic scoping for resource defaults because the way we changed it on
master makes it incompatible, and it is not replaced by something better.
Do you also mean that the new form of default declarations
will also have the same semantics (scope, laziness, ...) as the
traditional ones? (I suspect not.)
The new form of default is local to the resource instantiation
expression. it is processed when the resource is instantiated as if
the attribute operations had been written out in long form - only
now they are in a common section, and can come from a hash.
(This only applies to resource instantiation, this is not available in
the 3x style resource override and defaults expressions).
DECISION TWO
Resource instantiations are value producing expressions
Love it.
What about collection expressions? Or does their late evaluation
present too much of a problem?
We are discussing this now. The result that is produced by a
CollectionExpression is useless in the language - it has no information
in it of value at that point, only after the catalog is completed.
Although it may be possible to assign the value, it is of a type that
you cannot use for any practical purpose - a pice of dark matter.
QUESTION: should the value always be an array of references? That
would make it much more predictable.
How about making the value an array if and only if the title given in
the resource instantiation expression is an array? In most cases either
you know the type of the title or you don't care; in the odd case that
you don't know the type of the title but you do care about the result
being an array then you can write
$array = flatten( [ notify {$maybe_array: message => 'hi' } ] )
(requires stdlib).
You can also use splat for this:
$array = * notify {$maybe_array: message => 'hi' }
since the splat operator turns something into an array if it appears in
a place where individual elements are meaningless. (i.e. no standardlib
required to array-ify).
If you want an array but you have only a single title then you can write
either
$array = notify { [ 'adieu' ]: message => 'bye' }
or
$array = [ notify { 'adieu': message => 'bye' } ]
or simply splat it.
DECISION THREE
Resource instantiation expressions will not be allowed in
dangerous locations
Once resource expressions can be placed anywhere there are a few
places where they would actually just do more harm than good
(principle 2). One example is as a parameter default (define a($b =
notify {hi:}) {}).
Sounds wise, but even after reading the details in your googledoc I'm
not sure I follow the details.
Understood - it looked complicated at first but turned out to be quite
simple and I did not clean that up. Basically there are a couple of
places where assignment and resource creation is just weird, and we will
just statically validate expressions in those positions to not contain
any embedded assignments or resource expressions (instantiations,
overrides or defaults).
The places I can think of right now are:
- parameter default value expressions
- case and selector options
Better to validate these than to cause possible mysterious errors caused
by user mistakes. It is not taking away anything of value.
DECISION FOUR
The LHS of a resource *instantiation* expression can be an expression
What?!? This means you can do:
$a = notify
$a { hi: }
Once again, in clearing up odd cases in the grammar this is opened
up to us. This is a very powerful feature to have available. Since
this is very useful and fits well into the grammar I don't see this
being a temporary thing that would then have to go away later
(principle 1).
This one makes me a bit uncomfortable, but I could see it maybe being
useful. Are there limitations on the value produced by an expression
used as the LHS of a resource instantiation expression? For instance,
that it must evaluate to either a string or a (resource) type?
The LHS must evaluate to either a Resource[T] (e.g. Notify, File, etc)
or a String that complies with the class name rule.
We reasoned that we already have create_resources in frequent use to
solve real issues, so it is needed. I don't think create_resources is
used simply because you can. Instead, it is because you do not
statically know the type, or you want to decide which attributes to set
based on calculations you made. Both of those require create_resources
function. Now it moves into the language.
DECISION FIVE (how many of these are there?)
A resource with a title of default provides the default parameter
values for other resources in the same instantiation expression.
Thanks to David Schmitt for this idea!
Yes, this is cool.
DECISION SIX
There will be a splat operator for resource instantiation expressions
To make the default resources (decision five) really useful there
needs to be a way to reuse the same values across multiple defaults.
The current, dangerous, semantics of resource default expressions
skirt this issue by making defaults part of the (dynamic) evaluation
scope. In order to make the default resources nearly as useful but
much safer, we need to add a way to allow reuse of defaults across
multiple resource instantiation expressions explicitly (principle 2).
$owner_mode = { owner => andy, mode => '777' } # gotta make it secure
file { default: *=> $owner_mode;
'/home/andy/.bashrc': ;
'/home/andy/.ssh/id_rsa': ;
}
file { '/etc/passwd': *=> $owner_mode }
"*=>" looks weird, even for Puppet. What about contracting it to "*>",
parallel to the plussignment operator (+>) and to the ordinary value
binding operator (=>)?
The rationale is that you normally have:
name => value
Now, you do not have names, and * is often used as a wildcard/splat/
"split it up", implied, the name is picked from the hash, and you may
want to line them up:
file { default:
* => value ;
foo:
mode => '0777' ;
}
Does that make it feel better?
The first proposal was:
title: (expr)
Then, just use the splat operator:
title: *expr
But then it became weird, because it is a special kind of splat that
applies to the entire expression - that felt more confusing.
DECISION EIGHT
An array as a title expands to individual resource instantiation
expressions with titles of the elements of the array.
This isn't really too far off from the current semantics, no real
change here.
Is there any change /at all/ there with respect to what current Puppet
already supports? (I don't see any, but you've spooked me.)
Current implementation silently skips undef entries, balks at an undef
title (not in an array), but allows other types than Strings as
resulting individual titles (with the weird stringification taking place
that we talked about above). Hence, "not too far off". Feel better now?
- henrik
--
Visit my Blog "Puppet on the Edge"
http://puppet-on-the-edge.blogspot.se/
--
You received this message because you are subscribed to the Google Groups "Puppet
Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to puppet-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/puppet-dev/lqukti%24ej5%241%40ger.gmane.org.
For more options, visit https://groups.google.com/d/optout.