summaryrefslogtreecommitdiffstats
path: root/ext/yaml_nodes.rb
blob: 107e57aa28c361f0c79743ff02b34f2759a76581 (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
#!/usr/bin/ruby
#
# = Synopsis
#
# Use YAML files to provide external node support.
#
# = Usage
#
#   yaml-nodes <host>
#
# = Description
#
# This is a simple example external node script.  It allows you to maintain your
# node information in yaml files, and it will find a given node's file and produce
# it on stdout.  It has simple inheritance, in that a node can specify a parent
# node, and the node will inherit that parent's classes and parameters.
#
# = Options
#
# help::
#   Print this help message
#
# yamldir::
#   Specify where the yaml is found.  Defaults to 'yaml' in the current directory.
#
# = Author
#
# Luke Kanies
#
# = Copyright
#
# Copyright (c) 2009 Puppet Labs, Inc.
# Licensed under the GPL2

require 'yaml'
require 'optparse'

BASEDIR = Dir.chdir(File.dirname(__FILE__) + "/..") { Dir.getwd }

options = {:yamldir => File.join(BASEDIR, "yaml")}
OptionParser.new do |opts|
    opts.banner = "Usage: yaml-nodes [options] <host>"

    opts.on("-y dir", "--yamldir dir", "Specify the directory with the YAML files") do |arg|
        raise "YAML directory #{arg} does not exist or is not a directory" unless FileTest.directory?(arg)
        options[:yamldir] = arg
    end

    opts.on("-h", "--help", "Print this help") do
        puts opts.help
        exit(0)
    end
end.parse!

# Read in a pure yaml representation of our node.
def read_node(node)
    nodefile = File.join(YAMLDIR, "#{node}.yaml")
    if FileTest.exist?(nodefile)
        return YAML.load_file(nodefile)
    else
        raise "Could not find information for %s" % node
    end
end

node = ARGV[0]

info = read_node(node)

# Iterate over any provided parents, merging in there information.
parents_seen = []
while parent = info["parent"]
    raise "Found inheritance loop with parent %s" % parent if parents_seen.include?(parent)

    parents_seen << parent

    info.delete("parent")

    parent_info = read_node(parent)

    # Include any parent classes in our list.
    if pclasses = parent_info["classes"]
        info["classes"] += pclasses
        info["classes"].uniq!
    end

    # And inherit parameters from our parent, while preferring our own values.
    if pparams = parent_info["parameters"]
        # When using Hash#merge, the hash being merged in wins, and we
        # want the subnode parameters to be the parent node parameters.
        info["parameters"] = pparams.merge(info["parameters"])
    end

    # Copy over any parent node name.
    if pparent = parent_info["parent"]
        info["parent"] = pparent
    end
end

puts YAML.dump(info)