puppetdb_query 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91b27838db87cfeca399ae3ca4bcc003e6ccd529
4
- data.tar.gz: bbbf8a6880fdf6c4e74b5354767dcb6a7e2c127c
3
+ metadata.gz: dd4a70cd22ca95133379508256d33bc63c0d922d
4
+ data.tar.gz: 4c2d190ac3fac79c08bc99786123665d8aacdc75
5
5
  SHA512:
6
- metadata.gz: b46aa5c022e19434fb95c920f3746a87b25b0ac3cd01eed3e7499a69ecd8135de08bbe71783cc55ec428d6389d1904ffed5f0a89a02eb538ae06a0779b9e4aab
7
- data.tar.gz: 4e80609d15bc887be8aaf146793acb989a3243eadca4ed6e8786eadf55cc25ecf62a5e4f9e9b4c19170c17c2fe2a792ff844f7ad2c0eeea7ddb983c14f03ba6c
6
+ metadata.gz: 5d688015cbd72fc52980ecfc2415a3312a7d83a610cec35c4e41a851e5fddf30093ee8525a987ec1cf085073a5e686863a8cc1eddaf08cb70601ec73ca6ee96d
7
+ data.tar.gz: bff404d3da3089951c784e6508be8150e667f9b061d53a373ae7d50833aaa04ffbbf56a5bc6bfda5268bbc6646c2a7288bc9daea97097700af6a71542c3ca76a
@@ -5,6 +5,7 @@ require_relative "logging"
5
5
 
6
6
  module PuppetDBQuery
7
7
  # parse a puppetdb query string into #PuppetDBQuery::Term s
8
+ # rubocop:disable Metrics/ClassLength
8
9
  class Parser
9
10
  include Logging
10
11
 
@@ -14,12 +15,13 @@ module PuppetDBQuery
14
15
 
15
16
  # these are the operators we understand
16
17
  # rubocop:disable Style/ExtraSpacing
17
- AND = Operator.new(:and, true, 100, 2)
18
- OR = Operator.new(:or, true, 90, 2)
19
- NOT = Operator.new(:not, false, 150, 1, 1)
20
- EQUAL = Operator.new(:equal, true, 200, 2, 2)
21
- NOT_EQUAL = Operator.new(:not_equal, true, 200, 2, 2)
22
- MATCH = Operator.new(:match, true, 200, 2, 2)
18
+ AND = Operator.new(:_and, true, 100, 2)
19
+ OR = Operator.new(:_or, true, 90, 2)
20
+ NOT = Operator.new(:_not, false, 150, 1, 1)
21
+ EQUAL = Operator.new(:_equal, true, 200, 2, 2)
22
+ NOT_EQUAL = Operator.new(:_not_equal, true, 200, 2, 2)
23
+ MATCH = Operator.new(:_match, true, 200, 2, 2)
24
+ IN = Operator.new(:_in, true, 200, 2, 2)
23
25
  # rubocop:enable Style/ExtraSpacing
24
26
 
25
27
  # map certain symbols (we get them from a tokenizer) to our operators
@@ -30,6 +32,7 @@ module PuppetDBQuery
30
32
  EQUAL.symbol => EQUAL,
31
33
  NOT_EQUAL.symbol => NOT_EQUAL,
32
34
  MATCH.symbol => MATCH,
35
+ IN.symbol => IN,
33
36
  }.freeze
34
37
 
35
38
  attr_reader :symbols # array of symbols
@@ -46,10 +49,11 @@ module PuppetDBQuery
46
49
 
47
50
  private
48
51
 
49
- # Reads next maximal term. The following input doesn't make the term ore complete.
52
+ # Reads next maximal term. The following input doesn't make the term more complete.
50
53
  # Respects the priority of operators by comparing it to the given value.
51
54
  def read_maximal_term(priority)
52
55
  return nil if empty?
56
+ logger.debug "read maximal term (#{priority})"
53
57
  first = read_minimal_term
54
58
  term = add_next_infix_terms(priority, first)
55
59
  logger.debug "read maximal term: #{term}"
@@ -58,31 +62,55 @@ module PuppetDBQuery
58
62
 
59
63
  # Read next following term. This is a complete term but some infix operator
60
64
  # or some terms for an infix operator might follow.
61
- # rubocop:disable Metrics/PerceivedComplexity
65
+ # rubocop:disable Metrics/PerceivedComplexity,Metrics/AbcSize,Metrics/CyclomaticComplexity
66
+ # rubocop:disable Metrics/MethodLength
62
67
  def read_minimal_term
68
+ logger.debug "read minimal term"
63
69
  term = nil
64
70
  operator = get_operator
65
71
  if operator
66
72
  error("'#{operator}' is no prefix operator") unless operator.prefix?
67
73
  read_token
68
74
  term = Term.new(operator)
69
- arg = read_maximal_term(operator.priority)
70
- term.add(arg)
75
+ if operator.maximum > 1
76
+ error("'#{operator}' is prefix operator with more than one argument," \
77
+ " that is not supported yet")
78
+ end
79
+ if operator.minimum > 0
80
+ arg = read_maximal_term(operator.priority)
81
+ error("prefix operator '#{operator}' got no argument") if arg.nil?
82
+ term.add(arg)
83
+ end
71
84
  logger.debug "read_minimal_term: #{term}"
72
85
  return term
73
86
  end
74
87
  # no prefix operator found
75
88
  token = get_token
76
- if token == :begin
89
+ if token == :_begin
90
+ logger.debug "read ()"
77
91
  read_token
78
92
  term = read_maximal_term(0)
79
- error "'#{Tokenizer.symbol_to_string(:end)}' expected " unless read_token == :end
80
- elsif token == :list_begin
93
+ error "'#{Tokenizer.symbol_to_string(:_end)}' expected " unless get_token == :_end
81
94
  read_token
82
- term = read_maximal_term(0)
83
- error "'#{Tokenizer.symbol_to_string(:list_end)}' expected " unless read_token == :list_end
95
+ elsif token == :_list_begin
96
+ logger.debug "read []"
97
+ read_token
98
+ args = []
99
+ loop do
100
+ term = read_maximal_term(0)
101
+ if get_token != :_list_end && get_token != :_comma
102
+ error "'#{Tokenizer.symbol_to_string(:_list_end)}' or" \
103
+ " '#{Tokenizer.symbol_to_string(:_comma)}' expected"
104
+ end
105
+ args << term if term
106
+ break if read_token == :_list_end
107
+ end
108
+ term = args
84
109
  else
85
110
  error("no operator #{get_operator} expected here") if get_operator
111
+ if Tokenizer::LANGUAGE_STRINGS.include?(token) && ![:true, :false].include?(token)
112
+ error("that was not expected here: '#{Tokenizer.symbol_to_string(token)}'")
113
+ end
86
114
  token = read_token
87
115
  logger.debug "atom found: #{token}"
88
116
  term = token
@@ -90,7 +118,8 @@ module PuppetDBQuery
90
118
  logger.debug "read minimal term: #{term}"
91
119
  term
92
120
  end
93
- # rubocop:enable Metrics/PerceivedComplexity
121
+ # rubocop:enable Metrics/PerceivedComplexity,Metrics/AbcSize,Metrics/CyclomaticComplexity
122
+ # rubocop:enable Metrics/MethodLength
94
123
 
95
124
  # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
96
125
  # rubocop:disable Metrics/MethodLength,Metrics/PerceivedComplexity
@@ -100,10 +129,14 @@ module PuppetDBQuery
100
129
  loop do
101
130
  # we expect an infix operator
102
131
  operator = get_operator
103
- logger.debug "we found operator '#{operator}'" if operator
132
+ logger.debug "we found operator '#{operator}'" unless operator.nil?
104
133
  if operator.nil? || operator.prefix? || operator.priority <= priority
105
- logger.debug "'#{operator}' is prefex '#{operator && operator.prefix?}' or has less" \
106
- " priority #{operator && operator.priority} than #{priority}"
134
+ logger.debug "operator '#{operator}' is nil" if operator.nil?
135
+ logger.debug "operator '#{operator}' is prefex" if !operator.nil? && operator.prefix?
136
+ if !operator.nil? && operator.priority <= priority
137
+ logger.debug "operator '#{operator}' has less priority #{operator.priority}" \
138
+ " than #{priority}"
139
+ end
107
140
  logger.debug "get_next_infix_terms: #{term}"
108
141
  return term
109
142
  end
@@ -164,10 +197,11 @@ module PuppetDBQuery
164
197
  # rubocop:enable Style/AccessorMethodName
165
198
 
166
199
  def error(message)
167
- length = Tokenizer.query(symbols[0..position]).size
200
+ length = (position > 0 ? Tokenizer.query(symbols[0..(position - 1)]).size + 1 : 0)
168
201
  raise "parsing query failed\n#{message}\n\n#{Tokenizer.query(symbols)}\n#{' ' * length}^"
169
202
  end
170
203
  end
204
+ # rubocop:enable Metrics/ClassLength
171
205
  end
172
206
 
173
207
  if $0 == __FILE__
@@ -14,8 +14,8 @@ module PuppetDBQuery
14
14
  @destination = destination
15
15
  end
16
16
 
17
- def sync(minutes = 5, seconds = 10)
18
- logger.info "syncing puppetdb nodes and facts started"
17
+ def sync(minutes = 60, seconds = 10)
18
+ logger.info "syncing puppetdb nodes and facts started, running #{minutes} minutes"
19
19
 
20
20
  Timeout.timeout(60 * minutes - seconds) do
21
21
  updater = PuppetDBQuery::Updater.new(source, destination)
@@ -32,6 +32,9 @@ module PuppetDBQuery
32
32
  ts = Time.now
33
33
  updater.update3(timestamp - 2)
34
34
  timestamp = ts
35
+ rescue Timeout::Error
36
+ logger.info "syncing puppetdb nodes: now our time is up, we finsh"
37
+ return
35
38
  rescue
36
39
  logger.error $!
37
40
  end
@@ -18,7 +18,7 @@ module PuppetDBQuery
18
18
 
19
19
  private
20
20
 
21
- # rubocop:disable Metrics/PerceivedComplexity
21
+ # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
22
22
  def query_term(term)
23
23
  # rubocop:disable Style/GuardClause
24
24
  if term.is_a?(Symbol)
@@ -33,26 +33,28 @@ module PuppetDBQuery
33
33
  # rubocop:enable Style/GuardClause
34
34
  terms = term.args.map { |t| query_term(t) }
35
35
  case term.operator.symbol
36
- when :and
36
+ when :_and
37
37
  { :$and => terms }
38
- when :or
38
+ when :_or
39
39
  { :$or => terms }
40
- when :not
40
+ when :_not
41
41
  # $not currently (<=2.5.1) only supports negating equality operators.
42
42
  # so you can do { field: { $not : { [$eq,$gt,$lt,...] } }
43
43
  # but there is no way to negate an entire expression.
44
44
  # see https://jira.mongodb.org/browse/SERVER-10708
45
45
  { :$nor => terms }
46
- when :equal
46
+ when :_equal
47
47
  { term.args[0] => term.args[1].to_s }
48
- when :not_equal
48
+ when :_not_equal
49
49
  { term.args[0] => { :$ne => term.args[1].to_s } }
50
- when :match
50
+ when :_match
51
51
  { term.args[0] => { :$regex => term.args[1].to_s } }
52
+ when :_in
53
+ { term.args[0] => { :$in => term.args[1] } }
52
54
  else
53
55
  raise "can't handle operator '#{term.operator}' yet"
54
56
  end
55
57
  end
56
- # rubocop:enable Metrics/PerceivedComplexity
58
+ # rubocop:enable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
57
59
  end
58
60
  end
@@ -2,39 +2,40 @@ require_relative "logging"
2
2
 
3
3
  module PuppetDBQuery
4
4
  # tokenize puppetdb queries
5
+ # FIXME: distinguish between language tokens and other tokens
5
6
  # rubocop:disable Metrics/ClassLength
6
7
  class Tokenizer
7
8
  include Logging
8
9
  include Enumerable
9
10
 
10
11
  SINGLE_CHAR_TO_TOKEN = {
11
- "!" => :not,
12
- "=" => :equal,
13
- "(" => :begin,
14
- ")" => :end,
15
- "[" => :list_begin,
16
- "]" => :list_end,
17
- "<" => :less,
18
- ">" => :greater,
19
- "~" => :match,
20
- "," => :comma,
12
+ "!" => :_not,
13
+ "=" => :_equal,
14
+ "(" => :_begin,
15
+ ")" => :_end,
16
+ "[" => :_list_begin,
17
+ "]" => :_list_end,
18
+ "<" => :_less,
19
+ ">" => :_greater,
20
+ "~" => :_match,
21
+ "," => :_comma,
21
22
  }.freeze
22
23
 
23
24
  DOUBLE_CHAR_TO_TOKEN = {
24
- "!=" => :not_equal,
25
- "!~" => :not_match,
26
- "~>" => :match_array,
27
- "<=" => :less_or_equal,
28
- ">=" => :greater_or_equal,
25
+ "!=" => :_not_equal,
26
+ "!~" => :_not_match,
27
+ "~>" => :_match_array,
28
+ "<=" => :_less_or_equal,
29
+ ">=" => :_greater_or_equal,
29
30
  }.freeze
30
31
 
31
32
  STRING_TO_TOKEN = {
32
- "not" => :not,
33
- "or" => :or,
34
- "and" => :and,
35
- "in" => :in,
36
- "is" => :is,
37
- "null" => :null,
33
+ "not" => :_not,
34
+ "or" => :_or,
35
+ "and" => :_and,
36
+ "in" => :_in,
37
+ "is" => :_is,
38
+ "null" => :_null,
38
39
  "true" => :true,
39
40
  "false" => :false,
40
41
  }.freeze
@@ -93,11 +94,13 @@ module PuppetDBQuery
93
94
  if DOUBLE_CHAR_TO_TOKEN.include?(s)
94
95
  increase
95
96
  increase
97
+ logger.debug " resulting symbol: #{DOUBLE_CHAR_TO_TOKEN[s]}"
96
98
  return DOUBLE_CHAR_TO_TOKEN[s]
97
99
  end
98
100
  c = text[position]
99
101
  if SINGLE_CHAR_TO_TOKEN.include?(c)
100
102
  increase
103
+ logger.debug " resulting symbol: #{SINGLE_CHAR_TO_TOKEN[c]}"
101
104
  return SINGLE_CHAR_TO_TOKEN[c]
102
105
  end
103
106
  case c
@@ -113,9 +116,9 @@ module PuppetDBQuery
113
116
  end
114
117
 
115
118
  def read_quoted
116
- logger.debug "read quoted"
119
+ logger.debug " read quoted"
117
120
  skip_whitespace
118
- q = text[position]
121
+ q = text[position] # quote character
119
122
  increase
120
123
  r = ""
121
124
  while !empty? && (c = text[position]) != q
@@ -136,31 +139,33 @@ module PuppetDBQuery
136
139
  end
137
140
  error("I expected '#{q}' but I got '#{c}'") if c != q
138
141
  increase
139
- logger.debug "resulting string: '#{r}'"
142
+ logger.debug " resulting string: '#{r}'"
140
143
  r
141
144
  end
142
145
 
143
146
  def read_symbol
144
- logger.debug "read symbol"
147
+ logger.debug " read symbol"
145
148
  skip_whitespace
146
149
  r = ""
147
150
  while !empty? && (c = text[position]) =~ /[-a-zA-Z_0-9]/
148
151
  r << c
149
152
  increase
150
153
  end
151
- logger.debug "resulting symbol: '#{r}'"
152
- r.to_sym
154
+ s = STRING_TO_TOKEN[r]
155
+ s = r.to_sym unless s
156
+ logger.debug " resulting symbol: #{s}"
157
+ s
153
158
  end
154
159
 
155
160
  def read_number
156
- logger.debug "read number"
161
+ logger.debug " read number"
157
162
  skip_whitespace
158
163
  r = ""
159
164
  while !empty? && (c = text[position]) =~ /[-0-9\.E]/
160
165
  r << c
161
166
  increase
162
167
  end
163
- logger.debug "resulting number: '#{r}'"
168
+ logger.debug " resulting number: '#{r}'"
164
169
  Integer(r)
165
170
  rescue
166
171
  Float(r)
@@ -1,3 +1,3 @@
1
1
  module PuppetDBQuery
2
- VERSION = "0.0.8".freeze
2
+ VERSION = "0.0.9".freeze
3
3
  end
@@ -4,7 +4,7 @@ require "spec_helper"
4
4
  # rubocop:disable Style/MultilineMethodCallIndentation,Style/RedundantParentheses
5
5
  # rubocop:disable Style/ClosingParenthesisIndentation
6
6
  describe PuppetDBQuery::Parser do
7
- PARSER_DATA = [
7
+ CORRECT_PARSER_DATA = [
8
8
  [ 'hostname=\'puppetdb-mike-217922\'',
9
9
  [PuppetDBQuery::Term.new(PuppetDBQuery::Parser::EQUAL).add(:hostname, "puppetdb-mike-217922")]
10
10
  ],
@@ -32,9 +32,29 @@ describe PuppetDBQuery::Parser do
32
32
  ],
33
33
  ].freeze
34
34
 
35
- PARSER_DATA.each do |q, a|
35
+ CORRECT_PARSER_DATA.each do |q, a|
36
36
  it "translates correctly #{q.inspect}" do
37
37
  expect(subject.parse(q)).to eq(a)
38
38
  end
39
39
  end
40
+
41
+ it "complains about missing )" do
42
+ expect { subject.parse("a!=true and (b=false") }.to raise_error(/'\)' expected/)
43
+ end
44
+
45
+ it "complains about missing arguments for and" do
46
+ expect { subject.parse("a!=true and") }.to raise_error(/to few arguments for operator 'and'/)
47
+ end
48
+
49
+ it "complains about missing arguments for not" do
50
+ expect { subject.parse("not") }.to raise_error(/prefix operator 'not' got no argument/)
51
+ end
52
+
53
+ it "complains about closing bracket" do
54
+ expect { subject.parse(")") }.to raise_error(/that was not expected here: '\)'/)
55
+ end
56
+
57
+ it "complains about closing bracket 2" do
58
+ expect { subject.parse("not )") }.to raise_error(/that was not expected here: '\)'/)
59
+ end
40
60
  end
@@ -27,7 +27,7 @@ describe PuppetDBQuery::ToMongo do
27
27
  ]
28
28
  }
29
29
  ],
30
- [ '(group="develop-ci" or group=develop or group=mock) and (operatingsystemmajrelease="6")',
30
+ [ '(group="develop-ci" or group=develop or group=mock) and operatingsystemmajrelease="6"',
31
31
  { :$and => [
32
32
  { :$or => [
33
33
  { group: "develop-ci" },
@@ -39,10 +39,16 @@ describe PuppetDBQuery::ToMongo do
39
39
  ]
40
40
  }
41
41
  ],
42
- [ "server_type=zoo or server_type='mesos-magr') and group!='infrastructure-ci'",
42
+ [ "server_type=zoo or server_type='mesos-magr' and group!='infrastructure-ci'",
43
43
  { :$or => [
44
44
  { server_type: "zoo" },
45
- { server_type: "mesos-magr" }
45
+ { :$and => [
46
+ { server_type: "mesos-magr" },
47
+ { group:
48
+ { :$ne => "infrastructure-ci" }
49
+ }
50
+ ]
51
+ }
46
52
  ]
47
53
  }
48
54
  ],
@@ -58,6 +64,11 @@ describe PuppetDBQuery::ToMongo do
58
64
  ]
59
65
  }
60
66
  ],
67
+ [ "server_type in [zoo, kafka]",
68
+ { server_type:
69
+ { :$in => [:zoo, :kafka] }
70
+ }
71
+ ],
61
72
  ].freeze
62
73
 
63
74
  TO_MONGO_DATA.each do |q, a|
@@ -4,31 +4,32 @@ require "spec_helper"
4
4
  describe PuppetDBQuery::Tokenizer do
5
5
  TOKENIZER_DATA = [
6
6
  [ 'hostname=\'puppetdb-mike-217922\'',
7
- [:hostname, :equal, "puppetdb-mike-217922"]
7
+ [:hostname, :_equal, "puppetdb-mike-217922"]
8
8
  ],
9
9
  [ 'disable_puppet = true',
10
- [:disable_puppet, :equal, :true]
10
+ [:disable_puppet, :_equal, :true]
11
11
  ],
12
12
  [ 'fqdn~"app-dev" and group=develop and vertical~tracking and cluster_color~BLUE',
13
- [:fqdn, :match, "app-dev", :and, :group, :equal, :develop, :and, :vertical, :match,
14
- :tracking, :and, :cluster_color, :match, :BLUE]
13
+ [:fqdn, :_match, "app-dev", :_and, :group, :_equal, :develop, :_and, :vertical, :_match,
14
+ :tracking, :_and, :cluster_color, :_match, :BLUE]
15
15
  ],
16
16
  [ 'fqdn~"kafka" and group=develop and vertical=tracking',
17
- [:fqdn, :match, "kafka", :and, :group, :equal, :develop, :and, :vertical, :equal, :tracking]
17
+ [:fqdn, :_match, "kafka", :_and, :group, :_equal, :develop, :_and, :vertical, :_equal,
18
+ :tracking]
18
19
  ],
19
20
  [ '(group="develop-ci" or group=develop or group=mock) and (operatingsystemmajrelease="6")',
20
- [:begin, :group, :equal, "develop-ci", :or, :group, :equal, :develop, :or, :group, :equal,
21
- :mock, :end, :and, :begin, :operatingsystemmajrelease, :equal, "6", :end]
21
+ [:_begin, :group, :_equal, "develop-ci", :_or, :group, :_equal, :develop, :_or, :group,
22
+ :_equal, :mock, :_end, :_and, :_begin, :operatingsystemmajrelease, :_equal, "6", :_end]
22
23
  ],
23
24
  [ "server_type=zoo or server_type='mesos-magr') and group!='infrastructure-ci'",
24
- [:server_type, :equal, :zoo, :or, :server_type, :equal, "mesos-magr", :end, :and, :group,
25
- :not_equal, "infrastructure-ci"]
25
+ [:server_type, :_equal, :zoo, :_or, :server_type, :_equal, "mesos-magr", :_end, :_and,
26
+ :group, :_not_equal, "infrastructure-ci"]
26
27
  ],
27
28
  [ "server_type~'mesos-magr' and group='ops-ci' and operatingsystemmajrelease=7 and" \
28
29
  " vmtest_vm!=true and disable_puppet!=true and puppet_artifact_version!=NO_VERSION_CHECK",
29
- [:server_type, :match, "mesos-magr", :and, :group, :equal, "ops-ci", :and,
30
- :operatingsystemmajrelease, :equal, 7, :and, :vmtest_vm, :not_equal, :true, :and,
31
- :disable_puppet, :not_equal, :true, :and, :puppet_artifact_version, :not_equal,
30
+ [:server_type, :_match, "mesos-magr", :_and, :group, :_equal, "ops-ci", :_and,
31
+ :operatingsystemmajrelease, :_equal, 7, :_and, :vmtest_vm, :_not_equal, :true, :_and,
32
+ :disable_puppet, :_not_equal, :true, :_and, :puppet_artifact_version, :_not_equal,
32
33
  :NO_VERSION_CHECK]
33
34
  ],
34
35
  ].freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppetdb_query
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Meyling
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-15 00:00:00.000000000 Z
11
+ date: 2016-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake