summaryrefslogtreecommitdiffstats
path: root/lib/puppet/transportable.rb
blob: a9dea65ec720511447adfd6bcd9b1cab9d2966b8 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/local/bin/ruby -w

# $Id$

require 'puppet'

module Puppet
    #------------------------------------------------------------
    class TransObject < Hash
        attr_accessor :type, :name, :file, :line

        attr_writer :tags

        def initialize(name,type)
            self[:name] = name
            @type = type
            @name = name
            #self.class.add(self)
        end

        def longname
            return [self.type,self[:name]].join('--')
        end

        def tags
            return @tags + [@type, @name]
        end

        def to_s
            return "%s(%s) => %s" % [@type,self[:name],super]
        end

        def to_type
            retobj = nil
            if type = Puppet::Type.type(self.type)
                unless retobj = type.create(self)
                    return nil
                end
                retobj.file = @file
                retobj.line = @line
            else
                raise Puppet::Error.new("Could not find object type %s" % self.type)
            end

            if defined? @tags and @tags
                #Puppet.debug "%s(%s) tags: %s" % [@type, @name, @tags.join(" ")]
                retobj.tags = @tags
            end

            return retobj
        end
    end
    #------------------------------------------------------------

    #------------------------------------------------------------
    # just a linear container for objects
    class TransBucket < Array
        attr_accessor :name, :type, :file, :line

        def push(*args)
            args.each { |arg|
                case arg
                when Puppet::TransBucket, Puppet::TransObject
                    # nada
                else
                    raise "TransBuckets cannot handle objects of type %s" %
                        arg.class
                end
            }
            super
        end

        def to_type
            # this container will contain the equivalent of all objects at
            # this level
            #container = Puppet::Component.new(:name => @name, :type => @type)
            unless defined? @name
                raise Puppet::DevError, "TransBuckets must have names"
            end
            unless defined? @type
                Puppet.debug "TransBucket '%s' has no type" % @name
            end
            hash = {
                :name => @name,
                :type => @type
            }
            if defined? @parameters
                @parameters.each { |param,value|
                    Puppet.debug "Defining %s on %s of type %s" %
                        [param,@name,@type]
                    hash[param] = value
                }
            else
                Puppet.debug "%s has no parameters" % @name
            end
            container = Puppet::Type::Component.create(hash)

            # unless we successfully created the container, return an error
            unless container
                return nil
            end
            nametable = {}

            self.each { |child|
                # the fact that we descend here means that we are
                # always going to execute depth-first
                # which is _probably_ a good thing, but one never knows...
                if child.is_a?(Puppet::TransBucket)
                    # just perform the same operation on any children
                    obj = child.to_type
                    if obj
                        container.push(obj)
                    else
                        # FIXME we need to figure out error handling.
                        # really
                    end
                elsif child.is_a?(Puppet::TransObject)
                    # do a simple little naming hack to see if the object already
                    # exists in our scope
                    # this assumes that type/name combinations are globally
                    # unique

                    # FIXME this still might be wrong, because it doesn't search
                    # up scopes
                    # either that, or it's redundant
                    name = [child[:name],child.type].join("--")

                    if nametable.include?(name)
                        object = nametable[name]
                        child.each { |var,value|
                            # don't rename; this shouldn't be possible anyway
                            next if var == :name

                            Puppet.debug "Adding %s to %s" % [var,name]
                            # override any existing values
                            object[var] = value
                        }
                        object.parent = self
                    else # the object does not exist yet in our scope
                        # now we have the object instantiated, in our scope
                        if object = child.to_type
                            # the object will be nil if it failed
                            nametable[name] = object

                            # this sets the order of the object
                            container.push object
                        end
                    end
                else
                    raise "TransBucket#to_type cannot handle objects of type %s" %
                        child.class
                end
            }

            # at this point, no objects at are level are still Transportable
            # objects
            return container
        end

        def param(param,value)
            unless defined? @parameters
                @parameters = {}
            end
            @parameters[param] = value
        end

    end
    #------------------------------------------------------------
end