On 2014-28-07 8:34, Luke Kanies wrote:
On Jul 24, 2014, at 5:32 PM, Andy Parker <a...@puppetlabs.com
<mailto:a...@puppetlabs.com>> 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#


Sorry for the late comments here, but I have a couple of questions and
comments.

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.  It would be good to see these paired with what fits
into the "we really have to" section of #3.

Mostly, the "we have to" issues are those that relates to strictness, where it previously was relaxed and/or had undefined behavior.

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.

DECISION TWO

  Resource instantiations are value producing expressions

The expression based grammar that puppet 4 will be based on changed
almost everything into a general expression, which allowed a lot of
composition that wasn't possible before. This didn't change resource
expressions. Resource expressions could not be assigned ($a = notify
{hi:}). That is being changed. This removes several odd corners in the
grammar and makes it all more consistent. It is also highly unlikely
that it would be removed later (principle 1). The value of a resource
expression is a reference to the created resource, or an array of
references if there is more than one.

QUESTION: should the value always be an array of references? That
would make it much more predictable.

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:}) {}).

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).

Why is this?  It seems to make the language a lot more powerful, but a
lot more complex and harder to read.  I'd want to make sure there's a
good reason for that, especially since it takes the core statement in
the language and enables it to look and act very differently.

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!

Since we aren't going to change the behavior of resource default
expressions (Notify { ... }) it seems like there needs to be something
done to provide a better, safer way of specifying defaults. This will
allow:

  notify {
    default: message => hi;
    bye: }

The result will be a resource of type Notify with title bye and
message hi. It is highly unlikely that this will go away (principle 1)
as it is syntactic sugar for specifying the parameters for every resource.

I agree, this is cute and simple.

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 }

As a side note, do you see what can now be done?

  $a = notify
  $b = hi
  $c = { message => bye }
  $a { $b: *=> $c }

As above, this makes the language much more powerful and complex, and it
seems like makes it possible to build truly unreadable code without
trying very hard.

What's the use case for this, and why is that use case important enough
to justify this increase in complexity?


This is to support what is otherwise done in an opaque fashion with Ruby templates, or calling the create_resources function. It is mostly done by module authors that integrate with other modules, and where it is not known at authoring time what the name of the type is.

It allows allows a transformation of data to resources to be expressed in the puppet language. Again, the alternative is to transform to a generic hash and then call create_resources. Sometimes people create their own variants of create_resources as custom function because it
has been difficult to perform such transformations in the puppet language.

We believe that the ability to have indirection for the type is a better solution than the alternatives, even if looks more complex, it makes the logic visible and reduces the dependency on Ruby.

- 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/lr5mve%249an%241%40ger.gmane.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to