Update concat
[mirror/dsa-puppet.git] / 3rdparty / modules / concat / lib / puppet / type / concat_file.rb
1 require 'puppet/type/file/owner'
2 require 'puppet/type/file/group'
3 require 'puppet/type/file/mode'
4 require 'puppet/util/checksums'
5
6 Puppet::Type.newtype(:concat_file) do
7   @doc = "Gets all the file fragments and puts these into the target file.
8     This will mostly be used with exported resources.
9
10     example:
11       Concat_fragment <<| tag == 'unique_tag' |>>
12
13       concat_file { '/tmp/file':
14         tag            => 'unique_tag', # Mandatory
15         path           => '/tmp/file',  # Optional. If given it overrides the resource name
16         owner          => 'root',       # Optional. Default to undef
17         group          => 'root',       # Optional. Default to undef
18         mode           => '0644'        # Optional. Default to undef
19         order          => 'numeric'     # Optional, Default to 'numeric'
20         ensure_newline => false         # Optional, Defaults to false
21       }
22   "
23
24   ensurable do
25     defaultvalues
26
27     defaultto { :present }
28   end
29
30   def exists?
31     self[:ensure] == :present
32   end
33
34   newparam(:tag) do
35     desc "Tag reference to collect all concat_fragment's with the same tag"
36   end
37
38   newparam(:path, :namevar => true) do
39     desc "The output file"
40
41     validate do |value|
42       unless (Puppet::Util.absolute_path?(value, :posix) or Puppet::Util.absolute_path?(value, :windows))
43         raise ArgumentError, "File paths must be fully qualified, not '#{value}'"
44       end
45     end
46   end
47
48   newparam(:owner, :parent => Puppet::Type::File::Owner) do
49     desc "Desired file owner."
50   end
51
52   newparam(:group, :parent => Puppet::Type::File::Group) do
53     desc "Desired file group."
54   end
55
56   newparam(:mode, :parent => Puppet::Type::File::Mode) do
57     desc "Desired file mode."
58   end
59
60   newparam(:order) do
61     desc "Controls the ordering of fragments. Can be set to alpha or numeric."
62
63     newvalues(:alpha, :numeric)
64
65     defaultto :numeric
66   end
67
68   newparam(:backup) do
69     desc "Controls the filebucketing behavior of the final file and see File type reference for its use."
70     defaultto 'puppet'
71   end
72
73   newparam(:replace, :boolean => true, :parent => Puppet::Parameter::Boolean) do
74     desc "Whether to replace a file that already exists on the local system."
75     defaultto :true
76   end
77
78   newparam(:validate_cmd) do
79     desc "Validates file."
80   end
81
82   newparam(:ensure_newline, :boolean => true, :parent => Puppet::Parameter::Boolean) do
83     desc "Whether to ensure there is a newline after each fragment."
84     defaultto :false
85   end
86
87   # Inherit File parameters
88   newparam(:selinux_ignore_defaults) do
89   end
90
91   newparam(:selrange) do
92   end
93
94   newparam(:selrole) do
95   end
96
97   newparam(:seltype) do
98   end
99
100   newparam(:seluser) do
101   end
102
103   newparam(:show_diff) do
104   end
105   # End file parameters
106
107   # Autorequire the file we are generating below
108   autorequire(:file) do
109     [self[:path]]
110   end
111
112   def should_content
113     return @generated_content if @generated_content
114     @generated_content = ""
115     content_fragments = []
116
117     resources = catalog.resources.select do |r|
118       r.is_a?(Puppet::Type.type(:concat_fragment)) && r[:tag] == self[:tag]
119     end
120
121     resources.each do |r|
122       content_fragments << ["#{r[:order]}___#{r[:name]}", fragment_content(r)]
123     end
124
125     if self[:order] == :numeric
126       sorted = content_fragments.sort do |a, b|
127         def decompound(d)
128           d.split('___', 2).map { |v| v =~ /^\d+$/ ? v.to_i : v }
129         end
130
131         decompound(a[0]) <=> decompound(b[0])
132       end
133     else
134       sorted = content_fragments.sort_by do |a|
135         a_order, a_name = a[0].split('__', 2)
136         [a_order, a_name]
137       end
138     end
139
140     @generated_content = sorted.map { |cf| cf[1] }.join
141
142     @generated_content
143   end
144
145   def fragment_content(r)
146     if r[:content].nil? == false
147       fragment_content = r[:content]
148     elsif r[:source].nil? == false
149       @source = nil
150       Array(r[:source]).each do |source|
151         if Puppet::FileServing::Metadata.indirection.find(source)
152           @source = source 
153           break
154         end
155       end
156       self.fail "Could not retrieve source(s) #{r[:source].join(", ")}" unless @source
157       tmp = Puppet::FileServing::Content.indirection.find(@source)
158       fragment_content = tmp.content unless tmp.nil?
159     end
160
161     if self[:ensure_newline]
162       fragment_content<<"\n" unless fragment_content =~ /\n$/
163     end
164
165     fragment_content
166   end
167
168   def generate
169     file_opts = {
170       :ensure => self[:ensure] == :absent ? :absent : :file,
171     }
172
173     [:path,
174      :owner,
175      :group,
176      :mode,
177      :replace,
178      :backup,
179      :selinux_ignore_defaults,
180      :selrange,
181      :selrole,
182      :seltype,
183      :seluser,
184      :validate_cmd,
185      :show_diff].each do |param|
186       unless self[param].nil?
187         file_opts[param] = self[param]
188       end
189     end
190
191     metaparams = Puppet::Type.metaparams
192     excluded_metaparams = [ :before, :notify, :require, :subscribe, :tag ]
193
194     metaparams.reject! { |param| excluded_metaparams.include? param }
195
196     metaparams.each do |metaparam|
197       file_opts[metaparam] = self[metaparam] if self[metaparam]
198     end
199
200     [Puppet::Type.type(:file).new(file_opts)]
201   end
202
203   def eval_generate
204     content = should_content
205
206     if !content.nil? and !content.empty?
207       catalog.resource("File[#{self[:path]}]")[:content] = content
208     end
209
210     [ catalog.resource("File[#{self[:path]}]") ]
211   end
212 end