Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-12 Thread Felix Frank


On 01/09/2011 09:11 PM, Stefan Schulte wrote:
 On Fri, Jan 07, 2011 at 09:41:39PM +, R.I.Pienaar wrote:
 (forced to top post due to your html email)

 You cant avoid the scoping issues cos its broken.  You can work around them 
 though.

 
 To be honest I always found the current scoping kind of clear (because I
 thought of include like of »open a new block/subscope and drop the class
 contents right here«. What I always considered wrong was that you can include 
 a
 class more then once and it surprised me that it works. So you state
 that the include should always happen in top (node) scope? At least the
 multiple include whould then be sane.

The thing with this is: You cannot get sane and working all at once
when taking this use case into account:

class common {
  $ssh_listen_ip = 10.0.0.1
  include ssh_server
}

where $ssh_listen_ip is used in ssh_server. This dynamic scoping is the
only way of making classes dynamic where parameterized classes are not
used (or not available).

Putting all classes in the top scope implicitly kills dynamic scoping.
I'd estimate that lots of manifests (possibly all that aren't extlookup
based) cannot suffer the removal of dynamic scoping at this point.

The insanity this can induce is a huge problem (e.g.
http://projects.puppetlabs.com/issues/4748), as you mention, so it's
important (imho) for the puppet team to get the concept of parameterized
classes right. Once that's done, scoping may or may not be obsolete, but
at least the dynamic scoping as used in the above example could safely
go out the window.

Cheers,
Felix

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-10 Thread Peter Meier
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

 dont you find having to specify the relationships of httpd::ssl and
 httpd here to be wrong?
 
 Isn't the fact that the httpd module is designed to have this
 ordering requirement an implementation detail and not a usage
 detail?
 
 Surely people who just want to use the httpd module do not need to
 know this implementation detail?  They should just be able to say use
 the module without understanding or knowing the ordering of
 internals.

 It's also not very DRY.

Yep, I also recently started thinking about various new introduced
problems I see with parametrized classes. For example, how could I do
the following in the future with parametrized classes:

class apache {}
define apache::vhost(){
  include ::apache
  ...
}

so the user only needs to define:

apache::vhost{'example.com': }

and everything else is pulled in automatically.

This gives a very nice interface, is easy to use and if this way of
writing puppet code wouldn't be anymore possible my infrastracture code
would get *very* overloaded and ugly.

And as R.I.Pienaar outlined later, we learned in the past to deal with
the current scoping problems, but still producing more or less nice
code. Although, I agree that parametrized classes provide a much nicer
interface and I'm very happy they got introduced, I'm already seeing
some problems with them:

class apache($version = 'latest') {}
define apache::vhost(){
  class{'apache': }
  ...
}

This will raise problems if we define a second vhost. With the current
scoping issues and my rule of thumb (First define all variables, then
include classes) I had no problem with writing:

$apache_version = '2.2.18'
apache::vhost{'example.com': }
apache::vhost{'cdn.example.com': }

But how would I do that now?

A possible solution would be to put the variables in a config class:

class apache::config($version='latest'){}
class apache {
  package{'apache':
ensure = ${apache::config::version},
  }
}
define apache::vhost(){
  include ::apache
  ...
}

and then write:

class{'apache::config': version = '2.2.18' }
apache::vhost{'example.com': }
apache::vhost{'cdn.example.com': }

But how can I ensure that apache::config is loaded/included/applied when
we include ::apache?

I currently only see:

class apache {
  if !defined(Class['apache::config']){
class{'apache::config': }
  }
  package{'apache':
ensure = ${apache::config::version},
  }
}

But this raises other ordering problems and breaks another rule of thumb
of mine: Never use defined() as it can be seen as codesmell, for example
exactly due to the ordering problems it raises.
But this is the best solution I can currently come up with. Although, it
still smells in my opinion.

~pete

PS: Sorry, to come up with code examples, however I think I can express
the current *new* limitations with them the best way. I will try to
think about a non-code discussion contribution and maybe add it later to
the thread.
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk0rgaYACgkQbwltcAfKi38w4gCeJ8j3B6zcilYnXicgambV5Ty7
eqwAn1L86SUkKuMYwKTnVopNNgNntBBW
=ODmw
-END PGP SIGNATURE-

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-09 Thread Stefan Schulte
On Fri, Jan 07, 2011 at 09:41:39PM +, R.I.Pienaar wrote:
 (forced to top post due to your html email)
 
 You cant avoid the scoping issues cos its broken.  You can work around them 
 though.
 

To be honest I always found the current scoping kind of clear (because I
thought of include like of »open a new block/subscope and drop the class
contents right here«. What I always considered wrong was that you can include a
class more then once and it surprised me that it works. So you state
that the include should always happen in top (node) scope? At least the
multiple include whould then be sane.

And 2 short questions:
- Do parametrised classes behave any different from included classes
  (regarding the scope)
- How would a parametrised class inherit from another parametrised
  class?

-Stefan


pgp4KcuAumC2E.pgp
Description: PGP signature


Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-09 Thread Dan Bode
On Sun, Jan 9, 2011 at 12:11 PM, Stefan Schulte 
stefan.schu...@taunusstein.net wrote:

 On Fri, Jan 07, 2011 at 09:41:39PM +, R.I.Pienaar wrote:
  (forced to top post due to your html email)
 
  You cant avoid the scoping issues cos its broken.  You can work around
 them though.
 

 To be honest I always found the current scoping kind of clear (because I
 thought of include like of »open a new block/subscope and drop the class
 contents right here«. What I always considered wrong was that you can
 include a
 class more then once and it surprised me that it works. So you state
 that the include should always happen in top (node) scope? At least the
 multiple include whould then be sane.

 And 2 short questions:
 - Do parametrised classes behave any different from included classes
  (regarding the scope)


they behave like resources, in that they can only be declared once

the obvious difference is they allow parameters and can set defaults ;)


 - How would a parametrised class inherit from another parametrised
  class?


If the parent class requires parameters than it also must be declared and
those parameters should be set.



 -Stefan


-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-08 Thread Patrick

On Jan 7, 2011, at 3:35 PM, Jeff McCune wrote:

 OK, so what if declaring* a class always added it to the top scope?
 This seems like a relatively straight forward solution to a great many
 concerns.  The language doesn't change, existing manifests continue to
 work and only the convention of relying on the order of variable
 definitions is affected.  The problem of resource defaults also almost
 entirely goes away too.  This was proposed in the original discussion
 about scoping back in July and I'm just curious if there's any new
 information in this area.

Just some more feedback.

I'd always assumed it did this.  I probably would have found out the hard way 
if I hadn't read it here.

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Felix Frank
 class puppetmaster {
   include common
   include puppet
   include ldap_auth
   include iptables::disabled
   include httpd::ssl
   include ruby-enterprise::passenger
 }

Hi Luke,

I haven't dipped into 2.6 yet, but afaik, this would simply become

class puppetmaster {
  class { [
 puppet,
 ldap_auth,
 iptables::disabled,
 httpd::ssl,
 ruby-enterprise::passenger,
   ]:
}

The initial dumb translation shouldn't be hard.

Cheers,
Felix

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Jeff McCune
On Fri, Jan 7, 2011 at 2:47 AM, luke.bigum luke.bi...@fasthosts.co.ukwrote:

 Hi list,

 Reading the thread can a class require an other class? it's been
 mentioned that perhaps one way forward for the Puppet language is to
 phase out the include keyword in favour of parametrised classes. I'm
 thinking of my Puppet and the several levels of include chaining I use
 and I'm wondering how on earth that'd be possible. Maybe I'm designing
 my modules very differently to other people?

 I'll throw you an edited example from my environment and if the people
 who favour parametrised classes over includes could show me their
 alternatives that would be much appreciated. I haven't mentioned
 resources because the class names are pretty self explanatory - each
 class handles any package, service and config files related to it's
 name:

 node 'somenode' {
  include puppetmaster
 }

 class puppetmaster {
  include common
  include puppet
  include ldap_auth
  include iptables::disabled
  include httpd::ssl
  include ruby-enterprise::passenger
 }

 class ruby-enterprise::passenger {
  include common
  include httpd
  include ruby-enterprise
 }

 class httpd::ssl {
  include httpd
 }


The issue I'm trying to address is the current problem with scoping.
Considering class common, it will be nested inside of the puppetmaster OR
the ruby-enterprise::passenger class and it's not clear which one.  Behavior
can change depending on which if variables or resource defaults are being
referenced outside the scope of class common.

My recommendation is to try and make sure common classes, like class
common are only included in one place that make sense for you.  I would
personally write this collection of classes as:

(Note, this may be over-specifying dependency relationships, but ideally
this shouldn't be a huge problem for you if resources aren't establishing
direct relationships with resources in other classes.  Run stages may also
be a good substitute for the require metaparameter on classes.)

Also, I'm totally open to suggestions to improve this organization scheme,
it clearly has issues but it's the best I've come up so far and works well
across the largest subset of Puppet deployments I've worked with.

node 'somenode' {

  class { common: }

  class { [ ldap_auth,
puppet,
iptables::disabled,
httpd,
ruby-enterprise ]: require = Class[common],
  }

  class { puppetmaster: require = Class[puppet] }

  class { httpd::ssl: require = Class[httpd] }

  class { ruby-enterprise::passenger:
require = Class[ruby-enterprise, httpd]
  }

}

class puppetmaster { }
class ruby-enterprise::passenger { }
class httpd::ssl { }


Hope this helps,
-- 
Jeff McCune
http://www.puppetlabs.com/

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread R.I.Pienaar


- Original Message -
 On Fri, Jan 7, 2011 at 2:47 AM, luke.bigum 
 luke.bi...@fasthosts.co.uk  wrote:
 
 
 
 Hi list,
 
 Reading the thread can a class require an other class? it's been
 mentioned that perhaps one way forward for the Puppet language is to
 phase out the include keyword in favour of parametrised classes. I'm
 thinking of my Puppet and the several levels of include chaining I use
 and I'm wondering how on earth that'd be possible. Maybe I'm designing
 my modules very differently to other people?
 
 I'll throw you an edited example from my environment and if the people
 who favour parametrised classes over includes could show me their
 alternatives that would be much appreciated. I haven't mentioned
 resources because the class names are pretty self explanatory - each
 class handles any package, service and config files related to it's
 name:
 
 node 'somenode' {
 include puppetmaster
 }
 
 class puppetmaster {
 include common
 include puppet
 include ldap_auth
 include iptables::disabled
 include httpd::ssl
 include ruby-enterprise::passenger
 }
 
 class ruby-enterprise::passenger {
 include common
 include httpd
 include ruby-enterprise
 }
 
 class httpd::ssl {
 include httpd
 }
 
 
 The issue I'm trying to address is the current problem with scoping.
 Considering class common, it will be nested inside of the puppetmaster
 OR the ruby-enterprise::passenger class and it's not clear which one.
 Behavior can change depending on which if variables or resource
 defaults are being referenced outside the scope of class common.
 
 My recommendation is to try and make sure common classes, like class
 common are only included in one place that make sense for you. I
 would personally write this collection of classes as:
 
 (Note, this may be over-specifying dependency relationships, but
 ideally this shouldn't be a huge problem for you if resources aren't
 establishing direct relationships with resources in other classes. Run
 stages may also be a good substitute for the require metaparameter on
 classes.)
 
 Also, I'm totally open to suggestions to improve this organization
 scheme, it clearly has issues but it's the best I've come up so far
 and works well across the largest subset of Puppet deployments I've
 worked with.
 
 node 'somenode' {
 
 class { common: }
 
 class { [ ldap_auth,
 puppet,
 iptables::disabled,
 httpd,
 ruby-enterprise ]: require = Class[common],
 }
 
 class { puppetmaster: require = Class[puppet] }
 
 class { httpd::ssl: require = Class[httpd] }
 
 class { ruby-enterprise::passenger:
 require = Class[ruby-enterprise, httpd]
 }
 
 }


dont you find having to specify the relationships of httpd::ssl and httpd here 
to be wrong?

Isn't the fact that the httpd module is designed to have this ordering 
requirement an implementation detail and not a usage detail?

Surely people who just want to use the httpd module do not need to know this 
implementation detail?  They should just be able to say use the module without 
understanding or knowing the ordering of internals.  

If the internals of the modules are designed such that they require ordering of 
the sub classes then that is up to that module to specify in it.  People who 
download from the forge should not need to concern themselves with this.

It's also not very DRY.

 
 class puppetmaster { }
 class ruby-enterprise::passenger { }
 class httpd::ssl { }
 
 
 Hope this helps,
 --
 Jeff McCune
 http://www.puppetlabs.com/
 
 
 
 --
 You received this message because you are subscribed to the Google
 Groups Puppet Users group.
 To post to this group, send email to puppet-us...@googlegroups.com.
 To unsubscribe from this group, send email to
 puppet-users+unsubscr...@googlegroups.com.
 For more options, visit this group at
 http://groups.google.com/group/puppet-users?hl=en.

-- 
R.I.Pienaar

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Jeff McCune
On Fri, Jan 7, 2011 at 12:39 PM, R.I.Pienaar r...@devco.net wrote:



 - Original Message -
  On Fri, Jan 7, 2011 at 2:47 AM, luke.bigum 
  luke.bi...@fasthosts.co.uk  wrote:
 
 
 
  Hi list,
 
  Reading the thread can a class require an other class? it's been
  mentioned that perhaps one way forward for the Puppet language is to
  phase out the include keyword in favour of parametrised classes. I'm
  thinking of my Puppet and the several levels of include chaining I use
  and I'm wondering how on earth that'd be possible. Maybe I'm designing
  my modules very differently to other people?
 
  I'll throw you an edited example from my environment and if the people
  who favour parametrised classes over includes could show me their
  alternatives that would be much appreciated. I haven't mentioned
  resources because the class names are pretty self explanatory - each
  class handles any package, service and config files related to it's
  name:
 
  node 'somenode' {
  include puppetmaster
  }
 
  class puppetmaster {
  include common
  include puppet
  include ldap_auth
  include iptables::disabled
  include httpd::ssl
  include ruby-enterprise::passenger
  }
 
  class ruby-enterprise::passenger {
  include common
  include httpd
  include ruby-enterprise
  }
 
  class httpd::ssl {
  include httpd
  }
 
 
  The issue I'm trying to address is the current problem with scoping.
  Considering class common, it will be nested inside of the puppetmaster
  OR the ruby-enterprise::passenger class and it's not clear which one.
  Behavior can change depending on which if variables or resource
  defaults are being referenced outside the scope of class common.
 
  My recommendation is to try and make sure common classes, like class
  common are only included in one place that make sense for you. I
  would personally write this collection of classes as:
 
  (Note, this may be over-specifying dependency relationships, but
  ideally this shouldn't be a huge problem for you if resources aren't
  establishing direct relationships with resources in other classes. Run
  stages may also be a good substitute for the require metaparameter on
  classes.)
 
  Also, I'm totally open to suggestions to improve this organization
  scheme, it clearly has issues but it's the best I've come up so far
  and works well across the largest subset of Puppet deployments I've
  worked with.
 
  node 'somenode' {
 
  class { common: }
 
  class { [ ldap_auth,
  puppet,
  iptables::disabled,
  httpd,
  ruby-enterprise ]: require = Class[common],
  }
 
  class { puppetmaster: require = Class[puppet] }
 
  class { httpd::ssl: require = Class[httpd] }
 
  class { ruby-enterprise::passenger:
  require = Class[ruby-enterprise, httpd]
  }
 
  }


 dont you find having to specify the relationships of httpd::ssl and httpd
 here to be wrong?


No, not wrong.  Certainly not ideal, but the best I can come up with with
the current language features.


 Isn't the fact that the httpd module is designed to have this ordering
 requirement an implementation detail and not a usage detail?


Yes.  How can I re-factor this to move the ordering into the implementation
_without_ running into the scoping issues?

Surely people who just want to use the httpd module do not need to know this
 implementation detail?  They should just be able to say use the module
 without understanding or knowing the ordering of internals.


I fully agree this is how things should be.


 If the internals of the modules are designed such that they require
 ordering of the sub classes then that is up to that module to specify in it.
  People who download from the forge should not need to concern themselves
 with this.



 It's also not very DRY.


So I agree with every issue you've raised, but you haven't proposed any
suggestions that address the scoping issues I'm trying to address and avoid.

Scoping issues trump the inconvenience of specifying this sort of thing when
using the classes.

-- 
Jeff McCune
http://www.puppetlabs.com/

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread R.I.Pienaar
(forced to top post due to your html email)

You cant avoid the scoping issues cos its broken.  You can work around them 
though.

You can be careful about where you set variables and how you include things. 
This
isn't new we've been doing it for years.

You can use extlookup to fetch variables from your data store in the class you 
need
it and not rely on setting variables in one scope and accessing them in others.

You can have some very simple syntax and style rules that says include classes 
first
in your class then set variables to avoid the strange ordering issues.

You can create wrapper classes that include other classes but not set variables.
class apache includes apache::config, ::install and ::service and as above in 
each
case where you need to know apache version or something you can get that from 
extlookup
which gives you configurable classes today without the scoping issues.

By arranging modules like this - one class that exist only to include other 
classes -
you totally avoid issues like setting defaults bleeding into other scopes.  I 
have 100+
modules and never even realized the defaults propagate over included classes 
because
my coding style and standards simply doesnt allow that to happen.

We've avoided these issues for years and the techniques are well known.

Now when the language wish to get new features and improve itself you can 
either introduce
a whole slew of new syntax, deprecate old syntax etc and new ways of writing 
manifests
or you can fix the scoping problems which will result in existing techniques 
and language
features working sanely?

 Scoping issues trump the inconvenience of specifying this sort of
 thing when using the classes.

Correct, lets fix the scoping issues that's creating a language that forces us 
to write 
non obvious, non DRY and code that is coupled in ways it shouldnt be coupled.  
We cannot
now write really advanced modules that hide all the implimentation details even 
though
the language has all it needs to do this.  Whats preventing us from doing that 
is the 
scoping bugs.  So I am not sure why we arent fixing these instead.
 
- Original Message -
 On Fri, Jan 7, 2011 at 12:39 PM, R.I.Pienaar  r...@devco.net  wrote:
 
 
 
 
 
 
 
 
 - Original Message -
  On Fri, Jan 7, 2011 at 2:47 AM, luke.bigum 
  luke.bi...@fasthosts.co.uk  wrote:
 
 
 
  Hi list,
 
  Reading the thread can a class require an other class? it's been
  mentioned that perhaps one way forward for the Puppet language is to
  phase out the include keyword in favour of parametrised classes. I'm
  thinking of my Puppet and the several levels of include chaining I
  use
  and I'm wondering how on earth that'd be possible. Maybe I'm
  designing
  my modules very differently to other people?
 
  I'll throw you an edited example from my environment and if the
  people
  who favour parametrised classes over includes could show me their
  alternatives that would be much appreciated. I haven't mentioned
  resources because the class names are pretty self explanatory - each
  class handles any package, service and config files related to it's
  name:
 
  node 'somenode' {
  include puppetmaster
  }
 
  class puppetmaster {
  include common
  include puppet
  include ldap_auth
  include iptables::disabled
  include httpd::ssl
  include ruby-enterprise::passenger
  }
 
  class ruby-enterprise::passenger {
  include common
  include httpd
  include ruby-enterprise
  }
 
  class httpd::ssl {
  include httpd
  }
 
 
  The issue I'm trying to address is the current problem with scoping.
  Considering class common, it will be nested inside of the
  puppetmaster
  OR the ruby-enterprise::passenger class and it's not clear which
  one.
  Behavior can change depending on which if variables or resource
  defaults are being referenced outside the scope of class common.
 
  My recommendation is to try and make sure common classes, like class
  common are only included in one place that make sense for you. I
  would personally write this collection of classes as:
 
  (Note, this may be over-specifying dependency relationships, but
  ideally this shouldn't be a huge problem for you if resources aren't
  establishing direct relationships with resources in other classes.
  Run
  stages may also be a good substitute for the require metaparameter
  on
  classes.)
 
  Also, I'm totally open to suggestions to improve this organization
  scheme, it clearly has issues but it's the best I've come up so far
  and works well across the largest subset of Puppet deployments I've
  worked with.
 
  node 'somenode' {
 
  class { common: }
 
  class { [ ldap_auth,
  puppet,
  iptables::disabled,
  httpd,
  ruby-enterprise ]: require = Class[common],
  }
 
  class { puppetmaster: require = Class[puppet] }
 
  class { httpd::ssl: require = Class[httpd] }
 
  class { ruby-enterprise::passenger:
  require = Class[ruby-enterprise, httpd]
  }
 
  }
 
 
 dont you find having to specify the relationships of 

Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Patrick

On Jan 7, 2011, at 11:22 AM, Jeff McCune wrote:

 On Fri, Jan 7, 2011 at 2:47 AM, luke.bigum luke.bi...@fasthosts.co.uk wrote:
 Hi list,
 
 Reading the thread can a class require an other class? it's been
 mentioned that perhaps one way forward for the Puppet language is to
 phase out the include keyword in favour of parametrised classes. I'm
 thinking of my Puppet and the several levels of include chaining I use
 and I'm wondering how on earth that'd be possible. Maybe I'm designing
 my modules very differently to other people?
 
 I'll throw you an edited example from my environment and if the people
 who favour parametrised classes over includes could show me their
 alternatives that would be much appreciated. I haven't mentioned
 resources because the class names are pretty self explanatory - each
 class handles any package, service and config files related to it's
 name:
 
 node 'somenode' {
  include puppetmaster
 }
 
 class puppetmaster {
  include common
  include puppet
  include ldap_auth
  include iptables::disabled
  include httpd::ssl
  include ruby-enterprise::passenger
 }
 
 class ruby-enterprise::passenger {
  include common
  include httpd
  include ruby-enterprise
 }
 
 class httpd::ssl {
  include httpd
 }
 
 The issue I'm trying to address is the current problem with scoping.  
 Considering class common, it will be nested inside of the puppetmaster OR the 
 ruby-enterprise::passenger class and it's not clear which one.  Behavior can 
 change depending on which if variables or resource defaults are being 
 referenced outside the scope of class common.

I guess I'm really confused about how the language works.  My understanding is 
that common isn't nested inside of either class and just sits in he global 
namespace.  Can you give me an example of code that shows it in either class?

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Dan Bode
On Fri, Jan 7, 2011 at 1:41 PM, R.I.Pienaar r...@devco.net wrote:

 (forced to top post due to your html email)

 You cant avoid the scoping issues cos its broken.  You can work around them
 though.

 You can be careful about where you set variables and how you include
 things. This
 isn't new we've been doing it for years.

 You can use extlookup to fetch variables from your data store in the class
 you need
 it and not rely on setting variables in one scope and accessing them in
 others.

 You can have some very simple syntax and style rules that says include
 classes first
 in your class then set variables to avoid the strange ordering issues.


This is exactly what I have been recommending to people for variables.

The problem is that you can't manage the scope binding stacks in the same
way for resource defaults, or implicit tags.

I think that making resource defaults behave like variables in this sense
would go a long way to fixing the existing concerns with include.

ie:

in:

class foo {
  include bar
  File{mode = 777}
}

This resource default in foo should not effect resources in bar


 You can create wrapper classes that include other classes but not set
 variables.
 class apache includes apache::config, ::install and ::service and as above
 in each
 case where you need to know apache version or something you can get that
 from extlookup
 which gives you configurable classes today without the scoping issues.

 By arranging modules like this - one class that exist only to include other
 classes -
 you totally avoid issues like setting defaults bleeding into other scopes.
  I have 100+
 modules and never even realized the defaults propagate over included
 classes because
 my coding style and standards simply doesnt allow that to happen.

 We've avoided these issues for years and the techniques are well known.

 Now when the language wish to get new features and improve itself you can
 either introduce
 a whole slew of new syntax, deprecate old syntax etc and new ways of
 writing manifests
 or you can fix the scoping problems which will result in existing
 techniques and language
 features working sanely?


I agree with your point here about deprecating old features, but this is not
the only advantage of param classes, the other is that it specifies a real
interface:

class foo(
  $bar, $baz, $bad
) {
...
}

is way better then:

# this excepts bar,baz, and bad
class foo{
...
}

I am not a big fan of extlookup for the same reason, it hides the interface
for a class as opposed to exposing it. (although this does work better with
dynamic scoping for reasons mentioned in this thread)


  Scoping issues trump the inconvenience of specifying this sort of
  thing when using the classes.

 Correct, lets fix the scoping issues that's creating a language that forces
 us to write
 non obvious, non DRY and code that is coupled in ways it shouldnt be
 coupled.  We cannot
 now write really advanced modules that hide all the implimentation details
 even though
 the language has all it needs to do this.  Whats preventing us from doing
 that is the
 scoping bugs.  So I am not sure why we arent fixing these instead.

 - Original Message -
  On Fri, Jan 7, 2011 at 12:39 PM, R.I.Pienaar  r...@devco.net  wrote:
 
 
 
 
 
 
 
 
  - Original Message -
   On Fri, Jan 7, 2011 at 2:47 AM, luke.bigum 
   luke.bi...@fasthosts.co.uk  wrote:
  
  
  
   Hi list,
  
   Reading the thread can a class require an other class? it's been
   mentioned that perhaps one way forward for the Puppet language is to
   phase out the include keyword in favour of parametrised classes. I'm
   thinking of my Puppet and the several levels of include chaining I
   use
   and I'm wondering how on earth that'd be possible. Maybe I'm
   designing
   my modules very differently to other people?
  
   I'll throw you an edited example from my environment and if the
   people
   who favour parametrised classes over includes could show me their
   alternatives that would be much appreciated. I haven't mentioned
   resources because the class names are pretty self explanatory - each
   class handles any package, service and config files related to it's
   name:
  
   node 'somenode' {
   include puppetmaster
   }
  
   class puppetmaster {
   include common
   include puppet
   include ldap_auth
   include iptables::disabled
   include httpd::ssl
   include ruby-enterprise::passenger
   }
  
   class ruby-enterprise::passenger {
   include common
   include httpd
   include ruby-enterprise
   }
  
   class httpd::ssl {
   include httpd
   }
  
  
   The issue I'm trying to address is the current problem with scoping.
   Considering class common, it will be nested inside of the
   puppetmaster
   OR the ruby-enterprise::passenger class and it's not clear which
   one.
   Behavior can change depending on which if variables or resource
   defaults are being referenced outside the scope of class common.
  
   My recommendation is to try and 

Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread R.I.Pienaar


- Original Message -
 On Fri, Jan 7, 2011 at 1:41 PM, R.I.Pienaar  r...@devco.net  wrote:
 
 
 (forced to top post due to your html email)
 
 You cant avoid the scoping issues cos its broken. You can work around
 them though.
 
 You can be careful about where you set variables and how you include
 things. This
 isn't new we've been doing it for years.
 
 You can use extlookup to fetch variables from your data store in the
 class you need
 it and not rely on setting variables in one scope and accessing them
 in others.
 
 You can have some very simple syntax and style rules that says include
 classes first
 in your class then set variables to avoid the strange ordering issues.
 
 
 This is exactly what I have been recommending to people for variables.
 
 The problem is that you can't manage the scope binding stacks in the
 same way for resource defaults, or implicit tags.
 
 I think that making resource defaults behave like variables in this
 sense would go a long way to fixing the existing concerns with
 include.
 
 ie:
 
 in:
 
 class foo {
 include bar
 File{mode = 777}
 }
 
 This resource default in foo should not effect resources in bar
 
 
 You can create wrapper classes that include other classes but not set
 variables.
 class apache includes apache::config, ::install and ::service and as
 above in each
 case where you need to know apache version or something you can get
 that from extlookup
 which gives you configurable classes today without the scoping issues.
 
 By arranging modules like this - one class that exist only to include
 other classes -
 you totally avoid issues like setting defaults bleeding into other
 scopes. I have 100+
 modules and never even realized the defaults propagate over included
 classes because
 my coding style and standards simply doesnt allow that to happen.
 
 We've avoided these issues for years and the techniques are well
 known.
 
 Now when the language wish to get new features and improve itself you
 can either introduce
 a whole slew of new syntax, deprecate old syntax etc and new ways of
 writing manifests
 or you can fix the scoping problems which will result in existing
 techniques and language
 features working sanely?
 
 
 I agree with your point here about deprecating old features, but this
 is not the only advantage of param classes, the other is that it
 specifies a real interface:
 
 class foo(
 $bar, $baz, $bad
 ) {
 ...
 }
 
 is way better then:
 
 # this excepts bar,baz, and bad
 class foo{
 ...
 }
 
 I am not a big fan of extlookup for the same reason, it hides the
 interface for a class as opposed to exposing it. (although this does
 work better with dynamic scoping for reasons mentioned in this thread)


I totally agree and the new design for external variables - which I dont think 
has been shared with the community for comment yet - is a good replacement for 
extlookup last time I saw what was planned.

My issue is we're suggesting people write horrible code instead of teaching
them how to work around the scoping fail while we *fix the scoping fail*

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Nigel Kersten
On Fri, Jan 7, 2011 at 1:57 PM, R.I.Pienaar r...@devco.net wrote:

 I totally agree and the new design for external variables - which I dont think
 has been shared with the community for comment yet - is a good replacement for
 extlookup last time I saw what was planned.

The *only* reason that this hasn't been widely shared yet is that I
was hoping to get some kind of consensus from the Puppet users within
Puppet Labs who were involved in trying to design this solution before
opening it up to everyone.

There's no way it's going to get anywhere close to implemented without
significant input from the community. We're not going to create new
interfaces without doing that.

If we don't have consensus internally in the next few days, I'm going
to send it out early next week to get more smart people looking at it
as we've already sat on it too long.

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread Jeff McCune
Sorry for the previous HTML email.

On Fri, Jan 7, 2011 at 1:41 PM, R.I.Pienaar r...@devco.net wrote:

 You cant avoid the scoping issues cos its broken.  You can work around them 
 though.

 You can be careful about where you set variables and how you include things. 
 This
 isn't new we've been doing it for years.

 You can use extlookup to fetch variables from your data store in the class 
 you need
 it and not rely on setting variables in one scope and accessing them in 
 others.

 You can have some very simple syntax and style rules that says include 
 classes first
 in your class then set variables to avoid the strange ordering issues.

 You can create wrapper classes that include other classes but not set 
 variables.
 class apache includes apache::config, ::install and ::service and as above in 
 each
 case where you need to know apache version or something you can get that from 
 extlookup
 which gives you configurable classes today without the scoping issues.

 By arranging modules like this - one class that exist only to include other 
 classes -
 you totally avoid issues like setting defaults bleeding into other scopes.  I 
 have 100+
 modules and never even realized the defaults propagate over included classes 
 because
 my coding style and standards simply doesnt allow that to happen.

 We've avoided these issues for years and the techniques are well known.

Yes, I'm starting to see I took the easy way out by just
recommending switching to parametrized classes.  They force you to put
the class in only one place since you can't re-declare them.  As you
point out, this results in a difficult to easily use class structure.
Bad code.

Given Puppet 2.6.4 language features, is the general idea is to have
init.pp in each module include all of the classes contained within
that module in the order the author determines?

If two modules have a relationship to each other, then would you have
module a include only the module's initial class b and not a
specific class within module b, like b::ssl ?

I've played with this organization structure quite a bit, and I find
myself lot of wrapper and pass-thu classes to arrange things.  It is
harder for a module author to get right, but this is definitely
preferable to making it harder for a module consumer to use the
module.

 Now when the language wish to get new features and improve itself you can 
 either introduce
 a whole slew of new syntax, deprecate old syntax etc and new ways of writing 
 manifests
 or you can fix the scoping problems which will result in existing techniques 
 and language
 features working sanely?

I absolutely prefer fixing the scoping issues to the alternatives you
mentioned and I myself have been recommending.

  Scoping issues trump the inconvenience of specifying this sort of
  thing when using the classes.

 Correct, lets fix the scoping issues that's creating a language that forces 
 us to write
 non obvious, non DRY and code that is coupled in ways it shouldnt be coupled. 
  We cannot
 now write really advanced modules that hide all the implimentation details 
 even though
 the language has all it needs to do this.  Whats preventing us from doing 
 that is the
 scoping bugs.  So I am not sure why we arent fixing these instead.

OK, so what if declaring* a class always added it to the top scope?
This seems like a relatively straight forward solution to a great many
concerns.  The language doesn't change, existing manifests continue to
work and only the convention of relying on the order of variable
definitions is affected.  The problem of resource defaults also almost
entirely goes away too.  This was proposed in the original discussion
about scoping back in July and I'm just curious if there's any new
information in this area.

Similarly, we could leave include as is and add (and recommend the use
of) something like includetop which always adds the class to top
scope.  This would allow people relying on the current scoping
behavior to remain unaffected.

The other idea I had was to allow classes to be declared virtually,
but this drastically affects existing puppet code and makes the
language harder to learn.  (What the heck is @class { foo: }, Class |
title == foo | doing!?)

* To me, include foo and class { foo: } are both declaring the class.

--
Jeff McCune
http://www.puppetlabs.com/

-- 
You received this message because you are subscribed to the Google Groups 
Puppet Users group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.



Re: [Puppet Users] Exactly how do people replace include with parametrised classes?

2011-01-07 Thread R.I.Pienaar


- Original Message -
 Sorry for the previous HTML email.

no worries, usually I take the time to add extra 's to make them readable
but when they're long it becomes too much and I give in to the top posting
temptation :)

 On Fri, Jan 7, 2011 at 1:41 PM, R.I.Pienaar r...@devco.net wrote:
 
  You cant avoid the scoping issues cos its broken. You can work
  around them though.
 
  You can be careful about where you set variables and how you include
  things. This
  isn't new we've been doing it for years.
 
  You can use extlookup to fetch variables from your data store in the
  class you need
  it and not rely on setting variables in one scope and accessing them
  in others.
 
  You can have some very simple syntax and style rules that says
  include classes first
  in your class then set variables to avoid the strange ordering
  issues.
 
  You can create wrapper classes that include other classes but not
  set variables.
  class apache includes apache::config, ::install and ::service and as
  above in each
  case where you need to know apache version or something you can get
  that from extlookup
  which gives you configurable classes today without the scoping
  issues.
 
  By arranging modules like this - one class that exist only to
  include other classes -
  you totally avoid issues like setting defaults bleeding into other
  scopes. I have 100+
  modules and never even realized the defaults propagate over included
  classes because
  my coding style and standards simply doesnt allow that to happen.
 
  We've avoided these issues for years and the techniques are well
  known.
 
 Yes, I'm starting to see I took the easy way out by just
 recommending switching to parametrized classes. They force you to put
 the class in only one place since you can't re-declare them. As you
 point out, this results in a difficult to easily use class structure.
 Bad code.
 
 Given Puppet 2.6.4 language features, is the general idea is to have
 init.pp in each module include all of the classes contained within
 that module in the order the author determines?
 
 If two modules have a relationship to each other, then would you have
 module a include only the module's initial class b and not a
 specific class within module b, like b::ssl ?
 
 I've played with this organization structure quite a bit, and I find
 myself lot of wrapper and pass-thu classes to arrange things. It is
 harder for a module author to get right, but this is definitely
 preferable to making it harder for a module consumer to use the
 module.

The new relationship chaining syntax goes a way towards this, really I 
think if you have a class to install a webserver you should be able to
say use that and it should be a standalone thing that sets up a webserver.

now if you have a foo module - lets say some internal webapp that you deploy
and it too needs a webserver then it should specify relationships with the
require keyword or require on resources.  It's up to the situation though
i dont think there's always a right answer.  There's going to be edge cases.

A lot of the kind of approaches we do we shouldnt do, they're learned on by
spending hours with test.pp's and discovering the pifalls, they're not
documented and if you tell a new person that just to install ntp he needs
to make 3 classes he thinks you're crazy but underneath that crazy looking
recommendation sits a lot of lessons learned due to the issues manifesting
in the language.

It's obvious to anyone that the current situation is not ideal and needs
fixing, I do not dispute this but I feel the current push towards new 
features yields a less desirable result than our previous work arounds did.
Even if the current state is transient - but we do know its transient state
and so we should consider that in the kind of people we make recommendations
too.

 
  Now when the language wish to get new features and improve itself
  you can either introduce
  a whole slew of new syntax, deprecate old syntax etc and new ways of
  writing manifests
  or you can fix the scoping problems which will result in existing
  techniques and language
  features working sanely?
 
 I absolutely prefer fixing the scoping issues to the alternatives you
 mentioned and I myself have been recommending.

yes, the alternatives I propose are hacks and work arounds and they suck - 
yet they are almost at the same level I feel as the where param classes are 
today they too are fraught with hacks and work arounds.  

They are the right direction but they're still getting there.  Thus 
recommending 
to all rather than say the more early adopter crowd in the community like 
myself isn't the right hting to do right now I feel.

 
   Scoping issues trump the inconvenience of specifying this sort of
   thing when using the classes.
 
  Correct, lets fix the scoping issues that's creating a language that
  forces us to write
  non obvious, non DRY and code that is coupled in ways it shouldnt be
  coupled. We cannot
  now