solr_cloud-connection 0.1.0 → 0.3.0
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 +4 -4
- data/{.env.local → .env.github} +2 -2
- data/CHANGELOG.md +16 -1
- data/README.md +65 -107
- data/Rakefile +16 -1
- data/compose.yml +2 -2
- data/{env.development → env.test} +0 -1
- data/lib/solr_cloud/alias.rb +25 -18
- data/lib/solr_cloud/collection.rb +92 -22
- data/lib/solr_cloud/configset.rb +21 -4
- data/lib/solr_cloud/connection/alias_admin.rb +43 -41
- data/lib/solr_cloud/connection/collection_admin.rb +58 -39
- data/lib/solr_cloud/connection/configset_admin.rb +41 -29
- data/lib/solr_cloud/connection/version.rb +1 -1
- data/lib/solr_cloud/connection.rb +52 -14
- data/lib/solr_cloud/errors.rb +2 -0
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e273d22bc3c74c27f96e2e4441695c47c8561634d339b8dabdc0d9c0075922e6
|
4
|
+
data.tar.gz: e208564f23b12ad6554a075caf48f65d57e7dfbe15b800e85eb639f4d2dc6791
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a1ba3738d5908c753c49b6f813b14465ddb4213d925aa7c075d6665c01229d0aecd59b8479bf5ae54f1d94511579876e7d3c392847f1c0845eb130a0f9c0897
|
7
|
+
data.tar.gz: 14f6c01885f6d97b477311099e4399b9e74c400fce40c42cdccb3e56a798df3f0ce8b0475aa57299ad3054681c4de059bf80908102a9b98b3b67cd14ecbfb50b
|
data/{.env.local → .env.github}
RENAMED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.3.0] - 2023-12-06
|
4
|
+
|
5
|
+
- Major overhaul of the interface to use more-explicit and less-confusing method names
|
6
|
+
- Remove code that tried to "version" collections and configsets, since it was dumb
|
7
|
+
- Get github actions working to run tests
|
8
|
+
- Make aliases even more of a paper-thin wrapper around collections, such that, e.g.
|
9
|
+
`coll = get_collection(alias_name)` will return the appropriate alias. Use
|
10
|
+
`coll.alias?` to determine if it's an alias or collection if that becomes important.
|
11
|
+
|
12
|
+
## [0.2.0] - 2023-12-01
|
13
|
+
|
14
|
+
- Added options `:date` and `:datetime` to the `version:` argument to `create_collection`
|
15
|
+
to automatically generate, e.g., "2023-12-01" or "2023-12-01-09-50-56"
|
16
|
+
- Added utility method `legal_solr_name?` to check for validity for collection names
|
2
17
|
|
3
18
|
## [0.1.0] - 2023-11-29
|
4
19
|
|
data/README.md
CHANGED
@@ -2,150 +2,108 @@
|
|
2
2
|
|
3
3
|
Do basic administrative tasks on a running Solr cloud instance, including:
|
4
4
|
|
5
|
+
* create (i.e., upload) a configSet when given a `conf` directory
|
5
6
|
* list, create, and delete configsets, collections, and aliases
|
6
7
|
* get basic version information for the running solr
|
7
8
|
* check on the health of individual collections
|
8
|
-
* treat an alias (mostly) as a collection
|
9
|
+
* treat an alias (mostly) as a collection
|
9
10
|
* TODO automatically generate methods to talk to defined requestHandlers
|
10
|
-
* TODO
|
11
|
+
* TODO Add something useful for configsets to do
|
12
|
+
|
13
|
+
In almost all cases, you can treat an alias to a collection like the underlying collection.
|
14
|
+
|
15
|
+
## A note about deleting things
|
16
|
+
|
17
|
+
Collections, aliases, and configsets all have a `#delete!` method. Keep in mind that solr
|
18
|
+
enforces a rule that nothing in-use can be deleted. This gem will throw appropriate errors
|
19
|
+
if you try to delete a configset that's being used by a collection, or try to delete
|
20
|
+
a collections that's pointed to by an alias.
|
11
21
|
|
12
22
|
## Caveats
|
13
23
|
|
14
|
-
* At this point the API is unstable
|
15
|
-
*
|
16
|
-
|
17
|
-
|
24
|
+
* At this point the API is unstable
|
25
|
+
* Performance is desperately, hilariously terrible. Solr has no sense of an atomic action and plenty of other ways
|
26
|
+
(e.g, the admin interface) to mess with things, so nothing is cached.
|
27
|
+
This means that individual actions can involve several round-trips to solr. If you're doing so much admin
|
28
|
+
that this becomes a bottleneck, you're well outside this gem's target case.
|
18
29
|
* While solr aliases can point to more than one collection at a time, this gem enforces one collection
|
19
30
|
per alias (although many aliases can point to the same collection)
|
20
31
|
|
21
32
|
## Usage
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
The connection object is the basis of all the other stuff. Everything will be created, directly
|
26
|
-
or indirectly, through the connection. While using the collection/alias/configset objects
|
27
|
-
is preferred, the connection on its own can do most anything. See SolrCloud::Connection for
|
28
|
-
the docs.
|
29
|
-
|
30
|
-
A simple connection is made if you pass in basic info, or you can create a faraday connection
|
31
|
-
and pass it in yourself.
|
34
|
+
The code below covers all the basics. See the docs for full sets of parameters, which errors are
|
35
|
+
thrown, etc.
|
32
36
|
|
33
37
|
```ruby
|
34
38
|
|
35
39
|
require "solr_cloud/connection"
|
36
40
|
|
37
|
-
|
38
|
-
# #=> <SolrCloud::Connection http://localhost:
|
41
|
+
server = SolrCloud::connect.new(url: "http://localhost:8023", username: "user", password: "password")
|
42
|
+
# #=> <SolrCloud::Connection http://localhost:8023/>
|
39
43
|
|
40
44
|
# or bring your own Faraday object
|
41
|
-
|
42
|
-
|
43
|
-
```
|
44
|
-
|
45
|
-
### Configsets
|
46
|
-
|
47
|
-
Configuration sets can be created by giving a path to the `conf` directory (with
|
48
|
-
`solrconfig.xml` and the schema and such) and a name.
|
49
|
-
|
50
|
-
```ruby
|
51
|
-
connect.configset_names #=> []
|
52
|
-
cset = connect.create_configset(name: "myconfig", confdir: "/path/to/yourconfig/conf")
|
53
|
-
|
54
|
-
# Get a list of existing configsets
|
55
|
-
arr_of_configsets_objects = @connect.configsets
|
56
|
-
arr_of_names_as_strings = @connect.configset_names
|
57
|
-
|
58
|
-
# Test and see if it exists by name
|
59
|
-
connect.configset?("myconfig") #=> true
|
60
|
-
|
61
|
-
# If it already exists, you can just grab it by name
|
62
|
-
|
63
|
-
def_config = connect.configset("_default")
|
45
|
+
# server = SolrCloud::connect.new_with_faraday(faraday_connection)
|
64
46
|
|
65
|
-
|
66
|
-
|
67
|
-
#=> WontOverwriteError
|
47
|
+
server.configset_names #=> ["_default"]
|
48
|
+
default = server.get_configset("_default") #=> <SolrCloud::Configset '_default' at http://localhost:8983>
|
68
49
|
|
69
|
-
#
|
70
|
-
|
50
|
+
# Create a new one by taking a directory, zipping it up, and sending it to solr
|
51
|
+
cset = server.create_configset(name: "my_awesome_configset_for_cars", confdir: "/path/to/mycore/conf")
|
52
|
+
server.configset_names #=> ["_default", "my_awesome_configset_for_cars"]
|
71
53
|
|
72
|
-
#
|
73
|
-
|
74
|
-
|
54
|
+
# That's a dumb name. We'll try again.
|
55
|
+
cset.delete!
|
56
|
+
cset = server.create_configset(name: "cars_config", confdir: "/path/to/mycore/conf")
|
75
57
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
Collections can be listed, tested for health and aliases, used to create an alias, and deleted.
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
|
84
|
-
connect.collection_names #=> []
|
85
|
-
connect.create_collection(name: "mycoll", configset: "does_not_exist") #=> SolrCloud::NoSuchConfigSetError: Configset does_not_exist doesn't exist
|
86
|
-
mycoll = connect.create_collection(name: "mycoll", configset: "_default")
|
87
|
-
mycoll.name #=> "mycoll"
|
58
|
+
# Collections and aliases are mostly treated the same
|
59
|
+
server.collection_names #=> ["cars_v1", "cars_v2", "cars"] -- collections AND aliases
|
60
|
+
server.only_collection_names #=> ["cars_v1", "cars_v2"]
|
61
|
+
server.alias_names #=> ["cars"]
|
88
62
|
|
89
|
-
|
90
|
-
|
63
|
+
typo = server.get_collection("cars__V2") #=> nil, doesn't exist
|
64
|
+
cars_v2 = server.get_collection("cars_v2")
|
91
65
|
|
92
|
-
|
66
|
+
cars_v2.alive? #=> true
|
67
|
+
cars_v2.count #=> 133 -- we're assuming there's stuff in it.
|
93
68
|
|
94
|
-
arr_of_collection_objects = connect.collections
|
95
|
-
arr_of_names_as_strings = connect.collection_names
|
96
69
|
|
97
|
-
#
|
98
|
-
|
70
|
+
# Find out about its aliases, if any
|
71
|
+
cars_v2.alias? #=> false. It's a true collection
|
72
|
+
cars_v2.aliased? #=> true
|
73
|
+
cars_v2.aliases #=> [<SolrCloud::Alias "cars" (alias of "cars_v2")> ]
|
74
|
+
cars_v2.has_alias?("cars") #=> true
|
99
75
|
|
100
|
-
|
101
|
-
mycoll.healthy? #=> true. I'm not sure how these are different
|
76
|
+
cars_v2.delete! #=> SolrCloud::CollectionAliasedError: Collection 'cars_v2' can't be deleted; it's in use by aliases ["cars"]
|
102
77
|
|
103
|
-
|
78
|
+
# Make a new collection
|
79
|
+
cars_v3 = server.create_collection(name: "cars_v3", configset: "cars_config")
|
80
|
+
cars_v3.aliased? #=> false
|
81
|
+
cars_v3.count #=> 0
|
82
|
+
cars_v3.configset #=> <SolrCloud::Configset 'cars_config' at http://localhost:8023>
|
104
83
|
|
105
|
-
#
|
106
|
-
|
84
|
+
# Work directly with an alias as if it's a collection
|
85
|
+
cars = server.get_collection("cars")
|
86
|
+
cars.alias? #=> true
|
87
|
+
cars.collection #=> <SolrCloud::Collection 'cars_v2' (aliased by 'cars')>
|
107
88
|
|
108
|
-
#
|
109
|
-
|
110
|
-
|
89
|
+
# Make a new alias to v2
|
90
|
+
old_cars = cars_v2.alias_as("old_cars") #=> <SolrCloud::Alias "old_cars" (alias of "cars_v2")>
|
91
|
+
cars_v2.aliases #=> [<SolrCloud::Alias "cars" (alias of "cars_v2")>, <SolrCloud::Alias "old_cars" (alias of "cars_v2")>]
|
111
92
|
|
112
|
-
|
113
|
-
|
93
|
+
# Now lets point the "cars" alias at cars_v3
|
94
|
+
cars.switch_collection_to cars_v3
|
114
95
|
|
115
|
-
|
116
|
-
|
117
|
-
mycoll.collection #=>
|
118
|
-
mycoll.collection.get("path/from/connection/url", arg1: "One", arg2: "Two")
|
96
|
+
cars.collection.name #=> "cars_v3"
|
97
|
+
cars_v2.alias_names #=> ["old_cars"]
|
119
98
|
|
120
|
-
#
|
121
|
-
|
122
|
-
myalias.delete!
|
123
|
-
|
124
|
-
mycoll.delete!
|
99
|
+
# cars_v1 isn't doing anything for us anymore. Ditch it.
|
100
|
+
cars_v1.delete!
|
125
101
|
|
126
102
|
```
|
127
103
|
|
128
|
-
|
129
|
-
|
130
|
-
In all the important ways, aliases can be treated like collections. Here are the exceptions.
|
104
|
+
## Documentation
|
131
105
|
|
132
|
-
|
133
|
-
|
134
|
-
# You can create an alias from the collection you're aliasing
|
135
|
-
myalias = mycoll.alias_as("myalias")
|
136
|
-
|
137
|
-
# Ask the connection object if it exists, and get it
|
138
|
-
connect.alias?("myalias") #=> true
|
139
|
-
myalias = connect.alias("myalias")
|
140
|
-
|
141
|
-
# As this object if it's an alias, as opposed to a collection
|
142
|
-
myalias.alias? #=> true
|
143
|
-
|
144
|
-
# Set the collection this alias points to, removing its link from its existing collection
|
145
|
-
myalias.collection = my_other_collection #=> sets myalias to point at my_other_collection
|
146
|
-
|
147
|
-
myalias.delete!
|
148
|
-
```
|
106
|
+
Run `bundle exec rake docs` to generate the documentation in `docs/`
|
149
107
|
|
150
108
|
## Installation
|
151
109
|
|
@@ -168,4 +126,4 @@ This repository is set up to run tests under docker.
|
|
168
126
|
|
169
127
|
## Contributing
|
170
128
|
|
171
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/mlibrary/solr_cloud-
|
129
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/mlibrary/solr_cloud-connection.
|
data/Rakefile
CHANGED
@@ -7,4 +7,19 @@ RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
8
8
|
require "standard/rake"
|
9
9
|
|
10
|
-
task default: %i[spec standard]
|
10
|
+
task default: %i[spec standard docs]
|
11
|
+
task docs: %i[yard]
|
12
|
+
|
13
|
+
require 'yard'
|
14
|
+
|
15
|
+
YARD::Rake::YardocTask.new do |t|
|
16
|
+
t.files = ["lib/**/*.rb"] # optional
|
17
|
+
t.options = [
|
18
|
+
"-mmarkdown",
|
19
|
+
"--embed-mixin", "SolrCloud::Connection::CollectionAdmin",
|
20
|
+
"--embed-mixin", "SolrCloud::Connection::ConfigsetAdmin",
|
21
|
+
"--embed-mixin", "SolrCloud::Connection::AliasAdmin",
|
22
|
+
"--hide-void-return"
|
23
|
+
]
|
24
|
+
# t.stats_options = ["--list-undoc"] # optional
|
25
|
+
end
|
data/compose.yml
CHANGED
@@ -9,13 +9,13 @@ services:
|
|
9
9
|
- gem_cache:/gems
|
10
10
|
env_file:
|
11
11
|
- .env
|
12
|
-
- env.
|
12
|
+
- env.test
|
13
13
|
command: "tail -f /dev/null"
|
14
14
|
|
15
15
|
solr:
|
16
16
|
build: spec/data/solr_docker/.
|
17
17
|
ports:
|
18
|
-
- "
|
18
|
+
- "8983:8983"
|
19
19
|
environment:
|
20
20
|
- ZK_HOST=zoo:2181
|
21
21
|
depends_on:
|
data/lib/solr_cloud/alias.rb
CHANGED
@@ -2,51 +2,58 @@
|
|
2
2
|
|
3
3
|
module SolrCloud
|
4
4
|
# An alias can mostly be just treated as a collection. It will identify itself as an alias if you
|
5
|
-
# call #alias
|
5
|
+
# call #alias?, and it can return and change the underlying collection it points to.
|
6
6
|
|
7
7
|
# An alias shouldn't be created directly. Rather, get an existing one with
|
8
8
|
# Connection#alias, or from a collection, or create one with
|
9
9
|
# Collection#alias_as
|
10
10
|
class Alias < Collection
|
11
11
|
# An alias is, shockingly, an alias. Convenience to differentiate aliases from collections.
|
12
|
-
# @see SolrCloud::Connection#
|
12
|
+
# @see SolrCloud::Connection#get_alias?
|
13
13
|
def alias?
|
14
14
|
true
|
15
15
|
end
|
16
16
|
|
17
|
-
# Delete this alias
|
18
|
-
# @return [
|
17
|
+
# Delete this alias. Will be a no-op if it doesn't exist.
|
18
|
+
# @return [Connection] the connection
|
19
19
|
def delete!
|
20
|
-
|
21
|
-
connection.
|
22
|
-
|
20
|
+
return connection unless exist?
|
21
|
+
connection.get("solr/admin/collections", action: "DELETEALIAS", name: name)
|
22
|
+
connection
|
23
|
+
end
|
24
|
+
|
25
|
+
# Does this alias still exist?
|
26
|
+
def exist?
|
27
|
+
connection.alias_names.include?(name)
|
23
28
|
end
|
24
29
|
|
25
30
|
# Get the collection this alias points to.
|
26
31
|
# In real life, Solr will allow an alias to point to more than one collection. Functionality
|
27
32
|
# for this might be added at some point
|
28
|
-
# @return [
|
33
|
+
# @return [Collection]
|
29
34
|
def collection
|
30
|
-
connection.
|
35
|
+
connection.alias_map[name].collection
|
31
36
|
end
|
32
37
|
|
33
38
|
# Redefine what collection this alias points to
|
34
39
|
# This is equivalent to dropping/re-adding the alias, or calling connection.create_alias with `force: true`
|
35
40
|
# @param coll [String, Collection] either the name of the collection, or a collection object itself
|
36
41
|
# @return [Collection] the now-current collection
|
37
|
-
def
|
42
|
+
def switch_collection_to(coll)
|
38
43
|
collect_name = case coll
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
raise NoSuchCollectionError unless connection.
|
44
|
+
when String
|
45
|
+
coll
|
46
|
+
when Collection
|
47
|
+
coll.name
|
48
|
+
else
|
49
|
+
raise "Alias#switch_collection_to only takes a name(string) or a collection, not '#{coll}'"
|
50
|
+
end
|
51
|
+
raise NoSuchCollectionError unless connection.has_collection?(collect_name)
|
47
52
|
connection.create_alias(name: name, collection_name: collect_name, force: true)
|
48
53
|
end
|
49
54
|
|
55
|
+
alias_method :collection=, :switch_collection_to
|
56
|
+
|
50
57
|
# Get basic information on the underlying collection, so inherited methods that
|
51
58
|
# use it (e.g., #healthy?) will work.
|
52
59
|
# @overload info()
|
@@ -1,12 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "solr_cloud/connection"
|
4
|
+
require "forwardable"
|
4
5
|
|
5
6
|
module SolrCloud
|
6
7
|
# A Collection provides basic services on the collection -- checking its health,
|
7
8
|
# creating or reporting aliases, and deleting itself.
|
8
9
|
class Collection
|
9
|
-
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# Forward the HTTP verbs to the underlying connection
|
14
|
+
|
15
|
+
# @!method get
|
16
|
+
# Forwarded on to the underlying SolrCloud connection
|
17
|
+
# @see SolrCloud::Connection#get
|
18
|
+
def_delegator :@connection, :get
|
19
|
+
|
20
|
+
# @!method post
|
21
|
+
# Forwarded on to the underlying SolrCloud connection
|
22
|
+
# @see SolrCloud::Connection#post
|
23
|
+
def_delegator :@connection, :post
|
24
|
+
|
25
|
+
# @!method delete
|
26
|
+
# Forwarded on to the underlying SolrCloud connection
|
27
|
+
# @see SolrCloud::Connection#delete
|
28
|
+
def_delegator :@connection, :delete
|
29
|
+
|
30
|
+
# @!method put
|
31
|
+
# Forwarded on to the underlying SolrCloud connection
|
32
|
+
# @see SolrCloud::Connection#put
|
33
|
+
def_delegator :@connection, :put
|
34
|
+
|
35
|
+
# @return [SolrCloud::Connection] the underlying SolrCloud connection
|
36
|
+
attr_reader :name
|
37
|
+
|
38
|
+
# @return The name of the get_collection
|
39
|
+
attr_reader :connection
|
10
40
|
|
11
41
|
# In general, users shouldn't use Collection.new; instead, use
|
12
42
|
# connection.create_collection(name: "coll_name", configset: "existing_configset_name")
|
@@ -14,22 +44,28 @@ module SolrCloud
|
|
14
44
|
# @param [String] name The name of the (already existing) collection
|
15
45
|
# @param [SolrCloud::Connection] connection Connection to the solr "root" (http://blah:8888/)
|
16
46
|
def initialize(name:, connection:)
|
17
|
-
# raise NoSuchCollectionError.new("No collection #{name}") unless connection.
|
47
|
+
# raise NoSuchCollectionError.new("No collection #{name}") unless connection.has_collection?(name)
|
18
48
|
@connection = connection.dup
|
19
49
|
@name = name
|
20
50
|
@sp = "/solr/#{name}"
|
21
51
|
end
|
22
52
|
|
23
|
-
# Delete this collection.
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# @return [Connection] The underlying SolrCloud::Connection
|
53
|
+
# Delete this collection. Will no-op if the collection somehow doesn't still exist (because it was
|
54
|
+
# deleted via a different method, such as through the API)
|
55
|
+
# @return [Connection] The connection object used to create this collection object
|
27
56
|
def delete!
|
28
|
-
|
29
|
-
|
57
|
+
return connection unless exist?
|
58
|
+
raise CollectionAliasedError.new("Cannot delete collection #{name}; it has alias(s) #{alias_names.join(", ")}") if aliased?
|
59
|
+
connection.get("solr/admin/collections", { action: "DELETE", name: name })
|
30
60
|
connection
|
31
61
|
end
|
32
62
|
|
63
|
+
# Does this collection still exist?
|
64
|
+
# @return [Boolean]
|
65
|
+
def exist?
|
66
|
+
connection.only_collection_names.include?(name)
|
67
|
+
end
|
68
|
+
|
33
69
|
# Check to see if the collection is alive
|
34
70
|
# @return [Boolean]
|
35
71
|
def alive?
|
@@ -38,11 +74,9 @@ module SolrCloud
|
|
38
74
|
false
|
39
75
|
end
|
40
76
|
|
41
|
-
alias_method :exist?, :alive?
|
42
|
-
|
43
77
|
# Is this an alias?
|
44
78
|
# Putting this in here breaks all sorts of isolation principles,
|
45
|
-
# but being able to call #
|
79
|
+
# but being able to call #get_alias? on anything collection-like is
|
46
80
|
# convenient
|
47
81
|
def alias?
|
48
82
|
false
|
@@ -63,7 +97,7 @@ module SolrCloud
|
|
63
97
|
# A (possibly empty) list of aliases targeting this collection
|
64
98
|
# @return [Array<SolrCloud::Alias>] list of aliases that point to this collection
|
65
99
|
def aliases
|
66
|
-
connection.
|
100
|
+
connection.alias_map.select { |_alias_name, ac| ac.collection.name == name }.values.map(&:alias)
|
67
101
|
end
|
68
102
|
|
69
103
|
# The names of the aliases that point to this collection
|
@@ -72,10 +106,26 @@ module SolrCloud
|
|
72
106
|
aliases.map(&:name)
|
73
107
|
end
|
74
108
|
|
109
|
+
# Does this collection have at least one alias?
|
110
|
+
# @return [Boolean] whether or not it has an alias
|
111
|
+
def aliased?
|
112
|
+
!aliases.empty?
|
113
|
+
end
|
114
|
+
|
115
|
+
# Do we have an alias of the given name?
|
75
116
|
# Get a specific alias by name
|
76
|
-
# @param
|
77
|
-
|
78
|
-
|
117
|
+
# @param alias_name [String] name of the alias
|
118
|
+
# @return [Boolean]
|
119
|
+
def has_alias?(alias_name)
|
120
|
+
alias_names.include?(alias_name)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Get an alias that points to this collection by name, or nil if not found
|
124
|
+
# @param alias_name [String] name of the alias
|
125
|
+
# @return [Alias, nil] The alias object, or nil if not found
|
126
|
+
def get_alias(alias_name)
|
127
|
+
return nil unless has_alias?(alias_name)
|
128
|
+
connection.get_alias(alias_name)
|
79
129
|
end
|
80
130
|
|
81
131
|
# Create an alias for this collection. Always forces an overwrite unless you tell it not to
|
@@ -86,9 +136,6 @@ module SolrCloud
|
|
86
136
|
connection.create_alias(name: alias_name, collection_name: name, force: true)
|
87
137
|
end
|
88
138
|
|
89
|
-
alias_method :alias_to, :alias_as
|
90
|
-
alias_method :create_alias, :alias_as
|
91
|
-
|
92
139
|
# Send a commit (soft if unspecified)
|
93
140
|
# @return self
|
94
141
|
def commit(hard: false)
|
@@ -106,13 +153,36 @@ module SolrCloud
|
|
106
153
|
Configset.new(name: info["configName"], connection: connection)
|
107
154
|
end
|
108
155
|
|
156
|
+
# Add a document or array of documents
|
157
|
+
# @todo Gotta check for errors and such!
|
158
|
+
# @param docs [Hash, Array<Hash>] One or more documents to add
|
159
|
+
# @return self
|
160
|
+
|
161
|
+
def add(docs)
|
162
|
+
docarray = if docs === Array
|
163
|
+
docs
|
164
|
+
else
|
165
|
+
[docs]
|
166
|
+
end
|
167
|
+
post("solr/#{name}/update/") do |r|
|
168
|
+
r.body = docarray
|
169
|
+
end
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get a count of how many documents are in the index
|
174
|
+
# @return [Fixnum] the number of documents
|
175
|
+
def count
|
176
|
+
get("solr/#{name}/select", q: "*:*").body["response"]["numFound"]
|
177
|
+
end
|
178
|
+
|
109
179
|
def inspect
|
110
180
|
anames = alias_names
|
111
181
|
astring = if anames.empty?
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
182
|
+
""
|
183
|
+
else
|
184
|
+
" (aliased by #{anames.map { |x| "'#{x}'" }.join(", ")})"
|
185
|
+
end
|
116
186
|
"<#{self.class} '#{name}'#{astring}>"
|
117
187
|
end
|
118
188
|
|
data/lib/solr_cloud/configset.rb
CHANGED
@@ -7,7 +7,12 @@ module SolrCloud
|
|
7
7
|
# throw an error if that's an illegal operation (because a collection is
|
8
8
|
# using it)
|
9
9
|
class Configset
|
10
|
-
|
10
|
+
|
11
|
+
# @return [String] the name of this configset
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# @return [Connection] the connection object used to build this configset object
|
15
|
+
attr_reader :connection
|
11
16
|
|
12
17
|
def initialize(name:, connection:)
|
13
18
|
@name = name
|
@@ -15,11 +20,23 @@ module SolrCloud
|
|
15
20
|
end
|
16
21
|
|
17
22
|
# Delete this configset.
|
18
|
-
# @see
|
23
|
+
# @see Connection#delete_configset
|
19
24
|
# @return The underlying connection
|
20
25
|
def delete!
|
21
|
-
|
22
|
-
|
26
|
+
connection.delete_configset(name)
|
27
|
+
connection
|
28
|
+
end
|
29
|
+
|
30
|
+
# Which collections use this configset?
|
31
|
+
# @return [Array<Collection>] The collections defined to use this configset
|
32
|
+
def used_by
|
33
|
+
connection.only_collections.select { |coll| coll.configset.name == name }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Are there any collections currently using this configset?
|
37
|
+
# @return [Boolean]
|
38
|
+
def in_use?
|
39
|
+
!used_by.empty?
|
23
40
|
end
|
24
41
|
|
25
42
|
def inspect
|
@@ -5,56 +5,41 @@ module SolrCloud
|
|
5
5
|
# methods having to do with aliases, to be included by the connection object.
|
6
6
|
# These are split out only to make it easier to deal with them.
|
7
7
|
module AliasAdmin
|
8
|
+
|
9
|
+
# A simple data-class to pair an alias with its collection
|
8
10
|
AliasCollectionPair = Struct.new(:alias, :collection)
|
9
11
|
|
10
|
-
# Create an alias for the given collection name
|
11
|
-
#
|
12
|
+
# Create an alias for the given collection name.
|
13
|
+
#
|
14
|
+
# In general, prefer {Collection#alias_as} instead of
|
15
|
+
# running everything through the connection object.
|
12
16
|
# @param name [String] Name of the new alias
|
13
17
|
# @param collection_name [String] name of the collection
|
14
18
|
# @param force [Boolean] whether to overwrite an existing alias
|
15
|
-
# @raise [WontOverwriteError] if the alias exists and force isn't true
|
16
19
|
# @raise [NoSuchCollectionError] if the collections isn't found
|
17
20
|
# @return [Alias] the newly-created alias
|
18
21
|
def create_alias(name:, collection_name:, force: false)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
unless legal_solr_name?(name)
|
23
|
+
raise IllegalNameError.new("'#{name}' is not a valid solr alias name. Use only ASCII letters/numbers, dash, and underscore")
|
24
|
+
end
|
25
|
+
raise NoSuchCollectionError.new("Can't find collection #{collection_name}") unless has_collection?(collection_name)
|
26
|
+
if has_alias?(name) && !force
|
27
|
+
raise WontOverwriteError.new("Alias '#{name}' already points to collection '#{self.get_alias(name).collection.name}'; won't overwrite without force: true")
|
22
28
|
end
|
23
29
|
connection.get("solr/admin/collections", action: "CREATEALIAS", name: name, collections: collection_name)
|
24
|
-
|
30
|
+
get_alias(name)
|
25
31
|
end
|
26
32
|
|
27
33
|
# Is there an alias with this name?
|
28
34
|
# @return [Boolean]
|
29
|
-
def
|
35
|
+
def has_alias?(name)
|
30
36
|
alias_names.include? name
|
31
37
|
end
|
32
38
|
|
33
|
-
# Delete the alias
|
34
|
-
# @param name [String] Name of the alias to delete
|
35
|
-
# @return [SolrCloud::Connection]
|
36
|
-
def delete_alias(name)
|
37
|
-
connection.get("solr/admin/collections", action: "DELETEALIAS", name: name)
|
38
|
-
end
|
39
|
-
|
40
|
-
# The "raw" alias map, which just maps alias names to collection names
|
41
|
-
# @return [Hash<String, String>]
|
42
|
-
def raw_alias_map
|
43
|
-
connection.get("solr/admin/collections", action: "LISTALIASES").body["aliases"]
|
44
|
-
end
|
45
|
-
|
46
|
-
# Get the aliases and create a map of the form
|
47
|
-
# @return [Hash<String,Alias>] A hash mapping alias names to alias objects
|
48
|
-
def alias_map
|
49
|
-
raw_alias_map.keys.each_with_object({}) do |alias_name, h|
|
50
|
-
h[alias_name] = SolrCloud::Alias.new(name: alias_name, connection: self)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
39
|
# List of alias objects
|
55
40
|
# @return [Array<SolrCloud::Alias>] List of aliases
|
56
41
|
def aliases
|
57
|
-
alias_map.values
|
42
|
+
alias_map.values.map(&:alias)
|
58
43
|
end
|
59
44
|
|
60
45
|
# List of alias names
|
@@ -63,23 +48,40 @@ module SolrCloud
|
|
63
48
|
alias_map.keys
|
64
49
|
end
|
65
50
|
|
66
|
-
# Get an alias object for the given name
|
51
|
+
# Get an alias object for the given name, erroring out if not found
|
52
|
+
# @param name [String] the name of the existing alias
|
53
|
+
# @return [Alias, nil] The alias if found, otherwise nil
|
54
|
+
def get_alias(name)
|
55
|
+
return nil unless has_alias?(name)
|
56
|
+
alias_map[name].alias
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get an alias object for the given name, erroring out if not found
|
67
60
|
# @param name [String] the name of the existing alias
|
68
61
|
# @raise [SolrCloud::NoSuchAliasError] if it doesn't exist
|
69
62
|
# @return [SolrCloud::Alias]
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
am[name]
|
63
|
+
def get_alias!(name)
|
64
|
+
raise NoSuchAliasError unless has_alias?(name)
|
65
|
+
get_alias(name)
|
74
66
|
end
|
75
67
|
|
76
|
-
# Get the
|
77
|
-
# @
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
68
|
+
# Get the aliases and create a map of the form AliasName -> AliasObject
|
69
|
+
# @return [Hash<String,Alias>] A hash mapping alias names to alias objects
|
70
|
+
def alias_map
|
71
|
+
raw_alias_map.keys.each_with_object({}) do |alias_name, h|
|
72
|
+
a = Alias.new(name: alias_name, connection: self)
|
73
|
+
c = Collection.new(name: raw_alias_map[alias_name], connection: self)
|
74
|
+
h[alias_name] = AliasCollectionPair.new(a, c)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# The "raw" alias map, which just maps alias names to collection names
|
79
|
+
# @return [Hash<String, String>]
|
80
|
+
def raw_alias_map
|
81
|
+
connection.get("solr/admin/collections", action: "LISTALIASES").body["aliases"]
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
|
@@ -2,79 +2,98 @@
|
|
2
2
|
|
3
3
|
module SolrCloud
|
4
4
|
class Connection
|
5
|
-
# methods having to do with
|
5
|
+
# methods having to do with collections, to be included by the connection object.
|
6
6
|
# These are split out only to make it easier to deal with them.
|
7
|
+
#
|
8
|
+
# For almost everything in here, we treat aliases like collections -- calls to #collections,
|
9
|
+
# #has_collection?, #collection, etc. will respond to, and return, and alias if there is one.
|
10
|
+
# The idea is that you shouldn't need to know if something is an alias or a collection
|
11
|
+
# until it's relevant
|
7
12
|
module CollectionAdmin
|
8
|
-
# Create a new collection
|
13
|
+
# Create and return a new collection.
|
9
14
|
# @param name [String] Name for the new collection
|
10
|
-
# @param configset [String] name of the configset to use for this collection
|
11
|
-
# @param version [String] A "version" which will be appended to the name following an underscore, if given.
|
12
|
-
# Useful for testing and cronjobs.
|
15
|
+
# @param configset [String, Configset] (name of) the configset to use for this collection
|
13
16
|
# @param shards [Integer]
|
14
17
|
# @param replication_factor [Integer]
|
15
|
-
# @
|
18
|
+
# @raise [IllegalNameError]
|
16
19
|
# @raise [NoSuchConfigSetError] if the named configset doesn't exist
|
17
20
|
# @raise [WontOverwriteError] if the collection already exists
|
18
21
|
# @return [Collection] the collection created
|
19
|
-
def create_collection(name:, configset:,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
name
|
22
|
+
def create_collection(name:, configset:, shards: 1, replication_factor: 1)
|
23
|
+
|
24
|
+
unless legal_solr_name?(name)
|
25
|
+
raise IllegalNameError.new("'#{name}' is not a valid solr name. Use only ASCII letters/numbers, dash, and underscore")
|
24
26
|
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
configset_name = case configset
|
29
|
+
when Configset
|
30
|
+
configset.name
|
31
|
+
else
|
32
|
+
configset.to_s
|
33
|
+
end
|
34
|
+
raise WontOverwriteError.new("Collection #{name} already exists") if has_collection?(name)
|
35
|
+
raise NoSuchConfigSetError.new("Configset '#{configset_name}' doesn't exist") unless has_configset?(configset_name)
|
28
36
|
|
29
37
|
args = {
|
30
38
|
:action => "CREATE",
|
31
|
-
:name =>
|
39
|
+
:name => name,
|
32
40
|
:numShards => shards,
|
33
41
|
:replicationFactor => replication_factor,
|
34
|
-
"collection.configName" =>
|
42
|
+
"collection.configName" => configset_name
|
35
43
|
}
|
36
44
|
connection.get("solr/admin/collections", args)
|
37
|
-
|
45
|
+
get_collection(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get a list of _only_ collections, as opposed to the mix of collections and aliases we
|
49
|
+
# usually do.
|
50
|
+
def only_collections
|
51
|
+
connection.get("api/collections").body["collections"].map { |c| Collection.new(name: c, connection: self) }
|
38
52
|
end
|
39
53
|
|
40
|
-
#
|
41
|
-
# @return [Array<
|
54
|
+
# The names of only connections (and not aliases). Useful as a utility.
|
55
|
+
# @return [Array<String>] the names of the connections
|
56
|
+
def only_collection_names
|
57
|
+
only_collections.map(&:name)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get a list of collections (and aliases)
|
61
|
+
# @return [Array<Collection, Alias>] possibly empty list of collection and alias objects
|
42
62
|
def collections
|
43
|
-
|
63
|
+
only_collections.union(aliases)
|
44
64
|
end
|
45
65
|
|
46
|
-
# A list of the names of existing collections
|
47
|
-
# @return [Array<String>] the collection names, or empty array if there are none
|
66
|
+
# A list of the names of existing collections and aliases
|
67
|
+
# @return [Array<String>] the collection/alias names, or empty array if there are none
|
48
68
|
def collection_names
|
49
|
-
|
69
|
+
collections.map(&:name)
|
50
70
|
end
|
51
71
|
|
52
72
|
# @param name [String] name of the collection to check on
|
53
73
|
# @return [Boolean] Whether a collection with the passed name exists
|
54
|
-
def
|
74
|
+
def has_collection?(name)
|
55
75
|
collection_names.include? name
|
56
76
|
end
|
57
77
|
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# @
|
61
|
-
|
62
|
-
|
63
|
-
if
|
64
|
-
|
78
|
+
# Get a collection object specifically for the named collection
|
79
|
+
# @param collection_name [String] name of the (already existing) collection
|
80
|
+
# @return [Collection, Alias, nil] The collection or alias if found, nil if not
|
81
|
+
def get_collection(collection_name)
|
82
|
+
return nil unless has_collection?(collection_name)
|
83
|
+
if only_collection_names.include?(collection_name)
|
84
|
+
Collection.new(name: collection_name, connection: self)
|
85
|
+
else
|
86
|
+
get_alias(collection_name)
|
65
87
|
end
|
66
|
-
self
|
67
|
-
rescue Faraday::BadRequestError
|
68
|
-
raise SolrCloud::CollectionAliasedError.new("Collection '#{name}' can't be deleted; it's in use by aliases #{collection(name).alias_names}")
|
69
88
|
end
|
70
89
|
|
71
|
-
# Get a connection object
|
90
|
+
# Get a connection/alias object, throwing an error if it's not found
|
72
91
|
# @param collection_name [String] name of the (already existing) collection
|
73
|
-
# @return [
|
74
|
-
# @raise [NoSuchCollectionError] if the collection doesn't exist
|
75
|
-
def
|
76
|
-
raise NoSuchCollectionError.new("Collection '#{collection_name}' not found") unless
|
77
|
-
|
92
|
+
# @return [Collection, Alias] The collection or alias
|
93
|
+
# @raise [NoSuchCollectionError] if the collection/alias doesn't exist
|
94
|
+
def get_collection!(collection_name)
|
95
|
+
raise NoSuchCollectionError.new("Collection '#{collection_name}' not found") unless has_collection?(collection_name)
|
96
|
+
get_collection(collection_name)
|
78
97
|
end
|
79
98
|
end
|
80
99
|
end
|
@@ -7,6 +7,34 @@ module SolrCloud
|
|
7
7
|
# methods having to do with configsets, to be included by the connection object.
|
8
8
|
# These are split out only to make it easier to deal with them.
|
9
9
|
module ConfigsetAdmin
|
10
|
+
|
11
|
+
# Given the path to a solr configuration "conf" directory (i.e., the one with
|
12
|
+
# solrconfig.xml in it), zip it up and send it to solr as a new configset.
|
13
|
+
# @param name [String] Name to give the new configset
|
14
|
+
# @param confdir [String, Pathname] Path to the solr configuration "conf" directory
|
15
|
+
# @param force [Boolean] Whether or not to overwrite an existing configset if there is one
|
16
|
+
# @raise [WontOverwriteError] if the configset already exists and "force" is false
|
17
|
+
# @return [Configset] the configset created
|
18
|
+
def create_configset(name:, confdir:, force: false)
|
19
|
+
config_set_name = name
|
20
|
+
unless legal_solr_name?(config_set_name)
|
21
|
+
raise IllegalNameError.new("'#{config_set_name}' is not a valid solr configset name. Use only ASCII letters/numbers, dash, and underscore")
|
22
|
+
end
|
23
|
+
|
24
|
+
if has_configset?(config_set_name) && !force
|
25
|
+
raise WontOverwriteError.new("Won't replace configset #{config_set_name} unless 'force: true' passed ")
|
26
|
+
end
|
27
|
+
zfile = "#{Dir.tmpdir}/solr_add_configset_#{name}_#{Time.now.hash}.zip"
|
28
|
+
z = ZipFileGenerator.new(confdir, zfile)
|
29
|
+
z.write
|
30
|
+
@connection.put("api/cluster/configs/#{config_set_name}") do |req|
|
31
|
+
req.body = File.binread(zfile)
|
32
|
+
end
|
33
|
+
# TODO: Error check in here somewhere
|
34
|
+
FileUtils.rm(zfile, force: true)
|
35
|
+
get_configset(name)
|
36
|
+
end
|
37
|
+
|
10
38
|
# Get a list of the already-defined configSets
|
11
39
|
# @return [Array<Configset>] possibly empty list of configSets
|
12
40
|
def configsets
|
@@ -18,47 +46,29 @@ module SolrCloud
|
|
18
46
|
connection.get("api/cluster/configs").body["configSets"]
|
19
47
|
end
|
20
48
|
|
21
|
-
alias_method :configurations, :configsets
|
22
|
-
|
23
49
|
# Check to see if a configset is defined
|
24
50
|
# @param name [String] Name of the configSet
|
25
51
|
# @return [Boolean] Whether a configset with that name exists
|
26
|
-
def
|
52
|
+
def has_configset?(name)
|
27
53
|
configset_names.include? name.to_s
|
28
54
|
end
|
29
55
|
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
# @param confdir [String, Pathname] Path to the solr configuration "conf" directory
|
34
|
-
# @param force [Boolean] Whether or not to overwrite an existing configset if there is one
|
35
|
-
# @param version [String] A "version" which will be appended to the name if given. Useful for
|
36
|
-
# testing and cronjobs.
|
37
|
-
# @raise [WontOverwriteError] if the configset already exists and "force" is false
|
38
|
-
# @return [String] the name of the configset created
|
39
|
-
def create_configset(name:, confdir:, force: false, version: "")
|
40
|
-
config_set_name = name + version.to_s
|
41
|
-
if configset?(config_set_name) && !force
|
42
|
-
raise WontOverwriteError.new("Won't replace configset #{config_set_name} unless 'force: true' passed ")
|
43
|
-
end
|
44
|
-
zfile = "#{Dir.tmpdir}/solr_add_configset_#{name}_#{Time.now.hash}.zip"
|
45
|
-
z = ZipFileGenerator.new(confdir, zfile)
|
46
|
-
z.write
|
47
|
-
@raw_connection.put("api/cluster/configs/#{config_set_name}") do |req|
|
48
|
-
req.body = File.binread(zfile)
|
49
|
-
end
|
50
|
-
# TODO: Error check in here somewhere
|
51
|
-
FileUtils.rm(zfile, force: true)
|
52
|
-
config_set_name
|
56
|
+
# Get an existing configset
|
57
|
+
def get_configset(name)
|
58
|
+
Configset.new(name: name, connection: self)
|
53
59
|
end
|
54
60
|
|
55
61
|
# Remove the configuration set with the given name. No-op if the
|
56
|
-
# configset doesn't actually exist.
|
57
|
-
#
|
62
|
+
# configset doesn't actually exist. Test with {#has_configset?} and
|
63
|
+
# {Configset#in_use?} manually if need be.
|
64
|
+
#
|
65
|
+
# In general, prefer using {Configset#delete!} instead of running everything
|
66
|
+
# through the connection object.
|
67
|
+
# @param [String] name The name of the configuration set
|
58
68
|
# @raise [InUseError] if the configset can't be deleted because it's in use by a live collection
|
59
69
|
# @return [Connection] self
|
60
70
|
def delete_configset(name)
|
61
|
-
if
|
71
|
+
if has_configset? name
|
62
72
|
connection.delete("api/cluster/configs/#{name}")
|
63
73
|
end
|
64
74
|
self
|
@@ -73,6 +83,8 @@ module SolrCloud
|
|
73
83
|
|
74
84
|
# Pulled from the examples for rubyzip. No idea why it's not just a part
|
75
85
|
# of the normal interface, but I guess I'm not one to judge.
|
86
|
+
#
|
87
|
+
# Code taken wholesale from https://github.com/rubyzip/rubyzip/blob/master/samples/example_recursive.rb
|
76
88
|
class ZipFileGenerator
|
77
89
|
# Initialize with the directory to zip and the location of the output archive.
|
78
90
|
def initialize(input_dir, output_file)
|
@@ -28,9 +28,36 @@ module SolrCloud
|
|
28
28
|
include CollectionAdmin
|
29
29
|
include AliasAdmin
|
30
30
|
|
31
|
-
|
31
|
+
# @return [String] String representation of the URL to solr
|
32
|
+
attr_reader :url
|
32
33
|
|
33
|
-
|
34
|
+
# @return [#info] The logger
|
35
|
+
attr_reader :logger
|
36
|
+
|
37
|
+
# @return [Faraday::Connection] the underlying Faraday connection
|
38
|
+
attr_reader :connection
|
39
|
+
|
40
|
+
# let the underlying connection handle HTTP verbs
|
41
|
+
|
42
|
+
# @!method get
|
43
|
+
# Forwarded on to the underlying Faraday connection
|
44
|
+
# @see Faraday::Connection.get
|
45
|
+
def_delegator :@connection, :get
|
46
|
+
|
47
|
+
# @!method post
|
48
|
+
# Forwarded on to the underlying Faraday connection
|
49
|
+
# @see Faraday::Connection.post
|
50
|
+
def_delegator :@connection, :post
|
51
|
+
|
52
|
+
# @!method delete
|
53
|
+
# Forwarded on to the underlying Faraday connection
|
54
|
+
# @see Faraday::Connection.delete
|
55
|
+
def_delegator :@connection, :delete
|
56
|
+
|
57
|
+
# @!method put
|
58
|
+
# Forwarded on to the underlying Faraday connection
|
59
|
+
# @see Faraday::Connection.put
|
60
|
+
def_delegator :@connection, :put
|
34
61
|
|
35
62
|
# Create a new connection to talk to solr
|
36
63
|
# @param url [String] URL to the "root" of the solr installation. For a default solr setup, this will
|
@@ -38,21 +65,21 @@ module SolrCloud
|
|
38
65
|
# @param user [String] username for basic auth, if you're using it
|
39
66
|
# @param password [String] password for basic auth, if you're using it
|
40
67
|
# @param logger [#info, :off, nil] An existing logger to pass in. The symbol ":off" means
|
41
|
-
#
|
68
|
+
# don't do logging. If left undefined, will create a standard ruby logger to $stdout
|
42
69
|
# @param adapter [Symbol] The underlying http library to use within Faraday
|
43
70
|
def initialize(url:, user: nil, password: nil, logger: nil, adapter: :httpx)
|
44
71
|
@url = url
|
45
72
|
@user = user
|
46
73
|
@password = password
|
47
74
|
@logger = case logger
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@
|
75
|
+
when :off, :none
|
76
|
+
Logger.new(File::NULL, level: Logger::FATAL)
|
77
|
+
when nil
|
78
|
+
Logger.new($stderr, level: Logger::WARN)
|
79
|
+
else
|
80
|
+
logger
|
81
|
+
end
|
82
|
+
@connection = create_raw_connection(url: url, adapter: adapter, user: user, password: password, logger: @logger)
|
56
83
|
bail_if_incompatible!
|
57
84
|
@logger.info("Connected to supported solr at #{url}")
|
58
85
|
end
|
@@ -61,7 +88,7 @@ module SolrCloud
|
|
61
88
|
# @param faraday_connection [Faraday::Connection] A pre-build faraday connection object
|
62
89
|
def self.new_from_faraday(faraday_connection)
|
63
90
|
c = allocate
|
64
|
-
c.instance_variable_set(:@
|
91
|
+
c.instance_variable_set(:@connection, faraday_connection)
|
65
92
|
c.instance_variable_set(:@url, faraday_connection.build_url.to_s)
|
66
93
|
c
|
67
94
|
end
|
@@ -69,7 +96,7 @@ module SolrCloud
|
|
69
96
|
# Create a Faraday connection object to base the API client off of
|
70
97
|
# @see #initialize
|
71
98
|
def create_raw_connection(url:, adapter: :httpx, user: nil, password: nil, logger: nil)
|
72
|
-
Faraday.new(request: {params_encoder: Faraday::FlatParamsEncoder}, url: URI(url)) do |faraday|
|
99
|
+
Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }, url: URI(url)) do |faraday|
|
73
100
|
faraday.use Faraday::Response::RaiseError
|
74
101
|
faraday.request :url_encoded
|
75
102
|
if user
|
@@ -87,7 +114,7 @@ module SolrCloud
|
|
87
114
|
|
88
115
|
# Allow accessing the raw_connection via "connection". Yes, connection.connection
|
89
116
|
# can be confusing, but it makes the *_admin stuff easier to read.
|
90
|
-
alias_method :connection, :
|
117
|
+
alias_method :connection, :connection
|
91
118
|
|
92
119
|
# Check to see if we can actually talk to the solr in question
|
93
120
|
# raise [UnsupportedSolr] if the solr version isn't at least 8
|
@@ -145,6 +172,15 @@ module SolrCloud
|
|
145
172
|
_version_part_int(2)
|
146
173
|
end
|
147
174
|
|
175
|
+
# Check to see if the given string follows solr's rules for thing
|
176
|
+
# Solr only allows ASCII letters and numbers, underscore, and dash,
|
177
|
+
# and it can't start with an underscore.
|
178
|
+
# @param str [String] string to check
|
179
|
+
# @return [Boolean]
|
180
|
+
def legal_solr_name?(str)
|
181
|
+
!(/[^a-zA-Z_\-0-9]/.match?(str) or str.start_with?("_"))
|
182
|
+
end
|
183
|
+
|
148
184
|
def inspect
|
149
185
|
"<#{self.class} #{@url}>"
|
150
186
|
end
|
@@ -156,3 +192,5 @@ module SolrCloud
|
|
156
192
|
end
|
157
193
|
end
|
158
194
|
end
|
195
|
+
|
196
|
+
|
data/lib/solr_cloud/errors.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solr_cloud-connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Dueber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
description:
|
112
126
|
email:
|
113
127
|
- bill@dueber.com
|
@@ -115,7 +129,7 @@ executables: []
|
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
118
|
-
- ".env.
|
132
|
+
- ".env.github"
|
119
133
|
- ".rspec"
|
120
134
|
- ".standard.yml"
|
121
135
|
- CHANGELOG.md
|
@@ -124,7 +138,7 @@ files:
|
|
124
138
|
- README.md
|
125
139
|
- Rakefile
|
126
140
|
- compose.yml
|
127
|
-
- env.
|
141
|
+
- env.test
|
128
142
|
- lib/solr_cloud/alias.rb
|
129
143
|
- lib/solr_cloud/collection.rb
|
130
144
|
- lib/solr_cloud/configset.rb
|