puppetdb_query 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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