Module: AugeasProviders::Provider::ClassMethods
- Defined in:
- lib/augeasproviders/provider.rb
Overview
Class methods automatically added to a Puppet provider by including the AugeasProviders::Provider mixin.
Instance Method Summary collapse
-
#attr_aug_accessor(name, opts = {}) ⇒ Object
Define getter and setter for a property.
-
#attr_aug_reader(name, opts = {}) ⇒ Object
Defines a property getter with a provided implementation.
-
#attr_aug_writer(name, opts = {}) ⇒ Object
Defines a property setter using #augopen.
-
#aug_handler ⇒ Augeas
private
Returns an Augeas handler.
-
#aug_version ⇒ String
Returns the Augeas version used.
-
#augclose!(aug) ⇒ Object
Close the shared Augeas handler.
-
#augopen(resource = nil, yield_resource = false, *yield_params) {|aug, resource, *yield_params| ... } ⇒ Augeas
Opens Augeas and returns a handle to use.
-
#augopen!(resource = nil, yield_resource = false, *yield_params) {|aug, resource, *yield_params| ... } ⇒ Augeas
Opens Augeas and returns a handle to use.
-
#augsave!(aug, reload = false) ⇒ Object
Saves all changes made in the current Augeas handle and checks for any errors while doing so.
-
#default_file { ... } ⇒ Object
Setter for the default file path managed by the provider.
-
#define_aug_method(method) {|aug, resource, *args| ... } ⇒ Object
Define a method with a block passed to #augopen.
-
#define_aug_method!(method) {|aug, resource, *args| ... } ⇒ Object
Define a method with a block passed to #augopen!.
-
#lens(resource = nil) {|resource| ... } ⇒ String
Getter and setter for the Augeas lens used for this provider.
-
#parsed_as?(text, path, lens) ⇒ Boolean
Returns whether text is parsed as path using lens.
-
#path_label(aug, path) ⇒ String
Wrapper around aug.label for older versions of Augeas and values not found in the tree.
-
#post_resource_eval ⇒ Object
Sets the post_resource_eval class hook for Puppet This is only used with Puppet > 3.4.0 and allows to clean the shared Augeas handler.
-
#quoteit(value, resource = nil, oldvalue = nil) ⇒ String
Automatically quote a value.
-
#readquote(value) ⇒ Symbol
Detect what type of quoting a value uses.
-
#resource_path(resource = nil) {|resource| ... } ⇒ String
Getter and setter for the Augeas path expression representing an individual resource inside a file, that’s managed by this provider.
-
#setvars(aug, resource = nil) ⇒ Object
Sets useful Augeas variables for the session.
-
#supported?(feature) ⇒ Boolean
Returns whether a feature is supported.
-
#target(resource = nil) ⇒ String
Gets the path expression representing the file being managed.
-
#unquoteit(value) ⇒ String
Automatically unquote a value.
Instance Method Details
#attr_aug_accessor(name, opts = {}) ⇒ Object
Define getter and setter for a property
394 395 396 397 |
# File 'lib/augeasproviders/provider.rb', line 394 def attr_aug_accessor(name, opts = {}) attr_aug_reader(name, opts) attr_aug_writer(name, opts) end |
#attr_aug_reader(name, opts = {}) ⇒ Object
Defines a property getter with a provided implementation. It works from a node identified with the given ‘label` beneath the resource.
Supports three implementations based on the type specified:
:string causes the getter to return the value of the node below resource with the label given in opts
:array causes the getter to return an array of values matching the label. If sublabel is given, values of matching nodes beneath the label node will be returned in an array. If sublabel is :seq, values of nodes matching a numbered seq will be returned.
:hash causes the getter to return a hash of the value of each matching label node against the value of each sublabel node.
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/augeasproviders/provider.rb', line 228 def attr_aug_reader(name, opts = {}) label = opts[:label] || name.to_s default = opts[:default] || nil type = opts[:type] || :string sublabel = opts[:sublabel] || nil rpath = label == :resource ? '$resource' : "$resource/#{label}" if type == :hash and sublabel.nil? fail "You must provide a sublabel for type hash" end unless [:string, :array, :hash].include? type fail "Invalid type: #{type}" end # Class getter method using an existing aug handler # Emulate define_singleton_method for Ruby 1.8 = class << self; self; end .send(:define_method, "attr_aug_reader_#{name}") do |aug, *args| case type when :string aug.get(rpath) when :array aug.match(rpath).map do |p| if sublabel.nil? aug.get(p) else if sublabel == :seq sp = "#{p}/*[label()=~regexp('[0-9]+')]" else sp = "#{p}/#{sublabel}" end aug.match(sp).map { |sp| aug.get(sp) } end end.flatten when :hash values = {} aug.match(rpath).each do |p| sp = "#{p}/#{sublabel}" values[aug.get(p)] = aug.get(sp) || default end values end end # Instance getter method for the instance define_method("attr_aug_reader_#{name}") do |aug, *args| self.class.send("attr_aug_reader_#{name}", aug, *args) end # We are calling the resource's augopen here, not the class define_method(name) do |*args| augopen do |aug| self.send("attr_aug_reader_#{name}", aug, *args) end end end |
#attr_aug_writer(name, opts = {}) ⇒ Object
Defines a property setter using #augopen
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/augeasproviders/provider.rb', line 298 def attr_aug_writer(name, opts = {}) label = opts[:label] || name.to_s default = opts[:default] || nil type = opts[:type] || :string sublabel = opts[:sublabel] || nil purge_ident = opts[:purge_ident] || false rm_node = opts[:rm_node] || false rpath = label == :resource ? '$resource' : "$resource/#{label}" if type == :hash and sublabel.nil? fail "You must provide a sublabel for type hash" end unless [:string, :array, :hash].include? type fail "Invalid type: #{type}" end # Class setter method using an existing aug handler # Emulate define_singleton_method for Ruby 1.8 = class << self; self; end .send(:define_method, "attr_aug_writer_#{name}") do |aug, *args| aug.rm("#{rpath}[position() != 1]") if purge_ident case type when :string if args[0] aug.set(rpath, args[0]) elsif rm_node aug.rm(rpath) else aug.clear(rpath) end when :array if args[0].nil? aug.rm(rpath) else if sublabel.nil? aug.rm(rpath) count = 0 args[0].each do |v| count += 1 aug.set("#{rpath}[#{count}]", v) end elsif sublabel == :seq # Make sure only our values are used aug.rm("#{rpath}/*[label()=~regexp('[0-9]+')]") count = 0 args[0].each do |v| count += 1 aug.set("#{rpath}/#{count}", v) end else # Make sure only our values are used aug.rm("#{rpath}/#{sublabel}") count = 0 args[0].each do |v| count += 1 aug.set("#{rpath}/#{sublabel}[#{count}]", v) end end end when :hash # First get rid of all entries aug.rm(rpath) args[0].each do |k, v| aug.set("#{rpath}[.='#{k}']", k) unless v == default aug.set("#{rpath}[.='#{k}']/#{sublabel}", v) end end end end # Instance setter method for the instance define_method("attr_aug_writer_#{name}") do |aug, *args| self.class.send("attr_aug_writer_#{name}", aug, *args) end # We are calling the resource's augopen here, not the class define_method("#{name}=") do |*args| augopen! do |aug| self.send("attr_aug_writer_#{name}", aug, *args) end end end |
#aug_handler ⇒ Augeas
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns an Augeas handler.
On Puppet >= 3.4, stores and returns a shared Augeas handler for all instances of the class
76 77 78 79 80 81 82 |
# File 'lib/augeasproviders/provider.rb', line 76 def aug_handler if supported?(:post_resource_eval) @aug ||= Augeas.open(nil, loadpath, Augeas::NO_MODL_AUTOLOAD) else Augeas.open(nil, loadpath, Augeas::NO_MODL_AUTOLOAD) end end |
#aug_version ⇒ String
Returns the Augeas version used
44 45 46 |
# File 'lib/augeasproviders/provider.rb', line 44 def aug_version @aug_version ||= Augeas.open(nil, nil, Augeas::NO_MODL_AUTOLOAD) { |aug| aug.get('/augeas/version') } end |
#augclose!(aug) ⇒ Object
Close the shared Augeas handler.
88 89 90 |
# File 'lib/augeasproviders/provider.rb', line 88 def augclose!(aug) aug.close end |
#augopen(resource = nil, yield_resource = false, *yield_params) {|aug, resource, *yield_params| ... } ⇒ Augeas
Opens Augeas and returns a handle to use. It loads only the file identified by #target (and the supplied ‘resource`) using #lens.
If called with a block, this will be yielded to and the Augeas handle closed after the block has executed (on Puppet < 3.4.0). Otherwise, the handle will be returned and not closed automatically. On Puppet >= 3.4, the handle will be closed by ‘post_resource_eval`. On older versions, the caller is responsible for closing it to free resources.
If ‘yield_resource` is set to true, the supplied `resource` will be passed as a yieldparam to the block, after the `aug` handle. Any arguments passed after `yield_resource` will be added as yieldparams to the block.
116 117 118 |
# File 'lib/augeasproviders/provider.rb', line 116 def augopen(resource = nil, yield_resource = false, *yield_params, &block) augopen_internal(resource, false, yield_resource, *yield_params, &block) end |
#augopen!(resource = nil, yield_resource = false, *yield_params) {|aug, resource, *yield_params| ... } ⇒ Augeas
Opens Augeas and returns a handle to use. It loads only the file for the current Puppet resource using #lens. #augsave! is called after the block is evaluated.
If called with a block, this will be yielded to and the Augeas handle closed after the block has executed (on Puppet < 3.4.0). Otherwise, the handle will be returned and not closed automatically. On Puppet >= 3.4, the handle will be closed by ‘post_resource_eval`. On older versions, the caller is responsible for closing it to free resources.
If ‘yield_resource` is set to true, the supplied `resource` will be passed as a yieldparam to the block, after the `aug` handle. Any arguments passed after `yield_resource` will be added as yieldparams to the block.
145 146 147 |
# File 'lib/augeasproviders/provider.rb', line 145 def augopen!(resource = nil, yield_resource = false, *yield_params, &block) augopen_internal(resource, true, yield_resource, *yield_params, &block) end |
#augsave!(aug, reload = false) ⇒ Object
Saves all changes made in the current Augeas handle and checks for any errors while doing so. Reloads the tree afterwards to remove specific changes for next resource.
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/augeasproviders/provider.rb', line 157 def augsave!(aug, reload = false) begin aug.save! rescue Augeas::Error errors = [] aug.match("/augeas//error").each do |errnode| aug.match("#{errnode}/*").each do |subnode| subvalue = aug.get(subnode) errors << "#{subnode} = #{subvalue}" end end debug("Save failure details:\n" + errors.join("\n")) raise Augeas::Error, 'Failed to save Augeas tree to file. See debug logs for details.' ensure aug.load! if reload end end |
#default_file { ... } ⇒ Object
Setter for the default file path managed by the provider.
Takes a block to store, but doesn’t yield. Will be called when it’s needed.
407 408 409 |
# File 'lib/augeasproviders/provider.rb', line 407 def default_file(&block) @default_file_block = block end |
#define_aug_method(method) {|aug, resource, *args| ... } ⇒ Object
Define a method with a block passed to #augopen
183 184 185 186 187 188 |
# File 'lib/augeasproviders/provider.rb', line 183 def define_aug_method(method, &block) define_method(method) do |*args| # We are calling the resource's augopen here, not the class augopen(true, *args, &block) end end |
#define_aug_method!(method) {|aug, resource, *args| ... } ⇒ Object
Define a method with a block passed to #augopen!
198 199 200 201 202 203 |
# File 'lib/augeasproviders/provider.rb', line 198 def define_aug_method!(method, &block) define_method(method) do |*args| # We are calling the resource's augopen! here, not the class augopen!(true, *args, &block) end end |
#lens(resource = nil) {|resource| ... } ⇒ String
Getter and setter for the Augeas lens used for this provider.
When called with a block, will only store the block - it doesn’t yield.
When called without a block, expects ‘resource` parameter which is passed into the block, which returns the lens to be used.
425 426 427 428 429 430 431 432 |
# File 'lib/augeasproviders/provider.rb', line 425 def lens(resource = nil, &block) if block_given? @lens_block = block else fail 'Lens is not provided' unless @lens_block @lens_block.call(resource) end end |
#parsed_as?(text, path, lens) ⇒ Boolean
Returns whether text is parsed as path using lens
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
# File 'lib/augeasproviders/provider.rb', line 595 def parsed_as?(text, path, lens) Augeas.open(nil, nil, Augeas::NO_MODL_AUTOLOAD) do |aug| if aug.respond_to? :text_store aug.set('/input', text) if aug.text_store(lens, '/input', '/parsed') return aug.match("/parsed/#{path}").any? end else # ruby-augeas < 0.5 doesn't support text_store Tempfile.open('aug_text_store') do |tmpfile| tmpfile.write(text) tmpfile.flush aug.transform( :lens => lens, :name => 'Text_store', :incl => tmpfile.path.to_s, :excl => [] ) aug.load! return aug.match("/files#{tmpfile.path.to_s}/#{path}").any? end end end return false end |
#path_label(aug, path) ⇒ String
Wrapper around aug.label for older versions of Augeas and values not found in the tree.
441 442 443 444 445 446 447 448 |
# File 'lib/augeasproviders/provider.rb', line 441 def path_label(aug, path) if aug.respond_to? :label label = aug.label(path) end # Fallback label || path.split("/")[-1].split("[")[0] end |
#post_resource_eval ⇒ Object
Sets the post_resource_eval class hook for Puppet This is only used with Puppet > 3.4.0
and allows to clean the shared Augeas handler.
624 625 626 627 |
# File 'lib/augeasproviders/provider.rb', line 624 def post_resource_eval augclose!(aug_handler) @aug = nil end |
#quoteit(value, resource = nil, oldvalue = nil) ⇒ String
Automatically quote a value
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/augeasproviders/provider.rb', line 456 def quoteit(value, resource = nil, oldvalue = nil) oldquote = readquote oldvalue if resource and resource.parameters.include? :quoted quote = resource[:quoted] else quote = :auto end if quote == :auto quote = if oldquote oldquote elsif value =~ /[|&;()<>\s]/ :double else :none end end case quote when :double "\"#{value}\"" when :single "'#{value}'" else value end end |
#readquote(value) ⇒ Symbol
Detect what type of quoting a value uses
490 491 492 493 494 495 496 497 498 499 |
# File 'lib/augeasproviders/provider.rb', line 490 def readquote(value) if value =~ /^(["'])(.*)(?:\1)$/ case $1 when '"' then :double when "'" then :single else nil end else nil end end |
#resource_path(resource = nil) {|resource| ... } ⇒ String
Getter and setter for the Augeas path expression representing an individual resource inside a file, that’s managed by this provider.
When called with a block, will only store the block - it doesn’t yield. The block is later used to generate the path expression.
When called without a block, expects ‘resource` parameter which is passed into the block, which returns the path expression representing the supplied resource.
If no block has already been set, it returns the path expression representing the top-level of the file.
523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/augeasproviders/provider.rb', line 523 def resource_path(resource = nil, &block) if block_given? @resource_path_block = block else if @resource_path_block path = "/files#{target(resource)}" @resource_path_block.call(resource) else "#{target(resource)}/#{resource[:name]}" end end end |
#setvars(aug, resource = nil) ⇒ Object
Sets useful Augeas variables for the session.
-
‘$target` points to the root of the target file
-
‘$resource` points to path defined by #resource_path
It also sets ‘/augeas/context` to the target file so relative paths can be used, before the variables are set.
If supplied with a resource, it will be used to determine the path to the used file.
551 552 553 554 555 |
# File 'lib/augeasproviders/provider.rb', line 551 def setvars(aug, resource = nil) aug.set('/augeas/context', "/files#{target(resource)}") aug.defnode('target', "/files#{target(resource)}", nil) aug.defvar('resource', resource_path(resource)) if resource end |
#supported?(feature) ⇒ Boolean
Returns whether a feature is supported.
The following features are currently supported:
-
‘:regexpi`: whether Augeas supports an ’i’ flag in regexp expressions
-
‘:post_resource_eval`: whether Puppet supports `post_resource_eval` hooks
58 59 60 61 62 63 64 65 66 67 |
# File 'lib/augeasproviders/provider.rb', line 58 def supported?(feature) case feature when :regexpi Puppet::Util::Package.versioncmp(aug_version, '1.0.0') >= 0 when :post_resource_eval Puppet::Util::Package.versioncmp(Puppet.version, '3.4.0') >= 0 else raise Puppet::Error, "Unknown feature '#{feature}'" end end |
#target(resource = nil) ⇒ String
Gets the path expression representing the file being managed.
If supplied with a resource, this will represent the file identified by the resource, else the default file that the provider manages.
568 569 570 571 572 573 |
# File 'lib/augeasproviders/provider.rb', line 568 def target(resource = nil) file = @default_file_block.call if @default_file_block file = resource[:target] if resource and resource[:target] fail 'No target file given' if file.nil? file.chomp('/') end |
#unquoteit(value) ⇒ String
Automatically unquote a value
580 581 582 583 584 585 586 |
# File 'lib/augeasproviders/provider.rb', line 580 def unquoteit(value) if value =~ /^(["'])(.*)(?:\1)$/ $2 else value end end |