longleaf 0.1.0 → 1.1.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.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +94 -0
  3. data/.editorconfig +13 -0
  4. data/.gitignore +4 -1
  5. data/.rubocop.yml +44 -0
  6. data/.rubocop_todo.yml +834 -0
  7. data/.yardopts +1 -0
  8. data/Gemfile +16 -1
  9. data/README.md +98 -12
  10. data/Rakefile +6 -0
  11. data/bin/setup +16 -1
  12. data/docs/aboutlongleaf.md +28 -0
  13. data/docs/extra.css +32 -0
  14. data/docs/img/change-file.png +0 -0
  15. data/docs/img/ll-example-preserved.png +0 -0
  16. data/docs/index.md +19 -0
  17. data/docs/install.md +66 -0
  18. data/docs/ll-example/config-example-relative.yml +33 -0
  19. data/docs/ll-example/files-dir/LLexample-PDF.pdf +0 -0
  20. data/docs/ll-example/files-dir/LLexample-TOCHANGE.txt +15 -0
  21. data/docs/ll-example/files-dir/LLexample-tokeep.txt +10 -0
  22. data/docs/ll-example/metadata-dir/.gitkeep +0 -0
  23. data/docs/ll-example/replica-files/.gitkeep +0 -0
  24. data/docs/ll-example/replica-metadata/.gitkeep +0 -0
  25. data/docs/quickstart.md +270 -0
  26. data/docs/rdocs/Longleaf.html +135 -0
  27. data/docs/rdocs/Longleaf/AppFields.html +178 -0
  28. data/docs/rdocs/Longleaf/ApplicationConfigDeserializer.html +631 -0
  29. data/docs/rdocs/Longleaf/ApplicationConfigManager.html +610 -0
  30. data/docs/rdocs/Longleaf/ApplicationConfigValidator.html +238 -0
  31. data/docs/rdocs/Longleaf/CLI.html +909 -0
  32. data/docs/rdocs/Longleaf/ChecksumMismatchError.html +151 -0
  33. data/docs/rdocs/Longleaf/ConfigBuilder.html +1339 -0
  34. data/docs/rdocs/Longleaf/ConfigurationError.html +143 -0
  35. data/docs/rdocs/Longleaf/ConfigurationValidator.html +227 -0
  36. data/docs/rdocs/Longleaf/DeregisterCommand.html +420 -0
  37. data/docs/rdocs/Longleaf/DeregisterEvent.html +453 -0
  38. data/docs/rdocs/Longleaf/DeregistrationError.html +151 -0
  39. data/docs/rdocs/Longleaf/DigestHelper.html +419 -0
  40. data/docs/rdocs/Longleaf/EventError.html +147 -0
  41. data/docs/rdocs/Longleaf/EventNames.html +163 -0
  42. data/docs/rdocs/Longleaf/EventStatusTracking.html +656 -0
  43. data/docs/rdocs/Longleaf/FileCheckService.html +540 -0
  44. data/docs/rdocs/Longleaf/FileHelpers.html +520 -0
  45. data/docs/rdocs/Longleaf/FileRecord.html +716 -0
  46. data/docs/rdocs/Longleaf/FileSelector.html +901 -0
  47. data/docs/rdocs/Longleaf/FixityCheckService.html +691 -0
  48. data/docs/rdocs/Longleaf/IndexManager.html +1155 -0
  49. data/docs/rdocs/Longleaf/InvalidDigestAlgorithmError.html +143 -0
  50. data/docs/rdocs/Longleaf/InvalidStoragePathError.html +143 -0
  51. data/docs/rdocs/Longleaf/Logging.html +405 -0
  52. data/docs/rdocs/Longleaf/Logging/RedirectingLogger.html +1213 -0
  53. data/docs/rdocs/Longleaf/LongleafError.html +139 -0
  54. data/docs/rdocs/Longleaf/MDFields.html +193 -0
  55. data/docs/rdocs/Longleaf/MetadataBuilder.html +787 -0
  56. data/docs/rdocs/Longleaf/MetadataDeserializer.html +537 -0
  57. data/docs/rdocs/Longleaf/MetadataError.html +143 -0
  58. data/docs/rdocs/Longleaf/MetadataPersistenceManager.html +539 -0
  59. data/docs/rdocs/Longleaf/MetadataRecord.html +1411 -0
  60. data/docs/rdocs/Longleaf/MetadataSerializer.html +786 -0
  61. data/docs/rdocs/Longleaf/PreservationServiceError.html +147 -0
  62. data/docs/rdocs/Longleaf/PreserveCommand.html +410 -0
  63. data/docs/rdocs/Longleaf/PreserveEvent.html +491 -0
  64. data/docs/rdocs/Longleaf/RegisterCommand.html +428 -0
  65. data/docs/rdocs/Longleaf/RegisterEvent.html +628 -0
  66. data/docs/rdocs/Longleaf/RegisteredFileSelector.html +446 -0
  67. data/docs/rdocs/Longleaf/RegistrationError.html +151 -0
  68. data/docs/rdocs/Longleaf/ReindexCommand.html +576 -0
  69. data/docs/rdocs/Longleaf/RsyncReplicationService.html +1180 -0
  70. data/docs/rdocs/Longleaf/SequelIndexDriver.html +1978 -0
  71. data/docs/rdocs/Longleaf/ServiceCandidateFilesystemIterator.html +572 -0
  72. data/docs/rdocs/Longleaf/ServiceCandidateIndexIterator.html +532 -0
  73. data/docs/rdocs/Longleaf/ServiceCandidateLocator.html +333 -0
  74. data/docs/rdocs/Longleaf/ServiceClassCache.html +725 -0
  75. data/docs/rdocs/Longleaf/ServiceDateHelper.html +425 -0
  76. data/docs/rdocs/Longleaf/ServiceDefinition.html +683 -0
  77. data/docs/rdocs/Longleaf/ServiceDefinitionManager.html +371 -0
  78. data/docs/rdocs/Longleaf/ServiceDefinitionValidator.html +269 -0
  79. data/docs/rdocs/Longleaf/ServiceFields.html +173 -0
  80. data/docs/rdocs/Longleaf/ServiceManager.html +1229 -0
  81. data/docs/rdocs/Longleaf/ServiceMappingManager.html +410 -0
  82. data/docs/rdocs/Longleaf/ServiceMappingValidator.html +347 -0
  83. data/docs/rdocs/Longleaf/ServiceRecord.html +821 -0
  84. data/docs/rdocs/Longleaf/StorageLocation.html +985 -0
  85. data/docs/rdocs/Longleaf/StorageLocationManager.html +729 -0
  86. data/docs/rdocs/Longleaf/StorageLocationUnavailableError.html +143 -0
  87. data/docs/rdocs/Longleaf/StorageLocationValidator.html +373 -0
  88. data/docs/rdocs/Longleaf/StoragePathValidator.html +253 -0
  89. data/docs/rdocs/Longleaf/SystemConfigBuilder.html +441 -0
  90. data/docs/rdocs/Longleaf/SystemConfigFields.html +163 -0
  91. data/docs/rdocs/Longleaf/ValidateConfigCommand.html +451 -0
  92. data/docs/rdocs/Longleaf/ValidateMetadataCommand.html +408 -0
  93. data/docs/rdocs/_index.html +660 -0
  94. data/docs/rdocs/class_list.html +51 -0
  95. data/docs/rdocs/css/common.css +1 -0
  96. data/docs/rdocs/css/full_list.css +58 -0
  97. data/docs/rdocs/css/style.css +496 -0
  98. data/docs/rdocs/file.README.html +165 -0
  99. data/docs/rdocs/file_list.html +56 -0
  100. data/docs/rdocs/frames.html +17 -0
  101. data/docs/rdocs/index.html +165 -0
  102. data/docs/rdocs/js/app.js +303 -0
  103. data/docs/rdocs/js/full_list.js +216 -0
  104. data/docs/rdocs/js/jquery.js +4 -0
  105. data/docs/rdocs/method_list.html +2051 -0
  106. data/docs/rdocs/top-level-namespace.html +110 -0
  107. data/lib/longleaf/candidates/file_selector.rb +150 -0
  108. data/lib/longleaf/candidates/manifest_digest_provider.rb +17 -0
  109. data/lib/longleaf/candidates/physical_path_provider.rb +17 -0
  110. data/lib/longleaf/candidates/registered_file_selector.rb +67 -0
  111. data/lib/longleaf/candidates/service_candidate_filesystem_iterator.rb +93 -0
  112. data/lib/longleaf/candidates/service_candidate_index_iterator.rb +84 -0
  113. data/lib/longleaf/candidates/service_candidate_locator.rb +23 -0
  114. data/lib/longleaf/candidates/single_digest_provider.rb +13 -0
  115. data/lib/longleaf/cli.rb +252 -46
  116. data/lib/longleaf/commands/deregister_command.rb +51 -0
  117. data/lib/longleaf/commands/preserve_command.rb +50 -0
  118. data/lib/longleaf/commands/register_command.rb +34 -43
  119. data/lib/longleaf/commands/reindex_command.rb +92 -0
  120. data/lib/longleaf/commands/validate_config_command.rb +33 -8
  121. data/lib/longleaf/commands/validate_metadata_command.rb +51 -0
  122. data/lib/longleaf/errors.rb +26 -7
  123. data/lib/longleaf/events/deregister_event.rb +53 -0
  124. data/lib/longleaf/events/event_names.rb +9 -0
  125. data/lib/longleaf/events/event_status_tracking.rb +59 -0
  126. data/lib/longleaf/events/preserve_event.rb +82 -0
  127. data/lib/longleaf/events/register_event.rb +59 -51
  128. data/lib/longleaf/helpers/case_insensitive_hash.rb +38 -0
  129. data/lib/longleaf/helpers/digest_helper.rb +56 -0
  130. data/lib/longleaf/helpers/s3_uri_helper.rb +86 -0
  131. data/lib/longleaf/helpers/selection_options_parser.rb +215 -0
  132. data/lib/longleaf/helpers/service_date_helper.rb +78 -0
  133. data/lib/longleaf/indexing/index_manager.rb +101 -0
  134. data/lib/longleaf/indexing/sequel_index_driver.rb +306 -0
  135. data/lib/longleaf/logging.rb +5 -4
  136. data/lib/longleaf/logging/redirecting_logger.rb +30 -25
  137. data/lib/longleaf/models/app_fields.rb +7 -2
  138. data/lib/longleaf/models/file_record.rb +31 -8
  139. data/lib/longleaf/models/filesystem_metadata_location.rb +56 -0
  140. data/lib/longleaf/models/filesystem_storage_location.rb +52 -0
  141. data/lib/longleaf/models/md_fields.rb +3 -1
  142. data/lib/longleaf/models/metadata_location.rb +47 -0
  143. data/lib/longleaf/models/metadata_record.rb +43 -16
  144. data/lib/longleaf/models/s3_storage_location.rb +138 -0
  145. data/lib/longleaf/models/service_definition.rb +7 -6
  146. data/lib/longleaf/models/service_fields.rb +7 -1
  147. data/lib/longleaf/models/service_record.rb +10 -6
  148. data/lib/longleaf/models/storage_location.rb +24 -19
  149. data/lib/longleaf/models/storage_types.rb +9 -0
  150. data/lib/longleaf/models/system_config_fields.rb +9 -0
  151. data/lib/longleaf/preservation_services/file_check_service.rb +59 -0
  152. data/lib/longleaf/preservation_services/fixity_check_service.rb +124 -0
  153. data/lib/longleaf/preservation_services/rsync_replication_service.rb +198 -0
  154. data/lib/longleaf/preservation_services/s3_replication_service.rb +131 -0
  155. data/lib/longleaf/services/application_config_deserializer.rb +81 -24
  156. data/lib/longleaf/services/application_config_manager.rb +20 -6
  157. data/lib/longleaf/services/application_config_validator.rb +19 -9
  158. data/lib/longleaf/services/configuration_validator.rb +67 -4
  159. data/lib/longleaf/services/filesystem_location_validator.rb +16 -0
  160. data/lib/longleaf/services/metadata_deserializer.rb +115 -42
  161. data/lib/longleaf/services/metadata_persistence_manager.rb +47 -0
  162. data/lib/longleaf/services/metadata_serializer.rb +156 -23
  163. data/lib/longleaf/services/metadata_validator.rb +76 -0
  164. data/lib/longleaf/services/s3_location_validator.rb +19 -0
  165. data/lib/longleaf/services/service_class_cache.rb +112 -0
  166. data/lib/longleaf/services/service_definition_manager.rb +10 -7
  167. data/lib/longleaf/services/service_definition_validator.rb +25 -18
  168. data/lib/longleaf/services/service_manager.rb +86 -11
  169. data/lib/longleaf/services/service_mapping_manager.rb +13 -12
  170. data/lib/longleaf/services/service_mapping_validator.rb +36 -26
  171. data/lib/longleaf/services/storage_location_manager.rb +76 -15
  172. data/lib/longleaf/services/storage_location_validator.rb +49 -35
  173. data/lib/longleaf/specs/config_builder.rb +47 -23
  174. data/lib/longleaf/specs/config_validator_helpers.rb +16 -0
  175. data/lib/longleaf/specs/custom_matchers.rb +9 -0
  176. data/lib/longleaf/specs/file_helpers.rb +61 -0
  177. data/lib/longleaf/specs/metadata_builder.rb +98 -0
  178. data/lib/longleaf/specs/system_config_builder.rb +27 -0
  179. data/lib/longleaf/version.rb +1 -1
  180. data/longleaf.gemspec +20 -7
  181. data/mkdocs.yml +21 -0
  182. metadata +308 -24
  183. data/.travis.yml +0 -4
  184. data/lib/longleaf/commands/abstract_command.rb +0 -37
  185. data/lib/longleaf/services/storage_path_validator.rb +0 -16
@@ -0,0 +1,51 @@
1
+ require 'longleaf/services/application_config_deserializer'
2
+ require 'longleaf/events/deregister_event'
3
+ require 'longleaf/models/file_record'
4
+ require 'longleaf/events/event_names'
5
+ require 'longleaf/events/event_status_tracking'
6
+
7
+ module Longleaf
8
+ # Command for deregistering files with longleaf
9
+ class DeregisterCommand
10
+ include Longleaf::EventStatusTracking
11
+
12
+ def initialize(app_manager)
13
+ @app_manager = app_manager
14
+ end
15
+
16
+ # Execute the deregister command on the given parameters
17
+ # @param file_selector [FileSelector] selector for files to deregister
18
+ # @param force [Boolean] force flag
19
+ # @return [Integer] status code
20
+ def execute(file_selector:, force: false)
21
+ start_time = Time.now
22
+ logger.info('Performing deregister command')
23
+ begin
24
+ # Perform deregister events on each of the file paths provided
25
+ loop do
26
+ f_path = file_selector.next_path
27
+ break if f_path.nil?
28
+
29
+ storage_location = @app_manager.location_manager.get_location_by_path(f_path)
30
+
31
+ file_rec = FileRecord.new(f_path, storage_location)
32
+ unless file_rec.metadata_present?
33
+ raise DeregistrationError.new("Cannot deregister #{f_path}, file is not registered.")
34
+ end
35
+
36
+ @app_manager.md_manager.load(file_rec)
37
+
38
+ event = DeregisterEvent.new(file_rec: file_rec, force: force, app_manager: @app_manager)
39
+ track_status(event.perform)
40
+ end
41
+ rescue RegistrationError, DeregistrationError, InvalidStoragePathError, StorageLocationUnavailableError => err
42
+ record_failure(EventNames::DEREGISTER, nil, err.message)
43
+ rescue => err
44
+ record_failure(EventNames::DEREGISTER, error: err)
45
+ end
46
+
47
+ logger.info("Completed deregister command in #{Time.now - start_time}s")
48
+ return_status
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ require 'longleaf/errors'
2
+ require 'longleaf/events/event_status_tracking'
3
+ require 'longleaf/events/preserve_event'
4
+ require 'longleaf/services/application_config_deserializer'
5
+ require 'longleaf/candidates/file_selector'
6
+ require 'longleaf/candidates/service_candidate_locator'
7
+ require 'longleaf/events/event_names'
8
+ require 'longleaf/logging'
9
+
10
+ module Longleaf
11
+ # Command for preserving files
12
+ class PreserveCommand
13
+ include Longleaf::Logging
14
+ include Longleaf::EventStatusTracking
15
+
16
+ def initialize(app_manager)
17
+ @app_manager = app_manager
18
+ end
19
+
20
+ # Execute the preserve command on the given parameters
21
+ # @param file_selector [FileSelector] selector for files to preserve
22
+ # @param force [Boolean] force flag
23
+ # @return [Integer] status code
24
+ def execute(file_selector:, force: false)
25
+ start_time = Time.now
26
+ logger.info('Performing preserve command')
27
+ begin
28
+ # Perform preserve events on each of the file paths provided
29
+ candidate_locator = ServiceCandidateLocator.new(@app_manager)
30
+ candidate_it = candidate_locator.candidate_iterator(file_selector, EventNames::PRESERVE, force)
31
+ candidate_it.each do |file_rec|
32
+ begin
33
+ logger.debug("Selected candidate #{file_rec.path} for a preserve event")
34
+ preserve_event = PreserveEvent.new(file_rec: file_rec, force: force, app_manager: @app_manager)
35
+ track_status(preserve_event.perform)
36
+ rescue InvalidStoragePathError => e
37
+ record_failure(EventNames::PRESERVE, nil, e.message)
38
+ end
39
+ end
40
+ rescue LongleafError => e
41
+ record_failure(EventNames::PRESERVE, nil, e.message)
42
+ rescue => err
43
+ record_failure(EventNames::PRESERVE, error: err)
44
+ end
45
+
46
+ logger.info("Completed preserve command in #{Time.now - start_time}s")
47
+ return_status
48
+ end
49
+ end
50
+ end
@@ -1,59 +1,50 @@
1
1
  require 'longleaf/services/application_config_deserializer'
2
2
  require 'longleaf/events/register_event'
3
3
  require 'longleaf/models/file_record'
4
- require 'longleaf/commands/abstract_command'
4
+ require 'longleaf/events/event_names'
5
+ require 'longleaf/events/event_status_tracking'
5
6
 
6
- # Command for registering files with longleaf
7
7
  module Longleaf
8
- class RegisterCommand < AbstractCommand
9
-
10
- def initialize(config_path)
11
- @config_path = config_path
8
+ # Command for registering files with longleaf
9
+ class RegisterCommand
10
+ include Longleaf::EventStatusTracking
11
+
12
+ def initialize(app_manager)
13
+ @app_manager = app_manager
12
14
  end
13
15
 
14
16
  # Execute the register command on the given parameters
15
- def execute(file_paths: nil, force: false, checksums: nil)
16
- if file_paths.nil? || file_paths.empty?
17
- record_failure("Must provide one or more file paths to register")
18
- return return_status
19
- end
20
-
17
+ # @param file_selector [FileSelector] selector for files to register
18
+ # @param force [Boolean] force flag
19
+ # @param digest_provider [ManifestDigestProvider] object which provides digests for files being registered
20
+ # @param physical_provider [PhysicalPathProvider] object which provides physical paths for files being registered
21
+ # @return [Integer] status code
22
+ def execute(file_selector:, force: false, digest_provider: nil, physical_provider: nil)
23
+ start_time = Time.now
24
+ logger.info('Performing register command')
21
25
  begin
22
- # Retrieve the application configuration
23
- app_manager = Longleaf::ApplicationConfigDeserializer.deserialize(@config_path)
24
-
25
26
  # Perform register events on each of the file paths provided
26
- file_paths.each do |f_path|
27
- begin
28
- storage_location = app_manager.location_manager.get_location_by_path(f_path)
29
- if storage_location.nil?
30
- raise InvalidStoragePathError.new(
31
- "Unable to register '#{f_path}', it does not belong to any registered storage locations.")
32
- end
33
-
34
- raise InvalidStoragePathError.new("Unable to register '#{f_path}', file does not exist or is unreachable.") \
35
- unless File.file?(f_path)
36
-
37
- file_rec = FileRecord.new(f_path, storage_location)
38
-
39
- register_event = RegisterEvent.new(file_rec: file_rec, force: force, app_manager: app_manager,
40
- checksums: checksums)
41
- register_event.perform
42
-
43
- record_success(RegisterEvent::EVENT_NAME, f_path)
44
- rescue RegistrationError => err
45
- record_failure(RegisterEvent::EVENT_NAME, f_path, err.message)
46
- rescue InvalidStoragePathError => err
47
- record_failure(RegisterEvent::EVENT_NAME, f_path, err.message)
48
- end
27
+ loop do
28
+ f_path = file_selector.next_path
29
+ break if f_path.nil?
30
+
31
+ storage_location = @app_manager.location_manager.get_location_by_path(f_path)
32
+
33
+ phys_path = physical_provider.get_physical_path(f_path)
34
+ file_rec = FileRecord.new(f_path, storage_location, nil, phys_path)
35
+
36
+ register_event = RegisterEvent.new(file_rec: file_rec, force: force, app_manager: @app_manager,
37
+ digest_provider: digest_provider)
38
+ track_status(register_event.perform)
49
39
  end
50
- rescue ConfigurationError => err
51
- record_failure("Failed to load application configuration due to the following issue:\n#{err.message}")
40
+ rescue InvalidStoragePathError, StorageLocationUnavailableError => err
41
+ record_failure(EventNames::REGISTER, nil, err.message)
52
42
  rescue => err
53
- record_failure(RegisterEvent::EVENT_NAME, error: err)
43
+ record_failure(EventNames::REGISTER, error: err)
54
44
  end
55
-
45
+
46
+ logger.info("Completed register command in #{Time.now - start_time}s")
56
47
  return_status
57
48
  end
58
49
  end
59
- end
50
+ end
@@ -0,0 +1,92 @@
1
+ require 'longleaf/errors'
2
+ require 'longleaf/events/event_status_tracking'
3
+ require 'longleaf/logging'
4
+
5
+ module Longleaf
6
+ # Command for reindexing metadata
7
+ class ReindexCommand
8
+ include Longleaf::Logging
9
+ include Longleaf::EventStatusTracking
10
+
11
+ def initialize(app_manager)
12
+ @app_manager = app_manager
13
+ @index_manager = @app_manager.index_manager
14
+ end
15
+
16
+ # Execute the reindex command
17
+ # @param only_if_stale [boolean] if true, then the reindex command will perform no operation unless the index is stale.
18
+ # @return [Integer] status code
19
+ def execute(only_if_stale: false)
20
+ if !@index_manager.using_index?
21
+ record_failure("Cannot perform reindex, no index is configured")
22
+ return return_status
23
+ end
24
+
25
+ if only_if_stale && !@index_manager.index_stale?
26
+ record_success("Index is not stale, performing no action")
27
+ return return_status
28
+ end
29
+
30
+ start_time = Time.now
31
+ logger.info('Performing full reindex')
32
+ results = nil
33
+ begin
34
+ start_time = Time.now.utc
35
+
36
+ selector = all_storage_locations_selector
37
+
38
+ # Repopulate the index
39
+ results = index_all(selector)
40
+
41
+ # List and then clear all files which were not reindexed
42
+ @index_manager.each_registered_path(selector, older_than: start_time) do |file_path|
43
+ logger.warn("Clearing '#{file_path}' from index, file is no longer present.")
44
+ end
45
+ @index_manager.clear_index(start_time)
46
+
47
+ # Update the state of the index to indicate it has been reindexed
48
+ @index_manager.update_index_state
49
+ rescue => err
50
+ record_failure("Encountered error while reindexing", error: err)
51
+ end
52
+
53
+ if results['fail'] > 0
54
+ record_success("Completed reindexing, #{results['success']} successful, #{results['fail']} failed.")
55
+ else
56
+ record_success("Completed reindexing, #{results['success']} successful.")
57
+ end
58
+
59
+ logger.info("Completed full reindex in #{Time.now - start_time}s")
60
+ return_status
61
+ end
62
+
63
+ private
64
+ def index_all(selector)
65
+ count = 0
66
+ failures = 0
67
+
68
+ selector.each do |file_path|
69
+ begin
70
+ storage_loc = @app_manager.location_manager.get_location_by_path(file_path)
71
+ file_rec = FileRecord.new(file_path, storage_loc)
72
+
73
+ @app_manager.md_manager.load(file_rec)
74
+ @index_manager.index(file_rec)
75
+
76
+ record_success("Reindexed #{file_rec.path}")
77
+ count += 1
78
+ rescue LongleafError => err
79
+ record_failure("Failed to reindex #{file_rec.path}: #{err.message}")
80
+ failures += 1
81
+ end
82
+ end
83
+ {'success' => count, 'fail' => failures}
84
+ end
85
+
86
+ def all_storage_locations_selector
87
+ storage_loc_names = @app_manager.location_manager.locations.keys
88
+
89
+ RegisteredFileSelector.new(storage_locations: storage_loc_names, app_config: @app_manager)
90
+ end
91
+ end
92
+ end
@@ -1,29 +1,54 @@
1
1
  require 'longleaf/services/application_config_deserializer'
2
- require 'longleaf/commands/abstract_command'
2
+ require 'longleaf/events/event_status_tracking'
3
3
 
4
4
  module Longleaf
5
- class ValidateConfigCommand < AbstractCommand
5
+ # Command for validating an application configuration file
6
+ class ValidateConfigCommand
7
+ include Longleaf::EventStatusTracking
8
+
6
9
  def initialize(config_path)
7
10
  @config_path = config_path
8
11
  end
9
-
12
+
13
+ # Execute the validate command on the specified configuration yml file
10
14
  def execute
15
+ start_time = Time.now
16
+ logger.info('Performing validate configuration command')
11
17
  begin
12
18
  app_config_manager = Longleaf::ApplicationConfigDeserializer.deserialize(@config_path)
13
-
19
+
14
20
  location_manager = app_config_manager.location_manager
15
21
  location_manager.locations.each do |name, location|
16
22
  location.available?
17
23
  end
18
-
24
+
25
+ validate_services(app_config_manager.service_manager)
26
+
19
27
  record_success("Application configuration passed validation: #{@config_path}")
20
28
  rescue Longleaf::ConfigurationError, Longleaf::StorageLocationUnavailableError => err
21
- record_failure("Application configuration invalid due to the following issue:\n#{err.message}")
29
+ record_failure("Application configuration invalid due to the following issue(s):\n#{err.message}")
22
30
  rescue => err
23
31
  record_failure("Failed to validate application configuration", error: err)
24
32
  end
25
-
33
+
34
+ logger.info("Completed validate configuration command in #{Time.now - start_time}s")
26
35
  return_status
27
36
  end
37
+
38
+ private
39
+ # Verify that all defined services are valid and may be instantiated with the given configuration,
40
+ # according to internal expectations.
41
+ # @raise ConfigurationError if any services may not be instantiated
42
+ def validate_services(service_manager)
43
+ def_manager = service_manager.definition_manager
44
+
45
+ def_manager.services.each do |service_name, service_def|
46
+ begin
47
+ service_manager.service(service_name)
48
+ rescue => e
49
+ raise ConfigurationError.new(e.message)
50
+ end
51
+ end
52
+ end
28
53
  end
29
- end
54
+ end
@@ -0,0 +1,51 @@
1
+ require 'longleaf/services/application_config_deserializer'
2
+ require 'longleaf/models/file_record'
3
+ require 'longleaf/events/event_status_tracking'
4
+ require 'longleaf/errors'
5
+
6
+ module Longleaf
7
+ # Command for validating file metadata longleaf
8
+ class ValidateMetadataCommand
9
+ include Longleaf::EventStatusTracking
10
+
11
+ def initialize(app_manager)
12
+ @app_manager = app_manager
13
+ end
14
+
15
+ # Execute the validation command
16
+ # @param file_selector [FileSelector] selector for files to register
17
+ # @return [Integer] status code
18
+ def execute(file_selector:)
19
+ start_time = Time.now
20
+ logger.info('Performing validate metadata command')
21
+ begin
22
+ # Perform metadata validation on each of the file paths provided
23
+ loop do
24
+ f_path = file_selector.next_path
25
+ break if f_path.nil?
26
+
27
+ storage_location = @app_manager.location_manager.get_location_by_path(f_path)
28
+
29
+ begin
30
+ file_rec = FileRecord.new(f_path, storage_location)
31
+ unless file_rec.metadata_present?
32
+ raise MetadataError.new("Cannot validate metadata for #{f_path}, file is not registered.")
33
+ end
34
+
35
+ @app_manager.md_manager.load(file_rec)
36
+ record_success("Metadata for file passed validation: #{f_path}")
37
+ rescue LongleafError => err
38
+ record_failure(err.message)
39
+ end
40
+ end
41
+ rescue RegistrationError, InvalidStoragePathError, StorageLocationUnavailableError => err
42
+ record_failure(err.message)
43
+ rescue => err
44
+ record_failure("Encountered error while validating metadata files", error: err)
45
+ end
46
+
47
+ logger.info("Completed validate metadata command in #{Time.now - start_time}s")
48
+ return_status
49
+ end
50
+ end
51
+ end
@@ -1,15 +1,34 @@
1
1
  module Longleaf
2
+ # General Longleaf error
2
3
  class LongleafError < StandardError; end
3
-
4
+
5
+ # Invalid application configuration error
4
6
  class ConfigurationError < LongleafError; end
5
-
7
+
8
+ # Invalid storage path error
6
9
  class InvalidStoragePathError < LongleafError; end
7
-
10
+
11
+ # Metadata does not meet requirements error
8
12
  class MetadataError < LongleafError; end
9
-
13
+
14
+ # Unavailable storage location error
10
15
  class StorageLocationUnavailableError < LongleafError; end
11
-
16
+
17
+ # Error related to executing a preservation event
12
18
  class EventError < LongleafError; end
13
-
19
+
20
+ # Error with the registration state of a file or while attempting to perform a registration event
14
21
  class RegistrationError < EventError; end
15
- end
22
+
23
+ # Error while attempting to perform a deregistration event
24
+ class DeregistrationError < EventError; end
25
+
26
+ # Error while performing a preservation service
27
+ class PreservationServiceError < LongleafError; end
28
+
29
+ # Fixity check failure error
30
+ class ChecksumMismatchError < PreservationServiceError; end
31
+
32
+ # Error indicating an unknown or invalid digest algorithm was specified
33
+ class InvalidDigestAlgorithmError < LongleafError; end
34
+ end