hiera & profile & roles

237 views
Skip to first unread message

Albert Shih

unread,
Nov 16, 2016, 7:45:23 AM11/16/16
to puppet...@googlegroups.com
Hi,

When I read some recommendation about using hieradata/profile/roles I
always find people saying to put the data inside the profile (in hiera)
like

profile::cms::key1: value1
profile::mysql::key2: value2
profile::webserveur::key3: value3

Why it's not recommended to put the value inside the role like

role::my_cms::key1: value1
role::my_cms::key2: value2
role::my_cms::key3: value3

then inside the

role/my_cms/init.pp

do something like

class role::my_cms (
$key1,
$key2,
$key3,
)
{
class {'profile::cms':
key1 => $key1
}

class {'profile::mysql':
key2 => $key2
}
etc.

The reason I ask is, if the key1/value1 is the (for example) the password of the
database, I can either do

profile::cms::key1: value1
profile::mysql::key2: "%hiera('profile::cms::key1')

or put all "intelligence" inside the role by

class role::my_cms (
$key1,
$key2,
$key3,
)
{
class {'profile::cms':
key1 => $key1
}

class {'profile::mysql':
key2 => $key1
}

I find this second solution more clean, because the guy who need to create
a cms just got to put all information inside the hieradata (without
understand the hiera('profile::cms::Key1') )

Regards.


--
Albert SHIH
DIO bātiment 15
Observatoire de Paris
5 Place Jules Janssen
92195 Meudon Cedex
France
xmpp: j...@obspm.fr
Heure local/Local time:
mer 16 nov 2016 08:34:00 CET

Craig Dunn

unread,
Nov 16, 2016, 8:35:01 AM11/16/16
to puppet...@googlegroups.com
On Wed, Nov 16, 2016 at 8:45 AM, Albert Shih <Alber...@obspm.fr> wrote:
Hi,

When I read some recommendation about using hieradata/profile/roles I
always find people saying to put the data inside the profile (in hiera)
like

profile::cms::key1: value1
profile::mysql::key2: value2
profile::webserveur::key3: value3

Why it's not recommended to put the value inside the role like

role::my_cms::key1: value1
role::my_cms::key2: value2
role::my_cms::key3: value3

Firstly, the idea behind roles and profiles is that profiles are used to define logical "technology stacks" composing of your component modules.  That is to say, that profiles are the layer where you declare how your component modules are implemented to model the technology unit you are trying to manage.  Roles are a way to represent a more "business logic" view of Puppet and are generally just wraps one or more profiles that make up that business logic, eg: a "application server" is all you should care about at a business logic level, the technology stacks (profiles) that are included to make up the role of an application server may include "webserver", "security", "base", "tomcat"....    Ironically the value of roles is their simplicity, by keeping them essentially dumb and limiting their responsibility to just including profiles it provides a nice layer of separation between business logic representation and implementation details.

With the above in mind, I think having hiera data populate role classes blurs that line and you end up with implementation details in both roles and profiles and it starts not making sense to have that further layer of abstraction.

Going further, the best environments I have seen only need to populate profile class with hiera data in the most extreme of edge cases.  Good component modules should be able to get all the data they need by using data bindings and a well thought out hiera hierarchy should prove sufficient for ensuring that things get configured correctly, and often your profiles will generally just "include ::class" and let data bindings do the rest - obviously this isn't always the case, sometimes you need to do specific implementation around component modules, such as component modules which expose a defined resource type but have no "create_resources" style of dynamically creating the resources that it provides, which is what profiles serve to do, and in some cases it might make sense to populate profile data from hiera to achieve this.

So in summary;  If you have a lot of data in hiera for your roles/profiles, you might want to look at why this is and see if having a more suitable hierarchy and relying on native data binding lookups from the component modules isn't an option...  If you genuinely need data populated at this level, then it's part of the implementation of your technology stack, therefore should be at the profile level, not the role level.

I highly recommend you read this post by Gary Larizza ... http://garylarizza.com/blog/2014/02/17/puppet-workflow-part-2/

Disclaimer: all of this is just opinions, but they're well tested opinions ;)

HTH
Craig



--
Enviatics     |      Automation and Configuration Management
Puppet Labs Service Delivery Partner & Certified Consultant

Albert Shih

unread,
Nov 16, 2016, 9:18:21 AM11/16/16
to puppet...@googlegroups.com, cr...@craigdunn.org
Le 16/11/2016 à 09:34:50+0100, Craig Dunn a écrit
This is exaclty what I try to do. Event I sometime use create_resources (or
now loop). But I don't see how I can do for a data needed by two profile
like a share password. Or if I take your sample "webserver", "security", "base",
"tomcat". If I installed tomcat in some place ('/opt/tomcat') how the
module who manage the war going to kown where to put the war ?

>
> So in summary;  If you have a lot of data in hiera for your roles/profiles, you
> might want to look at why this is and see if having a more suitable hierarchy
> and relying on native data binding lookups from the component modules isn't an
> option...  If you genuinely need data populated at this level, then it's part
> of the implementation of your technology stack, therefore should be at the
> profile level, not the role level.
>

Ok got it.

> I highly recommend you read this post by Gary Larizza ... http://
> garylarizza.com/blog/2014/02/17/puppet-workflow-part-2/

thanks....google already give me that link.

> Disclaimer: all of this is just opinions, but they're well tested opinions ;)

Every opinions are good for me.

Thanks again.

Regards.
--
Albert SHIH
DIO bâtiment 15
Observatoire de Paris
5 Place Jules Janssen
92195 Meudon Cedex
France
xmpp: j...@obspm.fr
Heure local/Local time:
mer 16 nov 2016 10:09:08 CET

Craig Dunn

unread,
Nov 16, 2016, 9:34:46 AM11/16/16
to Albert Shih, puppet...@googlegroups.com
On Wed, Nov 16, 2016 at 10:18 AM, Albert Shih <Alber...@obspm.fr> wrote:
 Le 16/11/2016 à 09:34:50+0100, Craig Dunn a écrit


This is exaclty what I try to do. Event I sometime use create_resources (or
now loop). But I don't see how I can do for a data needed by two profile
like a share password. Or if I take your sample "webserver", "security", "base",
"tomcat". If I installed tomcat in some place ('/opt/tomcat') how the
module who manage the war going to kown where to put the war ?


As I said there are times when you need to populate profile data, and it sounds like you've thought well about that - as far as your tomcat example goes, it would be better to use the component module as an API to determine the install path (if possible) - something like this assuming you are using puppetlabs/tomcat....

# Tomcat class has an attribute called "catalina_home" which is looked up from hiera data binding....
include ::tomcat
 
class { "my_application":
  tomcat_root => $::tomcat::catalina_home
}

Here we've managed to solve this without having to populate profile data from hiera.

Albert Shih

unread,
Nov 16, 2016, 9:42:17 AM11/16/16
to Craig Dunn, puppet...@googlegroups.com
Le 16/11/2016 à 10:34:36+0100, Craig Dunn a écrit
>
>
> On Wed, Nov 16, 2016 at 10:18 AM, Albert Shih <Alber...@obspm.fr> wrote:
>
>  Le 16/11/2016 à 09:34:50+0100, Craig Dunn a écrit
>
>
> This is exaclty what I try to do. Event I sometime use create_resources (or
> now loop). But I don't see how I can do for a data needed by two profile
> like a share password. Or if I take your sample "webserver", "security",
> "base",
> "tomcat". If I installed tomcat in some place ('/opt/tomcat') how the
> module who manage the war going to kown where to put the war ?
>
>
>
> As I said there are times when you need to populate profile data, and it sounds
> like you've thought well about that - as far as your tomcat example goes, it
> would be better to use the component module as an API to determine the install
> path (if possible) - something like this assuming you are using puppetlabs/
> tomcat....
>
> # Tomcat class has an attribute called "catalina_home" which is looked up from
> hiera data binding....
> include ::tomcat
>  
> class { "my_application":
>   tomcat_root => $::tomcat::catalina_home
> }

SUPER nice.....

I didn't think about that....

Don't know why but I always thought that was « bad practice » to access
some attribute from outside the module.

Lots of thanks.

Regar
--
Albert SHIH
DIO bâtiment 15
Observatoire de Paris
5 Place Jules Janssen
92195 Meudon Cedex
France
xmpp: j...@obspm.fr
Heure local/Local time:
mer 16 nov 2016 10:37:23 CET

Craig Dunn

unread,
Nov 16, 2016, 9:51:46 AM11/16/16
to Albert Shih, puppet...@googlegroups.com
On Wed, Nov 16, 2016 at 10:42 AM, Albert Shih <Alber...@obspm.fr> wrote:
 Le 16/11/2016 à 10:34:36+0100, Craig Dunn a écrit
> # Tomcat class has an attribute called "catalina_home" which is looked up from
> hiera data binding....
> include ::tomcat
>  
> class { "my_application":
>   tomcat_root => $::tomcat::catalina_home
> }

SUPER nice.....

I didn't think about that....

Don't know why but I always thought that was « bad practice » to access
some attribute from outside the module.

Not at all - especially not when done from the profiles.

A module's attributes are effectively it's API - by accessing $::tomcat::catalina_home you don't need to know or care if the value is being set by hiera or by the modules default (params.pp), and it's the best source of truth for that value.  This is a very good example of the benefits of profiles too.

Craig

Craig Dunn

unread,
Nov 16, 2016, 10:02:59 AM11/16/16
to Albert Shih, puppet...@googlegroups.com
On Wed, Nov 16, 2016 at 10:51 AM, Craig Dunn <cr...@craigdunn.org> wrote:


On Wed, Nov 16, 2016 at 10:42 AM, Albert Shih <Alber...@obspm.fr> wrote:
 Le 16/11/2016 à 10:34:36+0100, Craig Dunn a écrit

> # Tomcat class has an attribute called "catalina_home" which is looked up from
> hiera data binding....
> include ::tomcat
>  
> class { "my_application":
>   tomcat_root => $::tomcat::catalina_home
> }

SUPER nice.....

I didn't think about that....

Don't know why but I always thought that was « bad practice » to access
some attribute from outside the module.

Not at all - especially not when done from the profiles.


Going off topic, but I should clarify my view on that - I don't consider it bad practice to access an attribute, if the module is following semver standards the attribute should be considered part of the public API and I should expect that not to break until a major version release... however this rule doesn't apply to *all* variables, consider this example

class tomcat (
  $catalina_home = $::tomcat::params::catalina_home,
  ...
) {

  $bindir = "${catalina_home}/bin"
  ...
}

In this example, I would consider $::tomcat::catalina_home to be part of the API and perfectly acceptable to call this from your profiles, I would urge caution using $::tomcat::bindir though because this is a variable used in the internals of the class and not exposed as a documented attribute, I would consider this to be 'private' and expect that even a patch version release could break this.

Craig 

Albert Shih

unread,
Dec 5, 2016, 3:08:32 PM12/5/16
to puppet...@googlegroups.com, cr...@craigdunn.org
Le 16/11/2016 à 10:51:39+0100, Craig Dunn a écrit

Hi,

> > class { "my_application":
> >   tomcat_root => $::tomcat::catalina_home
> > }
>
> SUPER nice.....
>
> I didn't think about that....
>
> Don't know why but I always thought that was « bad practice » to access
> some attribute from outside the module.
>
>
> Not at all - especially not when done from the profiles.
>
> A module's attributes are effectively it's API - by accessing
> $::tomcat::catalina_home you don't need to know or care if the value is being
> set by hiera or by the modules default (params.pp), and it's the best source of
> truth for that value.  This is a very good example of the benefits of profiles
> too.

Is they are any equivalent about ressources create by « define ». For
example I would like to get all vhost create by

apache::vhost

in some supervision module.

I try

$::apache::vhost

and didn't work.

The purpose is to automatically create supervision of each vhost by

class apache_supervision {

$vhost_hash = $::apache::vhost
$vhost_hash.each | String $site_name, $Hash $site_info |
etc.
}

Regards.


NB: I answer to a old post, hope that's not against some rule...

--
Albert SHIH
DIO bâtiment 15
Observatoire de Paris
5 Place Jules Janssen
92195 Meudon Cedex
France
Téléphone : +33 1 45 07 76 26/+33 6 86 69 95 71
xmpp: j...@obspm.fr
Heure local/Local time:
lun 5 déc 2016 16:07:23 CET
Reply all
Reply to author
Forward
0 new messages