Guidelines

This site is for tech Q&A. Please keep your posts focused on the subject at hand.

Ask one question at a time. Don't conflate multiple problems into a single question.

Make sure to include all relevant information in your posts. Try to avoid linking to external sites.

Links to documentation are fine, but in addition you should also quote the relevant parts in your posts.

0 votes
9 views
9 views

Some of our services need their SSL certificate (and key) in a particular place rather than the system default locations. We're using Puppet to copy the respective files there, which works fine in general. However, the subdirectory for the files doesn't necessarily exist, so I want Puppet to create that as well.

Currently my manifest looks like this:

file { dirname($ssl_key_dst):
  ensure  => 'directory',
  group   => $ssl_group,
  mode    => '0750',
  require => Group[$ssl_group],
}
-> file { $ssl_key_dst:
  ensure  => 'file',
  owner   => 'root',
  group   => $ssl_group,
  mode    => '0640',
  source  => $ssl_key_src,
  require => Group[$ssl_group],
}
file { $ssl_cert_dst:
  ensure  => 'file',
  owner   => 'root',
  group   => $ssl_group,
  mode    => '0644',
  source  => $ssl_cert_src,
  require => Group[$ssl_group],
}

which works fine if both files go into the same directory, but will fail if the certificate file should go into a different (non-existing) directory. I could add another file resource to create the certificate directory:

...
file { dirname($ssl_cert_dst):
  ensure  => 'directory',
  group   => $ssl_group,
  mode    => '0750',
  require => Group[$ssl_group],
}
-> file { $ssl_cert_dst:
  ensure  => 'file',
  owner   => 'root',
  group   => $ssl_group,
  mode    => '0644',
  source  => $ssl_cert_src,
  require => Group[$ssl_group],
}

but that would fail with a duplicate resource declaration error if both files go into the same directory.

I know I could replace the (directory) file resources with exec resources doing mkdir -p, but that's rather ugly, and I'd prefer to avoid it if possible.

in General by (30) 5
edited by

Your answer

Preview

Privacy: Your email address will only be used for sending these notifications.
Anti-spam verification:
By submitting this post you agree to our Terms & Conditions.
To avoid this verification in future, please log in or register.

1 Answer

0 votes
 
Best answer

For one thing, you can pass an array to a file resource, so that you only need one declaration to create both directories:

file { [dirname($ssl_cert_dst), dirname($ssl_cert_dst)]:
  ensure  => 'directory',
  group   => $ssl_group,
  mode    => '0750',
  require => Group[$ssl_group],
}

However, that alone would still throw a duplicate resource declaration error if both certificate and key go into the same directory. To avoid that use the unique() function, so that the array is reduced to just its unique elements:

unique([ '/foo/bar', '/foo/bar' ])    # result: [ '/foo/bar' ]
unique([ '/foo/bar', '/foo/baz' ])    # result: [ '/foo/bar', '/foo/baz' ]

If certificate and key go into the same directory you'll get one result. If they go into different directories you'll get two results. Use the require metaparameter instead of chaining arrows to define the proper resource order.

$ssl_key_dir  = dirname($ssl_key_dst)
$ssl_cert_dir = dirname($ssl_cert_dst)

file { unique([$ssl_key_dir, $ssl_cert_dir]):
  ensure  => 'directory',
  group   => $ssl_group,
  mode    => '0750',
  require => Group[$ssl_group],
}

file { $ssl_key_dst:
  ensure  => 'file',
  owner   => 'root',
  group   => $ssl_group,
  mode    => '0640',
  source  => $ssl_key_src,
  require => [
    Group[$ssl_group],
    File[$ssl_key_dir],
  ],
}
file { $ssl_cert_dst:
  ensure  => 'file',
  owner   => 'root',
  group   => $ssl_group,
  mode    => '0644',
  source  => $ssl_cert_src,
  require => [
    Group[$ssl_group],
    File[$ssl_cert_dir],
  ],  
}

Beware, however, that with this approach separate directories will have the same access rights (which may be undesired for either SSL keys or certificates). In that case you could make do with a simple condition like this:

if ($ssl_key_dir != $ssl_cert_dir) {
  file { $ssl_cert_dir:
    ensure => 'directory',
    mode   => '0755',
  }
}
file { $ssl_key_dir:
  ensure  => 'directory',
  group   => $ssl_group,
  mode    => '0750',
  require => Group[$ssl_group],
}
by (30) 5
...