ruby-puppetdb 2.0.0 → 2.0.1
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 +8 -8
- data/lib/puppetdb.rb +1 -1
- data/lib/puppetdb/lexer.rb +5 -5
- data/lib/puppetdb/lexer.rex +2 -2
- data/spec/unit/puppetdb/parser_spec.rb +150 -58
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjY0NTMwZTM1NjBkOTRjYmU4M2Y5N2VlNzlkZTUwMWEzZmMxYjk5Mg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjgxMGNiMjdjNjRjZDMyZWE2OTg4MDliODcxMTQyOTY1YWVlZmY5Mw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZThkNjAwMGZhYzZhNzIyOTI2NjJkNjZiMjY0YThiY2EzODIzODAzMWMwZmIz
|
10
|
+
MTJhNGQwN2NkNGExMzI4M2Q5ZmU2Y2I3ZTRhMWE4N2RlZDE4N2RiYjk3NjBk
|
11
|
+
ZTI4MzEwODYzZTI1ZTg3NzlhZThkOTVkMGFkZWNhZTZhOTQ1ODY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTU4NzI1OTBjMGUxMjVlNGQ2N2ExNGQ5YzZmNTc4NWM5NDZmZTQwODM3Nzli
|
14
|
+
MzBjZDA1ZjU1YjE4Y2E2MWRjNGI3MTAxNjk3YjViZmY1YjgzMWFmZGI1ZjZi
|
15
|
+
Y2I2OGNmNTA3MmVlZjM2MWQ2MTc2ZDYxMmZiNTg4MjVjMzE4NDg=
|
data/lib/puppetdb.rb
CHANGED
data/lib/puppetdb/lexer.rb
CHANGED
@@ -95,18 +95,18 @@ class PuppetDB::Lexer < Racc::Parser
|
|
95
95
|
when (text = @ss.scan(/\!~/))
|
96
96
|
action { [:NOTMATCH, text] }
|
97
97
|
|
98
|
-
when (text = @ss.scan(/</))
|
99
|
-
action { [:LESSTHAN, text] }
|
100
|
-
|
101
98
|
when (text = @ss.scan(/<=/))
|
102
99
|
action { [:LESSTHANEQ, text] }
|
103
100
|
|
104
|
-
when (text = @ss.scan(
|
105
|
-
action { [:
|
101
|
+
when (text = @ss.scan(/</))
|
102
|
+
action { [:LESSTHAN, text] }
|
106
103
|
|
107
104
|
when (text = @ss.scan(/>=/))
|
108
105
|
action { [:GREATERTHANEQ, text] }
|
109
106
|
|
107
|
+
when (text = @ss.scan(/>/))
|
108
|
+
action { [:GREATERTHAN, text] }
|
109
|
+
|
110
110
|
when (text = @ss.scan(/\*/))
|
111
111
|
action { [:ASTERISK, text] }
|
112
112
|
|
data/lib/puppetdb/lexer.rex
CHANGED
@@ -18,10 +18,10 @@ rule
|
|
18
18
|
\!= { [:NOTEQUALS, text] }
|
19
19
|
~ { [:MATCH, text] }
|
20
20
|
\!~ { [:NOTMATCH, text] }
|
21
|
-
< { [:LESSTHAN, text] }
|
22
21
|
<= { [:LESSTHANEQ, text] }
|
23
|
-
|
22
|
+
< { [:LESSTHAN, text] }
|
24
23
|
>= { [:GREATERTHANEQ, text] }
|
24
|
+
> { [:GREATERTHAN, text] }
|
25
25
|
\* { [:ASTERISK, text] }
|
26
26
|
\# { [:HASH, text] }
|
27
27
|
\. { [:DOT, text] }
|
@@ -4,108 +4,200 @@ require 'spec_helper'
|
|
4
4
|
require 'puppetdb/parser'
|
5
5
|
|
6
6
|
describe PuppetDB::Parser do
|
7
|
-
context
|
7
|
+
context 'Query parsing' do
|
8
8
|
let(:parser) { PuppetDB::Parser.new }
|
9
|
-
it
|
9
|
+
it 'should handle empty queries' do
|
10
10
|
parser.parse('').should be_nil
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
14
|
-
parser.parse('foo="bar"').should eq
|
13
|
+
it 'should handle double quoted strings' do
|
14
|
+
parser.parse('foo="bar"').should eq \
|
15
|
+
['in', 'certname',
|
16
|
+
['extract', 'certname',
|
17
|
+
['select_fact_contents',
|
18
|
+
['and',
|
19
|
+
['=', 'path', ['foo']],
|
20
|
+
['=', 'value', 'bar']]]]]
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should handle single quoted strings' do
|
24
|
+
parser.parse('foo=\'bar\'').should eq \
|
25
|
+
['in', 'certname',
|
26
|
+
['extract', 'certname',
|
27
|
+
['select_fact_contents',
|
28
|
+
['and',
|
29
|
+
['=', 'path', ['foo']],
|
30
|
+
['=', 'value', 'bar']]]]]
|
15
31
|
end
|
16
32
|
|
17
|
-
it
|
18
|
-
parser.parse('foo
|
33
|
+
it 'should handle = operator' do
|
34
|
+
parser.parse('foo=bar').should eq \
|
35
|
+
['in', 'certname',
|
36
|
+
['extract', 'certname',
|
37
|
+
['select_fact_contents',
|
38
|
+
['and',
|
39
|
+
['=', 'path', ['foo']],
|
40
|
+
['=', 'value', 'bar']]]]]
|
19
41
|
end
|
20
42
|
|
21
|
-
it
|
22
|
-
parser.parse('foo
|
23
|
-
|
43
|
+
it 'should handle != operator' do
|
44
|
+
parser.parse('foo!=bar').should eq \
|
45
|
+
['in', 'certname',
|
46
|
+
['extract', 'certname',
|
47
|
+
['select_fact_contents',
|
48
|
+
['and',
|
49
|
+
['=', 'path', ['foo']],
|
50
|
+
['not', ['=', 'value', 'bar']]]]]]
|
24
51
|
end
|
25
52
|
|
26
|
-
it
|
27
|
-
parser.parse('
|
53
|
+
it 'should handle ~ operator' do
|
54
|
+
parser.parse('foo~bar').should eq \
|
55
|
+
['in', 'certname',
|
56
|
+
['extract', 'certname',
|
57
|
+
['select_fact_contents',
|
58
|
+
['and',
|
59
|
+
['=', 'path', ['foo']],
|
60
|
+
['~', 'value', 'bar']]]]]
|
28
61
|
end
|
29
62
|
|
30
|
-
it
|
31
|
-
parser.parse('
|
63
|
+
it 'should handle !~ operator' do
|
64
|
+
parser.parse('foo!~bar').should eq \
|
65
|
+
['in', 'certname',
|
66
|
+
['extract', 'certname',
|
67
|
+
['select_fact_contents',
|
68
|
+
['and',
|
69
|
+
['=', 'path', ['foo']],
|
70
|
+
['not', ['~', 'value', 'bar']]]]]]
|
32
71
|
end
|
33
72
|
|
34
|
-
it
|
35
|
-
parser.parse('
|
73
|
+
it 'should handle >= operator' do
|
74
|
+
parser.parse('foo>=1').should eq \
|
75
|
+
['in', 'certname',
|
76
|
+
['extract', 'certname',
|
77
|
+
['select_fact_contents',
|
78
|
+
['and',
|
79
|
+
['=', 'path', ['foo']],
|
80
|
+
['>=', 'value', 1]]]]]
|
36
81
|
end
|
37
82
|
|
38
|
-
it
|
39
|
-
parser.parse('
|
40
|
-
|
83
|
+
it 'should handle <= operator' do
|
84
|
+
parser.parse('foo<=1').should eq \
|
85
|
+
['in', 'certname',
|
86
|
+
['extract', 'certname',
|
87
|
+
['select_fact_contents',
|
88
|
+
['and',
|
89
|
+
['=', 'path', ['foo']],
|
90
|
+
['<=', 'value', 1]]]]]
|
41
91
|
end
|
42
92
|
|
43
|
-
it
|
44
|
-
parser.parse('
|
93
|
+
it 'should handle > operator' do
|
94
|
+
parser.parse('foo>1').should eq \
|
95
|
+
['in', 'certname',
|
96
|
+
['extract', 'certname',
|
97
|
+
['select_fact_contents',
|
98
|
+
['and',
|
99
|
+
['=', 'path', ['foo']],
|
100
|
+
['>', 'value', 1]]]]]
|
45
101
|
end
|
46
102
|
|
47
|
-
it
|
48
|
-
parser.parse('
|
103
|
+
it 'should handle < operator' do
|
104
|
+
parser.parse('foo<1').should eq \
|
105
|
+
['in', 'certname',
|
106
|
+
['extract', 'certname',
|
107
|
+
['select_fact_contents',
|
108
|
+
['and',
|
109
|
+
['=', 'path', ['foo']],
|
110
|
+
['<', 'value', 1]]]]]
|
49
111
|
end
|
50
112
|
|
51
|
-
it
|
52
|
-
parser.parse('
|
113
|
+
it 'should handle precedence' do
|
114
|
+
parser.parse('foo=1 or bar=2 and baz=3').should eq ['or', ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['foo']], ['=', 'value', 1]]]]], ['and', ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['bar']], ['=', 'value', 2]]]]], ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['baz']], ['=', 'value', 3]]]]]]]
|
115
|
+
parser.parse('(foo=1 or bar=2) and baz=3').should eq ['and', ['or', ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['foo']], ['=', 'value', 1]]]]], ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['bar']], ['=', 'value', 2]]]]]], ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['baz']], ['=', 'value', 3]]]]]]
|
53
116
|
end
|
54
117
|
|
55
|
-
it
|
56
|
-
parser.parse('foo
|
118
|
+
it 'should parse resource queries for exported resources' do
|
119
|
+
parser.parse('@@file[foo]').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'File'], ['=', 'title', 'foo'], ['=', 'exported', true]]]]]
|
57
120
|
end
|
58
121
|
|
59
|
-
it
|
60
|
-
parser.parse('foo
|
122
|
+
it 'should parse resource queries with type, title and parameters' do
|
123
|
+
parser.parse('file[foo]{bar=baz}').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'File'], ['=', 'title', 'foo'], ['=', 'exported', false], ['=', %w(parameter bar), 'baz']]]]]
|
61
124
|
end
|
62
125
|
|
63
|
-
it
|
64
|
-
parser.parse('foo
|
126
|
+
it 'should parse resource queries with tags' do
|
127
|
+
parser.parse('file[foo]{tag=baz}').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'File'], ['=', 'title', 'foo'], ['=', 'exported', false], ['=', 'tag', 'baz']]]]]
|
65
128
|
end
|
66
129
|
|
67
|
-
it
|
68
|
-
parser.parse('foo
|
130
|
+
it 'should handle precedence within resource parameter queries' do
|
131
|
+
parser.parse('file[foo]{foo=1 or bar=2 and baz=3}').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'File'], ['=', 'title', 'foo'], ['=', 'exported', false], ['or', ['=', %w(parameter foo), 1], ['and', ['=', %w(parameter bar), 2], ['=', %w(parameter baz), 3]]]]]]]
|
132
|
+
parser.parse('file[foo]{(foo=1 or bar=2) and baz=3}').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'File'], ['=', 'title', 'foo'], ['=', 'exported', false], ['and', ['or', ['=', %w(parameter foo), 1], ['=', %w(parameter bar), 2]], ['=', %w(parameter baz), 3]]]]]]
|
69
133
|
end
|
70
134
|
|
71
|
-
it
|
72
|
-
parser.parse('foo
|
135
|
+
it 'should capitalize class names' do
|
136
|
+
parser.parse('class[foo::bar]').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'Class'], ['=', 'title', 'Foo::Bar'], ['=', 'exported', false]]]]]
|
73
137
|
end
|
74
138
|
|
75
|
-
it
|
76
|
-
parser.parse('
|
139
|
+
it 'should parse resource queries with regeexp title matching' do
|
140
|
+
parser.parse('class[~foo]').should eq ['in', 'certname', ['extract', 'certname', ['select_resources', ['and', ['=', 'type', 'Class'], ['~', 'title', 'foo'], ['=', 'exported', false]]]]]
|
77
141
|
end
|
78
142
|
|
79
|
-
it
|
80
|
-
parser.parse('
|
143
|
+
it 'should be able to negate expressions' do
|
144
|
+
parser.parse('not foo=bar').should eq ['not', ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['foo']], ['=', 'value', 'bar']]]]]]
|
81
145
|
end
|
82
146
|
|
83
|
-
it
|
84
|
-
parser.parse('
|
147
|
+
it 'should handle single string expressions' do
|
148
|
+
parser.parse('foo.bar.com').should eq ['~', 'certname', 'foo\\.bar\\.com']
|
85
149
|
end
|
86
150
|
|
87
|
-
it
|
88
|
-
parser.parse('
|
151
|
+
it 'should handle structured facts' do
|
152
|
+
parser.parse('foo.bar=baz').should eq ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', %w(foo bar)], ['=', 'value', 'baz']]]]]
|
89
153
|
end
|
90
154
|
|
91
|
-
it
|
92
|
-
|
93
|
-
|
155
|
+
it 'should handle structured facts with array component' do
|
156
|
+
parser.parse('foo.bar.0=baz').should eq ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['foo', 'bar', 0]], ['=', 'value', 'baz']]]]]
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should handle structured facts with match operator' do
|
160
|
+
parser.parse('foo.bar.~".*"=baz').should eq ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['~>', 'path', ['foo', 'bar', '.*']], ['=', 'value', 'baz']]]]]
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should handle structured facts with wildcard operator' do
|
164
|
+
parser.parse('foo.bar.*=baz').should eq ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['~>', 'path', ['foo', 'bar', '.*']], ['=', 'value', 'baz']]]]]
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should handle #node subqueries' do
|
168
|
+
parser.parse('#node.catalog_environment=production').should eq ['in', 'certname', ['extract', 'certname', ['select_nodes', ['=', 'catalog_environment', 'production']]]]
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should handle #node subqueries with block of conditions' do
|
172
|
+
parser.parse('#node { catalog_environment=production }').should eq ['in', 'certname', ['extract', 'certname', ['select_nodes', ['=', 'catalog_environment', 'production']]]]
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should handle #node subquery combined with fact query' do
|
176
|
+
parser.parse('#node.catalog_environment=production and foo=bar').should eq ['and', ['in', 'certname', ['extract', 'certname', ['select_nodes', ['=', 'catalog_environment', 'production']]]], ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['foo']], ['=', 'value', 'bar']]]]]]
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'should escape non match parts on structured facts with match operator' do
|
180
|
+
parser.parse('"foo.bar".~".*"=baz').should eq ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['~>', 'path', ['foo\\.bar', '.*']], ['=', 'value', 'baz']]]]]
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should parse dates in queries' do
|
184
|
+
date = Time.new(2014, 9, 9).iso8601
|
185
|
+
parser.parse('#node.report_timestamp<@"Sep 9, 2014"').should eq ['in', 'certname', ['extract', 'certname', ['select_nodes', ['<', 'report_timestamp', date]]]]
|
94
186
|
end
|
95
187
|
end
|
96
188
|
|
97
|
-
context
|
189
|
+
context 'facts_query' do
|
98
190
|
let(:parser) { PuppetDB::Parser.new }
|
99
191
|
it 'should return a query for all if no facts are specified' do
|
100
|
-
parser.facts_query('kernel=Linux').should eq [
|
192
|
+
parser.facts_query('kernel=Linux').should eq ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['kernel']], ['=', 'value', 'Linux']]]]]
|
101
193
|
end
|
102
194
|
|
103
195
|
it 'should return a query for specific facts if they are specified' do
|
104
|
-
parser.facts_query('kernel=Linux', ['ipaddress']). should eq [
|
196
|
+
parser.facts_query('kernel=Linux', ['ipaddress']). should eq ['and', ['in', 'certname', ['extract', 'certname', ['select_fact_contents', ['and', ['=', 'path', ['kernel']], ['=', 'value', 'Linux']]]]], ['or', ['=', 'name', 'ipaddress']]]
|
105
197
|
end
|
106
198
|
|
107
199
|
it 'should return a query for matching facts on all nodes if query is missing' do
|
108
|
-
parser.facts_query('', ['ipaddress']).should eq [
|
200
|
+
parser.facts_query('', ['ipaddress']).should eq ['or', ['=', 'name', 'ipaddress']]
|
109
201
|
end
|
110
202
|
end
|
111
203
|
|
@@ -113,16 +205,16 @@ describe PuppetDB::Parser do
|
|
113
205
|
let(:parser) { PuppetDB::Parser.new }
|
114
206
|
it 'should merge facts into a nested hash' do
|
115
207
|
parser.facts_hash([
|
116
|
-
{
|
117
|
-
{
|
118
|
-
{
|
119
|
-
{
|
120
|
-
{
|
121
|
-
{
|
208
|
+
{ 'certname' => 'ip-172-31-45-32.eu-west-1.compute.internal', 'environment' => 'production', 'name' => 'kernel', 'value' => 'Linux' },
|
209
|
+
{ 'certname' => 'ip-172-31-33-234.eu-west-1.compute.internal', 'environment' => 'production', 'name' => 'kernel', 'value' => 'Linux' },
|
210
|
+
{ 'certname' => 'ip-172-31-5-147.eu-west-1.compute.internal', 'environment' => 'production', 'name' => 'kernel', 'value' => 'Linux' },
|
211
|
+
{ 'certname' => 'ip-172-31-45-32.eu-west-1.compute.internal', 'environment' => 'production', 'name' => 'fqdn', 'value' => 'ip-172-31-45-32.eu-west-1.compute.internal' },
|
212
|
+
{ 'certname' => 'ip-172-31-33-234.eu-west-1.compute.internal', 'environment' => 'production', 'name' => 'fqdn', 'value' => 'ip-172-31-33-234.eu-west-1.compute.internal' },
|
213
|
+
{ 'certname' => 'ip-172-31-5-147.eu-west-1.compute.internal', 'environment' => 'production', 'name' => 'fqdn', 'value' => 'ip-172-31-5-147.eu-west-1.compute.internal' }
|
122
214
|
]).should eq(
|
123
|
-
|
124
|
-
|
125
|
-
|
215
|
+
'ip-172-31-45-32.eu-west-1.compute.internal' => { 'kernel' => 'Linux', 'fqdn' => 'ip-172-31-45-32.eu-west-1.compute.internal' },
|
216
|
+
'ip-172-31-33-234.eu-west-1.compute.internal' => { 'kernel' => 'Linux', 'fqdn' => 'ip-172-31-33-234.eu-west-1.compute.internal' },
|
217
|
+
'ip-172-31-5-147.eu-west-1.compute.internal' => { 'kernel' => 'Linux', 'fqdn' => 'ip-172-31-5-147.eu-west-1.compute.internal' }
|
126
218
|
)
|
127
219
|
end
|
128
220
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-puppetdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Dalen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|