I've tried to create a smart file definition for two files that belong into one directory using this code snippet:

file { ["check-disk-shell-net-snmp", ""]:
    ensure => present,
    path => "${check_base}/${name}",
    source => "puppet:///modules/icinga2/${name}",
    owner => icinga,
    group => icinga,
    mode => 775,
    require => File["${check_base}"];

As described in the puppet documentation, the path is usually constructed by using namevar, which I interpret as "the variable named name".

The problem

What happens is actually something totally different (puppet --version: 2.7.5):

err: Failed to apply catalog: Cannot alias File[check-disk-shell-net-snmp] to
["/opt/"] at
/etc/puppet/modules/icinga2/manifests/serverchecks.pp:25; resource
["File", "/opt/"] already defined at

The internal alias message is a bit confusing (I did not intentionally create an alias), but that puppet is using the classname instead of the name supplied to file is surprising.

Update: I've found the correct documentation part in the puppet language guide that describes the feature I was trying to use:

Most resources have an attribute (often called simply name) whose value 
will default to the title if you don’t specify it. (Internally, this is 
called the “namevar.”) For the file type, the path will default to the 
title. A resource’s namevar value almost always has to be unique. 
(The exec and notify types are the exceptions.)

The solution

Well, there are two solutions:

  • rewrite to two file entries (simple, code redundancy, ugly)
  • switch over to using cdist (more initial effort, biased author)

It is very good from time to time being remembered, which motivations I had when starting the cdist project. In this case, it had been:

  • Supply understandable, good error messages to the user
  • Do what the user expects
  • Consistent behaviour

\ If you are interested, there is commercial support available for puppet to cdist migrations. \