Commit 755d8684 authored by Angel L. Mateo's avatar Angel L. Mateo Committed by Raphaël Pinson
Browse files

Add a map define to create postfix maps (#138)

* Add a map define to create postfix maps

It is similar to existing hash define, but this define can create maps
of any type, not just hash.

* Refactor postfix::hash to avoid duplicate code

postfix::hash uses now the new postfix::map to create the hash
parent 00b87f11
Loading
Loading
Loading
Loading
+2 −31
Original line number Diff line number Diff line
@@ -47,40 +47,11 @@ define postfix::hash (
    fail 'You must provide either \'source\' or \'content\', not both'
  }

  File {
    mode    => '0600',
    owner   => root,
    group   => root,
    seltype => $postfix::params::seltype,
  }

  file { $name:
  postfix::map {$name:
    ensure  => $ensure,
    source  => $source,
    content => $content,
    owner   => 'root',
    group   => 'root',
    mode    => '0644',
    require => Package['postfix'],
  }

  file {"${name}.db":
    ensure  => $ensure,
    require => [File[$name], Exec["generate ${name}.db"]],
  }

  exec {"generate ${name}.db":
    command => "postmap ${name}",
    path    => $::path,
    creates => "${name}.db", # this prevents postmap from being run !
    require => File[$name],
  }
  exec {"regenerate ${name}.db":
    command     => "postmap ${name}",
    path        => $::path,
    #creates    => "${name}.db", # this prevents postmap from being run !
    subscribe   => File[$name],
    refreshonly => true,
    type    => 'hash',
  }

  Class['postfix'] -> Postfix::Hash[$title]

manifests/map.pp

0 → 100644
+91 −0
Original line number Diff line number Diff line
# == Definition: postfix::map
#
# Creates postfix "map" files. It will create "${name}", and then build
# "${name}.db" using the "postmap" command. The map file can then be referred to
# using postfix::config.
#
# === Parameters
#
# [*name*]   - the name of the map file.
# [*ensure*] - present/absent, defaults to present.
# [*source*] - file source.
# [*type*]   - type of the postfix map (valid values are cidr, pcre, hash...)
# [*path*]   - path of the created file. By default it is placed in the
#              postfix directory
#
# === Requires
#
# - Class["postfix"]
#
# === Examples
#
#   postfix::map { '/etc/postfix/virtual':
#     ensure => present,
#   }
#   postfix::config { 'virtual_alias_maps':
#     value => 'hash:/etc/postfix/virtual',
#   }
#
define postfix::map (
  $ensure = 'present',
  $source = undef,
  $content = undef,
  $type = 'hash',
  $path = "/etc/postfix/${name}",
) {
  include ::postfix::params

  validate_absolute_path($path)
#  validate_string($source)
#  validate_string($content)
  if !is_string($source) and !is_array($source) { fail("value for source should be either String type or Array type got ${source}") }
  if !is_string($content) and !is_array($content) { fail("value for source should be either String type or Array type got ${content}") }
  validate_string($ensure)
  validate_re($ensure, ['present', 'absent'],
    "\$ensure must be either 'present' or 'absent', got '${ensure}'")

  if (!defined(Class['postfix'])) {
    fail 'You must define class postfix before using postfix::config!'
  }

  if $source and $content {
    fail 'You must provide either \'source\' or \'content\', not both'
  }

  # CIDR and PCRE maps need a postfix reload, but not a postmap
  if $type =~ /^(cidr|pcre)$/ {
    $manage_notify = Service['postfix']
  } else {
    $manage_notify = Exec["generate ${name}.db"]
  }

  file { "postfix map ${name}":
    ensure  => $ensure,
    path    => $path,
    source  => $source,
    content => $content,
    owner   => 'root',
    group   => 'postfix',
    mode    => '0644',
    require => Package['postfix'],
    notify  => $manage_notify,
  }

  if $type !~ /^(cidr|pcre)$/ {
    file {"postfix map ${name}.db":
      ensure  => $ensure,
      path    => "${path}.db",
      owner   => 'root',
      group   => 'postfix',
      mode    => '0644',
      require => [File["postfix map ${name}"], Exec["generate ${name}.db"]],
    }
  }

  exec {"generate ${name}.db":
    command     => "postmap ${name}",
    path        => $::path,
    #creates    => "${name}.db", # this prevents postmap from being run !
    refreshonly => true,
  }
}
+9 −12
Original line number Diff line number Diff line
@@ -62,14 +62,14 @@ describe 'postfix::hash' do
          :source  => '/tmp/bar',
        } }

        it { is_expected.to contain_file('/tmp/foo').with(
        it { is_expected.to contain_file('postfix map /tmp/foo').with(
          :ensure => 'present',
          :source => '/tmp/bar'
        ).without(:content)
        }
        it { is_expected.to contain_file('/tmp/foo.db').with_ensure('present') }
        it { is_expected.to contain_file('postfix map /tmp/foo.db').with_ensure('present') }
        it { is_expected.to contain_exec('generate /tmp/foo.db') }
        it { is_expected.to contain_exec('regenerate /tmp/foo.db') }

      end

      context 'when passing content' do
@@ -77,24 +77,22 @@ describe 'postfix::hash' do
          :content => 'bar',
        } }

        it { is_expected.to contain_file('/tmp/foo').with(
        it { is_expected.to contain_file('postfix map /tmp/foo').with(
          :ensure  => 'present',
          :content => 'bar'
        ).without(:source)
        }
        it { is_expected.to contain_file('/tmp/foo.db').with_ensure('present') }
        it { is_expected.to contain_file('postfix map /tmp/foo.db').with_ensure('present') }
        it { is_expected.to contain_exec('generate /tmp/foo.db') }
        it { is_expected.to contain_exec('regenerate /tmp/foo.db') }
      end

      context 'when not passing source or content' do
        it { is_expected.to contain_file('/tmp/foo').with(
        it { is_expected.to contain_file('postfix map /tmp/foo').with(
          :ensure  => 'present'
        ).without(:source).without(:content)
        }
        it { is_expected.to contain_file('/tmp/foo.db').with_ensure('present') }
        it { is_expected.to contain_file('postfix map /tmp/foo.db').with_ensure('present') }
        it { is_expected.to contain_exec('generate /tmp/foo.db') }
        it { is_expected.to contain_exec('regenerate /tmp/foo.db') }
      end

      context 'when ensuring absence' do
@@ -102,10 +100,9 @@ describe 'postfix::hash' do
          :ensure => 'absent',
        } }

        it { is_expected.to contain_file('/tmp/foo').with_ensure('absent') }
        it { is_expected.to contain_file('/tmp/foo.db').with_ensure('absent') }
        it { is_expected.to contain_file('postfix map /tmp/foo').with_ensure('absent') }
        it { is_expected.to contain_file('postfix map /tmp/foo.db').with_ensure('absent') }
        it { is_expected.to contain_exec('generate /tmp/foo.db') }
        it { is_expected.to contain_exec('regenerate /tmp/foo.db') }
      end
    end
  end
+117 −0
Original line number Diff line number Diff line
require 'spec_helper'

describe 'postfix::map' do
  let (:title) { 'foo' }

  let :pre_condition do
    "class { '::postfix': }"
  end

  on_supported_os.each do |os, facts|
    context "on #{os}" do
      let(:facts) do
        facts
      end

      context 'when passing wrong type for ensure' do
        let (:params) { {
          :ensure => ['present'],
        } }
        it 'should fail' do
          expect {
            is_expected.to contain_file('postfix map foo')
          }.to raise_error(Puppet::Error, /\["present"\] is not a string/)
        end
      end

      context 'when passing wrong value for ensure' do
        let (:params) { {
          :ensure => 'running',
        } }
        it 'should fail' do
          expect {
            is_expected.to contain_file('postfix map foo')
          }.to raise_error(Puppet::Error, /must be either 'present' or 'absent'/)
        end
      end

      context 'when passing both source and content' do
        let (:params) { {
          :source  => '/tmp/bar',
          :content => 'bar',
        } }

        it 'should fail' do
          expect {
            is_expected.to contain_file('postfix map foo')
          }.to raise_error(Puppet::Error, /You must provide either 'source' or 'content'/)
        end
      end

      context 'when passing source' do
        let (:params) { {
          :source  => '/tmp/bar',
        } }

        it { is_expected.to contain_file('postfix map foo').with(
          :ensure => 'present',
          :source => '/tmp/bar'
        ).without(:content)
        }
        it { is_expected.to contain_file('postfix map foo.db').with_ensure('present') }
        it { is_expected.to contain_exec('generate foo.db') }
      end

      context 'when passing content' do
        let (:params) { {
          :content => 'bar',
        } }

        it { is_expected.to contain_file('postfix map foo').with(
          :ensure  => 'present',
          :content => 'bar'
        ).without(:source)
        }
        it { is_expected.to contain_file('postfix map foo.db').with_ensure('present') }
        it { is_expected.to contain_exec('generate foo.db') }
      end

      context 'when not passing source or content' do
        it { is_expected.to contain_file('postfix map foo').with(
          :ensure  => 'present'
        ).without(:source).without(:content)
        }
        it { is_expected.to contain_file('postfix map foo.db').with_ensure('present') }
        it { is_expected.to contain_exec('generate foo.db') }
      end

      context 'when ensuring absence' do
        let (:params) { {
          :ensure => 'absent',
        } }

        it { is_expected.to contain_file('postfix map foo').with_ensure('absent') }
        it { is_expected.to contain_file('postfix map foo.db').with_ensure('absent') }
        it { is_expected.to contain_exec('generate foo.db') }
      end

      context 'when using pcre type' do
        let (:params) { {
          :type => 'pcre',
        } }

        it { is_expected.to contain_file('postfix map foo').with_ensure('present') }
        it { is_expected.not_to contain_file('postfix map foo.db') }
      end

      context 'when using cidr type' do
        let (:params) { {
          :type => 'cidr',
        } }

        it { is_expected.to contain_file('postfix map foo').with_ensure('present') }
        it { is_expected.not_to contain_file('postfix map foo.db') }
      end
    end
  end
end