# frozen_string_literal: true
require 'puppet/util/tag_set'
module Puppet::Util::Tagging
ValidTagRegex = /\A[[:alnum:]_][[:alnum:]_:.-]*\Z/u
# Add a tag to the current tag set.
# When a tag set is used for a scope, these tags will be added to all of
# the objects contained in this scope when the objects are finished.
#
def tag(*ary)
@tags ||= new_tags
ary.flatten.compact.each do |tag|
name = tag.to_s.downcase
# Add the tag before testing if it's valid since this means that
# we never need to test the same valid tag twice. This speeds things
# up since we get a lot of duplicates and rarely fail on bad tags
if @tags.add?(name)
# not seen before, so now we test if it is valid
if valid_tag?(name)
if split_qualified_tags?
# avoid adding twice by first testing if the string contains '::'
@tags.merge(name.split('::')) if name.include?('::')
end
else
@tags.delete(name)
fail(Puppet::ParseError, _("Invalid tag '%{name}'") % { name: name })
end
end
end
end
# Add a name to the current tag set. Silently ignore names that does not
# represent valid tags.
#
# Use this method instead of doing this:
#
# tag(name) if is_valid?(name)
#
# since that results in testing the same string twice
#
def tag_if_valid(name)
if name.is_a?(String) && valid_tag?(name)
name = name.downcase
@tags ||= new_tags
if @tags.add?(name) && name.include?('::')
@tags.merge(name.split('::'))
end
end
end
# Answers if this resource is tagged with at least one of the given tags.
#
# The given tags are converted to downcased strings before the match is performed.
#
# @param *tags [String] splat of tags to look for
# @return [Boolean] true if this instance is tagged with at least one of the provided tags
#
def tagged?(*tags)
raw_tagged?(tags.collect {|t| t.to_s.downcase})
end
# Answers if this resource is tagged with at least one of the tags given in downcased string form.
#
# The method is a faster variant of the tagged? method that does no conversion of its
# arguments.
#
# @param tag_array [Array[String]] array of tags to look for
# @return [Boolean] true if this instance is tagged with at least one of the provided tags
#
def raw_tagged?(tag_array)
my_tags = self.tags
!tag_array.index { |t| my_tags.include?(t) }.nil?
end
# Only use this method when copying known tags from one Tagging instance to another
def set_tags(tag_source)
@tags = tag_source.tags
end
# Return a copy of the tag list, so someone can't ask for our tags
# and then modify them.
def tags
@tags ||= new_tags
@tags.dup
end
# Merge tags from a tagged instance with no attempts to split, downcase
# or verify the tags
def merge_tags_from(tag_source)
@tags ||= new_tags
tag_source.merge_into(@tags)
end
# Merge the tags of this instance into the provide TagSet
def merge_into(tag_set)
tag_set.merge(@tags) unless @tags.nil?
end
def tags=(tags)
@tags = new_tags
return if tags.nil?
tags = tags.strip.split(/\s*,\s*/) if tags.is_a?(String)
tag(*tags)
end
def valid_tag?(maybe_tag)
begin
tag_enc = maybe_tag.encoding
if tag_enc == Encoding::UTF_8 || tag_enc == Encoding::ASCII
maybe_tag =~ ValidTagRegex
else
maybe_tag.encode(Encoding::UTF_8) =~ ValidTagRegex
end
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
false
end
end
private
def split_qualified_tags?
true
end
def new_tags
Puppet::Util::TagSet.new
end
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez