How to use a single puppet erb template to create two different files with different contents - puppet

I'm trying to use a single template file to create the Solaris 11 /etc/hosts.deny and /etc/hosts.allow files, with the hiera data in data/Solaris.json.
How can I have the hosts.deny file contain only "ALL: ALL", while the hosts.allow contain the "ALL: ALL" and the variable content from the Solaris.json file?
It should be noted that my org is using Puppet 5.5 Open Source, with ruby templates and json instead of yaml.
Here's the manifest.
class etc::solaris_hosts_files (
Array[String] $entry,
) {
file { 'hosts.allow': # Creates /etc/hosts.allow using template.
ensure => 'present',
content => template('etc/solaris_hosts_template.erb'),
owner => 'root',
group => 'other',
path => '/etc/hosts.allow',
mode => '0444',
}
file { 'hosts.deny': # Creates /etc/hosts.deny using template.
ensure => 'present',
content => template('etc/solaris_hosts_template.erb'),
owner => 'root',
group => 'other',
path => '/etc/hosts.deny',
mode => '0444',
}
}
Here is the template file.
ALL: ALL
<% unless $etc::solaris_hosts_files::hosts.allow -%>
<%= #entry.join(' ') %>
Here is the data/Solaris.json variable info.
"etc::solaris_hosts_files::entry": [
"<some_net>:<some_mask>",
"<some_net>:<some_mask> #<some_hostname>" ],
In the interest of being thorough, yes, the #entry variable is included in data/common.json. We assign the value in Solaris.json.
"etc::solaris_hosts_files::entry": "",
I am a noob puppeteer. Any help will be much appreciated. Thank you!!

Posting an answer to Matt Schuchard's question.
hosts.deny
ALL: ALL
hosts.allow:
ALL: ALL
<ip>:<mask>
<ip>:<mask>
The ip:mask comes from the hiera data.
The rendered result is an error:
Info: Retrieving locales
Info: Loading facts
Error: Could not retrieve catalog from remote server: No content type in http response; cannot parse
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

Related

Iterate over a Puppet Hiera hash in a puppet manifest

Update 1
I've changed the structure of the Hiera data a little and trying a different manifest style.
I'm trying to iterate over the following Hiera hash in a Puppet manifest:
windows-10.yaml:
---
message: "This node is using Windows 10 data"
#profile::hiera_test::backups_enabled: false
profile::hiera_test::firewall:
rule1:
groupName: 'Cortana'
profileNames: ['Private','Public']
action: 'Deny'
rule2:
groupName: 'Microsoft Photos'
profileNames: 'Public'
action: 'Deny'
Although I've updated the data structure and puppet lookup... returns what appears to be valid, I'm not entirely confident in the structure.
I have tried multiple permutations of the manifest. The latest of which looks like the following (based on this answer given by Matt Schuchard):
hiera_test.pp:
class profile::hiera_test (
Hash $data = lookup('profile::hiera_test::firewall', "merge" => 'hash'),
){
$data.each | String $key, Hash $value = {}|{
notify {
default:
name => "Demo_${key}",
message => 'Item DEFAULT',
;
$key:
* => $value,
}
}
}
And the error / output from the above:
PS C:\Users\LocalAdmin> puppet agent -t
Notice: Local environment: 'production' doesn't match server specified node environment 'development', switching agent to 'development'.
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Loading facts
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: no parameter named 'groupName' (file: /etc/puppetlabs/code/environments/development/site-modules/profile/manifests/hiera_test.pp, line: 31) on Notify[rule1] (file: /etc/puppetlabs/code/environments/development/site-modules/profile/manifests/hiera_test.pp, line: 31) on node winnode1.domain.com
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
Ideally, I want it to work inside a class declaration (why?, because that's about as far as my Puppet learning has got, but happy to further my learning. I'm also using Puppet Enterprise (2019.0.2)).
There are several similar questions around the internet, but they are either out of date (Hiera <5), have incomplete examples including this, or I can't work out how to transpose them into what I need. Apparently create_resources is due for depreciation
?
If anyone can tell me where I'm going wrong that would be great.
I have got a working solution, but hopefully someone can chime in with a better way.
With the example in the question, the line * => $value substitutes * with keys from the Hiera hash. These keys are used as parameters of the notify resource and as per the error, there is no such parameter groupName for notify. I'd either have to change the keys in my Hiera data to match the parameters of notify which wouldn't make much sense or learn how to use the Hiera data keys as parameters...
Anyway, the Hiera data is the same as in the question, but the class is as follows:
class profile::hiera_test (
Hash $data = lookup('profile::hiera_test::firewall', "merge" => 'hash'),
){
$data.each | String $key, Hash $value = {}|{
notify {
default:
name => "Demo_${key}",
message => 'Item DEFAULT',
;
$key:
name => "Demo_${key}",
message => "Output: GroupName: ${value['groupName']}, Profile Names: ${value['profileNames']}, Action: ${value['action']}",
}
}
}
As you can see, I've replaced * with valid parameters of the notify resource.
And the output:
Notice: Output: GroupName: Cortana, Profile Names: [Private, Public], Action: Deny
Notice: Output: GroupName: Microsoft Photos, Profile Names: Public, Action: Deny
Now to replace Notify with the real exec resource. Converting the profileNames array to PowerShell will be fun, I have no doubt.

Puppet tries to rename sites-avaialbe folder

I am running Puppet on staging server, for some reasons puppet starts trying removing sites-available folder and I have no idea why. Any hint will be helpful.
Error: Could not set 'file' on ensure: Is a directory # rb_file_s_rename - (/etc/nginx/sites-available20180808-12536-11p54v, /etc/nginx/sites-available) at 12:/etc/puppet/modules/nginx/manifests/vhost.pp
Error: Could not set 'file' on ensure: Is a directory # rb_file_s_rename - (/etc/nginx/sites-available20180808-12536-11p54v, /etc/nginx/sites-available) at 12:/etc/puppet/modules/nginx/manifests/vhost.pp
Code:
define nginx::vhost($docroot, $port = 80, $template = 'nginx/vhost_php.erb', $allow = [], $deny = [], $aliases = [])
{
include nginx
file { "/etc/nginx/sites-available/${name}":
owner => 'root',
group => 'root',
mode => 644,
content => template($template),
require => Package['nginx'],
notify => Service['nginx'],
}
file { "/etc/nginx/sites-enabled/${name}":
ensure => 'link',
target => "/etc/nginx/sites-available/${name}",
require => File["/etc/nginx/sites-available/${name}"],
notify => Service['nginx'],
}
}
As #MattSchuchard remarked in comments, the error messages show that Puppet thinks you've asked it to convert a directory into a file. Furthermore, it appears to be associating that action with the first File resource in your manifest, which declares
file { "/etc/nginx/sites-available/${name}":
# ...
}
You will note that that resource appears to be trying to manage a file inside the directory, rather than the directory itself, but that discrepancy would be resolved if the automagic $name variable happened to take an empty string as its value. That's what I presume is happening.
You don't show the relevant declaration(s) of the nginx::vhost resources, but I think you'll find that the problem is there. The (slightly) broader context of those error messages would probably confirm this diagnosis: it normally contains a path-like specification of the resource in which the error occurred, and that would include the relevant resource title.

Puppet: unable to get hiera variable

I've been using hiera for several weeks now and all was working fine til few days ago when i started to get that kind of message:
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find data item nom in any Hiera data file and no default supplied on node d0puppetclient.victor-buck.com
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
So i tried to make a very simple test to check if the problem came from my last code changes and i'm still getting this message. I can't get hiera variable anymore.
Below the test i made:
hiera.yaml:
---
:backends:
- yaml
:yaml:
:datadir: /etc/puppet/hieradata
:hierarchy:
- common
site.pp:
# /etc/puppet/manifests/site.pp
case $operatingsystem {
'Solaris': { include role::solaris }
'RedHat', 'CentOS': { include redhat::roles::common }
/^(Debian|Ubuntu)$/: { include role::debian }
# default: { include role::generic }
}
case $hostname {
/^d0puppetclient/: { include test }
}
test.pp:
class test{
$nom = hiera('nom')
file {"/root/test.txt":
ensure => file,
source => "/etc/puppet/test.txt.erb",
}
}
test.txt.erb:
<%= nom %>
Any idea about to fix this? I thought this could be an file access right issue, so i tried to grante access on some files (755) and it's not working...
You need to define nom in your common.yaml in order for it to hold a value. You can set a default value and conditionally create the file if you don't plan on setting it.
class test {
$nom = hiera('nom', false)
if $nom {
file { '/root/test.txt':
ensure => file,
content => template('test/test.txt.erb')
}
}
}
Notice how i used content instead of source. When using erb templates you need to specify the content using the template() function.
Using Templates
If you use source it is expecting a file rather than an erb template.
Hope this helps.

Puppet: Multiple manifests in module

I am trying to create Puppet module to setup my web server.
What i want - is to split configuration to logical modules (manifests by services: webserver, database, ftp etc.) But I can not figure out how to use additional manifests in init.pp
I am going to use it only with puppet apply not server-client configuration.
My text module manifest (kp/manifests/init.pp):
class kp {
include kp::testfile
}
include kp
And additional manifest (kp/manifests/testfile.pp)
define kp::testfile {
$value = template("kp/some.erb")
file { 'testfile':
path => '/tmp/my.txt',
ensure => file,
content => $value
}
}
Documentation says:
If a class is defined in a module, you can declare that class by name in any manifest. Puppet will automatically find and load the manifest that contains the class definition.
But when I run puppet apply init.pp I am getting error message
Could not find class kp::testfile for myhost.com at /myDir/puppetModules/kp/manifests/init.pp:2 on node vagrant.example.com
Facts
/myDir/puppetModules/ is in modulepath so no problems here
Puppet version v2.7.11
Ubuntu 12.04 LTS
What I am doing wrong?
Thanks in advance!
Your kp::testfile is a defined type, not a class. To use a defined type you need to declare it like:
kp::testfile { 'name': }
Try redefining kp::testfile like
class kp::testfile {
$value = template("kp/some.erb")
file { 'testfile':
path => '/tmp/my.txt',
ensure => file,
content => $value
}
}
and you may have better luck.

Duplicate declaration error with puppet

I try to create a folder then trying to copy some files into it like below.
init.pp
$tempfolder = "D:/TempFolder/"
file { [ $tempfolder ]:
ensure => "directory",
}
file { [ $tempfolder ]:
ensure => present,
recurse => true,
source => "E:/TestFiules",
}
When I try to run this, it is giving below error
Error: Duplicate declaration: File [ D:/TempFolder/ ] is already declared.
What is the wrong in the usage?
For reference: http://docs.puppetlabs.com/guides/techniques.html#how-can-i-manage-whole-directories-of-files-without-explicitly-listing-the-files
Thus you could do
file { "$tempfolder":
ensure => directory,
recurse => true,
source => "E:/TestFiules",
}
The ensure => directory also ensures that it will be present, so you don't have to declare it again.
A node can only have one resources with the same name declared, in this case the $tempfolder.
Either the $tempfolder is created empty (your first declaration) or created and populated with your E:/TestFiule content (the second declaration).
Note that you can drop the array syntax it's often used to create multiple directory at once or ensure an order like creating a tree
I came across this message when, but the error was:
Error: Duplicate declaration: File[] is already declared in file init.pp:40; cannot redeclare at init.pp:46 on node (redacted)
The file it was looking up was not defined, because my Hiera configuration was incorrect. As a result it was declaring two files named "".
Verify that Hiera is passing values correctly.

Resources