knife-solo 0.3.0.pre2 → 0.3.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +70 -27
- data/README.rdoc +11 -6
- data/Rakefile +4 -2
- data/lib/chef/knife/bootstrap_solo.rb +40 -0
- data/lib/chef/knife/solo_bootstrap.rb +1 -1
- data/lib/chef/knife/solo_clean.rb +16 -4
- data/lib/chef/knife/solo_cook.rb +111 -36
- data/lib/chef/knife/solo_init.rb +14 -0
- data/lib/chef/knife/solo_prepare.rb +1 -1
- data/lib/knife-solo/bootstraps.rb +0 -18
- data/lib/knife-solo/bootstraps/darwin.rb +4 -16
- data/lib/knife-solo/bootstraps/linux.rb +36 -48
- data/lib/knife-solo/info.rb +1 -1
- data/lib/knife-solo/resources/knife.rb +4 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/.travis.yml +7 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/CHANGELOG +16 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/LICENSE +202 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/NOTICE +18 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/README.md +141 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/search.rb +72 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/search/overrides.rb +99 -0
- data/lib/{chef/knife/patches → knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/search}/parser.rb +1 -2
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/vendor/chef/solr_query/lucene.treetop +150 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/vendor/chef/solr_query/lucene_nodes.rb +285 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/vendor/chef/solr_query/query_transform.rb +65 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/metadata.rb +11 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/recipes/default.rb +2 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/Gemfile +8 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/node/alpha.json +10 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/node/beta.json +10 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/node/without_json_class.json +7 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/jerry.json +8 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/lea.json +10 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/mike.json +13 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/tom.json +10 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/test_data_bags.rb +44 -0
- data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/test_search.rb +241 -0
- data/lib/knife-solo/resources/solo.rb.erb +10 -0
- data/lib/knife-solo/ssh_command.rb +4 -3
- data/lib/knife-solo/tools.rb +22 -0
- data/test/bootstraps_test.rb +4 -11
- data/test/integration/cases/encrypted_data_bag.rb +3 -0
- data/test/integration/cases/knife_bootstrap.rb +14 -0
- data/test/integration/debian6_bootstrap_test.rb +1 -1
- data/test/integration/{debian7_bootstrap_test.rb → debian7_knife_bootstrap_test.rb} +3 -3
- data/test/knife_bootstrap_test.rb +61 -0
- data/test/solo_cook_test.rb +78 -3
- data/test/support/integration_test.rb +8 -3
- data/test/tools_test.rb +82 -0
- metadata +63 -21
- data/lib/chef/knife/patches/search.rb +0 -110
- data/lib/knife-solo/config.rb +0 -39
- data/lib/knife-solo/resources/solo.rb +0 -6
- data/test/knife-solo/config_test.rb +0 -38
@@ -0,0 +1,18 @@
|
|
1
|
+
========================
|
2
|
+
chef-solo-search Notices
|
3
|
+
========================
|
4
|
+
|
5
|
+
Developed at edelight GmbH (http://www.edelight-group.com/).
|
6
|
+
|
7
|
+
Contributors:
|
8
|
+
|
9
|
+
* Brian p o'rourke <bpo@somnambulance.net>
|
10
|
+
* Chris Roberts <chrisroberts.code@gmail.com>
|
11
|
+
* Jeff Wallace <jeff@tjwallace.ca>
|
12
|
+
* Miquel Torres <miquel.torres@edelight.de>
|
13
|
+
* Markus Korn <markus.korn@edelight.de>
|
14
|
+
* Matt Gleeson <matt@gleeson.org>
|
15
|
+
* Patrick Debois <Patrick.Debois@jedi.be>
|
16
|
+
* Patrick Wyatt <pat@codeofhonor.com>
|
17
|
+
* Seth Chisamore <schisamo@opscode.com>
|
18
|
+
* Tyler Rick
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# chef-solo-search
|
2
|
+
|
3
|
+
Chef-solo-search is a cookbook library that adds data bag search powers
|
4
|
+
to Chef Solo. Data bag support was added to Chef Solo by Chef 0.10.4.
|
5
|
+
Please see *Supported queries* for a list of query types which are supported.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
* ruby >= 1.8
|
10
|
+
* ruby-chef >= 0.10.4
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
In order to use this extension, create a (dummy-) cookbook and add a directory
|
15
|
+
called *libraries*. Next copy *libraries/search.rb* and *libraries/parser.rb* to the newly created directory.
|
16
|
+
Now you have to make sure chef-solo knows about data bags, therefore add
|
17
|
+
|
18
|
+
data_bag_path "<node_work_path>/data_bags"
|
19
|
+
|
20
|
+
to the config file of chef-solo (defaults to /etc/chef/solo.rb).
|
21
|
+
|
22
|
+
The same for your roles, add
|
23
|
+
|
24
|
+
role_path "<node_work_path>/roles"
|
25
|
+
|
26
|
+
## Supported queries
|
27
|
+
|
28
|
+
The search methods supports a basic sub-set of the lucene query language.
|
29
|
+
Sample supported queries are:
|
30
|
+
|
31
|
+
### General queries:
|
32
|
+
|
33
|
+
search(:users, "*:*")
|
34
|
+
search(:users)
|
35
|
+
search(:users, nil)
|
36
|
+
getting all items in ':users'
|
37
|
+
search(:users, "username:*")
|
38
|
+
search(:users, "username:[* TO *]")
|
39
|
+
getting all items from ':users' which have a 'username' attribute
|
40
|
+
search(:users, "(NOT username:*)")
|
41
|
+
search(:users, "(NOT username:[* TO *])")
|
42
|
+
getting all items from ':users' which don't have a 'username' attribute
|
43
|
+
|
44
|
+
### Queries on attributes with string values:
|
45
|
+
|
46
|
+
search(:users, "username:speedy")
|
47
|
+
getting all items from ':users' with username equals 'speedy'
|
48
|
+
search(:users, "NOT username:speedy")
|
49
|
+
getting all items from ':users' with username is unequal to 'speedy'
|
50
|
+
search(:users, "username:spe*")
|
51
|
+
getting all items which 'username'-value begins with 'spe'
|
52
|
+
|
53
|
+
### Queries on attributes with array values:
|
54
|
+
|
55
|
+
search(:users, "children:tom")
|
56
|
+
getting all items which 'children' attribute contains 'tom'
|
57
|
+
search(:users, "children:t*")
|
58
|
+
getting all items which have at least one element in 'children'
|
59
|
+
which starts with 't'
|
60
|
+
|
61
|
+
### Queries on attributes with boolean values:
|
62
|
+
|
63
|
+
search(:users, "married:true")
|
64
|
+
|
65
|
+
### Queries in attributes with integer values:
|
66
|
+
|
67
|
+
search(:users, "age:35")
|
68
|
+
|
69
|
+
### OR conditions in queries:
|
70
|
+
|
71
|
+
search(:users, "age:42 OR age:22")
|
72
|
+
|
73
|
+
### AND conditions in queries:
|
74
|
+
|
75
|
+
search(:users, "married:true AND age:35")
|
76
|
+
|
77
|
+
### NOT condition in queries:
|
78
|
+
|
79
|
+
search(:users, "children:tom NOT gender:female")
|
80
|
+
|
81
|
+
### More complex queries:
|
82
|
+
|
83
|
+
search(:users, "children:tom NOT gender:female AND age:42")
|
84
|
+
|
85
|
+
|
86
|
+
## Supported Objects
|
87
|
+
The search methods have support for 'roles', 'nodes' and 'databags'.
|
88
|
+
|
89
|
+
### Roles
|
90
|
+
You can use the standard role objects in json form and put them into your role path
|
91
|
+
|
92
|
+
{
|
93
|
+
"name": "monitoring",
|
94
|
+
"default_attributes": { },
|
95
|
+
"override_attributes": { },
|
96
|
+
"json_class": "Chef::Role",
|
97
|
+
"description": "This is just a monitoring role, no big deal.",
|
98
|
+
"run_list": [
|
99
|
+
],
|
100
|
+
"chef_type": "role"
|
101
|
+
|
102
|
+
|
103
|
+
### Nodes
|
104
|
+
Nodes are injected through a databag called 'node'. Create a databag called 'node' and put your json files there
|
105
|
+
You can use the standard node objects in json form.
|
106
|
+
|
107
|
+
{
|
108
|
+
"id": "vagrant",
|
109
|
+
"name": "vagrant-vm",
|
110
|
+
"chef_environment": "_default",
|
111
|
+
"json_class": "Chef::Node",
|
112
|
+
"automatic": {
|
113
|
+
"hostname": "vagrant.vm",
|
114
|
+
"os": "centos"
|
115
|
+
},
|
116
|
+
"normal": {
|
117
|
+
},
|
118
|
+
"chef_type": "node",
|
119
|
+
"default": {
|
120
|
+
},
|
121
|
+
"override": {
|
122
|
+
},
|
123
|
+
"run_list": [
|
124
|
+
"role[monitoring]"
|
125
|
+
]
|
126
|
+
}
|
127
|
+
|
128
|
+
### Databags
|
129
|
+
You can use the standard databag objects in json form
|
130
|
+
|
131
|
+
{
|
132
|
+
"id": "my-ssh",
|
133
|
+
"hostgroup_name": "all",
|
134
|
+
"command_line": "$USER1$/check_ssh $HOSTADDRESS$"
|
135
|
+
}
|
136
|
+
|
137
|
+
## Running tests
|
138
|
+
|
139
|
+
Running tests is as simple as:
|
140
|
+
|
141
|
+
% ruby -Ilibraries tests/test_search.rb -v
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011, edelight GmbH
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Markus Korn <markus.korn@edelight.de>
|
6
|
+
# Seth Chisamore <schisamo@opscode.com>
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
if Chef::Config[:solo]
|
22
|
+
|
23
|
+
# add currrent dir to load path
|
24
|
+
$: << File.dirname(__FILE__)
|
25
|
+
|
26
|
+
# All chef/solr_query/* classes were removed in Chef 11; Load vendored copy
|
27
|
+
# that ships with this cookbook
|
28
|
+
$: << File.expand_path("vendor", File.dirname(__FILE__)) if Chef::VERSION.to_i >= 11
|
29
|
+
|
30
|
+
# Ensure the treetop gem is installed and available
|
31
|
+
begin
|
32
|
+
require 'treetop'
|
33
|
+
rescue LoadError
|
34
|
+
run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)
|
35
|
+
Chef::Resource::ChefGem.new("treetop", run_context).run_action(:install)
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'search/overrides'
|
39
|
+
require 'search/parser'
|
40
|
+
|
41
|
+
module Search; class Helper; end; end
|
42
|
+
|
43
|
+
# The search and data_bag related methods moved form `Chef::Mixin::Language`
|
44
|
+
# to `Chef::DSL::DataQuery` in Chef 11.
|
45
|
+
if Chef::VERSION.to_i >= 11
|
46
|
+
module Chef::DSL::DataQuery
|
47
|
+
def self.included(base)
|
48
|
+
base.send(:include, Search::Overrides)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
Search::Helper.send(:include, Chef::DSL::DataQuery)
|
52
|
+
else
|
53
|
+
module Chef::Mixin::Language
|
54
|
+
def self.included(base)
|
55
|
+
base.send(:include, Search::Overrides)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
Search::Helper.send(:include, Chef::Mixin::Language)
|
59
|
+
end
|
60
|
+
|
61
|
+
class Chef
|
62
|
+
class Search
|
63
|
+
class Query
|
64
|
+
def initialize(*args)
|
65
|
+
end
|
66
|
+
def search(*args, &block)
|
67
|
+
::Search::Helper.new.search(*args, &block)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011, edelight GmbH
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Markus Korn <markus.korn@edelight.de>
|
6
|
+
# Seth Chisamore <schisamo@opscode.com>
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
module Search
|
22
|
+
module Overrides
|
23
|
+
# Overwrite the search method of recipes to operate locally by using
|
24
|
+
# data found in data_bags.
|
25
|
+
# Only very basic lucene syntax is supported and also sorting the result
|
26
|
+
# is not implemented, if this search method does not support a given query
|
27
|
+
# an exception is raised.
|
28
|
+
# This search() method returns a block iterator or an Array, depending
|
29
|
+
# on how this method is called.
|
30
|
+
def search(obj, query=nil, sort=nil, start=0, rows=1000, &block)
|
31
|
+
if !sort.nil?
|
32
|
+
raise "Sorting search results is not supported"
|
33
|
+
end
|
34
|
+
_query = Query.parse(query)
|
35
|
+
if _query.nil?
|
36
|
+
raise "Query #{query} is not supported"
|
37
|
+
end
|
38
|
+
_result = []
|
39
|
+
|
40
|
+
case obj
|
41
|
+
when :node
|
42
|
+
nodes = search_nodes(_query, start, rows, &block)
|
43
|
+
_result += nodes
|
44
|
+
when :role
|
45
|
+
roles = search_roles(_query, start, rows, &block)
|
46
|
+
_result += roles
|
47
|
+
else
|
48
|
+
bags = search_data_bag(_query, obj, start, rows, &block)
|
49
|
+
_result += bags
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
if block_given?
|
54
|
+
pos = 0
|
55
|
+
while (pos >= start and pos < (start + rows) and pos < _result.size)
|
56
|
+
yield _result[pos]
|
57
|
+
pos += 1
|
58
|
+
end
|
59
|
+
else
|
60
|
+
return _result.slice(start, rows)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def search_nodes(_query, start, rows, &block)
|
65
|
+
_result = []
|
66
|
+
Dir.glob(File.join(Chef::Config[:data_bag_path], "node", "*.json")).map do |f|
|
67
|
+
# parse and hashify the node
|
68
|
+
node = Chef::JSONCompat.from_json(IO.read(f))
|
69
|
+
if _query.match(node.to_hash)
|
70
|
+
_result << node
|
71
|
+
end
|
72
|
+
end
|
73
|
+
return _result
|
74
|
+
end
|
75
|
+
|
76
|
+
def search_roles(_query, start, rows, &block)
|
77
|
+
_result = []
|
78
|
+
Dir.glob(File.join(Chef::Config[:role_path], "*.json")).map do |f|
|
79
|
+
# parse and hashify the role
|
80
|
+
role = Chef::JSONCompat.from_json(IO.read(f))
|
81
|
+
if _query.match(role.to_hash)
|
82
|
+
_result << role
|
83
|
+
end
|
84
|
+
end
|
85
|
+
return _result
|
86
|
+
end
|
87
|
+
|
88
|
+
def search_data_bag(_query, bag_name, start, rows, &block)
|
89
|
+
_result = []
|
90
|
+
data_bag(bag_name.to_s).each do |bag_item_id|
|
91
|
+
bag_item = data_bag_item(bag_name.to_s, bag_item_id)
|
92
|
+
if _query.match(bag_item)
|
93
|
+
_result << bag_item
|
94
|
+
end
|
95
|
+
end
|
96
|
+
return _result
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -17,7 +17,6 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require 'treetop'
|
21
20
|
require 'chef/solr_query/query_transform'
|
22
21
|
|
23
22
|
# mock QueryTransform such that we can access the location of the lucene grammar
|
@@ -107,7 +106,7 @@ module Lucene
|
|
107
106
|
part = self.text_value.chomp("*")
|
108
107
|
item.keys.collect{ |key| key.start_with?(part)? key: nil}.compact
|
109
108
|
else
|
110
|
-
if item
|
109
|
+
if item.has_key?(self.text_value)
|
111
110
|
[self.text_value,]
|
112
111
|
else
|
113
112
|
nil
|
@@ -0,0 +1,150 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Falcon (<seth@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
grammar Lucene
|
20
|
+
|
21
|
+
rule body
|
22
|
+
(expression / space)* <Body>
|
23
|
+
end
|
24
|
+
|
25
|
+
rule expression
|
26
|
+
operation / group / field / field_range / term / string
|
27
|
+
end
|
28
|
+
|
29
|
+
rule term
|
30
|
+
keyword valid_letter+ <Term> / !keyword !"?" valid_letter <Term>
|
31
|
+
end
|
32
|
+
|
33
|
+
rule field
|
34
|
+
field_name ":" (term/string/group) <Field>
|
35
|
+
end
|
36
|
+
|
37
|
+
rule field_range
|
38
|
+
field_name ":" "[" range_value " TO " range_value "]" <InclFieldRange>
|
39
|
+
/
|
40
|
+
field_name ":" "{" range_value " TO " range_value "}" <ExclFieldRange>
|
41
|
+
end
|
42
|
+
|
43
|
+
rule field_name
|
44
|
+
!keyword valid_letter+ <FieldName>
|
45
|
+
end
|
46
|
+
|
47
|
+
rule range_value
|
48
|
+
valid_letter+ <RangeValue> / "*" <RangeValue>
|
49
|
+
end
|
50
|
+
|
51
|
+
rule group
|
52
|
+
space? '(' body ')' space? <Group>
|
53
|
+
end
|
54
|
+
|
55
|
+
rule operation
|
56
|
+
binary_op / unary_op / fuzzy_op / boost_op
|
57
|
+
end
|
58
|
+
|
59
|
+
rule unary_op
|
60
|
+
not_op / required_op / prohibited_op
|
61
|
+
end
|
62
|
+
|
63
|
+
rule binary_op
|
64
|
+
(group / field / field_range / term) space? boolean_operator space+ body <BinaryOp>
|
65
|
+
end
|
66
|
+
|
67
|
+
rule boolean_operator
|
68
|
+
and_operator / or_operator
|
69
|
+
end
|
70
|
+
|
71
|
+
rule and_operator
|
72
|
+
'AND' <AndOperator> / '&&' <AndOperator>
|
73
|
+
end
|
74
|
+
|
75
|
+
rule or_operator
|
76
|
+
'OR' <OrOperator> / '||' <OrOperator>
|
77
|
+
end
|
78
|
+
|
79
|
+
rule not_op
|
80
|
+
not_operator space (group / field / field_range / term / string) <UnaryOp>
|
81
|
+
/
|
82
|
+
bang_operator space? (group / field / field_range / term / string) <UnaryOp>
|
83
|
+
end
|
84
|
+
|
85
|
+
rule not_operator
|
86
|
+
'NOT' <NotOperator>
|
87
|
+
end
|
88
|
+
|
89
|
+
rule bang_operator
|
90
|
+
'!' <NotOperator>
|
91
|
+
end
|
92
|
+
|
93
|
+
rule required_op
|
94
|
+
!valid_letter required_operator (term/string) <UnaryOp>
|
95
|
+
/
|
96
|
+
required_operator (term/string) <UnaryOp>
|
97
|
+
end
|
98
|
+
|
99
|
+
rule required_operator
|
100
|
+
'+' <RequiredOperator>
|
101
|
+
end
|
102
|
+
|
103
|
+
rule prohibited_op
|
104
|
+
!valid_letter prohibited_operator (field/field_range/term/string) <UnaryOp>
|
105
|
+
end
|
106
|
+
|
107
|
+
rule prohibited_operator
|
108
|
+
'-' <ProhibitedOperator>
|
109
|
+
end
|
110
|
+
|
111
|
+
rule boost_op
|
112
|
+
(term/string) '^' fuzzy_param <BoostOp>
|
113
|
+
end
|
114
|
+
|
115
|
+
rule fuzzy_op
|
116
|
+
(term/string) '~' fuzzy_param? (space / !valid_letter) <FuzzyOp>
|
117
|
+
end
|
118
|
+
|
119
|
+
rule fuzzy_param
|
120
|
+
[0-9] '.'? [0-9] <FuzzyParam> / [0-9]+ <FuzzyParam>
|
121
|
+
end
|
122
|
+
|
123
|
+
rule string
|
124
|
+
'"' term (space term)* '"' <Phrase>
|
125
|
+
end
|
126
|
+
|
127
|
+
rule keyword
|
128
|
+
'AND' / 'OR' / 'NOT'
|
129
|
+
end
|
130
|
+
|
131
|
+
rule valid_letter
|
132
|
+
start_letter+ ([a-zA-Z0-9@*?_.-] / '\\' special_char)*
|
133
|
+
end
|
134
|
+
|
135
|
+
rule start_letter
|
136
|
+
[a-zA-Z0-9@._*] / '\\' special_char
|
137
|
+
end
|
138
|
+
|
139
|
+
rule end_letter
|
140
|
+
[a-zA-Z0-9*?_.] / '\\' special_char
|
141
|
+
end
|
142
|
+
|
143
|
+
rule special_char
|
144
|
+
[-+&|!(){}\[\]^"~*?:\\]
|
145
|
+
end
|
146
|
+
|
147
|
+
rule space
|
148
|
+
[\s]+
|
149
|
+
end
|
150
|
+
end
|