File: collector_transformer.rb

package info (click to toggle)
puppet-agent 7.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 19,092 kB
  • sloc: ruby: 245,074; sh: 456; makefile: 38; xml: 33
file content (234 lines) | stat: -rw-r--r-- 6,038 bytes parent folder | download | duplicates (3)
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
module Puppet::Pops
module Evaluator
class CollectorTransformer

  def initialize
    @@query_visitor    ||= Visitor.new(nil, "query", 1, 1)
    @@match_visitor    ||= Visitor.new(nil, "match", 1, 1)
    @@evaluator        ||= EvaluatorImpl.new
    @@compare_operator ||= CompareOperator.new()
  end

  def transform(o, scope)
    #TRANSLATORS 'CollectExpression' is a class name and should not be translated
    raise ArgumentError, _("Expected CollectExpression") unless o.is_a? Model::CollectExpression

    raise "LHS is not a type" unless o.type_expr.is_a? Model::QualifiedReference
    type = o.type_expr.value().downcase()

    if type == 'class'
      fail "Classes cannot be collected"
    end

    resource_type = Runtime3ResourceSupport.find_resource_type(scope, type)

    fail "Resource type #{type} doesn't exist" unless resource_type

    if !o.operations.empty?
      overrides = {
        :parameters => o.operations.map{ |x| @@evaluator.evaluate(x, scope)}.flatten,
        :file       => o.file,
        :line       => o.line,
        :source     => scope.source,
        :scope      => scope
      }
    end

    code = query_unless_nop(o.query, scope)

    case o.query
    when Model::VirtualQuery
      newcoll = Collectors::CatalogCollector.new(scope, resource_type, code, overrides)
    when Model::ExportedQuery
      match = match_unless_nop(o.query, scope)
      newcoll = Collectors::ExportedCollector.new(scope, resource_type, match, code, overrides)
    end

    scope.compiler.add_collection(newcoll)

    newcoll
  end

protected

  def query(o, scope)
    @@query_visitor.visit_this_1(self, o, scope)
  end

  def match(o, scope)
    @@match_visitor.visit_this_1(self, o, scope)
  end

  def query_unless_nop(query, scope)
    unless query.expr.nil? || query.expr.is_a?(Model::Nop)
      query(query.expr, scope)
    end
  end

  def match_unless_nop(query, scope)
    unless query.expr.nil? || query.expr.is_a?(Model::Nop)
      match(query.expr, scope)
    end
  end

  def query_AndExpression(o, scope)
    left_code = query(o.left_expr, scope)
    right_code = query(o.right_expr, scope)
    proc do |resource|
      left_code.call(resource) && right_code.call(resource)
    end
  end

  def query_OrExpression(o, scope)
    left_code = query(o.left_expr, scope)
    right_code = query(o.right_expr, scope)
    proc do |resource|
      left_code.call(resource) || right_code.call(resource)
    end
  end

  def query_ComparisonExpression(o, scope)
    left_code = query(o.left_expr, scope)
    right_code = query(o.right_expr, scope)

    case o.operator
    when '=='
      if left_code == "tag"
        # Ensure that to_s and downcase is done once, i.e. outside the proc block and
        # then use raw_tagged? instead of tagged?
        if right_code.is_a?(Array)
          tags = right_code
        else
          tags = [ right_code ]
        end
        tags = tags.collect do |t|
          raise ArgumentError, _('Cannot transform a number to a tag') if t.is_a?(Numeric)
          t.to_s.downcase
        end
        proc do |resource|
          resource.raw_tagged?(tags)
        end
      else
        proc do |resource|
          if (tmp = resource[left_code]).is_a?(Array)
            @@compare_operator.include?(tmp, right_code, scope)
          else
            @@compare_operator.equals(tmp, right_code)
          end
        end
      end
    when '!='
      proc do |resource|
        !@@compare_operator.equals(resource[left_code], right_code)
      end
    end
  end

  def query_AccessExpression(o, scope)
    pops_object = @@evaluator.evaluate(o, scope)

    # Convert to Puppet 3 style objects since that is how they are represented
    # in the catalog.
    @@evaluator.convert(pops_object, scope, nil)
  end

  def query_VariableExpression(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def query_LiteralBoolean(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def query_LiteralString(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def query_ConcatenatedString(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def query_LiteralNumber(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def query_LiteralUndef(o, scope)
    nil
  end

  def query_QualifiedName(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def query_ParenthesizedExpression(o, scope)
   query(o.expr, scope)
  end

  def query_Object(o, scope)
    raise ArgumentError, _("Cannot transform object of class %{klass}") % { klass: o.class }
  end

  def match_AccessExpression(o, scope)
    pops_object = @@evaluator.evaluate(o, scope)

    # Convert to Puppet 3 style objects since that is how they are represented
    # in the catalog.
    @@evaluator.convert(pops_object, scope, nil)
  end

  def match_AndExpression(o, scope)
    left_match = match(o.left_expr, scope)
    right_match = match(o.right_expr, scope)
    return [left_match, 'and', right_match]
  end

  def match_OrExpression(o, scope)
    left_match = match(o.left_expr, scope)
    right_match = match(o.right_expr, scope)
    return [left_match, 'or', right_match]
  end

  def match_ComparisonExpression(o, scope)
    left_match = match(o.left_expr, scope)
    right_match = match(o.right_expr, scope)
    return [left_match, o.operator.to_s, right_match]
  end

  def match_VariableExpression(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def match_LiteralBoolean(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def match_LiteralString(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def match_LiteralUndef(o, scope)
    nil
  end

  def match_ConcatenatedString(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def match_LiteralNumber(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def match_QualifiedName(o, scope)
    @@evaluator.evaluate(o, scope)
  end

  def match_ParenthesizedExpression(o, scope)
   match(o.expr, scope)
  end

  def match_Object(o, scope)
    raise ArgumentError, _("Cannot transform object of class %{klass}") % { klass: o.class }
  end
end
end
end