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
170
171
172
173
174
175
|
require 'puppet'
class Puppet::Provider::ParsedFile < Puppet::Provider
class << self
attr_accessor :filetype, :fields
attr_reader :path
attr_writer :fileobj
end
# Override 'newstate' so that all states default to having the
# correct parent type
def self.newstate(name, options = {}, &block)
options[:parent] ||= Puppet::State::ParsedParam
super(name, options, &block)
end
# Add another type var.
def self.initvars
@instances = []
super
end
# Add a non-object comment or whatever to our list of instances
def self.comment(line)
@instances << line
end
# Override the default Puppet::Type method, because instances
# also need to be deleted from the @instances hash
def self.delete(child)
if @instances.include?(child)
@instances.delete(child)
end
super
end
# Initialize the object if necessary.
def self.fileobj
@fileobj ||= @filetype.new(@path)
@fileobj
end
# Return the header placed at the top of each generated file, warning
# users that modifying this file manually is probably a bad idea.
def self.header
%{# HEADER: This file was autogenerated at #{Time.now}
# HEADER: by puppet. While it can still be managed manually, it
# HEADER: is definitely not recommended.\n}
end
# Parse a file
#
# Subclasses must override this method.
def self.parse(text)
raise Puppet::DevError, "Parse was not overridden in %s" %
self.name
end
# If they change the path, we need to get rid of our cache object
def self.path=(path)
@fileobj = nil
@path = path
end
# Retrieve the text for the file. Returns nil in the unlikely
# event that it doesn't exist.
def self.retrieve
text = fileobj.read
if text.nil? or text == ""
# there is no file
return []
else
self.parse(text)
end
end
# Write out the file.
def self.store(instances)
if instances.empty?
Puppet.notice "No %s instances for %s" % [self.name, @path]
else
fileobj.write(self.to_file(instances))
end
end
# Collect all Host instances convert them into literal text.
def self.to_file(instances)
str = self.header()
unless instances.empty?
# Reject empty hashes and those with :ensure == :absent
str += instances.reject { |obj|
obj.is_a? Hash and (obj.empty? or obj[:ensure] == :absent)
}.collect { |obj|
# If it's a hash, convert it, otherwise just write it out
if obj.is_a?(Hash)
to_record(obj)
else
obj.to_s
end
}.join("\n") + "\n"
return str
else
Puppet.notice "No %s instances" % self.name
return ""
end
end
# A Simple wrapper method that subclasses can override, so there's more control
# over how instances are retrieved.
def allinstances
self.class.retrieve
end
def clear
super
@instances = nil
end
# Return a hash that maps to our info, if possible.
def hash
@instances = allinstances()
namevar = @model.class.namevar
if @instances and h = @instances.find do |o|
o.is_a? Hash and o[namevar] == @model[namevar]
end
@me = h
else
@me = {}
if @instances.empty?
@instances = [@me]
else
@instances << @me
end
end
return @me
end
def initialize(model)
super
@instances = nil
end
def store(hash = nil)
hash ||= self.model.to_hash
unless @instances
self.hash
end
if hash.empty?
@me.clear
else
hash.each do |name, value|
if @me[name] != hash[name]
@me[name] = hash[name]
end
end
@me.each do |name, value|
unless hash.has_key? name
@me.delete(name)
end
end
end
self.class.store(@instances)
end
end
# $Id$
|