Class: ExternalNode

Inherits:
Object show all
Defined in:
ext/regexp_nodes/regexp_nodes.rb

Overview

This class holds all the methods for creating and accessing the properties of an external node. There are really only two public methods: initialize and a special version of to_yaml

Direct Known Subclasses

MyExternalNode

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hostname, classdir = 'classes/', parameterdir = 'parameters/') ⇒ ExternalNode

initialize takes three arguments:

hostname

usually passed in via ARGV but it could be anything

classdir

directory under WORKINGDIR to look for files named after

classes

parameterdir

directory under WORKINGDIR to look for directories to set

parameters



70
71
72
73
74
75
76
77
78
79
# File 'ext/regexp_nodes/regexp_nodes.rb', line 70

def initialize(hostname, classdir = 'classes/', parameterdir = 'parameters/')
  # instance variables that contain the lists of classes and parameters
  @hostname
  @classes = Set.new ["baseclass"]
  @parameters = Hash.new("unknown")    # sets a default value of "unknown"

  self.parse_argv(hostname)
  self.match_classes(WORKINGDIR + "/#{classdir}")
  self.match_parameters(WORKINGDIR + "/#{parameterdir}")
end

Instance Attribute Details

#classesObject

Make these instance variables get/set-able with eponymous methods



62
63
64
# File 'ext/regexp_nodes/regexp_nodes.rb', line 62

def classes
  @classes
end

#hostnameObject

Make these instance variables get/set-able with eponymous methods



62
63
64
# File 'ext/regexp_nodes/regexp_nodes.rb', line 62

def hostname
  @hostname
end

#parametersObject

Make these instance variables get/set-able with eponymous methods



62
63
64
# File 'ext/regexp_nodes/regexp_nodes.rb', line 62

def parameters
  @parameters
end

Instance Method Details

#match_classes(fullpath) ⇒ Object

private method - takes a path to look for files, iterates through all readable, regular files it finds, and matches this instance’s @hostname against each line; if any match, the class will be set for this node.



140
141
142
143
144
145
146
147
148
149
150
151
# File 'ext/regexp_nodes/regexp_nodes.rb', line 140

def match_classes(fullpath)
  Dir.foreach(fullpath) do |patternfile|
    filepath = "#{fullpath}/#{patternfile}"
    next unless File.file?(filepath) and
      File.readable?(filepath)
    $LOG.debug("Attempting to match [#{@hostname}] in [#{filepath}]")
    if matched_in_patternfile?(filepath,@hostname)
      @classes << patternfile.to_s
      $LOG.debug("Appended #{patternfile.to_s} to classes instance variable")
    end
  end
end

#match_parameters(fullpath) ⇒ Object

Parameters are handled slightly differently; we make another level of directories to get the parameter name, then use the names of the files contained in there for the values of those parameters.

ex: cat /var/lib/puppet/bin/parameters/environment/production ^prodweb would set parameters = “production” for prodweb001



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'ext/regexp_nodes/regexp_nodes.rb', line 160

def match_parameters(fullpath)
  Dir.foreach(fullpath) do |parametername|

    filepath = "#{fullpath}/#{parametername}"
    next if File.basename(filepath) =~ /^\./     # skip over dotfiles

    next unless File.directory?(filepath) and
      File.readable?(filepath)        # skip over non-directories

    $LOG.debug "Considering contents of #{filepath}"

    Dir.foreach("#{filepath}") do |patternfile|
      secondlevel = "#{filepath}/#{patternfile}"
      $LOG.debug "Found parameters patternfile at #{secondlevel}"
      next unless File.file?(secondlevel) and
        File.readable?(secondlevel)
      $LOG.debug("Attempting to match [#{@hostname}] in [#{secondlevel}]")
      if matched_in_patternfile?(secondlevel, @hostname)
        @parameters[ parametername.to_s ] = patternfile.to_s
        $LOG.debug("Set @parameters[#{parametername.to_s}] = #{patternfile.to_s}")
      end
    end
  end
end

#matched_in_patternfile?(filepath, matchthis) ⇒ Boolean

Private method that expects an absolute path to a file and a string to match - it returns true if the string was matched by any of the lines in the file

Returns:

  • (Boolean)


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
# File 'ext/regexp_nodes/regexp_nodes.rb', line 109

def matched_in_patternfile?(filepath, matchthis)

  patternlist = []

  begin
    open(filepath).each { |l|
      pattern = %r{#{l.chomp!}}
      patternlist <<  pattern
      $LOG.debug("appending [#{pattern}] to patternlist for [#{filepath}]")
    }
  rescue Exception
    $LOG.fatal("Problem reading #{filepath}: #{$ERROR_INFO}")
    exit(1)
  end

  $LOG.debug("list of patterns for #{filepath}: #{patternlist}")

  if matchthis =~ Regexp.union(patternlist)
    $LOG.debug("matched #{$~.to_s} in #{matchthis}, returning true")
    return true

  else    # hostname didn't match anything in patternlist
    $LOG.debug("#{matchthis} unmatched, returning false")
    return nil
  end

end

#parse_argv(hostname) ⇒ Object

private method called by initialize which sanity-checks our hostname. good candidate for overriding in a subclass if you need different checks



83
84
85
86
87
88
89
90
91
92
# File 'ext/regexp_nodes/regexp_nodes.rb', line 83

def parse_argv(hostname)
  if hostname =~ /^([-\w]+?)\.([-\w\.]+)/    # non-greedy up to the first . is hostname
    @hostname = $1
  elsif hostname =~ /^([-\w]+)$/       # sometimes puppet's @name is just a name
    @hostname = hostname
  else
    $LOG.fatal("didn't receive parsable hostname, got: [#{hostname}]")
    exit(1)
  end
end

#to_yamlObject

to_yaml massages a copy of the object and outputs clean yaml so we don’t feed weird things back to puppet []<



96
97
98
99
100
101
102
103
104
# File 'ext/regexp_nodes/regexp_nodes.rb', line 96

def to_yaml
  classes = self.classes.to_a
  if self.parameters.empty? # otherwise to_yaml prints "parameters: {}"
    parameters = nil
  else
    parameters = self.parameters
  end
  ({ 'classes' => classes, 'parameters' => parameters}).to_yaml
end