Concat params along a node.

42 views
Skip to first unread message

Albert Shih

unread,
Jun 11, 2015, 4:23:55 PM6/11/15
to puppet...@googlegroups.com
Hi,

Let's say I have a module to manage something on a server so

modules/things/manifests/init.pp
......................../addthing.pp

the addthing.pp whould be a define.

And I use this « addthing » inside other module, how can I get the list of
all thing I add. For example

class my_service {

include ::things

things::addthing { 'first' }
things::addthing { 'second' }
things::addthing { 'third' }

# and now I want inside $my_things a string like 'first, second, third'

}


Regards.


--
Albert SHIH
Heure local/Local time:
jeu 11 jui 2015 22:14:50 CEST

jcbollinger

unread,
Jun 12, 2015, 10:06:49 AM6/12/15
to puppet...@googlegroups.com


On Thursday, June 11, 2015 at 3:23:55 PM UTC-5, Albert Shih wrote:
Hi,

Let's say I have a module to manage something on a server so

  modules/things/manifests/init.pp
  ......................../addthing.pp

the addthing.pp whould be a define.

And I use this « addthing » inside other module, how can I get the list of
all thing I add. For example

  class my_service {

    include ::things

    things::addthing { 'first' }
    things::addthing { 'second' }
    things::addthing { 'third' }

    # and now I want inside $my_things a string like 'first, second, third'

    }



You don't.  If you were willing to write a custom function or possibly to engage in some ruby-fu inan inline template then you could extract a list of the titles of all Things::Addthing resources declared to that point during catalog building, but that's not necessarily the same thing, as instances may have been declared elsewhere, too.

More generally, it is never a good idea for your manifests to rely on extracting data from the catalog under construction. The result of any such inquiry is necessarily dependent on the order in which Puppet evaluates your manifests, which is difficult to predict.  Instead, focus on data first, and code second.  For example, if you want a list of the Thing::Addthings, then start with that, and use it to make your declarations, instead of making your declarations and after the fact trying to determine what you declared (which in truth you already know anyway):

class my_service {
  include
::things
 
  $thinglist
= [ 'first', 'second', 'third' ]
 
  things
::addthing { $thinglist: }
}

It's shorter, too.


John

Albert Shih

unread,
Jun 18, 2015, 10:17:10 AM6/18/15
to puppet...@googlegroups.com
Le 12/06/2015 à 07:06:49-0700, jcbollinger a écrit
>
> You don't. If you were willing to write a custom function or possibly to

That' sucks ...

> engage in some ruby-fu inan inline template then you could extract a list of
> the titles of all Things::Addthing resources declared to that point during
> catalog building, but that's not necessarily the same thing, as instances may
> have been declared elsewhere, too.

Exactly.

> More generally, it is never a good idea for your manifests to rely on
> extracting data from the catalog under construction. The result of any such
> inquiry is necessarily dependent on the order in which Puppet evaluates your

In fact the order don't matters for me.

> manifests, which is difficult to predict. Instead, focus on data first, and
> code second. For example, if you want a list of the Thing::Addthings, then
> start with that, and use it to make your declarations, instead of making your
> declarations and after the fact trying to determine what you declared (which in
> truth you already know anyway):
>
> class my_service {
> include ::things
>
> $thinglist = [ 'first', 'second', 'third' ]
>
> things::addthing { $thinglist: }
> }
>
> It's shorter, too.

Well, I can do that, but that's become really hard to read if for each
thing they are lots of parameters.

In fact I event don't how to do that with lots of parameters. Let's say I
want do what you say, how can I factorise

things:addthing { 'first':
'param1' => 'value1',
....
'param10' => 'value10',
}

things:addthing { 'second':
'param1' => 'value1',
....
'param10' => 'value10',
}

things:addthing { 'third':
'param1' => 'value1',
....
'param10' => 'value10',
}
(actually it's not 10 but 9).

How can I use a array ?

Thanks for your answer.

Regards.

JAS


--
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:
jeu 18 jui 2015 16:05:23 CEST

jcbollinger

unread,
Jun 19, 2015, 8:59:54 AM6/19/15
to puppet...@googlegroups.com


On Thursday, June 18, 2015 at 9:17:10 AM UTC-5, Albert Shih wrote:
Le 12/06/2015 à 07:06:49-0700, jcbollinger a écrit
>
> You don't.  If you were willing to write a custom function or possibly to

That' sucks ...

> engage in some ruby-fu inan inline template then you could extract a list of
> the titles of all Things::Addthing resources declared to that point during
> catalog building, but that's not necessarily the same thing, as instances may
> have been declared elsewhere, too.

Exactly.


So what made you think anything along these lines could work, then?  The data you wanted to extract is nowhere recorded, and I'm uncertain why you supposed it would be otherwise.

 

> More generally, it is never a good idea for your manifests to rely on
> extracting data from the catalog under construction. The result of any such
> inquiry is necessarily dependent on the order in which Puppet evaluates your

In fact the order don't matters for me.


It absolutely does matter to you if the outcome of the catalog-building process depends on that order.  It is undesirable for that to be the case, but the closest thing available to what you asked for would produce that result.

 
That's not the case you first presented.  Nevertheless, you can use an array title if all the parameters take the same values, in which case it simply looks like this:

class my_service {
  include
::things
 
  $thinglist
= [ 'first', 'second', 'third' ]
 
  things
::addthing { $thinglist:

    param1 => 'value1',
    param2 => 'value2',
    # ...
  }

}

If each may or does have distinct parameters, then your best bet is to externalize them instead of encoding them into your manifests (again: data first). There are then multiple ways to feed the parameters to your resources, and probably you can externalize the list of resources, too.  Automated data binding is a powerful and flexible tool, or you can access your external data directly, via the `hiera()` family of functions.  There are built-in functions that can help with handling the data, and some of the functions from the Stdlib module can be really useful here.

There are many examples of this sort of thing available on the Forge and elsewhere.  If you want more concrete advice, then pose a more concrete question.


John

Albert Shih

unread,
Jun 24, 2015, 7:31:06 AM6/24/15
to puppet...@googlegroups.com
Le 19/06/2015 à 05:59:54-0700, jcbollinger a écrit
>

Hi,

>

Sorry for the long time between my answer. And thank you for everything.

>
> That's not the case you first presented. Nevertheless, you can use an array
> title if all the parameters take the same values, in which case it simply looks
> like this:
>
> class my_service {
> include ::things
>
> $thinglist = [ 'first', 'second', 'third' ]
>
> things::addthing { $thinglist:
> param1 => 'value1',
> param2 => 'value2',
> # ...
> }
> }
>
> If each may or does have distinct parameters, then your best bet is to
> externalize them instead of encoding them into your manifests (again: data
> first). There are then multiple ways to feed the parameters to your resources,
> and probably you can externalize the list of resources, too. Automated data
> binding is a powerful and flexible tool, or you can access your external data
> directly, via the `hiera()` family of functions. There are built-in functions
> that can help with handling the data, and some of the functions from the Stdlib
> module can be really useful here.

Ok.

>
> There are many examples of this sort of thing available on the Forge and
> elsewhere. If you want more concrete advice, then pose a more concrete
> question.

Well let's say I have a server with a lot of Vhost (apache). So I used

apache::vhost { 'vhost1':
}

apache::vhost { 'vhost2':
}

etc..

what I want is to have inside one variable the list of all my vhost (event
by patching puppetlabs/apache module.

Yes I can create a huge hiera config but that's going to be very hard to
maintain because apache::vhost get lot of params. So I'm going to need to
create a very big hiera file.

Regards.

JAS


--
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:
mer 24 jui 2015 13:18:45 CEST

jcbollinger

unread,
Jun 25, 2015, 9:13:05 AM6/25/15
to puppet...@googlegroups.com


On Wednesday, June 24, 2015 at 6:31:06 AM UTC-5, Albert Shih wrote:
Le 19/06/2015 à 05:59:54-0700, jcbollinger a écrit
[...]

>
> There are many examples of this sort of thing available on the Forge and
> elsewhere.  If you want more concrete advice, then pose a more concrete
> question.

Well let's say I have a server with a lot of Vhost (apache). So I used

  apache::vhost { 'vhost1':
    }

  apache::vhost { 'vhost2':
    }

  etc..

what I want is to have inside one variable the list of all my vhost (event
by patching puppetlabs/apache module.


Yes I can create a huge hiera config but that's going to be very hard to
maintain because apache::vhost get lot of params. So I'm going to need to
create a very big hiera file.



You can create a huge hiera file, or you can create a huge manifest file.  The size of the data is whatever it is, and you have to put it somewhere.  Externalizing it separates the data representation from the logic, making both easier to understand and maintain.  Moreover, externalizing the data can make the logic you want to express easier to write.

One way to approach this would be to structure the data for use with Puppet's create_resources() function.  In YAML, the data would look something like this:

mymodule::apache::vhosts:
  vhost1
:
    param1
: value
    param2
: another_value
  vhost2
:
    param1
: different_value
    param2
: blah


The corresponding manifest code (Puppet 3 style) could be:

class mymodule::apache ($vhosts = {}) {
  include
'apache'

 
# The keys() function is from puppetlabs-stdlib
  $vhost_list
= keys($vhosts)

 
# create_resources() is a built-in
  create_resources
('apache::vhost', $vhosts)
}

The manifest code does not have to change when you change the data, and you can use any and all of Hiera's features to influence what data actually are presented for each node.

If you want more clarity or control over what's going on, then it is straightforward to replace create_resources() with DSL code, though such code will be specific to the resource type for which you want to create instances, and it will have to provide explicitly for every parameter of that resource type that you care about.


John

Tom Limoncelli

unread,
Jul 6, 2015, 7:25:13 AM7/6/15
to puppet...@googlegroups.com
[ sorry for the late reply ]

Have you considered Exported Resources?

Tom



--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/20150611202146.GB67815%40pcjas.obspm.fr.
For more options, visit https://groups.google.com/d/optout.



--
Email: t...@whatexit.org    Work: tlimo...@StackOverflow.com
Skype: YesThatTom
Blog:  http://EverythingSysadmin.com
Reply all
Reply to author
Forward
0 new messages