summaryrefslogtreecommitdiffstats
path: root/lib/puppet/node/searching.rb
blob: 3a632d50e5b1a3e4fe0e6d9ba5c2ea2ddc6d16d1 (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
# The module that handles actually searching for nodes.  This is only included
# in the Node class, but it's completely stand-alone functionality, so it's
# worth making it a separate module to simplify testing.
module Puppet::Node::Searching
    # Retrieve a node from the node source, with some additional munging
    # thrown in for kicks.
    def search(key)
        return nil unless key
        if node = cached?(key)
            return node
        end
        facts = node_facts(key)
        node = nil
        names = node_names(key, facts)
        names.each do |name|
            name = name.to_s if name.is_a?(Symbol)
            if node = get(name)
                #Puppet.info "Found %s in %s" % [name, @source]
                break
            end
        end

        # If they made it this far, we haven't found anything, so look for a
        # default node.
        unless node or names.include?("default")
            if node = get("default")
                Puppet.notice "Using default node for %s" % key
            end
        end

        if node
            node.names = names

            cache(node)

            return node
        else
            return nil
        end
    end

    private

    # Store the node to make things a bit faster.
    def cache(node)
        @node_cache ||= {}
        @node_cache[node.name] = node
    end

    # If the node is cached, return it.
    def cached?(name)
        # Don't use cache when the filetimeout is set to 0
        return false if [0, "0"].include?(Puppet[:filetimeout])
        @node_cache ||= {}

        if node = @node_cache[name] and Time.now - node.time < Puppet[:filetimeout]
            return node
        else
            return false
        end
    end

    # Look up the node facts from our fact handler.
    def node_facts(key)
        if facts = Puppet::Node::Facts.get(key)
            facts.values
        else
            {}
        end
    end

    # Calculate the list of node names we should use for looking
    # up our node.
    def node_names(key, facts = nil)
        facts ||= node_facts(key)
        names = []

        if hostname = facts["hostname"]
            unless hostname == key
                names << hostname
            end
        else
            hostname = key
        end

        if fqdn = facts["fqdn"]
            hostname = fqdn
            names << fqdn
        end

        # Make sure both the fqdn and the short name of the
        # host can be used in the manifest
        if hostname =~ /\./
            names << hostname.sub(/\..+/,'')
        elsif domain = facts['domain']
            names << hostname + "." + domain
        end

        # Sort the names inversely by name length.
        names.sort! { |a,b| b.length <=> a.length }

        # And make sure the key is first, since that's the most
        # likely usage.
        ([key] + names).uniq
    end
end