summaryrefslogtreecommitdiff
path: root/lib/gitlab/config/loader/multi_doc_yaml.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/config/loader/multi_doc_yaml.rb')
-rw-r--r--lib/gitlab/config/loader/multi_doc_yaml.rb65
1 files changed, 27 insertions, 38 deletions
diff --git a/lib/gitlab/config/loader/multi_doc_yaml.rb b/lib/gitlab/config/loader/multi_doc_yaml.rb
index 346adc79896..34080d26b7c 100644
--- a/lib/gitlab/config/loader/multi_doc_yaml.rb
+++ b/lib/gitlab/config/loader/multi_doc_yaml.rb
@@ -4,59 +4,48 @@ module Gitlab
module Config
module Loader
class MultiDocYaml
- TooManyDocumentsError = Class.new(Loader::FormatError)
- DataTooLargeError = Class.new(Loader::FormatError)
- NotHashError = Class.new(Loader::FormatError)
+ include Gitlab::Utils::StrongMemoize
- MULTI_DOC_DIVIDER = /^---$/.freeze
+ MULTI_DOC_DIVIDER = /^---\s+/.freeze
def initialize(config, max_documents:, additional_permitted_classes: [])
+ @config = config
@max_documents = max_documents
- @safe_config = load_config(config, additional_permitted_classes)
+ @additional_permitted_classes = 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)
+ def valid?
+ documents.all?(&:valid?)
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
+ def load_raw!
+ documents.map(&:load_raw!)
end
- def all_hashes?
- safe_config.all?(Hash)
+ def load!
+ documents.map(&:load!)
end
- def too_many_documents?
- safe_config.count > max_documents
- end
+ private
+
+ attr_reader :config, :max_documents, :additional_permitted_classes
+
+ # Valid YAML files can start with either a leading delimiter or no delimiter.
+ # To avoid counting a leading delimiter towards the document limit,
+ # this method splits the file by one more than the maximum number of permitted documents.
+ # It then discards the first document if it is blank.
+ def documents
+ docs = config
+ .split(MULTI_DOC_DIVIDER, max_documents_including_leading_delimiter)
+ .map { |d| Yaml.new(d, additional_permitted_classes: additional_permitted_classes) }
- def too_big?
- !deep_sizes.all?(&:valid?)
+ docs.shift if docs.first.blank?
+ docs
end
+ strong_memoize_attr :documents
- 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
+ def max_documents_including_leading_delimiter
+ max_documents + 1
end
end
end