Module: PuppetX::FileMagic

Defined in:
lib/puppet_x/filemagic.rb

Class Method Summary collapse

Class Method Details

.append(filename, regex_start, data) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/puppet_x/filemagic.rb', line 190

def self.append(filename, regex_start, data)
  # write the new content in one go
  content = File.readlines(filename).each {|l| l.chomp!}
  found_at = get_match(content, regex_start, true)

  if found_at > -1
    # Discard from the end of the file all lines including and after content[found_at]
    content = content[0..found_at-1]
  end

  # perform the append
  content += data2lines(data)

  File.open(filename, "w") do |f|
    f.puts(content)
  end
end

.data2lines(data) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/puppet_x/filemagic.rb', line 4

def self.data2lines(data)
  if data.class == String
    data = data.split("\n")
  end

  data
end

.exists?(filename, data, regex, position, check_type) ⇒ Boolean

sandwich position not implemented yet -1 TOP OF file 0 SANDWICH +1 END OF FILE

Parameters:

  • filename

    File to inspect

  • data

    Lines of data to look for. If n character found, newlines will be inserted or you can just pass an array

  • regex

    Regular expression to match or false to skip

  • position

    Where to look for a match - -1 top of file, 0 sandwich, +1 bottom of file

  • check_type

    what kind of check are we doing? :present, :absent

Returns:

  • (Boolean)


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
# File 'lib/puppet_x/filemagic.rb', line 65

def self.exists?(filename, data, regex, position, check_type)
  exists = true
  data_lines = data2lines(data)

  # IO readlines keeps the newlines and IO writelines strips them - can't
  # eat its own dogfood so we need to write our own here...
  if ! File.exist?(filename)
    Puppet.err("File missing at #{filename} (file must already exist to do filemagic on it...)")
    exists = if check_type == :absent
               false
             else
               true
             end
  else
    file_lines = File.readlines(filename).each {|l| l.chomp!}

    if check_type == :absent
      found = false
      if regex and get_match(file_lines, regex, true) > -1
        found = true
      end
      
      
      file_lines.each {|l|
        if data_lines
          data_lines.each { |d|
            if l==d
              found = true
            end
          }
        end
      }

      exists = found

    elsif check_type == :replace
      needs_replace = false
      data_lines.each { |line|
        if line =~ /#{regex}/ or line == data
          needs_replace = true
        end

        exists = exists and needs_replace
      }

    else

      # Test 1:  Exact match
      # reverse match order if we are checking the end of the file
      if position > 0
        data_lines = data_lines.reverse
        file_lines = file_lines.reverse
      end

      # check-off that each line in our data is already in the file
      i = 0
      while exists and data_lines and i < data_lines.size
        data_line = data_lines[i]
        file_line = file_lines[i]

        if file_line != data_line
          exists = false
        end
        i += 1
      end

      # Test 2 (optional): We may still exist based on the presence/absence of
      # a regex in the file.  At this point our exists? status depends on whether
      # we are being ensured :present or :absent -- if we are supposed to be
      # :present, then a regex match without an exact match means we need to
      # update the file to update it, whereas :absent means that we should clean
      # out the old value to make the file identical to if we had added new data
      # and then removed it.

      # Test 3: if the regex matches any lines in the file then we need to run
      # so that we can nuke them all and rewrite
    end
  end


  exists
end

.get_match(lines, regex, first) ⇒ Object

return the index of the first/last match of regex in lines or -1 if no match. Be careful with if statements using this! It's very possible that 0 will be returned to indicate a match in the first element of the array which is of course false

Parameters:

  • lines

    data to search

  • regex

    regex to match

  • first

    match the first instance? otherwise match the last



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
# File 'lib/puppet_x/filemagic.rb', line 19

def self.get_match(lines, regex, first)
  found_at = -1
  if regex
    i = 0

    if ! first
      lines = lines.reverse
    end

    while found_at == -1 and i < lines.size
      # puppet passes regex's as strings to ruby even regex is a primative
      # now.  Hands up who's suprised by that
      real_regex = Regexp.new regex
      if lines[i] =~ real_regex
        found_at = i
      end
      i += 1
    end

    if !first and found_at > -1
      # need to correct the index since we reversed the array we searched
      #
      #      V = 5
      # XXXXXXX size == 7
      #
      # want
      #
      #  V=1
      # XXXXXXX
      found_at = lines.size - found_at - 1
    end
  end
  found_at
end

.prepend(filename, regex_end, data) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/puppet_x/filemagic.rb', line 148

def self.prepend(filename, regex_end, data)
  # read the old content into an array and prepend the required lines
  content = File.readlines(filename).each {|l| l.chomp!}
  found_at = get_match(content, regex_end, false)
  if found_at > -1
    # Discard from the beginning of the file all lines before and including content[found_at]
    content = content[found_at+1..content.size-1]
  end

  # insert the lines at the start of the file
  content.unshift(data2lines(data))

  # write the new content in one go
  File.open(filename, "w") do |f|
    f.puts(content)
  end
end

.remove_match(filename, regex) ⇒ Object



228
229
230
231
232
233
234
235
236
# File 'lib/puppet_x/filemagic.rb', line 228

def self.remove_match(filename, regex)
  content = File.readlines(filename).reject { |line|
    line =~ /#{regex}/
  }
  File.open(filename, "w") do |f|
    f.puts(content)
  end

end

.replace_match(filename, regex, data) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/puppet_x/filemagic.rb', line 238

def self.replace_match(filename, regex, data)
  content = []
  matched = false
  File.readlines(filename).each { |line|
    if line =~ /#{regex}/
      if ! matched
        content << line.gsub(regex, data)
        matched = true
      end
    else
      content << line
    end
  }
  File.open(filename, "w") do |f|
    f.puts(content)
  end

end

.unappend(filename, regex_start, data) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/puppet_x/filemagic.rb', line 208

def self.unappend(filename, regex_start, data)
  content = File.readlines(filename).each {|l| l.chomp!}
  found_at = get_match(content, regex_start, true)
  if found_at > -1
    # Discard from the end of the file all lines including and after content[found_at]
    content = content[0..found_at-1]
  else
    data2lines(data).reverse.each { |line|
      if content[-1] == line
        content.pop
      end
    }
  end
  # write the new content in one go
  File.open(filename, "w") do |f|
    f.puts(content)
  end
end

.unprepend(filename, regex_end, data) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/puppet_x/filemagic.rb', line 166

def self.unprepend(filename, regex_end, data)
  # read the old content into an array and remove the required lines
  content = File.readlines(filename).each {|l| l.chomp!}
  found_at = get_match(content, regex_end, false)
  if found_at > -1
    # Discard from the beginning of the file all lines before and including content[found_at]
    content = content[found_at+1..content.size-1]
  else
    # remove as many lines as we are told to
    data2lines(data).each { |line|
      # we double check that the lines read are still valid since we
      # checked with exists? to prevent possible race conditions (although
      # we could still encounter them since there's no locking)
      if content[0] == line
        content.shift
      end
    }
  end
  # write the new content in one go
  File.open(filename, "w") do |f|
    f.puts(content)
  end
end