quant
quant

Reputation: 512

Puppet Error: You cannot specify more than one of content, source, target

I am trying to create one file and one symbolic link via Puppet (with Hiera). I'm running on Ubuntu 16.04, and I am using all latest modules. The file is called "a" and the link is called "b". These files are not related directly.

I have a init.pp file for the node:

define hiera::files (
    $ensure,
    $content= "",
    $target="/./.",
    $mode = "",
    $owner = "root",
    $force = "false" ) {

  file { $title:
    ensure  => $ensure,
    owner   => $owner,
    force   => $force,
    content => $content,
    mode    => $mode,
    target  => $target,
  }
}

create_resources('hiera::files', hiera_hash('files', {}))

node "default" {
  hiera_include('classes')
}

There is also a node.yaml file containing the corresponding data:

files:
   /etc/a.txt:
   ensure: "present"
   mode: "2770"
   owner: "simon"
   content: "[d] \n type = sss \n resource = samba_1"

/etc/b:
   ensure: "link"
   target: "/usr/share/b"
   mode: "777"

I have tried other variations, but I always get an error that I cannot specify more than one of content, source, target. Is it possible to have both? Not for the same file, but for separate files like I am trying to do?

Upvotes: 1

Views: 1480

Answers (1)

Dominic Cleal
Dominic Cleal

Reputation: 3205

The hiera::files defaults are the issue here, as even if you're not specifying content and target in your Hiera hash, they're being set:

define hiera::files ( $ensure, $content= "", $target="/./.", $mode = "",   $owner = "root", $force = "false" ){

Change the $content and $target defaults to undef so they must be specified if you're going to use them.

define hiera::files ( $ensure, $content = undef, $target = undef, $mode = "",   $owner = "root", $force = "false" ){

If you really need these default values, then you need a way to avoid setting target on a file with content, and content on a file/symlink with target, e.g.

define hiera::files ( $ensure, $content = undef, $target = undef, $mode = "",   $owner = "root", $force = "false" ){
  # Provide a default empty content value when ensure => present, and no content is given
  $real_content = $ensure ? {
    "present" => $content ? {
      undef   => "",
      default => $content,
    },
    default   => undef,
  }

  # Provide a default /./. target value when ensure => link, and no target is given
  $real_target = $ensure ? {
    "link"  => $target ? {
      undef   => "/./.",
      default => $target,
    },
    default => undef,
  }

  file { $title:
    ensure => $ensure,
    owner => $owner,
    force => $force,
    content => $real_content,
    mode => $mode,
    target => $real_target,
  }
}

Or perhaps preferably, use separate defines to make the behaviour clear.

Upvotes: 2

Related Questions