Search code examples
puppetinfrastructure-as-codehiera

Puppet Hiera Data Objects


I'm trying to pass a list of hashes into a class. The need is to pass in one or more objects into my class - each object has a small set of data that is used to generate a templated script with the data points found in the hash.

I've successfully used Hiera Arrays & Hashes:

mymods::keyvaultcerts::array::certNames: ['cert1','cert2','cert3']
mymods::chocopackages::hash::packages:
   dotnetfx   : 4.8
   urlrewrite : 2.1
   azure-cli  : 2.31
   vcredist   : 12.0` 

The above has worked great. I can access the Hash data very easily

class mymods::chocopackages::hash (
   Hash $packages
){
    $packages.each | $packageName, $packageVersion | {
       package{$packageName: 
          ensure => $packageVersion,
    }
}

What I'm trying to do now, is building off the above. I need to pass in a list of objects to my class. So I'm trying to use an array of hash objects:

profile::octopus::worker::workerConfigurations:[
{
   Port: 10933,
   Pool: "General Worker Pool",
   User: "Dummy1",
   DisplaySuffix: "",
},
{
   Port: 10934,
   Pool: "General Dev Pool",
   User: "Dummy2",
   DisplaySuffix: "Dev",
},
{
   Port: 10935,
   Pool: "General QA Pool",
   User: "Dummy3",
   DisplaySuffix: "_QA",
}
]

Then, in my class I'm trying to iterate through the list and access the data like so ...

class profile::octopus::worker(
    Array $workerConfigurations
){
     $workerConfigurations.each | Integer $workerIndex, Hash $workerConfigurationData | {
         $workerConfigurationData.each | $workerPort, $workerPool, $workerUser, $workerDisplaySuffix | {
             notify{"\$workerPort ${$workerPort}" :}
         }
     }
}

What I was expecting, was to see notifications of the ports (10933, 10934, 10935). However, I'm receiving an error on the client-side:

Error while evaluating a Method Call, 'each' block expects between 1 and 2 arguments, got 4

My question is: Is this possible? If not, are there any recommendations on how to pass in a list of one or more objects into my class?


Solution

  • The built-in each function accepts a lambda that takes either one or two parameters. The significance of those parameters depends on whether one or two are given and on whether the first argument to each() is an array or a hash.

    In no event may the block accept four parameters:

             $workerConfigurationData.each | $workerPort, $workerPool, $workerUser, $workerDisplaySuffix | {
                 notify{"\$workerPort ${$workerPort}" :}
             }
    

    Nor is it clear what you expect the each to be doing for you there. Rather than iterating, you seem to want to select and use one of the mappings from the hash. You do that by subscripting the hash with the wanted key(s):

                 notify { "Port: ${workerConfigurationData['Port']}" :}
    

    That has nothing in particular to do with Hiera, by the way. You can declare and use hashes (and arrays) without Hiera being involved.