summaryrefslogtreecommitdiffstats
path: root/lib/puppet/type/file/content.rb
blob: f48e601fb8f0051a0d74ed3ef6b284971d4ea874 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
require 'puppet/util/checksums'

module Puppet
    Puppet::Type.type(:file).newproperty(:content) do
        include Puppet::Util::Diff
        include Puppet::Util::Checksums

        desc "Specify the contents of a file as a string.  Newlines, tabs, and
            spaces can be specified using the escaped syntax (e.g., \\n for a
            newline).  The primary purpose of this parameter is to provide a
            kind of limited templating::

                define resolve(nameserver1, nameserver2, domain, search) {
                    $str = \"search $search
                domain $domain
                nameserver $nameserver1
                nameserver $nameserver2
                \"

                    file { \"/etc/resolv.conf\":
                        content => $str
                    }
                }
            
            This attribute is especially useful when used with
            `PuppetTemplating templating`:trac:."

        # Store a checksum as the value, rather than the actual content.
        # Simplifies everything.
        munge do |value|
            if value == :absent
                value
            else
                @actual_content = value
                "{#{checksum_type}}" + send(self.checksum_type, value)
            end
        end

        def checksum_type
            if source = resource.parameter(:source)
                source.checksum =~ /^\{(\w+)\}.+/
                return $1.to_sym
            elsif checksum = resource.parameter(:checksum)
                result = checksum.checktype
                if result =~ /^\{(\w+)\}.+/
                    return $1.to_sym
                else
                    return result
                end
            else
                return :md5
            end
        end

        # If content was specified, return that; else try to return the source content;
        # else, return nil.
        def actual_content
            if defined?(@actual_content) and @actual_content
                return @actual_content
            end

            if s = resource.parameter(:source)
                return s.content
            end
            return nil
        end
        
        def content
            self.should || (s = resource.parameter(:source) and s.content)
        end

        # Override this method to provide diffs if asked for.
        # Also, fix #872: when content is used, and replace is true, the file
        # should be insync when it exists
        def insync?(is)
            if resource.should_be_file?
                return false if is == :absent
            else
                return true
            end

            return true if ! @resource.replace?

            if self.should
                return super
            elsif source = resource.parameter(:source)
                fail "Got a remote source with no checksum" unless source.checksum
                result = (is == source.checksum)
            else
                # We've got no content specified, and no source from which to
                # get content.
                return true
            end

            if ! result and Puppet[:show_diff]
                string_file_diff(@resource[:path], actual_content)
            end
            return result
        end

        def retrieve
            return :absent unless stat = @resource.stat

            # Don't even try to manage the content on directories or links
            return nil if stat.ftype == "directory"

            begin
                return "{#{checksum_type}}" + send(checksum_type.to_s + "_file", resource[:path]).to_s
            rescue => detail
                raise Puppet::Error, "Could not read %s: %s" % [@resource.title, detail]
            end
        end

        # Make sure we're also managing the checksum property.
        def should=(value)
            @resource.newattr(:checksum) unless @resource.parameter(:checksum)
            super
        end

        # Just write our content out to disk.
        def sync
            return_event = @resource.stat ? :file_changed : :file_created
            
            # We're safe not testing for the 'source' if there's no 'should'
            # because we wouldn't have gotten this far if there weren't at least
            # one valid value somewhere.
            @resource.write(actual_content, :content)

            return return_event
        end
    end
end