Class: Filter
Overview
The Filter class is used to hold the information about the filter conditions that should be applied during certain Machinery commands.
Filters are usually created by passing a filter definition string to the constructor, e.g.
filter = Filter.new("/unmanaged_files/files/name=/opt")
Existing filters can be extended by amending the definition:
filter.add_element_filter_from_definition("/unmanaged_files/files/name=/srv")
or by adding ElementFilters directly:
element_filter = ElementFilter.new("/unmanaged_files/files/name", ["/opt", "/srv"])
filter.add_element_filter(element_filter)
The actual filtering can be done by passing values to Filter#matches?
filter = Filter.new("/unmanaged_files/files/name=/opt*")
filter.matches?("/unmanaged_files/files/name", "/opt/foo")
=> true
filter.matches?("/unmanaged_files/files/name", "/srv/bar")
=> false
More details about how the filter work can be found at github.com/SUSE/machinery/blob/master/docs/Filtering-Design.md
Constant Summary collapse
- OPERATOR_EQUALS =
"="
- OPERATOR_EQUALS_NOT =
"!="
Instance Attribute Summary collapse
-
#element_filters ⇒ Object
Returns the value of attribute element_filters.
Class Method Summary collapse
Instance Method Summary collapse
- #add_element_filter_from_definition(filter_definition) ⇒ Object
- #add_element_filters(element_filters) ⇒ Object
- #apply!(system_description) ⇒ Object
- #element_filter_for(path) ⇒ Object
- #element_filters_for_scope(scope) ⇒ Object
- #empty? ⇒ Boolean
-
#initialize(definitions = []) ⇒ Filter
constructor
A new instance of Filter.
- #matches?(path, value) ⇒ Boolean
- #set_element_filters_for_scope(scope, element_filters) ⇒ Object
- #to_array ⇒ Object
Constructor Details
#initialize(definitions = []) ⇒ Filter
Returns a new instance of Filter.
88 89 90 |
# File 'lib/filter.rb', line 88 def initialize(definitions = []) @element_filters = Filter.parse_filter_definitions(definitions) end |
Instance Attribute Details
#element_filters ⇒ Object
Returns the value of attribute element_filters.
47 48 49 |
# File 'lib/filter.rb', line 47 def element_filters @element_filters end |
Class Method Details
.from_default_definition(command) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/filter.rb', line 72 def self.from_default_definition(command) filter = Filter.new default_filters_file = File.join(Machinery::ROOT, "filters", "default_filters.json") if File.exists?(default_filters_file) default_filters = JSON.parse(File.read(default_filters_file)) if default_filters[command] default_filters[command].each do |definition| filter.add_element_filter_from_definition(definition) end end end filter end |
.parse_filter_definitions(filter_definitions) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/filter.rb', line 52 def self.parse_filter_definitions(filter_definitions) element_filters = {} Array(filter_definitions).each do |definition| path, operator, matcher_definition = definition.scan(/([a-zA-Z_\/]+)(.*=)(.*)/)[0] raise Machinery::Errors::InvalidFilter.new("Invalid filter: '#{definition}'") if !operator element_filters[path] ||= ElementFilter.new(path) if matcher_definition.index(",") matchers = matcher_definition.split(/(?<!\\),/) matchers.map! { |matcher| matcher.gsub("\\,", ",") } # Unescape escaped commas element_filters[path].add_matchers(operator, [matchers]) else element_filters[path].add_matchers(operator, matcher_definition) end end element_filters end |
Instance Method Details
#add_element_filter_from_definition(filter_definition) ⇒ Object
92 93 94 |
# File 'lib/filter.rb', line 92 def add_element_filter_from_definition(filter_definition) add_element_filters(Filter.parse_filter_definitions(filter_definition).values) end |
#add_element_filters(element_filters) ⇒ Object
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/filter.rb', line 96 def add_element_filters(element_filters) Array(element_filters).each do |element_filter| path = element_filter.path @element_filters[path] ||= ElementFilter.new(path) element_filter.matchers.each do |operator, matchers| @element_filters[path].add_matchers(operator, matchers) end end end |
#apply!(system_description) ⇒ Object
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 |
# File 'lib/filter.rb', line 142 def apply!(system_description) element_filters.each do |path, element_filter| steps = path.split("/").reject(&:empty?) target = steps.pop pointer = system_description container = nil steps.each do |step| break if !pointer pointer = pointer[step] container ||= pointer if pointer.is_a?(Machinery::Array) end next if !pointer begin pointer.delete_if do |element| element_filter.matches?(element[target]) end rescue Machinery::Errors::ElementFilterTypeMismatch => e Machinery::Ui.warn("Warning: Filter '#{e.failed_matcher}' tries to match an array, " \ "but the according element is not an array.") end end end |
#element_filter_for(path) ⇒ Object
107 108 109 |
# File 'lib/filter.rb', line 107 def element_filter_for(path) element_filters[path] end |
#element_filters_for_scope(scope) ⇒ Object
111 112 113 114 115 |
# File 'lib/filter.rb', line 111 def element_filters_for_scope(scope) @element_filters.values.select do |element_filter| element_filter.filters_scope?(scope) end end |
#empty? ⇒ Boolean
168 169 170 |
# File 'lib/filter.rb', line 168 def empty? element_filters.empty? end |
#matches?(path, value) ⇒ Boolean
135 136 137 138 139 140 |
# File 'lib/filter.rb', line 135 def matches?(path, value) filter = element_filter_for(path) return false if !filter filter.matches?(value) end |
#set_element_filters_for_scope(scope, element_filters) ⇒ Object
117 118 119 120 121 122 123 |
# File 'lib/filter.rb', line 117 def set_element_filters_for_scope(scope, element_filters) @element_filters.reject! do |_path, element_filter| element_filter.filters_scope?(scope) end add_element_filters(element_filters) end |
#to_array ⇒ Object
125 126 127 128 129 130 131 132 133 |
# File 'lib/filter.rb', line 125 def to_array @element_filters.flat_map do |path, element_filter| element_filter.matchers.flat_map do |operator, matchers| matchers.map do |matcher| "#{path}#{operator}#{Array(matcher).join(",")}" end end end end |