diff --git a/lib/puppet/provider/mailalias/aliases.rb b/lib/puppet/provider/mailalias/aliases.rb index 87ee5b465..025c2a752 100644 --- a/lib/puppet/provider/mailalias/aliases.rb +++ b/lib/puppet/provider/mailalias/aliases.rb @@ -1,39 +1,50 @@ require 'puppet/provider/parsedfile' Puppet::Type.type(:mailalias).provide( :aliases, :parent => Puppet::Provider::ParsedFile, :default_target => "/etc/aliases", :filetype => :flat ) do text_line :comment, :match => /^#/ text_line :blank, :match => /^\s*$/ record_line :aliases, :fields => %w{name recipient}, :separator => /\s*:\s*/, :block_eval => :instance do def post_parse(record) - record[:recipient] = record[:recipient].split(/\s*,\s*/).collect { |d| d.gsub(/^['"]|['"]$/, '') } + if record[:recipient] + record[:recipient] = record[:recipient].split(/\s*,\s*/).collect { |d| d.gsub(/^['"]|['"]$/, '') } + end record end def process(line) ret = {} - records = line.split(':',2) + records = line.split(':',4) ret[:name] = records[0].strip - ret[:recipient] = records[1].strip + if records.length == 4 and records[2].strip == 'include' + ret[:file] = records[3].strip + else + records = line.split(':',2) + ret[:recipient] = records[1].strip + end ret end def to_line(record) - dest = record[:recipient].collect do |d| - # Quote aliases that have non-alpha chars - if d =~ /[^-\w@.]/ - '"%s"' % d - else - d - end - end.join(",") - "#{record[:name]}: #{dest}" + if record[:recipient] + dest = record[:recipient].collect do |d| + # Quote aliases that have non-alpha chars + if d =~ /[^-\w@.]/ + '"%s"' % d + else + d + end + end.join(",") + "#{record[:name]}: #{dest}" + elsif record[:file] + "#{record[:name]}: :include: #{record[:file]}" + end end end end diff --git a/lib/puppet/type/mailalias.rb b/lib/puppet/type/mailalias.rb index 0a8f03af1..624f293a7 100644 --- a/lib/puppet/type/mailalias.rb +++ b/lib/puppet/type/mailalias.rb @@ -1,48 +1,62 @@ module Puppet Type.newtype(:mailalias) do @doc = "Creates an email alias in the local alias database." ensurable newparam(:name, :namevar => true) do desc "The alias name." end newproperty(:recipient, :array_matching => :all) do desc "Where email should be sent. Multiple values - should be specified as an array." + should be specified as an array. The file and the + recipient entries are mutually exclusive." def is_to_s(value) if value.include?(:absent) super else value.join(",") end end - def should - @should - end - def should_to_s(value) if value.include?(:absent) super else value.join(",") end end end + newproperty(:file) do + desc "A file containing the alias's contents. The file and the + recipient entries are mutually exclusive." + + validate do |value| + unless Puppet::Util.absolute_path?(value) + fail Puppet::Error, "File paths must be fully qualified, not '#{value}'" + end + end + end + newproperty(:target) do desc "The file in which to store the aliases. Only used by those providers that write to disk." defaultto { if @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile) @resource.class.defaultprovider.default_target else nil end } end + + validate do + if self[:recipient] && self[:file] + self.fail "You cannot specify both a recipient and a file" + end + end end end diff --git a/spec/fixtures/integration/provider/mailalias/aliases/test1 b/spec/fixtures/integration/provider/mailalias/aliases/test1 index ecf532213..a69be8a2f 100644 --- a/spec/fixtures/integration/provider/mailalias/aliases/test1 +++ b/spec/fixtures/integration/provider/mailalias/aliases/test1 @@ -1,28 +1,31 @@ # Basic system aliases -- these MUST be present MAILER-DAEMON: postmaster postmaster: root # General redirections for pseudo accounts bin: root daemon: root named: root nobody: root uucp: root www: root ftp-bugs: root postfix: root # Put your local aliases here. # Well-known aliases manager: root dumper: root operator: root abuse: postmaster # trap decode to catch security attacks decode: root # Other tests anothertest: "|/path/to/rt-mailgate --queue 'another test' --action correspond --url http://my.com/" test: "|/path/to/rt-mailgate --queue 'test' --action correspond --url http://my.com/" + +# Included file +incfile: :include: /tmp/somefile diff --git a/spec/unit/type/mailalias_spec.rb b/spec/unit/type/mailalias_spec.rb index 0ba60ce52..abb8f32b0 100755 --- a/spec/unit/type/mailalias_spec.rb +++ b/spec/unit/type/mailalias_spec.rb @@ -1,21 +1,48 @@ #! /usr/bin/env ruby require 'spec_helper' describe Puppet::Type.type(:mailalias) do include PuppetSpec::Files let :target do tmpfile('mailalias') end - let :resource do + let :recipient_resource do described_class.new(:name => "luke", :recipient => "yay", :target => target) end - it "should be initially absent" do - resource.retrieve_resource[:recipient].should == :absent + let :file_resource do + described_class.new(:name => "lukefile", :file => "/tmp/afile", :target => target) + end + + it "should be initially absent as a recipient" do + recipient_resource.retrieve_resource[:recipient].should == :absent + end + + it "should be initially absent as an included file" do + file_resource.retrieve_resource[:file].should == :absent end it "should try and set the recipient when it does the sync" do - resource.retrieve_resource[:recipient].should == :absent - resource.property(:recipient).expects(:set).with(["yay"]) - resource.property(:recipient).sync + recipient_resource.retrieve_resource[:recipient].should == :absent + recipient_resource.property(:recipient).expects(:set).with(["yay"]) + recipient_resource.property(:recipient).sync + end + + it "should try and set the included file when it does the sync" do + file_resource.retrieve_resource[:file].should == :absent + file_resource.property(:file).expects(:set).with("/tmp/afile") + file_resource.property(:file).sync + end + + it "should fail when file is not an absolute path" do + expect { + Puppet::Type.type(:mailalias).new(:name => 'x', :file => 'afile') + }.to raise_error Puppet::Error, /File paths must be fully qualified/ + end + + it "should fail when both file and recipient are specified" do + expect { + Puppet::Type.type(:mailalias).new(:name => 'x', :file => '/tmp/afile', + :recipient => 'foo@example.com') + }.to raise_error Puppet::Error, /cannot specify both a recipient and a file/ end end