Re: [Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-19 Thread David Schmitt

On 2014-07-17 23:41, Henrik Lindberg wrote:

On 2014-17-07 14:56, David Schmitt wrote:

On 2014-07-12 04:50, Henrik Lindberg wrote:

On 2014-11-07 10:55, David Schmitt wrote:


[...snip...]


[1] It might be worthwhile to start requiring to always write
'realize(Type| expr |)' for this side-effect. This looks annoying.


it could be

   Type | expr |.realize


Ugh.


A positive Ugh, or a Ugh of agonizing pain? :-)


The latter.

[...snip ...]


I think this may just move the problem to dueling defaults, dueling
values, and dueling overrides. (This problem occurs in the binder and
there the problem is solved by the rules (expressed in the terms we use
here (except the term 'layer', which I will come back to):
- if two defaults are in conflict, a set value wins
- if two values are in conflict, an override wins
- if two overrides are in conflict, then the one made in the highest
layer wins.
- a layer must be conflict free


Don't you mean the highest layer with a value must be conflict free ?


yes, that is true, since some higher layer must resolve the issue. Not
meaningful to enforce resolution in every layer.


Good.


Highest (most important) layer is the environment, secondly all
modules - this means that conflicts bubble to the top, where a user
must resolve the conflict by making the final decision.

The environment level can be thought of as what is expressed in
site.pp, global or expressed for a  node (if we forget for a while
about all the crazy things puppet allows you to do with global scope;
open and redefine code etc).


If you mean what I think you mean, I think like it.

Another example to try to understand this:

   class somemodule { package { git: ensure = installed } }

   class othermodule { package { git: ensure = '2.0' } }

   node 'developer-workstation' {
 # force conflict on Package[git]#ensure here: installed != '2.0'
 include somemodule
 include othermodule

 # conflict resolved: higher layer saves the day
 Package[git] { ensure = '2.1' }
   }

How would the parser/grammar/evaluator understand which manifests are
part of what layer?



We will have a new catalog model (the result built by the new catalog
builder slated to replace the current compiler). There we have a richer
model for defining the information about resources. We also have a new
loader system that knows where code came from. Thus, anything loaded at
the environment level (i.e. node definitions) knows it is in a higher
layer.


Slick. The next question then is: How does the user know? ;-) And How 
fine-grained are levels? Each entry on the module path? Will I be able 
to query the puppetmaster for a report on which sources influenced (or 
did not influence) a specific value?


[snip]


If we make variables be part of the lazy logic you would be able to
write:

   $a = $b + 2
   $b = 2

I think this will confuse people greatly.


Hehe, I can imagine that. When accessing variables across files/classes
I do not see that as a big problem, though. Within a single file/scope
it can be forbidden, or at least warned/linted.


We will see what we end up with - this is currently not a primary
concern. One neat thing you can do with the future parser (and in 4.0)
is to evaluate code in a local block using the function 'with', and then
pass it arguments, the variables in the lambda given to with are all
local! Thus you can assign the final value from what that lambda returns.


I see, I'll have to read up on the future parser...


The crux here is that just having one expression being followed by
another - e.g:

   1 1

is this a call to 1 with 1 as an argument, or the production of one
value 1, followed by another?


Is the parser and the evaluator so intertwined that that cannot be
interpreted in context? 1 is not a callable, therefore it cannot be a
function call.


They are not intertwined except that the parser builds a model that the
evaluator evaluates. The evaluator does exactly what you say, it
evaluates the LHS, and if that is not a NAME it fails, and if the NAME
is not a reference to a Function it fails. But the evaluator can not do
that in general, there may be a sequence of say if statements, they all
produce a value, should the second if be an argument to attempting to
call what the first produced ?

   if true { teapot }
   if true { 'yes I am'}

The evaluator would have no way of knowing, except doing static analysis
(which limits the expressiveness).

Currently the parser rewrites NAME expr, or NAME expr ',' expr ... into
a function call. I do not want to add additional magic of the same kind
if it can be avoided.


Accepted.

[snip]


I am hacking on ideas to fix the problematic constructs in the grammar.
I have had some success, but it is to early to write about. Will come
back when I know more.


Good hunting!


Regards, David

--
You received this message because you are subscribed to the Google Groups Puppet 
Developers group.
To unsubscribe from this group and stop receiving emails 

Re: [Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-19 Thread David Schmitt

On 2014-07-18 02:01, Henrik Lindberg wrote:
[snip]

As David Schmitt pointed out, having to use multiple variables is a pita
in several use cases because imperative programming (discrete steps) has
to be taken to get the task done. We eventually would end up with
something F# or Haskel like, or something resembling Prolog, since doing

[snip]


You say that as if it were something bad./tongue-in-cheek



Regards, David

--
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/53CA3244.1080508%40dasz.at.
For more options, visit https://groups.google.com/d/optout.


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-19 Thread Henrik Lindberg

On 2014-19-07 10:51, David Schmitt wrote:



[...snip...]

We will have a new catalog model (the result built by the new catalog
builder slated to replace the current compiler). There we have a richer
model for defining the information about resources. We also have a new
loader system that knows where code came from. Thus, anything loaded at
the environment level (i.e. node definitions) knows it is in a higher
layer.


Slick. The next question then is: How does the user know? ;-) And How
fine-grained are levels? Each entry on the module path? Will I be able
to query the puppetmaster for a report on which sources influenced (or
did not influence) a specific value?



The model is borrowed from OSGi. Each component has visibility into 
its own things, and on the things it depends. A component may have 
private things that are not visible to other components. (OSGi also has 
a friend concept that we did not implement, and we have not (yet?) 
implemented re-publish (i.e. that one module (A) has visibility into 
another (B) and making its public loadable entities available to those 
who depend only on A). For that to make sense we need a way to alias the 
things in (B) or something in (C) can not address them because it only 
knows about things in the a:: namespace. (Either that or that a 
component may publish things in other name spaces under certain 
conditions).


For the purpose of loading, view the environment as a component that all 
modules have visibility into. There is also a system component (i.e. 
puppet runtime), and a static/internal (functions and things generated; 
like the logging functions, data types etc.) that is visible to all.




[snip]


Good hunting!



Spear in one hand, axe in the other...
- 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/lqe3nd%24mvi%241%40ger.gmane.org.
For more options, visit https://groups.google.com/d/optout.


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-19 Thread Henrik Lindberg

On 2014-19-07 17:43, Henrik Lindberg wrote:

On 2014-19-07 10:51, David Schmitt wrote:



[...snip...]

We will have a new catalog model (the result built by the new catalog
builder slated to replace the current compiler). There we have a richer
model for defining the information about resources. We also have a new
loader system that knows where code came from. Thus, anything loaded at
the environment level (i.e. node definitions) knows it is in a higher
layer.


Slick. The next question then is: How does the user know? ;-) And How
fine-grained are levels? Each entry on the module path? Will I be able
to query the puppetmaster for a report on which sources influenced (or
did not influence) a specific value?



The model is borrowed from OSGi. Each component has visibility into
its own things, and on the things it depends. A component may have
private things that are not visible to other components. (OSGi also has
a friend concept that we did not implement, and we have not (yet?)
implemented re-publish (i.e. that one module (A) has visibility into
another (B) and making its public loadable entities available to those
who depend only on A). For that to make sense we need a way to alias the
things in (B) or something in (C) can not address them because it only
knows about things in the a:: namespace. (Either that or that a
component may publish things in other name spaces under certain
conditions).



I should also have mentioned that in Puppet 3.7 future parser (and 4.0), 
the new loaders are only used for the functions using the new Functions 
API. We expect to move the rest over in stepwise fashion.


Also, worth mentioning is that modules that lack meta data, or have no 
dependency section in their metadata has visibility into the environment 
and every other module.


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


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-18 Thread John Bollinger


On Friday, July 11, 2014 9:50:47 PM UTC-5, henrik lindberg wrote:

 On 2014-11-07 10:55, David Schmitt wrote: 
   [...]
 * 'Type| expr |' is the list of local resources of type 'type' in 
   the current compilation where 'expr' evaluates true. As a 
   side-effect, it realizes all matched virtual resources.[1] 
 Some sort of query operator. If we keep the | |, it could mean 
 selection of the virtual here container/subset, currently it is 
 everything defined here. 


[...]
 

   
  [1] It might be worthwhile to start requiring to always write 
  'realize(Type| expr |)' for this side-effect.



You are by no means the first to suggest that conflating realization of 
virtual resources with selecting a collection of resources was a poor 
idea.  With the much higher profile that collections have nowadays, I think 
that is becoming a more pressing issue.

 

  This looks annoying. 

 it could be 

Type | expr |.realize 



Couldn't it also just be

realize Type | expr |

?  I mean, at least some Puppet functions already do not require 
parentheses around their arguments under some circumstances (e.g. 
include()).  It makes more sense to me to put the function name / keyword 
first, but the parentheses are optional as far as I am concerned, and it 
reads more cleanly without them.

Alternatively, perhaps there can be a new selection criterion that limits 
collections to resources that are in the catalog (at the time the 
collection's contents are determined).  That would allow current collector 
semantics to remain the same, while still affording manifest authors the 
ability to collect resources without realizing still-virtual ones.  The 
same or similar criteria could be used to narrow results to other 
categories of resources.


Also, long ago I made a feature request that collections be usable as 
r-values.  My main idea for that was to be able to assign collections to 
the relational metaparameters, and that purpose is now served by chain 
expressions instead.  Still, I suspect there are still other uses for 
collections as r-values, and it sounds like that may be one of the 
directions this is going.  If that can be made to work smoothly, then it 
would be pretty cool.  On the other hand, I don't have specific use cases 
in mind, so I wouldn't personally consider this a priority, and maybe not 
even a real candidate for implementation.


John

-- 
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/78ba2133-5f94-4625-b6bf-04edd4e0b1f3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-18 Thread Henrik Lindberg

On 2014-18-07 19:33, John Bollinger wrote:

On Friday, July 11, 2014 9:50:47 PM UTC-5, henrik lindberg wrote:
On 2014-11-07 10:55, David Schmitt wrote:
  [...]
 * 'Type| expr |' is the list of local resources of type
'type' in
   the current compilation where 'expr' evaluates true. As a
   side-effect, it realizes all matched virtual resources.[1]
Some sort of query operator. If we keep the | |, it could mean
selection of the virtual here container/subset, currently it is
everything defined here.

[...]


  [1] It might be worthwhile to start requiring to always write
  'realize(Type| expr |)' for this side-effect.

You are by no means the first to suggest that conflating realization of
virtual resources with selecting a collection of resources was a poor
idea.  With the much higher profile that collections have nowadays, I
think that is becoming a more pressing issue.

  This looks annoying.

it could be

Type | expr |.realize



Couldn't it also just be

 realize Type | expr |


yes, it could, realize is a function that may be called without parentheses.


?  I mean, at least some Puppet functions already do not require
parentheses around their arguments under some circumstances (e.g.
include()).  It makes more sense to me to put the function name /
keyword first, but the parentheses are optional as far as I am
concerned, and it reads more cleanly without them.

Alternatively, perhaps there can be a new selection criterion that
limits collections to resources that are in the catalog (at the time the
collection's contents are determined).  That would allow current
collector semantics to remain the same, while still affording manifest
authors the ability to collect resources without realizing still-virtual
ones.  The same or similar criteria could be used to narrow results to
other categories of resources.

We are thinking about a new kind of query mechanism. This because 
changing semantics of the current mechanism is going to cause lots of 
breakage.




Also, long ago I made a feature request that collections be usable as
r-values.  My main idea for that was to be able to assign collections to
the relational metaparameters, and that purpose is now served by chain
expressions instead.  Still, I suspect there are still other uses for
collections as r-values, and it sounds like that may be one of the
directions this is going.  If that can be made to work smoothly, then it
would be pretty cool.  On the other hand, I don't have specific use
cases in mind, so I wouldn't personally consider this a priority, and
maybe not even a real candidate for implementation.


These are indeed the kinds of things we want to be able to do.

Priority wise, we are first going to reimplement the collection 
mechanism in such a way that we can delete the old code it depends on. 
Later (after 4.0) we are going to be working on the new catalog builder.


What we want to ensure now is that we make the necessary grammar changes 
to the language that makes it possible for us to gradually introduce 
these new features.


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


Re: [Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-17 Thread David Schmitt

On 2014-07-12 04:50, Henrik Lindberg wrote:

On 2014-11-07 10:55, David Schmitt wrote:

I really dig this idea. Reading it sparked a crazy idea in the
language-designer part of my brain: What about going even further and
making the RHS also an Expression?

In the grammar basically everything would become a function call or just
a sequence of expressions. For the expressiveness of the language it
might do wonders:


Yes, that is how everything else works, but cannot because of the
ambiguity in hash vs. resource body/bodies (in the two different shapes
for regular, override/defaults).


   $ref = File[id]
   $select = File|title == id|
   $ref == $select # true
   $type = File


Yes, except we will have issues with the query (it is lazy now). We
either need to make it evaluate immediately, or make the return value
a Future.


   $values = { id = { mode = 0664, owner = root } }
   # equivalent hash shortcut notation for backwards compat and
   # keystroke reduction
   $values = { id: mode = 0664, owner = root }


Ah, neat idea make { x: y = z } mean the same as {x = { y = z}} !


   $defaults = { owner = def, group = def }
   $overrides = { mode = 0 }

   $final = hash_merge($values, { default: $defaults })


Did you mean?
 hash_merge($defaults, $overrides)

(which btw is the same as $defaults + $overrides).
Or, was that an example of a special instruction to the hash_merge to
treat a key of literal 'default' as things that do not override (i.e.
all other keys override, but 'default' defines what to pick if nothing
defined. If so, This is easily expressed directly in the language like
this:

 $final = $defaults + $values + $overrides


Ah, nice! Actually I was thinking of something completely different, but 
this is better.



   # old style
   create_resources($type, $values, $defaults)
   # basic resource statement
   $type $final

This is problematic, we cannot make any sequence a function call without
requiring that every expression is terminated with punctuation (e.g.
';') - but that must then be applied everywhere.



You are right, having that in the grammar makes no sense. I still think 
it is a neat detail to keep in mind when thinking about the underlying 
structure of what we're building.



   # interpreted as function call
   $type($final)


This is problematic because:
- selecting what to call via a general expression has proven in several
languages to be a source of thorny bugs in user code.


Conceded.


   # override chaining
   $ref $overrides
   $select $overrides

   # if create_resources would return the created resources:

It should.


   $created = create_resources($type, $values, $defaults)
   $created $overrides

   # replace create_resources
   File hiera('some_files')

   # different nesting
   file { /tmp/foo: $value_hash }

   # extreme override chaining
   File['/tmp/bar']
   { mode = 0644 }
   { owner = root }
   { group = root }

   # inverse defaulting
   file { [ '/tmp/1', '/tmp/2' ]: } { mode = 0664, owner = root }

   # define defined()
   defined(File['/tmp/bar']) == !empty(File|title == '/tmp/bar'|)

This would require unifying the attribute overriding semantics as almost
everything would become a override.

It would also lift set-of-resources as currently used in simple
collect-and-override statements to an important language element as
almost everything touching resources would return such a set.

Formalizing this a little bit:

   * 'type' is a type reference.
   * 'Type' is the list of resources of type 'type' in the current
 catalog (compilation).

This is actually a reference to the set that includes all instances of
that type (irrespective of if they actually exist anywhere). Something
needs to narrow that set to in the catalog (which is actually several
sets; realized, virtual, exported from here, imported to here, ...). To
get such a set, there should be a query operator (it operates on a
container and takes a type and predicates for that type).


   * 'Type[expr]' is the resource of type 'type' and the title equal
 to the result of evaluating 'expr'

yes

   * 'Type| expr |' is the list of local resources of type 'type' in
 the current compilation where 'expr' evaluates true. As a
 side-effect, it realizes all matched virtual resources.[1]

Some sort of query operator. If we keep the | |, it could mean
selection of the virtual here container/subset, currently it is
everything defined here.


If functions can return sets of resources that can be manipulated, the 
special query operator syntax can be abolished - or at least 
de-emphasised. See Eric's puppetdbquery for an example.



   * 'Type| expr |' is the list of local and exported resources of
 type 'type' where 'expr' evaluates true. As a side-effect,
 it realizes all matched exported resources.[2]

Same comment as above, but using a different container.


   * '{ key = value, }' is a simple hash ('hash')
   * '{ title: key = value, }' is a hash-of-hashes. Let's call this a
 

[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-17 Thread Reid Vandewiele
On Friday, July 11, 2014 7:50:47 PM UTC-7, henrik lindberg wrote:


 Here we have another problem; variables defined in classes are very 
 different from those defined elsewhere - they are really 
 attributes/parameters of the class. All other variables follow the 
 imperative flow. That has always bothered me and causes leakage from 
 classes (all the temporary variables, those used for internal purposes 
 etc). This is also the source of immutable variables, they really do 
 not have to be immutable (except in this case). 

 If we make variables be part of the lazy logic you would be able to write: 

$a = $b + 2 
$b = 2 

 I think this will confuse people greatly. 


Slightly off-topic so I'll keep it short.

I have a huge appreciation for immutable variables in the Puppet language 
as I think it helps keep people centered in the mindset of declarative 
configuration and not procedural programming. The fact that variable values 
are parse-order dependent is detrimental in that it forces users to hold 
and visualize a more complex model in order to not get tripped up by 
parse-order dependencies. Resources can only be declared once and can be 
referred to before they've been hit by the parser. I would strongly support 
variables being the same. Today they are immutable and so have one foot in 
that door. Making them part of the lazy logic sounds like it could get them 
the rest of the way.

Outside of technical implementation challenges, it would be a good thing if 
variables were immutable and lazily evaluated in such a way as to make the 
example given above work.

Is there an existing thread or Jira ticket that would be a more appropriate 
place to discuss further?

-- 
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/e492657e-4deb-4f85-afa5-fc404bc9518e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-17 Thread Henrik Lindberg

On 2014-17-07 14:56, David Schmitt wrote:

On 2014-07-12 04:50, Henrik Lindberg wrote:

On 2014-11-07 10:55, David Schmitt wrote:

[...snip...]


   # old style
   create_resources($type, $values, $defaults)
   # basic resource statement
   $type $final

This is problematic, we cannot make any sequence a function call without
requiring that every expression is terminated with punctuation (e.g.
';') - but that must then be applied everywhere.



You are right, having that in the grammar makes no sense. I still think
it is a neat detail to keep in mind when thinking about the underlying
structure of what we're building.

yes, basically an expression that is a kind of join between a Puppet 
Type[Resource] and application of one or multiple sets of data.


[...snip...]


If functions can return sets of resources that can be manipulated, the
special query operator syntax can be abolished - or at least
de-emphasised. See Eric's puppetdbquery for an example.


yes, that is the direction this is going.


   * 'Type| expr |' is the list of local and exported resources of
 type 'type' where 'expr' evaluates true. As a side-effect,
 it realizes all matched exported resources.[2]

Same comment as above, but using a different container.


   * '{ key = value, }' is a simple hash ('hash')
   * '{ title: key = value, }' is a hash-of-hashes. Let's call this a
 untyped resource ('ur') due to its special syntax[3].
   * 'type ur' now syntactically matches what puppet3 has and evaluates
 to the set of resources ('resset') created by
 create_resources('type', 'ur').
   * '[Type1[expr1], Type2[expr2]]' is the resset containing
 'Type1[expr1]' and 'Type2[expr2]'.

That is what you get now. (or rather you get a set of references to the
resource instances, not the instances themselves).


Is there a distinguishable difference for the language user?

No, not really. The type is a reference, the operations on it looks it 
up or creates new. In the current implementation the one and same class 
is used for both references and the real thing (this causes great pain 
and confusion in the code).



   * 'resset hash' (e.g. 'File { mode = 0 }') is an override
expression.
 It sets all values from 'hash' on all resources in 'resset'.
   * 'resset - resset' (and friends) define resource relationships
 between sets of resources.
 'Yumrepo - Package' would be a nice example, also avoiding
 premature realization.

The relations are recorded as being between references.


   * 'create_resource(type, ur)' returns a resset containing resources
 of type 'type' with the values from 'ur'. Written differently,
 'create_resource' becomes a cast-and-realize operator.[4]
 - This allows things like 'create_resource(...) - resset' and
   'create_resource(...) hash'
   * 'include someclass' returns the resset of all resources included in
 'someclass'. Note that 'included' is a very weakly defined concept
 in puppet, see Anchor Pattern.

Hm, intriguing idea.


   * Instances of user-defined types might also be seen as heterogeneous
 ressets.


Yes.



[1] It might be worthwhile to start requiring to always write
'realize(Type| expr |)' for this side-effect. This looks annoying.


it could be

   Type | expr |.realize


Ugh.


A positive Ugh, or a Ugh of agonizing pain? :-)


[2] Unintentionally realized exported resources seem a much less
frequent problem than the same side-effect on virtual resources causes.
It might make sense to avoid [1] and instead introduce something like
'Type[|expr|]' and 'Type[[|expr|]]' to select without realizing.


I like to go in the other direction with fewer special operators.


As said above, functions returning resource sets might be the way to go
then. It's not like we need to design the next APL ;-)

yes agree, functions are good - operators are ok too when they are non 
ambiguous and not too exotic :-)


[...snip ...]

I think this may just move the problem to dueling defaults, dueling
values, and dueling overrides. (This problem occurs in the binder and
there the problem is solved by the rules (expressed in the terms we use
here (except the term 'layer', which I will come back to):
- if two defaults are in conflict, a set value wins
- if two values are in conflict, an override wins
- if two overrides are in conflict, then the one made in the highest
layer wins.
- a layer must be conflict free


Don't you mean the highest layer with a value must be conflict free ?

yes, that is true, since some higher layer must resolve the issue. Not 
meaningful to enforce resolution in every layer.



Highest (most important) layer is the environment, secondly all
modules - this means that conflicts bubble to the top, where a user
must resolve the conflict by making the final decision.

The environment level can be thought of as what is expressed in
site.pp, global or expressed for a  node (if we forget for a while
about all the crazy things puppet allows you to do 

[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-17 Thread Henrik Lindberg

On 2014-17-07 20:53, Reid Vandewiele wrote:

On Friday, July 11, 2014 7:50:47 PM UTC-7, henrik lindberg wrote:


Here we have another problem; variables defined in classes are very
different from those defined elsewhere - they are really
attributes/parameters of the class. All other variables follow the
imperative flow. That has always bothered me and causes leakage from
classes (all the temporary variables, those used for internal purposes
etc). This is also the source of immutable variables, they really do
not have to be immutable (except in this case).

If we make variables be part of the lazy logic you would be able to
write:

$a = $b + 2
$b = 2

I think this will confuse people greatly.


Slightly off-topic so I'll keep it short.

I have a huge appreciation for immutable variables in the Puppet
language as I think it helps keep people centered in the mindset of
declarative configuration and not procedural programming. The fact that
variable values are parse-order dependent is detrimental in that it
forces users to hold and visualize a more complex model in order to not
get tripped up by parse-order dependencies. Resources can only be
declared once


This is going to change - many want to be able to declare the a resource 
multiple times, and that the non conflicting result is merged.
The resource does not exist until it is evaluated; you can have 
references to it (or to any non existing resource) - things must resolve 
at the end naturally.



and can be referred to before they've been hit by the
parser.


The are never hit by the parser - the parser is what translates the 
source text into something that can be acted on, it does not evaluate 
anything, or schedule lazy evaluation etc. That is the combination of 
the evaluator (in the future parser), and an invisible evaluator that is 
split up between all the AST objects in the current implementation.


I think you meant, can be referenced independently of the evaluation 
order... but that is always true - you can reference anything even 
things that do not exist (only you get an error at the end).


It is the instruction / operator that have lazy evaluation; say $a - $b 
which evaluates $a and $b to produce references to resource and then 
asks the compiler to make it so that everything in $b is after 
everything in $a. It is at the point where the lazy operator is 
evaluated that it is an error to reference something that does not exist.



I would strongly support variables being the same. Today they
are immutable and so have one foot in that door. Making them part of the
lazy logic sounds like it could get them the rest of the way.

Well, there are different kinds of variables; those in a class are not 
really variables; they are more like the class' attributes/parameters. 
For a define the variables are not attributes (only the declared 
parameters are).



Outside of technical implementation challenges, it would be a good thing
if variables were immutable and lazily evaluated in such a way as to
make the example given above work.

Is there an existing thread or Jira ticket that would be a more
appropriate place to discuss further?

There have been several tickets in the past where this has been 
discussed (starting with various ideas). We already have complex 
dependency orders in our evaluation, adding yet another such mechanism 
on top seems like more opportunities to create endless loops and 
deadlocks. The capability lazy values must be introduced in a safe 
way. On that topic we do have some ideas, but it will take a while to 
write them up into a coherent proposal.


I do not think lazy evaluation is appropriate for all kinds of variables 
because we have an imperative language that constructs a lazily 
evaluated catalog that in turn is declarative.


As David Schmitt pointed out, having to use multiple variables is a pita 
in several use cases because imperative programming (discrete steps) has 
to be taken to get the task done. We eventually would end up with 
something F# or Haskel like, or something resembling Prolog, since doing 
this for variables is just the tip of the iceberg. Would be cool to see 
a full function oriented puppet language variant...


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


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-11 Thread Henrik Lindberg

On 2014-11-07 10:55, David Schmitt wrote:

Hi *,

On 2014-07-07 03:26, Henrik Lindberg wrote:

The egrammar (as well as the current grammar in 3x) tries to be helpful
by recognizing certain combinations as illegal (an override that is
virtual or exported), a resource default or override cannot specify a
title. This unfortunately means that the grammar has to recognize
sequences of tokens that makes this grammar ambiguous and it has to be
solved via operator precedence tricks (that makes the problem show up as
other corner cases of the grammar). (This is a classic mistake of trying
to implement too much semantics in the grammar / parser).

So...

What if we simply made the three resource expressions (create resource,
set resource defaults, an resource override) have exactly the same
grammar, and push of validation to the static validation that takes
place and the runtime.

Basically the grammar would be (I am cheating just a little here to
avoid irrelevant details):

 ResourceExpression
   : At? left_expr = Expression '{' ResourceBodies ';'? '}'
   ;

 ResourceBodies
   : ResourceBody (';' ResourceBody)*
   ;

 ResourceBody
   : title = Expression ':' AttributeOperations ','?
   ;

 AttributeOperations
   : AttributeOperation (',' AttributeOperation)*
   ;

 AttributeOperation
   : AttributeName ('=' | '+') Expression

 AttributeName
   : NAME |  KeywordsAcceptableAsAttributeName
   ;

 # Details here irrelevant, meaning is: virtual or exported resource
 # AT is the '@' token
 At
   : AT
   | AT AT
   | ATAT
   ;

So, how are the three kinds expressed? Notice that a title is required
for each ResourceBody. So we are basically going to handle different
combinations of left_expr and titles. We simply evaluate the left_expr
at runtime and treat the combinations of the *resulting* type and type
of title:

[...]

Since what I propose simply evaluates the left expression there is no
reason to deny certain expression in this place, and it is possible to
use say a variable as indirection to the actual type.

   $a = Notify
   $a { hi: message = 'hello there' }

(Which is *very* useful to alias types). Strings can also be used - e.g.

   'notify' { hi: message = 'hello there'}

which also makes the grammar more symmetric (a bare word like notify is
just a string value i.e. 'notify'). (We still would not allow types
to have funny characters, spaces etc. but it is at least symmetrical).



I really dig this idea. Reading it sparked a crazy idea in the
language-designer part of my brain: What about going even further and
making the RHS also an Expression?

In the grammar basically everything would become a function call or just
a sequence of expressions. For the expressiveness of the language it
might do wonders:

Yes, that is how everything else works, but cannot because of the 
ambiguity in hash vs. resource body/bodies (in the two different shapes

for regular, override/defaults).


   $ref = File[id]
   $select = File|title == id|
   $ref == $select # true
   $type = File

Yes, except we will have issues with the query (it is lazy now). We 
either need to make it evaluate immediately, or make the return value

a Future.


   $values = { id = { mode = 0664, owner = root } }
   # equivalent hash shortcut notation for backwards compat and
   # keystroke reduction
   $values = { id: mode = 0664, owner = root }


Ah, neat idea make { x: y = z } mean the same as {x = { y = z}} !


   $defaults = { owner = def, group = def }
   $overrides = { mode = 0 }

   $final = hash_merge($values, { default: $defaults })


Did you mean?
hash_merge($defaults, $overrides)

(which btw is the same as $defaults + $overrides).
Or, was that an example of a special instruction to the hash_merge to 
treat a key of literal 'default' as things that do not override (i.e. 
all other keys override, but 'default' defines what to pick if nothing 
defined. If so, This is easily expressed directly in the language like this:


$final = $defaults + $values + $overrides


   # old style
   create_resources($type, $values, $defaults)
   # basic resource statement
   $type $final
This is problematic, we cannot make any sequence a function call without 
requiring that every expression is terminated with punctuation (e.g. 
';') - but that must then be applied everywhere.



   # interpreted as function call
   $type($final)


This is problematic because:
- selecting what to call via a general expression has proven in several 
languages to be a source of thorny bugs in user code.



   # override chaining
   $ref $overrides
   $select $overrides

   # if create_resources would return the created resources:

It should.


   $created = create_resources($type, $values, $defaults)
   $created $overrides

   # replace create_resources
   File hiera('some_files')

   # different nesting
   file { /tmp/foo: $value_hash }

   # extreme override chaining
   

[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-09 Thread John Bollinger


On Tuesday, July 8, 2014 3:16:46 PM UTC-5, henrik lindberg wrote:

 On 2014-08-07 18:09, John Bollinger wrote: 
  I tried hard to not like this, but then I recognized how congruent it is 
  -- or could be -- with one of my pet ideas: resource constraints.  Felix 
  implemented part of that idea, but as I understand it, he handled only 
  the diagnostic part (recognizing whether constraints were satisfied) and 
  not the prescriptive part (updating the catalog, if possible, to ensure 
  that declared constraints /are/ satisfied). 
  
  I don't much like the idea of overriding resource declarations as 
  such, but it's not such a big leap to reposition that as simply 
  declaring additional requirements (i.e. constraints) on resources that 
  (may) be declared elsewhere.  We get the rest of the way to a limited 
  form of prescriptive constraints by collapsing this variety of resource 
  overrides with resource declarations.  In other words, consider these 
  two expressions: 
  
  file { '/tmp/hello': ensure = 'file' } 
  File { '/tmp/hello': ensure = 'file' } 
  
  What if they meant exactly the same thing?  Specifically, what if they 
  meant there must be a resource in the catalog of type File and name 
  '/tmp/hello', having the value 'file' for its 'ensure' property? 
  Either one would then insert such a resource into the catalog if 
  necessary, and afterward attempt to set the (then) existing resource's 
  'ensure' parameter. 
  
  I say attempt to set the existing resource's parameter, because I 
  think we still need to forbid modifying a value that was set (to a 
  different value) somewhere else.  And that's more complicated than just 
  checking for undef, because it may be that undef is itself the 
  intentionally assigned parameter value, so that it would be an error to 
  change it.  It also might need to be more permissive for subclasses and 
  collectors. 
  
 Note that collection currently can modify any already set value on all 
 kinds of resources (regular, virtual and exported) at any point 
 throughout the evaluation. How is it that these rules are given such 
 mighty powers when a rule such as File['tmp/foo'] { owner = x } is 
 not allowed to override a set mode of the same file? (I understand the 
 need to guard against typos and unintentional changes). Basically I see 
 File[id] { x = y } as the same expression as File | title == id | { x 
 = y }. 



Well, they are manifestly different at least in that the collector version 
will realize the selected resource if need be.  I anyway agree that there 
is an issue there, but I'm not confident that I characterize it the same 
way you do.  That is, I don't think File[id] { x = y } is too weak; 
rather, I think File| title == id | { x = y } is too strong.  If one 
part of my manifest set declares a property value for some resource, then 
it is *wrong* for a different part to change it, because the result no 
longer satisfies the original requirement.

There's some room to moderate that position a bit, of course.  For example, 
I have less objection to these kinds of changes being performed via 
subclasses -- after all, that's the whole point of subclasses.  One could 
also argue, for instance, about whether it should be ok to override 
parameters of virtual or exported resources.  I think even these cases are 
uncomfortable, but I'm not prepared advocate for their foreclosure against 
the opposition that would surely arise.

 

  We could go farther with that.  If it seems wasteful to have two 
  different forms of the same statement, then we could apply additional 
  semantics to one or the other.  For example, perhaps the lowercase form 
  could implicitly declare all unmentioned parameters as undef, with the 
  effect that they could not be overridden to anything different..  I 
  don't know whether that would be useful, or whether there is some other 
  behavior that would be more useful.  Perhaps it would be best to just 
  let the two forms be equivalent, or maybe even to deprecate one. 
  
  
  Anyway, a few corner cases exist. A + is only allowed if it is a 
  default or override expression. 
  
  
  
  + is a bit of a dark horse in the regime of overrides, as modifying a 
  previously-declared parameter value is inherent in its design.  On the 
  other hand, it is currently useful for overrides only in subclasses and 
  collectors, where modifying a declared value is considered acceptable. 
  I don't think it's a major issue that evaluating a statement containing 
  a plussignment may yield an error, as long as the meaning of the 
  statement is not itself in question. 
  

 I like the direction this is going! You are absolutely right that 
 basically all these expressions (resource attribute settings, 
 overrides, defaults) basically define a set of rules that together 
 should define the resulting resources and the values of their attributes 
 (call them constraints or rules). 

 This would mean that + would be 

[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-09 Thread Henrik Lindberg

On 2014-09-07 20:56, John Bollinger wrote:



On Tuesday, July 8, 2014 3:16:46 PM UTC-5, henrik lindberg wrote:

On 2014-08-07 18:09, John Bollinger wrote:
  I tried hard to not like this, but then I recognized how
congruent it is
  -- or could be -- with one of my pet ideas: resource constraints.
  Felix
  implemented part of that idea, but as I understand it, he handled
only
  the diagnostic part (recognizing whether constraints were
satisfied) and
  not the prescriptive part (updating the catalog, if possible, to
ensure
  that declared constraints /are/ satisfied).
 
  I don't much like the idea of overriding resource declarations as
  such, but it's not such a big leap to reposition that as simply
  declaring additional requirements (i.e. constraints) on resources
that
  (may) be declared elsewhere.  We get the rest of the way to a
limited
  form of prescriptive constraints by collapsing this variety of
resource
  overrides with resource declarations.  In other words, consider
these
  two expressions:
 
  file { '/tmp/hello': ensure = 'file' }
  File { '/tmp/hello': ensure = 'file' }
 
  What if they meant exactly the same thing?  Specifically, what if
they
  meant there must be a resource in the catalog of type File and name
  '/tmp/hello', having the value 'file' for its 'ensure' property?
  Either one would then insert such a resource into the catalog if
  necessary, and afterward attempt to set the (then) existing
resource's
  'ensure' parameter.
 
  I say attempt to set the existing resource's parameter, because I
  think we still need to forbid modifying a value that was set (to a
  different value) somewhere else.  And that's more complicated
than just
  checking for undef, because it may be that undef is itself the
  intentionally assigned parameter value, so that it would be an
error to
  change it.  It also might need to be more permissive for
subclasses and
  collectors.
 
Note that collection currently can modify any already set value on all
kinds of resources (regular, virtual and exported) at any point
throughout the evaluation. How is it that these rules are given such
mighty powers when a rule such as File['tmp/foo'] { owner = x } is
not allowed to override a set mode of the same file? (I understand the
need to guard against typos and unintentional changes). Basically I see
File[id] { x = y } as the same expression as File | title == id |
{ x
= y }.



Well, they are manifestly different at least in that the collector
version will realize the selected resource if need be..  I anyway agree
that there is an issue there, but I'm not confident that I characterize
it the same way you do.  That is, I don't think File[id] { x = y } is
too weak; rather, I think File| title == id | { x = y } is too
strong.  If one part of my manifest set declares a property value for
some resource, then it is *wrong* for a different part to change it,
because the result no longer satisfies the original requirement.

I can agree with that too. That was my first reaction - overriding 
anything is just horrible.



There's some room to moderate that position a bit, of course.  For
example, I have less objection to these kinds of changes being performed
via subclasses -- after all, that's the whole point of subclasses.


Yeah, but that is like allowing it if you add please to the request,
since there would be nothing stopping you from subclassing and overriding.


One
could also argue, for instance, about whether it should be ok to
override parameters of virtual or exported resources.


I have less qualms about the virtual - they are sort of not baked yet.
It is when they are realized that it gets prickly IMO... also when 
mutating something that was exported from elsewhere (rewriting history).



I think even
these cases are uncomfortable, but I'm not prepared advocate for their
foreclosure against the opposition that would surely arise.

  We could go farther with that.  If it seems wasteful to have two
  different forms of the same statement, then we could apply
additional
  semantics to one or the other.  For example, perhaps the
lowercase form
  could implicitly declare all unmentioned parameters as undef,
with the
  effect that they could not be overridden to anything different..  I
  don't know whether that would be useful, or whether there is some
other
  behavior that would be more useful.  Perhaps it would be best to
just
  let the two forms be equivalent, or maybe even to deprecate one.
 
 
  Anyway, a few corner cases exist. A + is only allowed if it
is a
  default or override expression.
 
 
 
  + is a bit of a dark horse in the regime of overrides, as
modifying a
  

[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-08 Thread Henrik Lindberg
Oh, and another insight - there is a desire to be able to specify the 
same resource multiple times - if the values are the same, or augmenting 
values then it is not a conflict. This will require the new catalog 
builder we have been sketching on since it has a richer catalog model.


It just struck me, that if we do that, then there is really no 
difference between a Resource Override, and specifying values more than 
once and the Resource Override syntax can be removed.


- henrik



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


Re: [Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-08 Thread Trevor Vaughan

 there is a desire to be able to specify the same resource multiple times -
 if the values are the same, or augmenting values then it is not a conflict


Yes, please! I've wanted this for years!

Trevor


On Tue, Jul 8, 2014 at 7:05 AM, Henrik Lindberg 
henrik.lindb...@cloudsmith.com wrote:

 Oh, and another insight - there is a desire to be able to specify the same
 resource multiple times - if the values are the same, or augmenting values
 then it is not a conflict. This will require the new catalog builder we
 have been sketching on since it has a richer catalog model.

 It just struck me, that if we do that, then there is really no difference
 between a Resource Override, and specifying values more than once and the
 Resource Override syntax can be removed.

 - henrik




 --
 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/lpgjan%24thf%241%40ger.gmane.org.

 For more options, visit https://groups.google.com/d/optout.




-- 
Trevor Vaughan
Vice President, Onyx Point, Inc
(410) 541-6699
tvaug...@onyxpoint.com

-- This account not approved for unencrypted proprietary information --

-- 
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/CANs%2BFoXEmCqKWGZ92jzApa_qP4RKk7zdodUL6OgxiPMU5tc4SQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-08 Thread Ashley Penney
I've skipped everything else about these messages to beg for this too, this
is the single most important change we can make to the language to allow
users to use modules off the forge more easily.


On Tue, Jul 8, 2014 at 8:31 AM, Trevor Vaughan tvaug...@onyxpoint.com
wrote:

 there is a desire to be able to specify the same resource multiple times -
 if the values are the same, or augmenting values then it is not a conflict


 Yes, please! I've wanted this for years!

 Trevor


 On Tue, Jul 8, 2014 at 7:05 AM, Henrik Lindberg 
 henrik.lindb...@cloudsmith.com wrote:

 Oh, and another insight - there is a desire to be able to specify the
 same resource multiple times - if the values are the same, or augmenting
 values then it is not a conflict. This will require the new catalog builder
 we have been sketching on since it has a richer catalog model.

 It just struck me, that if we do that, then there is really no difference
 between a Resource Override, and specifying values more than once and the
 Resource Override syntax can be removed.

 - henrik




 --
 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/lpgjan%24thf%241%40ger.gmane.org.

 For more options, visit https://groups.google.com/d/optout.




 --
 Trevor Vaughan
 Vice President, Onyx Point, Inc
 (410) 541-6699
 tvaug...@onyxpoint.com

 -- This account not approved for unencrypted proprietary information --

 --
 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/CANs%2BFoXEmCqKWGZ92jzApa_qP4RKk7zdodUL6OgxiPMU5tc4SQ%40mail.gmail.com
 https://groups.google.com/d/msgid/puppet-dev/CANs%2BFoXEmCqKWGZ92jzApa_qP4RKk7zdodUL6OgxiPMU5tc4SQ%40mail.gmail.com?utm_medium=emailutm_source=footer
 .

 For more options, visit https://groups.google.com/d/optout.




-- 
Ashley Penney
ashley.pen...@puppetlabs.com
Module Engineer

*Join us at PuppetConf 2014**, September 23-24 in San Francisco
- http://puppetconf.com http://puppetconf.com/*

-- 
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/CAC9eg%2BnkNoDtt-ny83jAZ3tY4urD6iNj_%2BYVFSsYu7-FrR7%2BZQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-08 Thread Henrik Lindberg

On 2014-08-07 16:55, Ashley Penney wrote:

I've skipped everything else about these messages to beg for this too,
this is the single most important change we can make to the language to
allow users to use modules off the forge more easily.



Hear ya, load and clear. The first cut of the new catalog model has 
features that makes it possible to implement this (basically keeping 
track of multiple places or source). Lots of work remains, expect this 
to arrive in Puppet 5.


The first hurdle; dynamic scope has already been fixed - it would 
otherwise have made the feature impossible.


We do have to define how defaults work as well (who's defaults win).

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


[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-08 Thread John Bollinger


On Sunday, July 6, 2014 8:26:28 PM UTC-5, henrik lindberg wrote:

 Thank you everyone that commented on the first RFC for Resource Defaults 
 (and Collection) - some very good ideas came up. I am creating a new 
 thread because I wanted to take the Collection part in a separate 
 discussion (honestly I would like to burn the entire implementation - 
 but that is separate topic), and I want to present some new ideas about 
 defaults triggered by David Schmitts idea about defaults applicable to 
 only a resource body. 

 Let me back up and first describe a problem we have in the grammar. 

 The egrammar (as well as the current grammar in 3x) tries to be helpful 
 by recognizing certain combinations as illegal (an override that is 
 virtual or exported), a resource default or override cannot specify a 
 title. This unfortunately means that the grammar has to recognize 
 sequences of tokens that makes this grammar ambiguous and it has to be 
 solved via operator precedence tricks (that makes the problem show up as 
 other corner cases of the grammar).



I agree that that is a problem.  Are you saying that the 3.x grammar also 
has such ambiguities, or just that it also rejects some token sequences (as 
any grammar must do)?

 

 (This is a classic mistake of trying 
 to implement too much semantics in the grammar / parser). 

 So... 

 What if we simply made the three resource expressions (create resource, 
 set resource defaults, an resource override) have exactly the same 
 grammar, and push of validation to the static validation that takes 
 place and the runtime. 

 Basically the grammar would be (I am cheating just a little here to 
 avoid irrelevant details): 

  ResourceExpression 
: At? left_expr = Expression '{' ResourceBodies ';'? '}' 
; 

  ResourceBodies 
: ResourceBody (';' ResourceBody)* 
; 

  ResourceBody 
: title = Expression ':' AttributeOperations ','? 
; 

  AttributeOperations 
: AttributeOperation (',' AttributeOperation)* 
; 

  AttributeOperation 
: AttributeName ('=' | '+') Expression 

  AttributeName 
: NAME |  KeywordsAcceptableAsAttributeName 
; 

  # Details here irrelevant, meaning is: virtual or exported resource 
  # AT is the '@' token 
  At 
: AT 
| AT AT 
| ATAT 
; 

 So, how are the three kinds expressed? Notice that a title is required 
 for each ResourceBody. So we are basically going to handle different 
 combinations of left_expr and titles. We simply evaluate the left_expr 
 at runtime and treat the combinations of the *resulting* type and type 
 of title: 

 If left (result) is a String, it must be the name of a Resource Type. 
 The title works as it does now in 3x. In addition the title (of one 
 resource body) may be Default, which sets the defaults for this resource 
 expression only (all bodies in the same resource expression) - i.e. 
 Schmitt style. 

notify { hi: message = 'hello there' } 

file { 
  default: 
mode = '0331', 
owner = 'weird'; 
  '/tmp:foo': 
content = 'content 1' 
} 

 If the left is the keyword 'class', it works the same way as for when 
 the left is a String but defaults can now only set defaults for meta 
 parameters since there are no other attributes that work safely across 
 all classes. (Yes you can do this today with Class { } in 3x) 

 class { 'a::b': param = value } 
 class { default: audit = true } 

 If the left is Type[CatalogEntry] (i.e. a resource or class reference), 
 the meaning changes to either a default or an override.



I'm not fully up to speed on the type system, but surely if the left side 
evaluates to a resource or class *reference* then the statement can only be 
an override.  Right?  For it to express resource defaults, the left side 
must evaluate to a type -- either Class or a resource type.

 

 An example is 
 probably easier that lots of words to describe this: 

 Define the defaults for all instances of the resource type Notify: 

 Notify { default: 
   message = 'the default message' 
 } 

 Override the message for the notify resource hi. 

 Notify { hi: 
   message = 'ciao' 
 } 

 If the left type is instance specific it is now an error (since a title 
 followed by ':' is required to create a less ambiguous grammar) - if we 
 allowed this, a user could write: 

Notify[hi] { bye: message = 'adieu' } 

 we allow a very odd statement (and the reason why resource overrides 
 currently does not allow a title in its resource body). So, an error 
 for this case. 



I tried hard to not like this, but then I recognized how congruent it is -- 
or could be -- with one of my pet ideas: resource constraints.  Felix 
implemented part of that idea, but as I understand it, he handled only the 
diagnostic part (recognizing whether constraints were satisfied) and not 
the prescriptive part 

[Puppet-dev] Re: RFC2 - Resource Defaults

2014-07-08 Thread Henrik Lindberg

On 2014-08-07 18:09, John Bollinger wrote:



On Sunday, July 6, 2014 8:26:28 PM UTC-5, henrik lindberg wrote:

Thank you everyone that commented on the first RFC for Resource
Defaults
(and Collection) - some very good ideas came up. I am creating a new
thread because I wanted to take the Collection part in a separate
discussion (honestly I would like to burn the entire implementation -
but that is separate topic), and I want to present some new ideas about
defaults triggered by David Schmitts idea about defaults applicable to
only a resource body.

Let me back up and first describe a problem we have in the grammar.

The egrammar (as well as the current grammar in 3x) tries to be helpful
by recognizing certain combinations as illegal (an override that is
virtual or exported), a resource default or override cannot specify a
title. This unfortunately means that the grammar has to recognize
sequences of tokens that makes this grammar ambiguous and it has to be
solved via operator precedence tricks (that makes the problem show
up as
other corner cases of the grammar).



I agree that that is a problem.  Are you saying that the 3.x grammar
also has such ambiguities, or just that it also rejects some token
sequences (as any grammar must do)?

3x grammar does not have this specific problem; instead it has a dozen 
other problems because people worked around ambiguities by creating 
sub-trees of the expression tree for different kinds of expressions. It 
is just horrible.



(This is a classic mistake of trying
to implement too much semantics in the grammar / parser).

So...

What if we simply made the three resource expressions (create resource,
set resource defaults, an resource override) have exactly the same
grammar, and push of validation to the static validation that takes
place and the runtime.

Basically the grammar would be (I am cheating just a little here to
avoid irrelevant details):

  ResourceExpression
: At? left_expr = Expression '{' ResourceBodies ';'? '}'
;

  ResourceBodies
: ResourceBody (';' ResourceBody)*
;

  ResourceBody
: title = Expression ':' AttributeOperations ','?
;

  AttributeOperations
: AttributeOperation (',' AttributeOperation)*
;

  AttributeOperation
: AttributeName ('=' | '+') Expression

  AttributeName
: NAME | KeywordsAcceptableAsAttributeName
;

  # Details here irrelevant, meaning is: virtual or exported
resource
  # AT is the '@' token
  At
: AT
| AT AT
| ATAT
;

So, how are the three kinds expressed? Notice that a title is required
for each ResourceBody. So we are basically going to handle different
combinations of left_expr and titles. We simply evaluate the left_expr
at runtime and treat the combinations of the *resulting* type and type
of title:

If left (result) is a String, it must be the name of a Resource Type.
The title works as it does now in 3x. In addition the title (of one
resource body) may be Default, which sets the defaults for this
resource
expression only (all bodies in the same resource expression) - i.e.
Schmitt style.

notify { hi: message = 'hello there' }

file {
  default:
mode = '0331',
owner = 'weird';
  '/tmp:foo':
content = 'content 1'
}

If the left is the keyword 'class', it works the same way as for when
the left is a String but defaults can now only set defaults for meta
parameters since there are no other attributes that work safely across
all classes. (Yes you can do this today with Class { } in 3x)

 class { 'a::b': param = value }
 class { default: audit = true }

If the left is Type[CatalogEntry] (i.e. a resource or class reference),
the meaning changes to either a default or an override.



I'm not fully up to speed on the type system, but surely if the left
side evaluates to a resource or class *reference* then the statement can
only be an override.  Right?  For it to express resource defaults, the
left side must evaluate to a type -- either Class or a resource type.

The problem is that this happens before anything is evaluated, the 
grammar is making decisions on tokens, not what the result evaluates to.


What I want to do is to push the validation off to the runtime (where
it is known what the expressions evaluate to). Doing so requires that 
the resource expression is unambiguous - now I have to treat the 
following { } body as a kind of operator having a particular precedence. 
To be able to do this, I would like all resource expressions to have a 
title, as that makes the expr { expr : part unique

and cannot be