Eugene Brodsky
2013-May-13 16:26 UTC
[Puppet Users] Creating defined resources based on array of parameters.
Hi all, With the goal of making my code a little more DRY, I am trying to define resource parameters in an array of hashes, and then create defined resources from these array items. I am having trouble figuring out the syntax for accessing the hash values for the hash currently being worked on ("self?"). Here''s the code to make it clear: ##### Configuration arguments $sites = [{ sitedomain => ''site1.domain.dev'', repo => ''git@repo.address/Repo'', branch => ''develop'', serveralias => "", priority => ''010'' },{ sitedomain => ''site2.domain.dev'', repo => ''git@repo.address/Repo'', branch => ''develop'', serveralias => "", priority => ''020'' },] #### Deploy configuration apache::vhost { $sites : priority => ${????}[priority], sitedomain => ${????}[sitedomain], serveralias => ${????}[serveralias], } git::clone { $sites : repo => ${????}[repo], branch => ${????}[branch], } How do I access the hash values for the current hash? (trouble spots marked with "????"). I''ve experimented a lot while reading documentation and these forums, but didn''t get anywhere. I tried assigning each hash to a variable, but I still can''t get at that variable''s name from within resource definition. Is what i''m trying to do even possible? Or am I stuck copying and pasting the roughly identical block of code for every site that needs to be present on the server? Thank you in advance for any insight. -- 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+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
jcbollinger
2013-May-13 20:42 UTC
[Puppet Users] Re: Creating defined resources based on array of parameters.
On Monday, May 13, 2013 11:26:21 AM UTC-5, Eugene Brodsky wrote:> > Hi all, > With the goal of making my code a little more DRY, I am trying to define > resource parameters in an array of hashes, and then create defined > resources from these array items. I am having trouble figuring out the > syntax for accessing the hash values for the hash currently being worked on > ("self?"). > > Here''s the code to make it clear: > > ##### Configuration arguments > > $sites = [{ > sitedomain => ''site1.domain.dev'', > repo => ''git@repo.address/Repo'', > branch => ''develop'', > serveralias => "", > priority => ''010'' > },{ > sitedomain => ''site2.domain.dev'', > repo => ''git@repo.address/Repo'', > branch => ''develop'', > serveralias => "", > priority => ''020'' > },] > > #### Deploy configuration > > apache::vhost { $sites : > priority => ${????}[priority], > sitedomain => ${????}[sitedomain], > serveralias => ${????}[serveralias], > } > git::clone { $sites : > repo => ${????}[repo], > branch => ${????}[branch], > } > > How do I access the hash values for the current hash? (trouble spots > marked with "????"). > > I''ve experimented a lot while reading documentation and these forums, but > didn''t get anywhere. I tried assigning each hash to a variable, but I still > can''t get at that variable''s name from within resource definition. > > Is what i''m trying to do even possible? Or am I stuck copying and pasting > the roughly identical block of code for every site that needs to be present > on the server? > > Thank you in advance for any insight. >The specific approach you are attempting will not work, but there are variations that will. First off, the title of a resource is always a string. Not a hash, not an array, but a string. Puppet DSL provides a shortcut for declaring multiple resources (native or defined-type) having the same parameters, by writing a single resource declaration where the (string) titles are given as an array literal or an array-valued variable. The result is exactly equivalent to multiple resource declarations, one for each given title, each with the specified parameters. That shortcut does not generalize. It never makes sense to specify a hash as a resource title, nor an array containing any non-string values. Moreover, all elements of a resource declaration itself are evaluated in the context in which the declaration appears. That applies here in that inside your resource *declarations*, there cannot be a sense of a ''current'' element of a composite title. That sort of thing has to go into the * implementation* of the resource type (where the ''current'' element is just the plain resource title of one of several similar resources). Again: titles are always strings. Back to the question of how you achieve what you''re after. There are at least two relatively straightforward ways, both requiring a slightly different form for your data. Instead of an array of hashes, you need a hash of hashes, with the keys of the outer hash being identifying strings suitable for use as resource titles or parts of them. The inner hashes can be similar or perhaps the same as the parameter hashes you have now. For example: $sites = { ''site1'' => { sitedomain => ''site1.domain.dev'', repo => ''git@repo.address/Repo'', branch => ''develop'', serveralias => "", priority => ''010'' }, ... } Having your data in that general form, you have two basic alternatives: 1. Use the built-in create_resources() function 2. Create a defined type that performs a similar function If, as in your case, your inner hashes combine parameters for resources of different types, option (1) would require a defined-type wrapper to use as the resource type passed to create_resources(), so that doesn''t end up being any simpler. You should read docs for that function, but there isn''t really much more to say. I will illustrate the alternative, however. The defined type you need for option (2) is a bit different from the one you would need for option (1). In this case, the defined type needs only one parameter, that being the hash of hashes: define mymodule::site($sites) { include ''apache'' # if necessary include ''git'' # if necessary # Select the inner hash for this site from # the hash of hashes, using this resource''s # title as the key: $site_data = $sites[$title] # Declare resources apache::vhost { "${title}-vhost" : priority => $site_data[''priority''], sitedomain => $site_data[''sitedomain''], serveralias => $site_data[''serveralias''], } git::clone { "${title}-git" : repo => $site_data[''repo''], branch => $site_data[''branch''], } } You use then that defined type like so: class somemodule::someclass { $site_names = <see below> mymodule::sites { $keys: sites => $sites } } The last bit is how to get the site names. It may be the case that which sites to declare is a separate question from which sites'' parameters are recorded in the $sites hash, in which case you''ll have to determine for yourself how to get a suitable array of site names (each being one of the keys of the $sites hash). If you just want to declare them all, however, then PuppetLabs''s add-in ''stdlib'' module provides a keys() function that will return an array of the keys of a hash, which is just what you want for this purpose. Or you can roll your own; by itself, a keys() function is not very hard. $site_names = keys(sites) John -- 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+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Eugene Brodsky
2013-May-14 18:08 UTC
[Puppet Users] Re: Creating defined resources based on array of parameters.
John, thank you so much for such a detailed and thoughtful response!! I was definitely confused about resource titles'' data type, and I think variable scope too. Also I made an incorrect assumption that providing a hash as a resource title will somehow expand its values for use within the declaration. Thanks for making these concepts clear. I was already using defined types for my apache::vhost and git::clone., so your approach worked perfectly. This is what I ended up doing: ##### in site.pp: $sitenames = [''foo'', ''bar''] $sitedata = { ''foo'' => { sitedomain => ''foo.dev'', repo => ''git@host/Foo.git'', branch => ''develop'', serveralias => "", priority => ''010'' }, ''bar'' => { ......... } } deployed_sites { $sitenames : sitedata => $sitedata } ##### in a module: define baz::deployed_sites ($sitedata) { $settings = $sitedata[$title] apache::vhost { $title : priority => $settings[priority], sitedomain => $settings[sitedomain], serveralias => $settings[serveralias], } git::clone { $title : repo => $settings[repo], branch => $settings[branch], sitedomain => $settings[sitedomain], } } Once again, thank you very much for this, and hope it helps someone else down the road. Eugene On Monday, May 13, 2013 4:42:42 PM UTC-4, jcbollinger wrote:> > > The specific approach you are attempting will not work, but there are > variations that will. > > First off, the title of a resource is always a string. Not a hash, not an > array, but a string. Puppet DSL provides a shortcut for declaring multiple > resources (native or defined-type) having the same parameters, by writing a > single resource declaration where the (string) titles are given as an array > literal or an array-valued variable. The result is exactly equivalent to > multiple resource declarations, one for each given title, each with the > specified parameters. That shortcut does not generalize. It never makes > sense to specify a hash as a resource title, nor an array containing any > non-string values. > > Moreover, all elements of a resource declaration itself are evaluated in > the context in which the declaration appears. That applies here in that > inside your resource *declarations*, there cannot be a sense of a > ''current'' element of a composite title. That sort of thing has to go into > the *implementation* of the resource type (where the ''current'' element is > just the plain resource title of one of several similar resources). Again: > titles are always strings. > > Back to the question of how you achieve what you''re after. There are at > least two relatively straightforward ways, both requiring a slightly > different form for your data. Instead of an array of hashes, you need a > hash of hashes, with the keys of the outer hash being identifying strings > suitable for use as resource titles or parts of them. The inner hashes can > be similar or perhaps the same as the parameter hashes you have now. For > example: > > $sites = { > ''site1'' => { > sitedomain => ''site1.domain.dev'', > repo => ''git@repo.address/Repo'', > branch => ''develop'', > serveralias => "", > priority => ''010'' > }, > ... > } > > > Having your data in that general form, you have two basic alternatives: > > 1. Use the built-in create_resources() function > 2. Create a defined type that performs a similar function > > If, as in your case, your inner hashes combine parameters for resources of > different types, option (1) would require a defined-type wrapper to use as > the resource type passed to create_resources(), so that doesn''t end up > being any simpler. You should read docs for that function, but there isn''t > really much more to say. I will illustrate the alternative, however. > > The defined type you need for option (2) is a bit different from the one > you would need for option (1). In this case, the defined type needs only > one parameter, that being the hash of hashes: > > define mymodule::site($sites) { > include ''apache'' # if necessary > include ''git'' # if necessary > > # Select the inner hash for this site from > # the hash of hashes, using this resource''s > # title as the key: > $site_data = $sites[$title] > > # Declare resources > > apache::vhost { "${title}-vhost" : > priority => $site_data[''priority''], > sitedomain => $site_data[''sitedomain''], > serveralias => $site_data[''serveralias''], > } > > git::clone { "${title}-git" : > repo => $site_data[''repo''], > branch => $site_data[''branch''], > } > } > > You use then that defined type like so: > > class somemodule::someclass { > $site_names = <see below> > mymodule::sites { $keys: sites => $sites } > } > > The last bit is how to get the site names. It may be the case that which > sites to declare is a separate question from which sites'' parameters are > recorded in the $sites hash, in which case you''ll have to determine for > yourself how to get a suitable array of site names (each being one of the > keys of the $sites hash). > > If you just want to declare them all, however, then PuppetLabs''s add-in > ''stdlib'' module provides a keys() function that will return an array of the > keys of a hash, which is just what you want for this purpose. Or you can > roll your own; by itself, a keys() function is not very hard. > > $site_names = keys(sites) > > > John > >-- 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+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users?hl=en. For more options, visit https://groups.google.com/groups/opt_out.