diff options
24 files changed, 166 insertions, 81 deletions
| diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..8925a904 --- /dev/null +++ b/Gemfile @@ -0,0 +1,13 @@ +source "https://rubygems.org" + +group :test do +  gem "rake" +  gem "rspec", '< 3.2.0' +  gem "puppet", ENV['PUPPET_VERSION'] || ENV['GEM_PUPPET_VERSION'] || ENV['PUPPET_GEM_VERSION'] || '~> 3.7.0' +  gem "facter", ENV['FACTER_VERSION'] || ENV['GEM_FACTER_VERSION'] || ENV['FACTER_GEM_VERSION'] || '~> 2.2.0' +  gem "rspec-puppet" +  gem "puppetlabs_spec_helper" +  gem "metadata-json-lint" +  gem "rspec-puppet-facts" +  gem "mocha" +end diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..8f7a9686 --- /dev/null +++ b/Rakefile @@ -0,0 +1,47 @@ +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +require 'puppet-syntax/tasks/puppet-syntax' + +# return list of modules, either +# submodules or custom modules +# so we can check each array seperately +def modules_pattern (type) +  submodules = Array.new +  custom_modules = Array.new + +  Dir['puppet/modules/*'].sort.each do |m| +    system("grep -q #{m} .gitmodules") +    if $?.exitstatus == 0 +      submodules << m + '/**/*.pp' +    else +      custom_modules << m + '/**/*.pp' +    end +  end + +  if type == 'submodule' +    submodules +  elsif type == 'custom' +    custom_modules +  else +  end + +end + + + +# redefine lint task with specific configuration +Rake::Task[:lint].clear +desc "boo" +PuppetLint::RakeTask.new :lint do |config| +  # Pattern of files to check, defaults to `**/*.pp` +  config.pattern           = modules_pattern('custom') +  config.ignore_paths     = ["spec/**/*.pp", "pkg/**/*.pp", "vendor/**/*.pp"] +  config.disable_checks   = ['documentation', '80chars'] +  config.fail_on_warnings = false +end + +# rake syntax::* tasks +PuppetSyntax.exclude_paths = ["**/vendor/**/*"] + +desc "Run all puppet checks required for CI" +task :test => [:lint, :syntax , :validate, :spec] diff --git a/puppet/modules/clamav/manifests/daemon.pp b/puppet/modules/clamav/manifests/daemon.pp index bf232e2c..2e13a8fb 100644 --- a/puppet/modules/clamav/manifests/daemon.pp +++ b/puppet/modules/clamav/manifests/daemon.pp @@ -1,3 +1,4 @@ +# deploy clamav daemon  class clamav::daemon {    $domain_hash           = hiera('domain') @@ -55,7 +56,7 @@ class clamav::daemon {        require => Package['clamav-daemon'],        notify  => Service['clamav-daemon']; -     'enable_phishscanurls': +    'enable_phishscanurls':        path    => '/etc/clamav/clamd.conf',        match   => 'PhishingScanURLs no',        line    => 'PhishingScanURLs yes', diff --git a/puppet/modules/leap_mx/manifests/init.pp b/puppet/modules/leap_mx/manifests/init.pp index 6dfee44d..d758e3ab 100644 --- a/puppet/modules/leap_mx/manifests/init.pp +++ b/puppet/modules/leap_mx/manifests/init.pp @@ -1,3 +1,4 @@ +# deploy leap mx service  class leap_mx {    $leap_mx          = hiera('couchdb_leap_mx_user') @@ -85,7 +86,7 @@ class leap_mx {    }    leap::logfile { 'leap-mx': -    log => '/var/log/leap/mx.log', +    log     => '/var/log/leap/mx.log',      process => 'leap-mx'    } diff --git a/puppet/modules/obfsproxy/manifests/init.pp b/puppet/modules/obfsproxy/manifests/init.pp index 5c78560a..6a3d2c72 100644 --- a/puppet/modules/obfsproxy/manifests/init.pp +++ b/puppet/modules/obfsproxy/manifests/init.pp @@ -1,3 +1,4 @@ +# deploy obfsproxy service  class obfsproxy (    $transport,    $bind_address, @@ -23,18 +24,18 @@ class obfsproxy (    }    file { '/etc/init.d/obfsproxy': -    path      => '/etc/init.d/obfsproxy', -    ensure    => present, -    source    => 'puppet:///modules/obfsproxy/obfsproxy_init', -    owner     => 'root', -    group     => 'root', -    mode      => '0750', -    require   => File[$conf], +    ensure  => present, +    path    => '/etc/init.d/obfsproxy', +    source  => 'puppet:///modules/obfsproxy/obfsproxy_init', +    owner   => 'root', +    group   => 'root', +    mode    => '0750', +    require => File[$conf],    }    file { $conf : -    path    => $conf,      ensure  => present, +    path    => $conf,      owner   => 'root',      group   => 'root',      mode    => '0600', diff --git a/puppet/modules/site_config/manifests/caching_resolver.pp b/puppet/modules/site_config/manifests/caching_resolver.pp index 50824fdd..8bf465c1 100644 --- a/puppet/modules/site_config/manifests/caching_resolver.pp +++ b/puppet/modules/site_config/manifests/caching_resolver.pp @@ -1,3 +1,4 @@ +# deploy local caching resolver  class site_config::caching_resolver {    tag 'leap_base' @@ -6,7 +7,7 @@ class site_config::caching_resolver {      anchor     => false,      ssl        => false,      settings   => { -      server       => { +      server => {          verbosity      => '1',          interface      => [ '127.0.0.1', '::1' ],          port           => '53', diff --git a/puppet/modules/site_config/manifests/dhclient.pp b/puppet/modules/site_config/manifests/dhclient.pp index 7755413b..a1f87d41 100644 --- a/puppet/modules/site_config/manifests/dhclient.pp +++ b/puppet/modules/site_config/manifests/dhclient.pp @@ -1,10 +1,10 @@ +# Unfortunately, there does not seem to be a way to reload the dhclient.conf +# config file, or a convenient way to disable the modifications to +# /etc/resolv.conf. So the following makes the functions involved noops and +# ships a script to kill and restart dhclient. See the debian bugs: +# #681698, #712796  class site_config::dhclient { -  # Unfortunately, there does not seem to be a way to reload the dhclient.conf -  # config file, or a convenient way to disable the modifications to -  # /etc/resolv.conf. So the following makes the functions involved noops and -  # ships a script to kill and restart dhclient. See the debian bugs: -  # #681698, #712796    include site_config::params @@ -23,10 +23,10 @@ class site_config::dhclient {    }    file { '/etc/dhcp/dhclient-enter-hooks.d': -    ensure  => directory, -    mode    => '0755', -    owner   => 'root', -    group   => 'root', +    ensure => directory, +    mode   => '0755', +    owner  => 'root', +    group  => 'root',    }    file { '/etc/dhcp/dhclient-enter-hooks.d/disable_resolvconf': diff --git a/puppet/modules/site_couchdb/manifests/logrotate.pp b/puppet/modules/site_couchdb/manifests/logrotate.pp index e1039d49..bb8843bb 100644 --- a/puppet/modules/site_couchdb/manifests/logrotate.pp +++ b/puppet/modules/site_couchdb/manifests/logrotate.pp @@ -1,12 +1,14 @@ +# configure couchdb logrotation  class site_couchdb::logrotate {    augeas {      'logrotate_bigcouch':        context => '/files/etc/logrotate.d/bigcouch/rule', -      changes => [ 'set file /opt/bigcouch/var/log/*.log', 'set rotate 7', -                   'set schedule daily', 'set compress compress', -                   'set missingok missingok', 'set ifempty notifempty', -                   'set copytruncate copytruncate' ] +      changes => [ +        'set file /opt/bigcouch/var/log/*.log', 'set rotate 7', +        'set schedule daily', 'set compress compress', +        'set missingok missingok', 'set ifempty notifempty', +        'set copytruncate copytruncate' ]    }  } diff --git a/puppet/modules/site_couchdb/manifests/mirror.pp b/puppet/modules/site_couchdb/manifests/mirror.pp index abe35c4c..fb82b897 100644 --- a/puppet/modules/site_couchdb/manifests/mirror.pp +++ b/puppet/modules/site_couchdb/manifests/mirror.pp @@ -1,3 +1,4 @@ +# configure mirroring of couch nodes  class site_couchdb::mirror {    Class['site_couchdb::add_users'] @@ -22,55 +23,55 @@ class site_couchdb::mirror {    ### customer database    couchdb::mirror_db { 'customers': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## identities database    couchdb::mirror_db { 'identities': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## keycache database    couchdb::mirror_db { 'keycache': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## sessions database    couchdb::mirror_db { 'sessions': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## shared database    couchdb::mirror_db { 'shared': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## tickets database    couchdb::mirror_db { 'tickets': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## tokens database    couchdb::mirror_db { 'tokens': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## users database    couchdb::mirror_db { 'users': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    }    ## messages db    couchdb::mirror_db { 'messages': -    from => $from, +    from    => $from,      require => Couchdb::Query::Setup['localhost']    } diff --git a/puppet/modules/site_couchdb/manifests/upload_design.pp b/puppet/modules/site_couchdb/manifests/upload_design.pp index 7b0cabd7..bd73ebf2 100644 --- a/puppet/modules/site_couchdb/manifests/upload_design.pp +++ b/puppet/modules/site_couchdb/manifests/upload_design.pp @@ -1,4 +1,5 @@ -define site_couchdb::upload_design($db = $title, $design) { +# upload a design doc to a db +define site_couchdb::upload_design($design, $db = $title) {    $design_name = regsubst($design, '^.*\/(.*)\.json$', '\1')    $id = "_design/${design_name}"    $file = "/srv/leap/couchdb/designs/${design}" diff --git a/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp index b27c0e3c..c93c3ba2 100644 --- a/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp +++ b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp @@ -1,3 +1,4 @@ +# configure smtp tls  class site_postfix::mx::smtp_tls {    include site_config::x509::ca @@ -24,7 +25,7 @@ class site_postfix::mx::smtp_tls {      'smtp_tls_fingerprint_digest':        value => 'sha1';      'smtp_tls_session_cache_database': -      value => 'btree:${data_directory}/smtp_cache'; +      value => "btree:\${data_directory}/smtp_cache";      # see issue #4011      'smtp_tls_protocols':        value => '!SSLv2, !SSLv3'; diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp index 02a59942..66297f55 100644 --- a/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp +++ b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp @@ -1,3 +1,4 @@ +# configure smtpd tls  class site_postfix::mx::smtpd_tls {    include x509::variables @@ -19,7 +20,7 @@ class site_postfix::mx::smtpd_tls {      'smtpd_tls_eecdh_grade':        value => 'ultra';      'smtpd_tls_session_cache_database': -      value => 'btree:${data_directory}/smtpd_scache'; +      value => "btree:\${data_directory}/smtpd_scache";      # see issue #4011      'smtpd_tls_mandatory_protocols':        value => '!SSLv2, !SSLv3'; diff --git a/puppet/modules/site_shorewall/manifests/obfsproxy.pp b/puppet/modules/site_shorewall/manifests/obfsproxy.pp index 68fb9b9f..75846705 100644 --- a/puppet/modules/site_shorewall/manifests/obfsproxy.pp +++ b/puppet/modules/site_shorewall/manifests/obfsproxy.pp @@ -1,3 +1,4 @@ +# configure shorewell for obfsproxy  class site_shorewall::obfsproxy {    include site_shorewall::defaults @@ -8,7 +9,7 @@ class site_shorewall::obfsproxy {    # define macro for incoming services    file { '/etc/shorewall/macro.leap_obfsproxy': -    content => "PARAM   -       -       tcp    $scram_port ", +    content => "PARAM   -       -       tcp    ${scram_port} ",      notify  => Service['shorewall'],      require => Package['shorewall']    } diff --git a/puppet/modules/site_shorewall/manifests/service/webapp_api.pp b/puppet/modules/site_shorewall/manifests/service/webapp_api.pp index 0c6c824d..d3a1aeed 100644 --- a/puppet/modules/site_shorewall/manifests/service/webapp_api.pp +++ b/puppet/modules/site_shorewall/manifests/service/webapp_api.pp @@ -1,3 +1,4 @@ +# configure shorewall for webapp api  class site_shorewall::service::webapp_api {    $api = hiera('api') @@ -5,7 +6,7 @@ class site_shorewall::service::webapp_api {    # define macro for incoming services    file { '/etc/shorewall/macro.leap_webapp_api': -    content => "PARAM   -       -       tcp    $api_port ", +    content => "PARAM   -       -       tcp    ${api_port} ",      notify  => Service['shorewall'],      require => Package['shorewall']    } diff --git a/puppet/modules/site_shorewall/manifests/sshd.pp b/puppet/modules/site_shorewall/manifests/sshd.pp index 88b4102c..e2332592 100644 --- a/puppet/modules/site_shorewall/manifests/sshd.pp +++ b/puppet/modules/site_shorewall/manifests/sshd.pp @@ -1,3 +1,4 @@ +# configure shorewall for sshd  class site_shorewall::sshd {    $ssh_config     = hiera('ssh') @@ -7,7 +8,7 @@ class site_shorewall::sshd {    # define macro for incoming sshd    file { '/etc/shorewall/macro.leap_sshd': -    content => "PARAM   -       -       tcp    $ssh_port", +    content => "PARAM   -       -       tcp    ${ssh_port}",      notify  => Service['shorewall'],      require => Package['shorewall']    } diff --git a/puppet/modules/site_shorewall/manifests/tor.pp b/puppet/modules/site_shorewall/manifests/tor.pp index f35af985..324b4844 100644 --- a/puppet/modules/site_shorewall/manifests/tor.pp +++ b/puppet/modules/site_shorewall/manifests/tor.pp @@ -1,3 +1,4 @@ +# configure shorewall for tor  class site_shorewall::tor {    include site_shorewall::defaults @@ -7,7 +8,7 @@ class site_shorewall::tor {    # define macro for incoming services    file { '/etc/shorewall/macro.leap_tor': -    content => "PARAM   -       -       tcp    $tor_port ", +    content => "PARAM   -       -       tcp    ${tor_port} ",      notify  => Service['shorewall'],      require => Package['shorewall']    } diff --git a/puppet/modules/site_sshd/manifests/authorized_keys.pp b/puppet/modules/site_sshd/manifests/authorized_keys.pp index 90a33d8d..a1fde3f6 100644 --- a/puppet/modules/site_sshd/manifests/authorized_keys.pp +++ b/puppet/modules/site_sshd/manifests/authorized_keys.pp @@ -1,20 +1,22 @@ +# We want to purge unmanaged keys from the authorized_keys file so that only +# keys added in the provider are valid. Any manually added keys will be +# overridden. +# +# In order to do this, we have to use a custom define to deploy the +# authorized_keys file because puppet's internal resource doesn't allow +# purging before populating this file. +# +# See the following for more information: +# https://tickets.puppetlabs.com/browse/PUP-1174 +# https://leap.se/code/issues/2990 +# https://leap.se/code/issues/3010 +#  define site_sshd::authorized_keys ($keys, $ensure = 'present', $home = '') { -  # We want to purge unmanaged keys from the authorized_keys file so that only -  # keys added in the provider are valid. Any manually added keys will be -  # overridden. -  # -  # In order to do this, we have to use a custom define to deploy the -  # authorized_keys file because puppet's internal resource doesn't allow -  # purging before populating this file. -  # -  # See the following for more information: -  # https://tickets.puppetlabs.com/browse/PUP-1174 -  # https://leap.se/code/issues/2990 -  # https://leap.se/code/issues/3010 -  #    # This line allows default homedir based on $title variable.    # If $home is empty, the default is used.    $homedir = $home ? {'' => "/home/${title}", default => $home} +  $owner   = $ensure ? {'present' => $title, default => undef } +  $group   = $ensure ? {'present' => $title, default => undef }    file {      "${homedir}/.ssh":        ensure  => 'directory', @@ -23,8 +25,8 @@ define site_sshd::authorized_keys ($keys, $ensure = 'present', $home = '') {        mode    => '0700';      "${homedir}/.ssh/authorized_keys":        ensure  => $ensure, -      owner   => $ensure ? {'present' => $title, default => undef }, -      group   => $ensure ? {'present' => $title, default => undef }, +      owner   => $owner, +      group   => $group,        mode    => '0600',        require => File["${homedir}/.ssh"],        content => template('site_sshd/authorized_keys.erb'); diff --git a/puppet/modules/site_static/manifests/domain.pp b/puppet/modules/site_static/manifests/domain.pp index 5537d247..8b9378f2 100644 --- a/puppet/modules/site_static/manifests/domain.pp +++ b/puppet/modules/site_static/manifests/domain.pp @@ -1,3 +1,4 @@ +# configure static service for domain  define site_static::domain (    $ca_cert,    $key, @@ -16,15 +17,15 @@ define site_static::domain (    x509::cert { $domain:      content => $cert, -    notify => Service[apache] +    notify  => Service[apache]    }    x509::key { $domain:      content => $key, -    notify => Service[apache] +    notify  => Service[apache]    }    x509::ca { "${domain}_ca":      content => $ca_cert, -    notify => Service[apache] +    notify  => Service[apache]    }    apache::vhost::file { $domain: diff --git a/puppet/modules/site_static/manifests/init.pp b/puppet/modules/site_static/manifests/init.pp index 76ee6e19..4a722d62 100644 --- a/puppet/modules/site_static/manifests/init.pp +++ b/puppet/modules/site_static/manifests/init.pp @@ -1,3 +1,4 @@ +# deploy static service  class site_static {    tag 'leap_service' @@ -48,8 +49,8 @@ class site_static {    if (member($formats, 'amber')) {      rubygems::gem{'amber-0.3.8': -       require =>  Package['zlib1g-dev'] -     } +      require =>  Package['zlib1g-dev'] +    }      package { 'zlib1g-dev':          ensure => installed diff --git a/puppet/modules/site_static/manifests/location.pp b/puppet/modules/site_static/manifests/location.pp index ce2af9af..d116de2f 100644 --- a/puppet/modules/site_static/manifests/location.pp +++ b/puppet/modules/site_static/manifests/location.pp @@ -1,3 +1,4 @@ +# configure static service for location  define site_static::location($path, $format, $source) {    $file_path = "/srv/static/${name}" @@ -14,10 +15,10 @@ define site_static::location($path, $format, $source) {    if ($format == 'amber') {      exec {"amber_build_${name}": -      cwd     => $file_path, -      command => 'amber rebuild', -      user    => 'www-data', -      timeout => 600, +      cwd       => $file_path, +      command   => 'amber rebuild', +      user      => 'www-data', +      timeout   => 600,        subscribe => Vcsrepo[$file_path]      }    } diff --git a/puppet/modules/site_stunnel/manifests/init.pp b/puppet/modules/site_stunnel/manifests/init.pp index d919a072..a874721f 100644 --- a/puppet/modules/site_stunnel/manifests/init.pp +++ b/puppet/modules/site_stunnel/manifests/init.pp @@ -36,8 +36,8 @@ class site_stunnel {    # the default is to keep 356 log files for each stunnel.    # here we set a more reasonable number.    augeas { -    "logrotate_stunnel": -      context => "/files/etc/logrotate.d/stunnel4/rule", +    'logrotate_stunnel': +      context => '/files/etc/logrotate.d/stunnel4/rule',        changes => [          'set rotate 5',        ] diff --git a/puppet/modules/site_stunnel/manifests/override_service.pp b/puppet/modules/site_stunnel/manifests/override_service.pp index 96187048..435b9aa0 100644 --- a/puppet/modules/site_stunnel/manifests/override_service.pp +++ b/puppet/modules/site_stunnel/manifests/override_service.pp @@ -1,4 +1,9 @@ +# override stunnel::debian defaults +# +# ignore puppet lint error about inheriting from different namespace +# lint:ignore:inherits_across_namespaces  class site_stunnel::override_service inherits stunnel::debian { +# lint:endignore    include site_config::x509::cert    include site_config::x509::key diff --git a/puppet/modules/site_webapp/manifests/cron.pp b/puppet/modules/site_webapp/manifests/cron.pp index 7147a0d2..70b9da04 100644 --- a/puppet/modules/site_webapp/manifests/cron.pp +++ b/puppet/modules/site_webapp/manifests/cron.pp @@ -1,3 +1,4 @@ +# setup webapp cronjobs  class site_webapp::cron {    # cron tasks that need to be performed to cleanup the database @@ -19,12 +20,12 @@ class site_webapp::cron {      # there is no longer a need to remove expired sessions, since the database      # will get destroyed.      'remove_expired_sessions': +      ensure      => absent,        command     => 'cd /srv/leap/webapp && bundle exec rake cleanup:sessions',        environment => 'RAILS_ENV=production',        user        => 'leap-webapp',        hour        => 2, -      minute      => 30, -      ensure      => absent; +      minute      => 30;      'remove_expired_tokens':        command     => 'cd /srv/leap/webapp && bundle exec rake cleanup:tokens', diff --git a/puppet/modules/try/manifests/file.pp b/puppet/modules/try/manifests/file.pp index cd1bb035..2493d343 100644 --- a/puppet/modules/try/manifests/file.pp +++ b/puppet/modules/try/manifests/file.pp @@ -32,17 +32,17 @@ define try::file (    exec {      "chmod_${name}":        command => "/bin/chmod -R ${mode} '${name}'", -      onlyif => "/usr/bin/test $mode", +      onlyif => "/usr/bin/test ${mode}",        refreshonly => true,        loglevel => debug;      "chown_${name}":        command => "/bin/chown -R ${owner} '${name}'", -      onlyif => "/usr/bin/test $owner", +      onlyif => "/usr/bin/test ${owner}",        refreshonly => true,        loglevel => debug;      "chgrp_${name}":        command => "/bin/chgrp -R ${group} '${name}'", -      onlyif => "/usr/bin/test $group", +      onlyif => "/usr/bin/test ${group}",        refreshonly => true,        loglevel => debug;    } @@ -50,31 +50,31 @@ define try::file (    if $target {      exec { "symlink_${name}":        command => "/bin/ln -s ${target} ${name}", -      onlyif => "/usr/bin/test -d '${target}'", +      onlyif  => "/usr/bin/test -d '${target}'",      }    } elsif $source {      if $ensure == 'directory' {        if $purge {          exec { "rsync_${name}":            command => "/usr/bin/rsync -r --delete '${source}/' '${name}'", -          onlyif => "/usr/bin/test -d '${source}'", -          unless => "/usr/bin/diff -rq '${source}' '${name}'", -          notify => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] +          onlyif  => "/usr/bin/test -d '${source}'", +          unless  => "/usr/bin/diff -rq '${source}' '${name}'", +          notify  => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]]          }        } else {          exec { "cp_r_${name}":            command => "/bin/cp -r '${source}' '${name}'", -          onlyif => "/usr/bin/test -d '${source}'", -          unless => "/usr/bin/diff -rq '${source}' '${name}'", -          notify => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] +          onlyif  => "/usr/bin/test -d '${source}'", +          unless  => "/usr/bin/diff -rq '${source}' '${name}'", +          notify  => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]]          }        }      } else {        exec { "cp_${name}":          command => "/bin/cp --remove-destination '${source}' '${name}'", -        onlyif => "/usr/bin/test -e '${source}'", -        unless => "/usr/bin/test ! -h '${name}' && /usr/bin/diff -q '${source}' '${name}'", -        notify => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] +        onlyif  => "/usr/bin/test -e '${source}'", +        unless  => "/usr/bin/test ! -h '${name}' && /usr/bin/diff -q '${source}' '${name}'", +        notify  => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]]        }      }    } | 
