65 lines
1.9 KiB
Ruby
65 lines
1.9 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Gitlab
|
||
|
module Config
|
||
|
module Loader
|
||
|
class MultiDocYaml
|
||
|
TooManyDocumentsError = Class.new(Loader::FormatError)
|
||
|
DataTooLargeError = Class.new(Loader::FormatError)
|
||
|
NotHashError = Class.new(Loader::FormatError)
|
||
|
|
||
|
MULTI_DOC_DIVIDER = /^---$/.freeze
|
||
|
|
||
|
def initialize(config, max_documents:, additional_permitted_classes: [])
|
||
|
@max_documents = max_documents
|
||
|
@safe_config = load_config(config, additional_permitted_classes)
|
||
|
end
|
||
|
|
||
|
def load!
|
||
|
raise TooManyDocumentsError, 'The parsed YAML has too many documents' if too_many_documents?
|
||
|
raise DataTooLargeError, 'The parsed YAML is too big' if too_big?
|
||
|
raise NotHashError, 'Invalid configuration format' unless all_hashes?
|
||
|
|
||
|
safe_config.map(&:deep_symbolize_keys)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
attr_reader :safe_config, :max_documents
|
||
|
|
||
|
def load_config(config, additional_permitted_classes)
|
||
|
config.split(MULTI_DOC_DIVIDER).filter_map do |document|
|
||
|
YAML.safe_load(document,
|
||
|
permitted_classes: [Symbol, *additional_permitted_classes],
|
||
|
permitted_symbols: [],
|
||
|
aliases: true
|
||
|
)
|
||
|
end
|
||
|
rescue Psych::Exception => e
|
||
|
raise Loader::FormatError, e.message
|
||
|
end
|
||
|
|
||
|
def all_hashes?
|
||
|
safe_config.all?(Hash)
|
||
|
end
|
||
|
|
||
|
def too_many_documents?
|
||
|
safe_config.count > max_documents
|
||
|
end
|
||
|
|
||
|
def too_big?
|
||
|
!deep_sizes.all?(&:valid?)
|
||
|
end
|
||
|
|
||
|
def deep_sizes
|
||
|
safe_config.map do |config|
|
||
|
Gitlab::Utils::DeepSize.new(config,
|
||
|
max_size: Gitlab::CurrentSettings.current_application_settings.max_yaml_size_bytes,
|
||
|
max_depth: Gitlab::CurrentSettings.current_application_settings.max_yaml_depth)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|