solr_makr 0.0.4 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.agignore +1 -0
  3. data/README.md +24 -2
  4. data/Rakefile +1 -1
  5. data/bin/console +13 -0
  6. data/exe/solr-makr +9 -0
  7. data/lib/solr_makr.rb +76 -23
  8. data/lib/solr_makr/application.rb +24 -44
  9. data/lib/solr_makr/application_action.rb +182 -0
  10. data/lib/solr_makr/application_dispatch.rb +85 -0
  11. data/lib/solr_makr/collection.rb +17 -0
  12. data/lib/solr_makr/commands.rb +14 -0
  13. data/lib/solr_makr/commands/abstract_command.rb +60 -0
  14. data/lib/solr_makr/commands/buffer.rb +98 -0
  15. data/lib/solr_makr/commands/create_collection.rb +57 -0
  16. data/lib/solr_makr/commands/delete_collection.rb +13 -0
  17. data/lib/solr_makr/commands/execute.rb +67 -0
  18. data/lib/solr_makr/commands/fetch_collection_list.rb +17 -0
  19. data/lib/solr_makr/commands/push_config.rb +36 -0
  20. data/lib/solr_makr/commands/reload_collection.rb +13 -0
  21. data/lib/solr_makr/commands/set_up_local_configuration.rb +27 -0
  22. data/lib/solr_makr/commands/write_yaml.rb +28 -19
  23. data/lib/solr_makr/configsets.rb +15 -0
  24. data/lib/solr_makr/configsets/directory.rb +32 -0
  25. data/lib/solr_makr/configsets/get_nodes.rb +33 -0
  26. data/lib/solr_makr/configsets/install_default.rb +17 -0
  27. data/lib/solr_makr/configsets/lookup_dependent_collections.rb +20 -0
  28. data/lib/solr_makr/configsets/node.rb +56 -0
  29. data/lib/solr_makr/configsets/push_to_zookeeper.rb +19 -0
  30. data/lib/solr_makr/configsets/remote.rb +30 -0
  31. data/lib/solr_makr/configuration.rb +45 -0
  32. data/lib/solr_makr/errors/halt_execution.rb +4 -0
  33. data/lib/solr_makr/files/default-configset/README.md +1 -0
  34. data/lib/solr_makr/files/default-configset/conf/_rest_managed.json +1 -0
  35. data/lib/solr_makr/files/default-configset/conf/admin-extra.html +31 -0
  36. data/lib/solr_makr/files/default-configset/conf/currency.xml +67 -0
  37. data/lib/solr_makr/files/default-configset/conf/elevate.xml +1672 -0
  38. data/lib/solr_makr/files/default-configset/conf/lang/stopwords_en.txt +54 -0
  39. data/lib/solr_makr/files/default-configset/conf/mapping-ISOLatin1Accent.txt +2586 -0
  40. data/lib/solr_makr/files/default-configset/conf/protwords.txt +1613 -0
  41. data/lib/{files → solr_makr/files/default-configset/conf}/schema.xml +132 -40
  42. data/lib/solr_makr/files/default-configset/conf/scripts.conf +1623 -0
  43. data/lib/{files → solr_makr/files/default-configset/conf}/solrconfig.xml +294 -328
  44. data/lib/solr_makr/files/default-configset/conf/spellings.txt +1534 -0
  45. data/lib/solr_makr/files/default-configset/conf/synonyms.txt +1646 -0
  46. data/lib/solr_makr/local_configuration.rb +42 -0
  47. data/lib/solr_makr/local_configuration/cache.rb +21 -0
  48. data/lib/solr_makr/local_configuration/config_directory.rb +17 -0
  49. data/lib/solr_makr/local_configuration/directory.rb +17 -0
  50. data/lib/solr_makr/local_configuration/helper.rb +19 -0
  51. data/lib/solr_makr/local_configuration/save_settings.rb +9 -0
  52. data/lib/solr_makr/local_configuration/settings.rb +50 -0
  53. data/lib/solr_makr/meta/abstract_runner.rb +36 -0
  54. data/lib/solr_makr/meta/application_logger.rb +13 -0
  55. data/lib/solr_makr/meta/buffer_interaction.rb +41 -0
  56. data/lib/solr_makr/meta/disable_paging.rb +6 -0
  57. data/lib/solr_makr/meta/has_solr_attributes.rb +13 -0
  58. data/lib/solr_makr/meta/indifferent_options.rb +13 -0
  59. data/lib/solr_makr/meta/option_definition.rb +105 -0
  60. data/lib/solr_makr/meta/option_mapping.rb +38 -0
  61. data/lib/solr_makr/meta/pathlike.rb +9 -0
  62. data/lib/solr_makr/meta/set_global_options.rb +23 -0
  63. data/lib/solr_makr/meta/utility.rb +99 -0
  64. data/lib/solr_makr/meta/wraps_directory.rb +27 -0
  65. data/lib/solr_makr/meta/wraps_path.rb +18 -0
  66. data/lib/solr_makr/solr_api.rb +12 -0
  67. data/lib/solr_makr/solr_api/client.rb +32 -0
  68. data/lib/solr_makr/solr_api/client_macros.rb +61 -0
  69. data/lib/solr_makr/solr_api/cluster_response.rb +21 -0
  70. data/lib/solr_makr/solr_api/endpoint.rb +15 -0
  71. data/lib/solr_makr/solr_api/list_response.rb +19 -0
  72. data/lib/solr_makr/solr_api/request_params.rb +50 -0
  73. data/lib/solr_makr/solr_api/response.rb +69 -0
  74. data/lib/solr_makr/sunspot_configuration.rb +49 -0
  75. data/lib/solr_makr/version.rb +1 -1
  76. data/solr_makr.gemspec +17 -9
  77. metadata +171 -31
  78. data/bin/solr-makr +0 -7
  79. data/lib/solr_makr/commands/create_core.rb +0 -21
  80. data/lib/solr_makr/commands/destroy_core.rb +0 -17
  81. data/lib/solr_makr/commands/list_cores.rb +0 -17
  82. data/lib/solr_makr/commands/shared.rb +0 -84
  83. data/lib/solr_makr/core.rb +0 -94
  84. data/lib/solr_makr/core_status.rb +0 -56
  85. data/lib/solr_makr/solr_configuration.rb +0 -84
  86. data/lib/solr_makr/solr_request.rb +0 -23
@@ -0,0 +1,85 @@
1
+ module SolrMakr
2
+ class ApplicationDispatch
3
+ include SolrMakr::AbstractRunner
4
+
5
+ action! :setup, interaction: :SetUpLocalConfiguration do |action|
6
+ action.description 'Setup the config directory for solr-makr.'
7
+ end
8
+
9
+ action! :create_collection, requires_name: true, specifies_configset: true do |action|
10
+ action.description 'Create a new collection'
11
+
12
+ action.option :config_name, type: String, short_name: 'C' do |o|
13
+ o.description = "Key of the configset in zookeeper"
14
+ o.default_value = :name
15
+ o.value_name = 'NAME'
16
+ end
17
+
18
+ action.option :number_of_shards, type: Integer do |o|
19
+ o.description = 'Number of shards for this collection'
20
+ o.value_name = 'SHARDS'
21
+ o.default_value = 1
22
+ end
23
+
24
+ action.option :replication_factor, type: Integer do |o|
25
+ o.description = 'How many replicas to create'
26
+ o.value_name = 'FACTOR'
27
+ o.default_value = 1
28
+ end
29
+
30
+ action.option :max_shards_per_node, type: Integer do |o|
31
+ o.description = 'How many shards per solr node'
32
+ o.value_name = 'MAX'
33
+ o.default_value = 1
34
+ end
35
+ end
36
+
37
+ action! :delete_collection, requires_name: true do |action|
38
+ action.description 'Delete a collection'
39
+ end
40
+
41
+ action! :reload_collection, requires_name: true do |action|
42
+ action.description 'Reload a collection'
43
+ end
44
+
45
+ action! :fetch_collection_list, command_name: 'list' do |action|
46
+ action.description 'List all collections'
47
+ end
48
+
49
+ action! :push_config, requires_name: true, specifies_configset: true do |action|
50
+ action.description 'Push a new configuration to zookeeper'
51
+
52
+ action.option :reload do |o|
53
+ o.description = 'Whether to reload all configurations that use this when updating'
54
+ o.default_value = false
55
+ end
56
+ end
57
+
58
+ action! :write_yaml, command_name: 'yaml', requires_name: true do |action|
59
+ action.description 'Generate a YAML configuration suitable for use with sunspot'
60
+
61
+ action.option :config_name, type: String, short_name: 'C' do |o|
62
+ o.description = "Key of the configset in zookeeper"
63
+ o.default_value = :name
64
+ o.value_name = 'NAME'
65
+ end
66
+
67
+ action.option :environment, type: String, short_name: 'e' do |o|
68
+ o.description = 'Rails environment'
69
+ o.default_value = proc { SunspotConfiguration.default_environment }
70
+ o.value_name = 'ENV'
71
+ end
72
+
73
+ action.option :output, type: String, short_name: 'o' do |o|
74
+ o.description = 'Write configuration to file'
75
+ o.value_name = 'FILE'
76
+ end
77
+
78
+ action.option :log_level, type: String do |o|
79
+ o.description = "Sunspot's log level"
80
+ o.default_value = proc { SunspotConfiguration.default_log_level }
81
+ o.value_name = 'LEVEL'
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ module SolrMakr
2
+ class Collection
3
+ include Virtus.model strict: true
4
+
5
+ attribute :name, String
6
+ attribute :managed, Boolean, lazy: true, default: :detect_if_managed?
7
+
8
+ def detect_if_managed?
9
+ false
10
+ end
11
+
12
+ # @return [(String, Boolean)]
13
+ def to_table_row
14
+ [name, managed?]
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,19 @@
1
1
  module SolrMakr
2
2
  # @api private
3
3
  module Commands
4
+ extend ActiveSupport::Autoload
5
+
6
+ eager_autoload do
7
+ autoload :AbstractCommand
8
+ autoload :Buffer
9
+ autoload :CreateCollection
10
+ autoload :DeleteCollection
11
+ autoload :Execute
12
+ autoload :FetchCollectionList
13
+ autoload :PushConfig
14
+ autoload :ReloadCollection
15
+ autoload :SetUpLocalConfiguration
16
+ autoload :WriteYaml
17
+ end
4
18
  end
5
19
  end
@@ -0,0 +1,60 @@
1
+ module SolrMakr
2
+ module Commands
3
+ module AbstractCommand
4
+ extend ActiveSupport::Concern
5
+ include SolrMakr::BufferInteraction
6
+ include SolrMakr::Utility
7
+
8
+ included do
9
+ set_callback :validate, :after, :invalid_buffer_if_errors!
10
+
11
+ object :buffer, class: 'SolrMakr::Commands::Buffer', default: proc { SolrMakr::Commands::Buffer.new }
12
+
13
+ delegate :directory, :settings, :cache, to: :local_configuration, prefix: true
14
+ end
15
+
16
+ # @return [SolrMakr::Configsets::Directory]
17
+ def fetch_configset(name)
18
+ SolrMakr.local_configuration.configsets[name]
19
+ end
20
+
21
+ def local_configuration
22
+ SolrMakr::LocalConfiguration
23
+ end
24
+
25
+ attr_lazy_reader :solr_client do
26
+ SolrMakr::SolrAPI::Client.new
27
+ end
28
+
29
+ # @param [SolrMakr::SolrAPI::Response] response
30
+ def expect_success!(response, success_message: nil, error_message: nil, halt_on_error: true, &on_failure)
31
+ if response.success?
32
+ if success_message.present?
33
+ buffer.ok success_message
34
+ end
35
+ else
36
+ errors.add '[solr]', response.failure
37
+
38
+ buffer.exit_status = 1
39
+
40
+ if error_message.present?
41
+ buffer.logger.error error_message
42
+ elsif block_given?
43
+ yield response
44
+ end
45
+
46
+ throw :interrupt, response if halt_on_error
47
+ end
48
+
49
+ return response
50
+ end
51
+
52
+ private
53
+ def invalid_buffer_if_errors!
54
+ if buffer.success? && errors.any?
55
+ buffer.exit_status = 1
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,98 @@
1
+ module SolrMakr
2
+ module Commands
3
+ # Captures output for buffers
4
+ #
5
+ # @api private
6
+ class Buffer
7
+ def initialize(context: nil, **options)
8
+ @context = context
9
+
10
+ @output = StringIO.new
11
+
12
+ @logger = Logger.new @output
13
+
14
+ @logger.formatter = default_formatter
15
+
16
+ @exit_status = 0
17
+ end
18
+
19
+ attr_reader :context
20
+ attr_reader :output
21
+ attr_reader :logger
22
+ attr_reader :exit_status
23
+
24
+ delegate :log, :debug, :error, :warn, :fatal, :info, to: :logger
25
+ delegate :write, to: :output
26
+
27
+ def import(buffer)
28
+ write buffer.to_s
29
+
30
+ unless buffer.success?
31
+ self.exit_status = buffer.exit_status
32
+ end
33
+
34
+ return self
35
+ end
36
+
37
+ def error!(status: 1, message: nil)
38
+ if message.present?
39
+ logger.error message
40
+ end
41
+
42
+ if exit_status != status
43
+ self.exit_status = status
44
+ end
45
+ end
46
+
47
+ def ok(message = 'OK')
48
+ print "\u2713 #{message}"
49
+ end
50
+
51
+ alias_method :success, :ok
52
+
53
+ def failure(message)
54
+ print "\u2717 #{message}"
55
+ end
56
+
57
+ def issue(message)
58
+ print "\u2757 #{message}"
59
+ end
60
+
61
+ def separator!
62
+ write "\n\n"
63
+ end
64
+
65
+ def print(*lines)
66
+ lines.each { |line| write line }
67
+
68
+ write "\n"
69
+ end
70
+
71
+ def exit_status=(new_retval)
72
+ @exit_status = Integer(new_retval) rescue -1
73
+ end
74
+
75
+ def success?
76
+ @exit_status.zero?
77
+ end
78
+
79
+ def to_s
80
+ output.string
81
+ end
82
+
83
+ # @return [Proc]
84
+ def default_formatter
85
+ proc do |severity, time, progname, message|
86
+ context_name = progname.presence || context.presence || SolrMakr::BIN_NAME
87
+
88
+ [].tap do |parts|
89
+ parts << severity
90
+ parts << "[#{time.iso8601}]" unless STDOUT.tty?
91
+ parts << "[#{context_name}]" if context_name.present?
92
+ parts << message
93
+ end.join(' ') + "\n"
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,57 @@
1
+ module SolrMakr
2
+ module Commands
3
+ class CreateCollection < ActiveInteraction::Base
4
+ include AbstractCommand
5
+
6
+ string :name, description: 'name of the collection'
7
+ string :config_name, description: 'the name to use in zookeeper', default: nil
8
+ string :configset, description: 'local configset to base on', default: proc { SolrMakr.configuration.default_configset }
9
+
10
+ integer :number_of_shards, default: 1
11
+ integer :replication_factor, default: 1
12
+ integer :max_shards_per_node, default: 1
13
+
14
+ def execute
15
+ configset_directory = fetch_configset(configset)
16
+
17
+ unless remote_configset_exists?
18
+ buffer.print ". Zookeeper configuration `#{config_name}` does not exist... creating"
19
+
20
+ compose_buffer SolrMakr::Configsets::PushToZookeeper, name: remote_configset_name, directory: configset_directory
21
+ end
22
+
23
+ expect_success! solr_client.create(params_for_create)
24
+
25
+ buffer.ok "Created collection: #{name}"
26
+ end
27
+
28
+ # @api private
29
+ # @return [Hash]
30
+ def params_for_create
31
+ {
32
+ name: name,
33
+ config_name: remote_configset_name,
34
+ number_of_shards: number_of_shards,
35
+ replication_factor: replication_factor,
36
+ max_shards_per_node: max_shards_per_node
37
+ }
38
+ end
39
+
40
+ # @!attribute [r] remote_configset_name
41
+ # @return [String]
42
+ attr_lazy_reader :remote_configset_name do
43
+ config_name.presence || name
44
+ end
45
+
46
+ attr_lazy_reader :remote_configset do
47
+ SolrMakr::Configsets::Remote.new name: remote_configset_name
48
+ end
49
+
50
+ attr_lazy_reader :remote_configset_exists do
51
+ remote_configset.exists?
52
+ end
53
+
54
+ alias_method :remote_configset_exists?, :remote_configset_exists
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,13 @@
1
+ module SolrMakr
2
+ module Commands
3
+ class DeleteCollection < ActiveInteraction::Base
4
+ include AbstractCommand
5
+
6
+ string :name
7
+
8
+ def execute
9
+ expect_success! solr_client.delete(name: name), success_message: "Deleted collection: `#{name}`"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,67 @@
1
+ module SolrMakr
2
+ module Commands
3
+ # Execute an application command based on its configuration.
4
+ class Execute < ActiveInteraction::Base
5
+ include SolrMakr::BufferInteraction
6
+ include SolrMakr::Utility
7
+
8
+ object :action, class: 'SolrMakr::ApplicationAction'
9
+
10
+ array :command_args, default: [] do
11
+ string
12
+ end
13
+
14
+ object :command_options, class: 'Commander::Command::Options', default: proc { Commander::Command::Options.new }
15
+
16
+ # @return [SolrMakr::Commands::Buffer]
17
+ def execute
18
+ set_global_options!
19
+
20
+ set_default_options!
21
+
22
+ validate_options!
23
+
24
+ unless errors.any?
25
+ compose_buffer action.interaction_klass, **raw_options
26
+ end
27
+
28
+ return buffer
29
+ end
30
+
31
+ attr_lazy_reader :verbose do
32
+ command_options.verbose.present?
33
+ end
34
+
35
+ alias_method :verbose?, :verbose
36
+
37
+ # Set global options for the environment.
38
+ #
39
+ # @return [void]
40
+ def set_global_options!
41
+ compose SolrMakr::SetGlobalOptions, raw_options
42
+ end
43
+
44
+ # Inherit default options for the action if any.
45
+ #
46
+ # @return [void]
47
+ def set_default_options!
48
+ action.set_default_options!(command_args, command_options)
49
+ end
50
+
51
+ # @return [void]
52
+ def validate_options!
53
+ action.option_mapping.each do |option|
54
+ unless option.valid_in?(command_options)
55
+ errors.add :base, "Missing required argument: #{option.long_name}"
56
+ end
57
+ end
58
+ end
59
+
60
+ # @api private
61
+ # @return [Hash]
62
+ def raw_options
63
+ command_options.__hash__.symbolize_keys
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,17 @@
1
+ module SolrMakr
2
+ module Commands
3
+ class FetchCollectionList < ActiveInteraction::Base
4
+ include AbstractCommand
5
+
6
+ def execute
7
+ response = solr_client.list
8
+
9
+ collections = response.array(:collections).map do |name|
10
+ SolrMakr::Collection.new name: name
11
+ end
12
+
13
+ buffer.print default_table(collection: collections, headings: %w[Collection Managed?], if_blank: 'No collections.')
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ module SolrMakr
2
+ module Commands
3
+ class PushConfig < ActiveInteraction::Base
4
+ include AbstractCommand
5
+
6
+ string :name, description: 'the name of the config in zookeeper'
7
+ string :configset, description: 'the name of the local configset'
8
+
9
+ boolean :reload, description: 'Whether to reload every collection that depends', default: true
10
+
11
+ attr_reader :remote
12
+
13
+ def execute
14
+ configset_directory = fetch_configset(configset)
15
+
16
+ compose_buffer SolrMakr::Configsets::PushToZookeeper, name: name, directory: configset_directory
17
+
18
+ buffer.ok "Pushed configuration named `#{name}` to zookeeper."
19
+
20
+ @remote = SolrMakr::Configsets::Remote.new name: name
21
+
22
+ if reload
23
+ remote.dependent_collections.each do |collection|
24
+ response = solr_client.reload name: collection
25
+
26
+ if response.success?
27
+ buffer.ok "Reloaded collection: `#{collection}`"
28
+ else
29
+ buffer.failure "Couldn't reload collection: `#{collection}`: #{response.failure}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end