1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# frozen_string_literal: true
module Gitlab
module Config
module Entry
##
# This mixin is responsible for adding DSL, which purpose is to
# simplify the process of adding child nodes.
#
# This can be used only if parent node is a configuration entry that
# holds a hash as a configuration value, for example:
#
# job:
# script: ...
# artifacts: ...
#
module Configurable
extend ActiveSupport::Concern
included do
include Validatable
validations do
validates :config, type: Hash, unless: :skip_config_hash_validation?
end
end
def compose!(deps = nil)
return unless valid?
super do
self.class.nodes.each do |key, factory|
# If we override the config type validation
# we can end with different config types like String
next unless config.is_a?(Hash)
entry_create!(key, config[key])
end
yield if block_given?
entries.each_value do |entry|
entry.compose!(deps)
end
end
end
# rubocop: disable CodeReuse/ActiveRecord
def entry_create!(key, value)
factory = self.class
.nodes[key]
.value(value)
.with(key: key, parent: self)
entries[key] = factory.create!
end
# rubocop: enable CodeReuse/ActiveRecord
def skip_config_hash_validation?
false
end
class_methods do
def nodes
return {} unless @nodes
@nodes.transform_values(&:dup)
end
def reserved_node_names
self.nodes.select do |_, node|
node.reserved?
end.keys
end
private
# rubocop: disable CodeReuse/ActiveRecord
def entry(key, entry, description: nil, default: nil, inherit: nil, reserved: nil, deprecation: nil, metadata: {})
entry_name = key.to_sym
raise ArgumentError, "Entry '#{key}' already defined in '#{name}'" if @nodes.to_h[entry_name]
factory = ::Gitlab::Config::Entry::Factory.new(entry)
.with(description: description)
.with(default: default)
.with(inherit: inherit)
.with(reserved: reserved)
.with(deprecation: deprecation)
.metadata(metadata)
@nodes ||= {}
@nodes[entry_name] = factory
helpers(entry_name)
end
# rubocop: enable CodeReuse/ActiveRecord
def dynamic_helpers(*nodes)
helpers(*nodes, dynamic: true)
end
def helpers(*nodes, dynamic: false)
nodes.each do |symbol|
if method_defined?("#{symbol}_defined?") || method_defined?("#{symbol}_entry") || method_defined?("#{symbol}_value")
raise ArgumentError, "Method '#{symbol}_defined?', '#{symbol}_entry' or '#{symbol}_value' already defined in '#{name}'"
end
unless @nodes.to_h[symbol]
raise ArgumentError, "Entry for #{symbol} is undefined" unless dynamic
end
define_method("#{symbol}_defined?") do
entries[symbol]&.specified?
end
define_method("#{symbol}_entry") do
entries[symbol]
end
define_method("#{symbol}_value") do
entry = entries[symbol]
entry.value if entry&.valid?
end
end
end
end
end
end
end
end
|