bbk-utils 1.1.6.376358 → 1.1.6.409139
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.
- checksums.yaml +4 -4
- data/README.md +78 -3
- data/lib/bbk/utils/config.rb +371 -5
- data/lib/bbk/utils/env_helper.rb +137 -4
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40fafd60b7a8a9c337c28b002831b29f57da91633306857f5a9fff5c73c3d4a1
|
|
4
|
+
data.tar.gz: 5a67d746083afb0e0ed01b606ae8c1fe1f2ccb2f5d8184f5a584aaef82ea834f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c4a4c724e029d7492dd2dcaeda86dc667deef657fb668ae518cd54d9fa1d8d1e1ae6f5bc896cb27cc20e063346fc12280a3ccb4aed6330e7ee67cd804b808b5c
|
|
7
|
+
data.tar.gz: 5f2b6c7980b27a9e1aa6e05e47adf0b1af6b6ddb9f62f06d25c4e2153ce05791527af20438e07c09647b2d9bad9ae6ee1fce8ff7b77cf7889e835a5fc856ec24
|
data/README.md
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
|
-
Common classes and helpers for BBK library stack.
|
|
16
|
+
Набор общих классов и вспомогательных модулей для стека библиотек BBK. / Common classes and helpers for BBK library stack.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Установка / Installation
|
|
17
20
|
|
|
18
21
|
## Installation
|
|
19
22
|
|
|
@@ -37,9 +40,81 @@ Or adding to your project:
|
|
|
37
40
|
gem "bbk-utils", "~> 1.0.0"
|
|
38
41
|
```
|
|
39
42
|
|
|
40
|
-
## Features
|
|
43
|
+
## Возможности / Features
|
|
44
|
+
|
|
45
|
+
### EnvHelper — сборка URL подключений / URL Building Helper
|
|
46
|
+
|
|
47
|
+
Нормализует переменные окружения: собирает URL из отдельных компонентов и раскладывает обратно. Три уровня приоритетов: ENV-переменная > компонент из базового URL > значение по умолчанию.
|
|
48
|
+
|
|
49
|
+
Normalizes environment variables: builds URLs from individual components and decomposes back. Three-level priorities: env var > component from base URL > default.
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
# Базы данных / Databases — prepare_database_envs
|
|
53
|
+
env = { 'DATABASE_URL' => 'postgres://user:pass@host:5432/db', 'DATABASE_HOST' => 'newhost' }
|
|
54
|
+
BBK::Utils::EnvHelper.prepare_database_envs(env)
|
|
55
|
+
# => env['DATABASE_URL'] = 'postgres://user:pass@newhost:5432/db'
|
|
56
|
+
|
|
57
|
+
# Очереди сообщений / Message Queues — prepare_mq_envs
|
|
58
|
+
env = { 'MQ_HOST' => 'mq1;mq2;mq3', 'MQ_USER' => 'guest' }
|
|
59
|
+
BBK::Utils::EnvHelper.prepare_mq_envs(env)
|
|
60
|
+
# => env['MQ_URL'] = 'amqps://guest@mq1:5671/;amqps://guest@mq2:5671/;amqps://guest@mq3:5671/'
|
|
61
|
+
|
|
62
|
+
# Jaeger Tracing — prepare_jaeger_envs
|
|
63
|
+
BBK::Utils::EnvHelper.prepare_jaeger_envs(ENV)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Config — декларативная работа с переменными окружения / Declarative ENV Management
|
|
67
|
+
|
|
68
|
+
Декларативное описание, валидация и чтение переменных окружения с поддержкой типов, значений по умолчанию, подконфигураций и маскирования секретов.
|
|
69
|
+
|
|
70
|
+
Declarative description, validation, and reading of environment variables with type casting, defaults, subconfigurations, and secret masking.
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
require 'bbk/utils'
|
|
74
|
+
|
|
75
|
+
BBK::Utils::Config.instance.tap do |cfg|
|
|
76
|
+
cfg.require('API_KEY', desc: 'API key', secure: true)
|
|
77
|
+
cfg.optional('LOG_LEVEL', default: 'info', desc: 'Logging level')
|
|
78
|
+
cfg.optional('TIMEOUT', default: 30, type: method(:Integer), desc: 'Timeout in seconds')
|
|
79
|
+
cfg.optional('DEBUG_MODE', default: false, bool: true, desc: 'Enable debug mode')
|
|
80
|
+
cfg.optional('CLEAN_INTERVAL', default: '3month', type: method(:duration_parser))
|
|
81
|
+
|
|
82
|
+
cfg.map('SSL_CERT', '/etc/ssl/cert.pem', desc: 'SSL certificate')
|
|
83
|
+
|
|
84
|
+
cfg.subconfig(prefix: 'REDIS') do |redis|
|
|
85
|
+
redis.optional('URL', default: 'redis://redis:6379/0', desc: 'Redis URL')
|
|
86
|
+
redis.optional('POOL_SIZE', default: 5, type: method(:Integer), desc: 'Pool size')
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Важно: сначала EnvHelper, потом Config
|
|
91
|
+
# Important: EnvHelper first, then Config
|
|
92
|
+
BBK::Utils::EnvHelper.prepare_database_envs(ENV)
|
|
93
|
+
BBK::Utils::EnvHelper.prepare_mq_envs(ENV)
|
|
94
|
+
BBK::Utils::Config.run!(ENV)
|
|
95
|
+
|
|
96
|
+
# Доступ к значениям / Accessing values
|
|
97
|
+
BBK::Utils::Config['LOG_LEVEL'] # => "info"
|
|
98
|
+
BBK::Utils::Config['REDIS_URL'] # => "redis://redis:6379/0"
|
|
99
|
+
puts BBK::Utils::Config.to_s
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Префиксы и альтернативные имена / Prefixes & Alternative Names
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
config = BBK::Utils::Config.instance(prefix: 'MYAPP')
|
|
106
|
+
config.optional('PORT', default: 3000) # читает MYAPP_PORT
|
|
107
|
+
|
|
108
|
+
cfg.require('DB_URL', key: 'DATABASE_URL', desc: 'Database URL') # ищет DATABASE_URL, доступен как DB_URL
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Приведение булевых значений / Boolean Casting
|
|
112
|
+
|
|
113
|
+
`false, 0, '0', 'f', 'false', 'off'` (и их вариации) → `false`. Всё остальное → `true`. Пустая строка и `nil` → `nil`.
|
|
114
|
+
|
|
115
|
+
`false, 0, '0', 'f', 'false', 'off'` (and variations) → `false`. Everything else → `true`. Empty string and `nil` → `nil`.
|
|
41
116
|
|
|
42
|
-
### bbkdocs
|
|
117
|
+
### bbkdocs — генерация документации / Documentation Generator
|
|
43
118
|
|
|
44
119
|
Создать `bin/bbkdocs`:
|
|
45
120
|
|
data/lib/bbk/utils/config.rb
CHANGED
|
@@ -2,18 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
module BBK
|
|
4
4
|
module Utils
|
|
5
|
+
# Класс управления конфигурацией приложения через переменные окружения.
|
|
6
|
+
#
|
|
7
|
+
# Предоставляет декларативный способ описания конфигурационных параметров
|
|
8
|
+
# с поддержкой префиксов, подконфигураций, приведения типов, безопасных значений
|
|
9
|
+
# и файловых конфигураций. Реализует паттерн Singleton.
|
|
10
|
+
#
|
|
11
|
+
# @example Базовое использование
|
|
12
|
+
# BBK::Utils::Config.instance.tap do |cfg|
|
|
13
|
+
# cfg.optional('LOG_LEVEL', default: 'info', desc: 'Уровень логирования')
|
|
14
|
+
# cfg.require('DATABASE_URL', desc: 'Строка подключения к БД')
|
|
15
|
+
# cfg.optional('REDIS_URL', default: 'redis://localhost:6379/0')
|
|
16
|
+
# end
|
|
17
|
+
# BBK::Utils::Config.run!(ENV)
|
|
18
|
+
#
|
|
19
|
+
# # Доступ к значениям
|
|
20
|
+
# BBK::Utils::Config['LOG_LEVEL'] # => "info"
|
|
21
|
+
# BBK::Utils::Config['DATABASE_URL'] # => значение из ENV
|
|
22
|
+
#
|
|
23
|
+
# @example Использование с префиксами
|
|
24
|
+
# config = BBK::Utils::Config.instance(prefix: 'MYAPP')
|
|
25
|
+
# config.optional('PORT', default: 3000)
|
|
26
|
+
# config.run!(ENV)
|
|
27
|
+
# # Читает переменную MYAPP_PORT из ENV
|
|
28
|
+
#
|
|
29
|
+
# @example Подконфигурации
|
|
30
|
+
# config = BBK::Utils::Config.instance
|
|
31
|
+
# config.subconfig(prefix: 'DB') do |db|
|
|
32
|
+
# db.require('HOST', desc: 'Хост базы данных')
|
|
33
|
+
# db.optional('PORT', default: '5432')
|
|
34
|
+
# end
|
|
35
|
+
# config.run!(ENV)
|
|
36
|
+
# # Читает переменные DB_HOST и DB_PORT из ENV
|
|
37
|
+
#
|
|
38
|
+
# @note Все методы класса делегируются единственному экземпляру (Singleton)
|
|
39
|
+
# @see Config::BooleanCaster Класс для приведения булевых значений
|
|
5
40
|
class Config
|
|
6
41
|
|
|
42
|
+
# @return [String] Разделитель между частями префикса
|
|
7
43
|
PREFIX_SEP = '_'
|
|
44
|
+
|
|
45
|
+
# @return [String] Заглушка для отображения безопасных значений в выводе
|
|
8
46
|
FILTERED_VALUE = '[FILTERED]'
|
|
9
47
|
|
|
10
|
-
|
|
11
|
-
|
|
48
|
+
# @return [Hash] Хранилище конфигурационных элементов
|
|
49
|
+
attr_accessor :store
|
|
50
|
+
|
|
51
|
+
# @return [String, nil] Имя конфигурации (для отображения)
|
|
52
|
+
attr_accessor :name
|
|
53
|
+
|
|
54
|
+
# @return [String, nil] Префикс данной конфигурации
|
|
55
|
+
attr_reader :prefix
|
|
56
|
+
|
|
57
|
+
# @return [String] Полный префикс с учётом родительских (для ENV)
|
|
58
|
+
attr_reader :env_prefix
|
|
12
59
|
|
|
60
|
+
# @return [Config, nil] Родительская конфигурация
|
|
61
|
+
attr_reader :parent
|
|
62
|
+
|
|
63
|
+
# Ошибка при обращении к несуществующему ключу конфигурации
|
|
13
64
|
class KeyError < StandardError; end
|
|
14
65
|
|
|
66
|
+
# Класс для приведения значений к булевому типу.
|
|
67
|
+
#
|
|
68
|
+
# Распознаёт широкий набор "ложных" значений: 0, 'f', 'false', 'off' и их варианты.
|
|
69
|
+
# Всё остальное считается истиной. Пустые значения возвращают +nil+.
|
|
70
|
+
#
|
|
71
|
+
# @example
|
|
72
|
+
# BooleanCaster.cast('true') # => true
|
|
73
|
+
# BooleanCaster.cast('0') # => false
|
|
74
|
+
# BooleanCaster.cast('off') # => false
|
|
75
|
+
# BooleanCaster.cast(nil) # => nil
|
|
76
|
+
# BooleanCaster.cast('') # => nil
|
|
77
|
+
# BooleanCaster.cast('yes') # => true
|
|
15
78
|
class BooleanCaster
|
|
16
79
|
|
|
80
|
+
# Множество значений, интерпретируемых как +false+
|
|
17
81
|
FALSE_VALUES = [
|
|
18
82
|
false, 0,
|
|
19
83
|
'0', :"0",
|
|
@@ -25,6 +89,10 @@ module BBK
|
|
|
25
89
|
'OFF', :OFF
|
|
26
90
|
].to_set.freeze
|
|
27
91
|
|
|
92
|
+
# Приводит значение к булевому типу.
|
|
93
|
+
#
|
|
94
|
+
# @param value [Object] Значение для приведения
|
|
95
|
+
# @return [Boolean, nil] +true+, +false+ или +nil+ (для пустых значений)
|
|
28
96
|
def self.cast(value)
|
|
29
97
|
if value.nil? || value == ''
|
|
30
98
|
nil
|
|
@@ -35,14 +103,55 @@ module BBK
|
|
|
35
103
|
|
|
36
104
|
end
|
|
37
105
|
|
|
106
|
+
# Возвращает единственный экземпляр конфигурации (Singleton).
|
|
107
|
+
#
|
|
108
|
+
# @param prefix [String, nil] Префикс для переменных окружения (только при первом вызове)
|
|
109
|
+
# @return [Config] Единственный экземпляр
|
|
110
|
+
#
|
|
111
|
+
# @example
|
|
112
|
+
# config = BBK::Utils::Config.instance
|
|
113
|
+
# config = BBK::Utils::Config.instance(prefix: 'MYAPP')
|
|
38
114
|
def self.instance(prefix: nil)
|
|
39
115
|
@instance ||= new(prefix: prefix)
|
|
40
116
|
end
|
|
41
117
|
|
|
118
|
+
# Приводит значение к булевому типу.
|
|
119
|
+
#
|
|
120
|
+
# @param value [Object] Значение для приведения
|
|
121
|
+
# @return [Boolean, nil] Результат приведения
|
|
122
|
+
# @see BooleanCaster.cast
|
|
42
123
|
def self.parse_bool_value(value)
|
|
43
124
|
BooleanCaster.cast(value)
|
|
44
125
|
end
|
|
45
126
|
|
|
127
|
+
# Делегирование методов экземпляра на уровень класса
|
|
128
|
+
#
|
|
129
|
+
# @!method self.map(env, file, required: true, desc: nil, bool: false, key: nil, rewrite: true, category: nil, warning: nil)
|
|
130
|
+
# @see #map
|
|
131
|
+
# @!method self.require(env, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil)
|
|
132
|
+
# @see #require
|
|
133
|
+
# @!method self.optional(env, default: nil, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil)
|
|
134
|
+
# @see #optional
|
|
135
|
+
# @!method self.run!(source = ENV)
|
|
136
|
+
# @see #run!
|
|
137
|
+
# @!method self.[](key)
|
|
138
|
+
# @see #[]
|
|
139
|
+
# @!method self.[]=(key, value)
|
|
140
|
+
# @see #[]=
|
|
141
|
+
# @!method self.content(key)
|
|
142
|
+
# @see #content
|
|
143
|
+
# @!method self.to_s
|
|
144
|
+
# @see #to_s
|
|
145
|
+
# @!method self.as_json(*args)
|
|
146
|
+
# @see #as_json
|
|
147
|
+
# @!method self.to_json(*args)
|
|
148
|
+
# @see #to_json
|
|
149
|
+
# @!method self.to_yaml(*args)
|
|
150
|
+
# @see #to_yaml
|
|
151
|
+
# @!method self.fetch(key, default = nil)
|
|
152
|
+
# @see #fetch
|
|
153
|
+
# @!method self.root?
|
|
154
|
+
# @see #root?
|
|
46
155
|
class << self
|
|
47
156
|
|
|
48
157
|
delegate :map, :require, :optional, :run!, :[], :[]=, :content, :to_s,
|
|
@@ -51,6 +160,16 @@ module BBK
|
|
|
51
160
|
|
|
52
161
|
end
|
|
53
162
|
|
|
163
|
+
# Инициализирует новый экземпляр конфигурации.
|
|
164
|
+
#
|
|
165
|
+
# Обычно не вызывается напрямую — используйте {.instance}.
|
|
166
|
+
#
|
|
167
|
+
# @param name [String, nil] Имя конфигурации (для отображения в логах)
|
|
168
|
+
# @param prefix [String, nil] Префикс для переменных окружения
|
|
169
|
+
# @param parent [Config, nil] Родительская конфигурация (для подконфигураций)
|
|
170
|
+
#
|
|
171
|
+
# @example
|
|
172
|
+
# config = BBK::Utils::Config.new(name: 'myapp', prefix: 'MYAPP')
|
|
54
173
|
def initialize(name: nil, prefix: nil, parent: nil)
|
|
55
174
|
@name = name
|
|
56
175
|
@store = {}
|
|
@@ -65,6 +184,27 @@ module BBK
|
|
|
65
184
|
@env_prefix = normalize_key(@prefixes.join(PREFIX_SEP))
|
|
66
185
|
end
|
|
67
186
|
|
|
187
|
+
# Регистрирует файловый конфигурационный параметр.
|
|
188
|
+
#
|
|
189
|
+
# Значение переменной окружения записывается в указанный файл.
|
|
190
|
+
# Используется для сертификатов, ключей и других файловых данных.
|
|
191
|
+
#
|
|
192
|
+
# @param env [String] Имя переменной окружения (без префикса)
|
|
193
|
+
# @param file [String] Путь к файлу, куда будет записано значение
|
|
194
|
+
# @param required [Boolean] Обязательность параметра (по умолчанию: true)
|
|
195
|
+
# @param desc [String, nil] Описание параметра
|
|
196
|
+
# @param bool [Boolean] (устарел) Не используется для файловых параметров, оставлен для совместимости
|
|
197
|
+
# @param key [String, nil] Альтернативное имя переменной окружения
|
|
198
|
+
# @param rewrite [Boolean] Перезаписывать при повторной регистрации (по умолчанию: true)
|
|
199
|
+
# @param category [String, nil] Имя категории, к которой относится параметр.
|
|
200
|
+
# Используется генератором документации `BBK::Utils::Cli::Docs::Builder`
|
|
201
|
+
# @param warning [String, nil] Предупреждение для отображения
|
|
202
|
+
# @return [void]
|
|
203
|
+
#
|
|
204
|
+
# @example
|
|
205
|
+
# config.map('SSL_CERT', '/etc/ssl/cert.pem', desc: 'SSL-сертификат')
|
|
206
|
+
# config.run!(ENV)
|
|
207
|
+
# # Значение ENV['SSL_CERT'] будет записано в /etc/ssl/cert.pem
|
|
68
208
|
def map(env, file, required: true, desc: nil, bool: false, key: nil, rewrite: true, category: nil, warning: nil)
|
|
69
209
|
conf_key = full_prefixed_key(env)
|
|
70
210
|
return if @store.key?(conf_key) && !rewrite
|
|
@@ -81,10 +221,34 @@ module BBK
|
|
|
81
221
|
}
|
|
82
222
|
end
|
|
83
223
|
|
|
224
|
+
# Регистрирует обязательный конфигурационный параметр.
|
|
225
|
+
#
|
|
226
|
+
# При отсутствии переменной в источнике во время {#run!} будет выброшено исключение.
|
|
227
|
+
#
|
|
228
|
+
# @param env [String] Имя переменной окружения (без префикса)
|
|
229
|
+
# @param desc [String, nil] Описание параметра
|
|
230
|
+
# @param bool [Boolean] Интерпретировать как булево значение (по умолчанию: false)
|
|
231
|
+
# @param type [#call, Class, nil] Кастер типа: объект с методом +call+ или класс с методом +new+
|
|
232
|
+
# *Примечание:* для встроенных классов (например, `Integer`, `Float`) передавайте `method(:Integer)`, так как они не имеют публичного метода `new`.
|
|
233
|
+
# @param key [String, nil] Альтернативное имя переменной окружения (используется для чтения из ENV).
|
|
234
|
+
# Например: `config.require('MY_DB', key: 'DATABASE_URL')` прочитает `DATABASE_URL`,
|
|
235
|
+
# но в коде вы будете обращаться к нему как `config['MY_DB']`.
|
|
236
|
+
# @param rewrite [Boolean] Перезаписывать при повторной регистрации (по умолчанию: true)
|
|
237
|
+
# @param secure [Boolean] Скрывать значение в выводе (по умолчанию: false)
|
|
238
|
+
# @param category [String, nil] Имя категории, к которой относится параметр.
|
|
239
|
+
# Используется генератором документации `BBK::Utils::Cli::Docs::Builder`
|
|
240
|
+
# @param warning [String, nil] Предупреждение для отображения
|
|
241
|
+
# @return [void]
|
|
242
|
+
# @raise [ArgumentError] Если одновременно указаны +bool+ и +type+
|
|
243
|
+
#
|
|
244
|
+
# @example
|
|
245
|
+
# config.require('DATABASE_URL', desc: 'Строка подключения к БД')
|
|
246
|
+
# config.require('API_KEY', secure: true, desc: 'Секретный ключ')
|
|
247
|
+
# config.require('WORKERS_COUNT', type: method(:Integer), desc: 'Число воркеров')
|
|
84
248
|
def require(env, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil)
|
|
85
249
|
raise ArgumentError.new('Specified type and bool') if bool && type.present?
|
|
86
250
|
|
|
87
|
-
type = BBK::Config::BooleanCaster.singleton_method(:cast) if bool
|
|
251
|
+
type = BBK::Utils::Config::BooleanCaster.singleton_method(:cast) if bool
|
|
88
252
|
conf_key = full_prefixed_key(env)
|
|
89
253
|
return if @store.key?(conf_key) && !rewrite
|
|
90
254
|
|
|
@@ -101,6 +265,30 @@ module BBK
|
|
|
101
265
|
}
|
|
102
266
|
end
|
|
103
267
|
|
|
268
|
+
# Регистрирует опциональный конфигурационный параметр со значением по умолчанию.
|
|
269
|
+
#
|
|
270
|
+
# @param env [String] Имя переменной окружения (без префикса)
|
|
271
|
+
# @param default [Object] Значение по умолчанию (по умолчанию: nil)
|
|
272
|
+
# @param desc [String, nil] Описание параметра
|
|
273
|
+
# @param bool [Boolean] Интерпретировать как булево значение (по умолчанию: false)
|
|
274
|
+
# @param type [#call, Class, nil] Кастер типа: объект с методом +call+ или класс с методом +new+
|
|
275
|
+
# *Примечание:* для встроенных классов (например, `Integer`, `Float`) передавайте `method(:Integer)`, так как они не имеют публичного метода `new`.
|
|
276
|
+
# @param key [String, nil] Альтернативное имя переменной окружения (используется для чтения из ENV).
|
|
277
|
+
# Например: `config.optional('REDIS_URL', key: 'REDIS_CACHE_URL', default: 'redis://localhost:6379/0')` прочитает `REDIS_CACHE_URL`,
|
|
278
|
+
# но в коде вы будете обращаться к нему как `config['REDIS_URL']`.
|
|
279
|
+
# @param rewrite [Boolean] Перезаписывать при повторной регистрации (по умолчанию: true)
|
|
280
|
+
# @param secure [Boolean] Скрывать значение в выводе (по умолчанию: false)
|
|
281
|
+
# @param category [String, nil] Имя категории, к которой относится параметр.
|
|
282
|
+
# Используется генератором документации `BBK::Utils::Cli::Docs::Builder`
|
|
283
|
+
# @param warning [String, nil] Предупреждение для отображения
|
|
284
|
+
# @return [void]
|
|
285
|
+
# @raise [ArgumentError] Если одновременно указаны +bool+ и +type+
|
|
286
|
+
#
|
|
287
|
+
# @example
|
|
288
|
+
# config.optional('LOG_LEVEL', default: 'info', desc: 'Уровень логирования')
|
|
289
|
+
# config.optional('PORT', default: '3000', type: method(:Integer))
|
|
290
|
+
# config.optional('DEBUG', default: false, bool: true)
|
|
291
|
+
# config.optional('PASSWORD', default: '', secure: true)
|
|
104
292
|
def optional(env, default: nil, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil)
|
|
105
293
|
raise ArgumentError.new('Specified type and bool') if bool && type.present?
|
|
106
294
|
|
|
@@ -122,6 +310,20 @@ module BBK
|
|
|
122
310
|
}
|
|
123
311
|
end
|
|
124
312
|
|
|
313
|
+
# Запускает обработку всех зарегистрированных параметров.
|
|
314
|
+
#
|
|
315
|
+
# Проходит по всем элементам хранилища и читает значения из источника.
|
|
316
|
+
# Рекурсивно обрабатывает все подконфигурации.
|
|
317
|
+
#
|
|
318
|
+
# @param source [Hash{String=>String}, #fetch] Источник значений (объект с методом #fetch, например ENV)
|
|
319
|
+
# @return [nil]
|
|
320
|
+
# @raise [RuntimeError] Если обязательный параметр отсутствует в источнике
|
|
321
|
+
#
|
|
322
|
+
# @example Чтение из ENV
|
|
323
|
+
# config.run!
|
|
324
|
+
#
|
|
325
|
+
# @example Чтение из хэша
|
|
326
|
+
# config.run!({ 'DATABASE_URL' => 'postgres://...' })
|
|
125
327
|
def run!(source = ENV)
|
|
126
328
|
@store.each_value do |item|
|
|
127
329
|
process(source, item)
|
|
@@ -130,6 +332,26 @@ module BBK
|
|
|
130
332
|
nil
|
|
131
333
|
end
|
|
132
334
|
|
|
335
|
+
# Создаёт подконфигурацию с собственным префиксом.
|
|
336
|
+
#
|
|
337
|
+
# Переменные окружения подконфигурации получают дополнительный префикс.
|
|
338
|
+
# Например, при префиксе родителя 'APP' и префиксе подконфигурации 'DB',
|
|
339
|
+
# переменная 'HOST' будет читаться как 'APP_DB_HOST'.
|
|
340
|
+
#
|
|
341
|
+
# @param prefix [String, Symbol] Префикс подконфигурации
|
|
342
|
+
# @param name [String, nil] Имя подконфигурации
|
|
343
|
+
# @yield [sub] Блок для регистрации параметров подконфигурации
|
|
344
|
+
# @yieldparam sub [Config] Экземпляр подконфигурации
|
|
345
|
+
# @return [Config] Созданная подконфигурация
|
|
346
|
+
# @raise [ArgumentError] Если подконфигурация с таким префиксом уже существует
|
|
347
|
+
#
|
|
348
|
+
# @example
|
|
349
|
+
# config = BBK::Utils::Config.instance(prefix: 'APP')
|
|
350
|
+
# config.subconfig(prefix: 'DB', name: 'database') do |db|
|
|
351
|
+
# db.require('HOST')
|
|
352
|
+
# db.optional('PORT', default: '5432')
|
|
353
|
+
# end
|
|
354
|
+
# # Будут читаться переменные APP_DB_HOST и APP_DB_PORT
|
|
133
355
|
def subconfig(prefix:, name: nil)
|
|
134
356
|
raise ArgumentError.new("Subconfig with prefix #{prefix} already exists") if @subconfigs.any? {|sub| sub.prefix == prefix.to_s }
|
|
135
357
|
|
|
@@ -139,14 +361,43 @@ module BBK
|
|
|
139
361
|
sub
|
|
140
362
|
end
|
|
141
363
|
|
|
364
|
+
# Возвращает значение конфигурационного параметра.
|
|
365
|
+
#
|
|
366
|
+
# Поиск происходит с учётом префиксов, вверх по иерархии (к родителю)
|
|
367
|
+
# и вниз (в подконфигурации).
|
|
368
|
+
#
|
|
369
|
+
# @param key [String] Имя параметра
|
|
370
|
+
# @return [Object] Значение параметра
|
|
371
|
+
# @raise [Config::KeyError] Если параметр не найден
|
|
372
|
+
#
|
|
373
|
+
# @example
|
|
374
|
+
# BBK::Utils::Config['LOG_LEVEL'] # => "info"
|
|
142
375
|
def [](key)
|
|
143
376
|
self.get(key, search_up: true, search_down: true)[:value]
|
|
144
377
|
end
|
|
145
378
|
|
|
379
|
+
# Устанавливает значение конфигурационного параметра.
|
|
380
|
+
#
|
|
381
|
+
# @param key [String] Имя параметра
|
|
382
|
+
# @param value [Object] Новое значение
|
|
383
|
+
# @return [Object] Установленное значение
|
|
384
|
+
#
|
|
385
|
+
# @example
|
|
386
|
+
# BBK::Utils::Config['LOG_LEVEL'] = 'debug'
|
|
146
387
|
def []=(key, value)
|
|
147
388
|
@store[normalize_key(key)][:value] = value
|
|
148
389
|
end
|
|
149
390
|
|
|
391
|
+
# Возвращает содержимое параметра.
|
|
392
|
+
#
|
|
393
|
+
# Для файловых параметров читает содержимое файла.
|
|
394
|
+
# Для остальных возвращает значение.
|
|
395
|
+
#
|
|
396
|
+
# @param key [String] Имя параметра
|
|
397
|
+
# @return [String, Object] Содержимое файла или значение параметра
|
|
398
|
+
#
|
|
399
|
+
# @example
|
|
400
|
+
# config.content('SSL_CERT') # => содержимое файла сертификата
|
|
150
401
|
def content(key)
|
|
151
402
|
item = @store[normalize_key(key)]
|
|
152
403
|
if (file = item[:file])
|
|
@@ -156,6 +407,17 @@ module BBK
|
|
|
156
407
|
end
|
|
157
408
|
end
|
|
158
409
|
|
|
410
|
+
# Возвращает значение параметра или значение по умолчанию.
|
|
411
|
+
#
|
|
412
|
+
# В отличие от {#[]}, не выбрасывает исключение при отсутствии параметра.
|
|
413
|
+
#
|
|
414
|
+
# @param key [String] Имя параметра
|
|
415
|
+
# @param default [Object] Значение по умолчанию (по умолчанию: nil)
|
|
416
|
+
# @return [Object] Значение параметра или +default+
|
|
417
|
+
#
|
|
418
|
+
# @example
|
|
419
|
+
# BBK::Utils::Config.fetch('LOG_LEVEL', 'warn') # => "info" (если значение установлено) или "warn" (если не установлено)
|
|
420
|
+
# BBK::Utils::Config.fetch('NONEXISTENT', 'fallback') # => "fallback"
|
|
159
421
|
def fetch(key, default = nil)
|
|
160
422
|
if (rec = self.get(key, search_up: true, search_down: true)) && rec.key?(:value)
|
|
161
423
|
rec[:value]
|
|
@@ -166,6 +428,19 @@ module BBK
|
|
|
166
428
|
default
|
|
167
429
|
end
|
|
168
430
|
|
|
431
|
+
# Возвращает человекочитаемое представление конфигурации.
|
|
432
|
+
#
|
|
433
|
+
# Выводит все параметры с их значениями, описаниями и статусом обязательности.
|
|
434
|
+
# Безопасные параметры отображаются как +[FILTERED]+.
|
|
435
|
+
#
|
|
436
|
+
# @return [String] Форматированный вывод конфигурации
|
|
437
|
+
#
|
|
438
|
+
# @example Вывод
|
|
439
|
+
# # Environment variables:
|
|
440
|
+
# # <DATABASE_URL> Строка подключения к БД
|
|
441
|
+
# # -> "postgres://localhost/mydb"
|
|
442
|
+
# # [LOG_LEVEL] (=info) Уровень логирования
|
|
443
|
+
# # -> "info"
|
|
169
444
|
def to_s
|
|
170
445
|
result = StringIO.new
|
|
171
446
|
result.puts "Environment variables#{@name ? " for #{@name}" : ''}:"
|
|
@@ -184,6 +459,12 @@ module BBK
|
|
|
184
459
|
result.string
|
|
185
460
|
end
|
|
186
461
|
|
|
462
|
+
# Возвращает конфигурацию как хэш.
|
|
463
|
+
#
|
|
464
|
+
# @param _args [Array] Игнорируется (для совместимости с ActiveSupport)
|
|
465
|
+
# @return [Hash] Хэш вида { "ИМЯ_ПЕРЕМЕННОЙ" => { параметры } }
|
|
466
|
+
# @note Если в конфигурации используются кастомные type-кастеры (Method, Proc, Class),
|
|
467
|
+
# поле `type` будет сериализовано как строковое представление объекта (например, "#<Method: Object(Kernel)#Integer(*)>").
|
|
187
468
|
def as_json(*_args)
|
|
188
469
|
values = store_with_subconfigs.values.sort_by do |item|
|
|
189
470
|
[item[:file].present? ? 0 : 1, item[:required] ? 0 : 1]
|
|
@@ -194,22 +475,46 @@ module BBK
|
|
|
194
475
|
@name ? { @name => values } : values
|
|
195
476
|
end
|
|
196
477
|
|
|
478
|
+
# Возвращает конфигурацию в формате JSON.
|
|
479
|
+
#
|
|
480
|
+
# @param _args [Array] Игнорируется (для совместимости с ActiveSupport)
|
|
481
|
+
# @return [String] JSON-представление конфигурации
|
|
482
|
+
# @note Если в конфигурации используются кастомные type-кастеры (Method, Proc, Class),
|
|
483
|
+
# поле `type` будет сериализовано как строковое представление объекта (например, "#<Method: Object(Kernel)#Integer(*)>").
|
|
197
484
|
def to_json(*_args)
|
|
198
485
|
JSON.pretty_generate(as_json)
|
|
199
486
|
end
|
|
200
487
|
|
|
488
|
+
# Возвращает конфигурацию в формате YAML.
|
|
489
|
+
#
|
|
490
|
+
# @param _args [Array] Игнорируется (для совместимости с ActiveSupport)
|
|
491
|
+
# @return [String] YAML-представление конфигурации
|
|
492
|
+
# @note Если в конфигурации используются кастомные type-кастеры (Method, Proc, Class),
|
|
493
|
+
# поле `type` будет сериализовано как строковое представление объекта (например, "#<Method: Object(Kernel)#Integer(*)>").
|
|
201
494
|
def to_yaml(*_args)
|
|
202
495
|
JSON.parse(to_json).to_yaml
|
|
203
496
|
end
|
|
204
497
|
|
|
498
|
+
# Проверяет, является ли конфигурация корневой (не имеет родителя).
|
|
499
|
+
#
|
|
500
|
+
# @return [Boolean] +true+ если конфигурация корневая
|
|
205
501
|
def root?
|
|
206
502
|
@parent.nil?
|
|
207
503
|
end
|
|
208
504
|
|
|
209
505
|
protected
|
|
210
506
|
|
|
507
|
+
# @return [Array<String>] Массив префиксов от корня до текущего уровня
|
|
211
508
|
attr_reader :prefixes
|
|
212
509
|
|
|
510
|
+
# Ищет конфигурационный элемент по ключу.
|
|
511
|
+
#
|
|
512
|
+
# @param key [String] Имя параметра
|
|
513
|
+
# @param search_up [Boolean] Искать в родительских конфигурациях
|
|
514
|
+
# @param search_down [Boolean] Искать в подконфигурациях
|
|
515
|
+
# @return [Hash] Конфигурационный элемент
|
|
516
|
+
# @raise [KeyError] Если параметр не найден
|
|
517
|
+
# @api private
|
|
213
518
|
def get(key, search_up: false, search_down: false)
|
|
214
519
|
normalized_key = normalize_key(key)
|
|
215
520
|
return @store[normalized_key] if @store.key?(normalized_key)
|
|
@@ -232,6 +537,10 @@ module BBK
|
|
|
232
537
|
raise KeyError.new("There is no such key: #{key} in config!")
|
|
233
538
|
end
|
|
234
539
|
|
|
540
|
+
# Возвращает все элементы хранилища включая подконфигурации.
|
|
541
|
+
#
|
|
542
|
+
# @return [Hash] Объединённое хранилище всех уровней
|
|
543
|
+
# @api private
|
|
235
544
|
def store_with_subconfigs
|
|
236
545
|
res = @store.dup
|
|
237
546
|
@subconfigs.each do |sub|
|
|
@@ -242,12 +551,22 @@ module BBK
|
|
|
242
551
|
|
|
243
552
|
private
|
|
244
553
|
|
|
554
|
+
# Нормализует ключ: переводит в верхний регистр, заменяет дефисы на подчёркивания.
|
|
555
|
+
#
|
|
556
|
+
# @param key [String, nil] Ключ для нормализации
|
|
557
|
+
# @return [String, nil] Нормализованный ключ
|
|
558
|
+
# @api private
|
|
245
559
|
def normalize_key(key)
|
|
246
560
|
return nil if key.nil?
|
|
247
561
|
|
|
248
562
|
key.to_s.upcase.gsub('-', '_')
|
|
249
563
|
end
|
|
250
564
|
|
|
565
|
+
# Формирует полный ключ с учётом префикса.
|
|
566
|
+
#
|
|
567
|
+
# @param key [String] Базовый ключ
|
|
568
|
+
# @return [String] Ключ с префиксом (например, "APP_DB_HOST")
|
|
569
|
+
# @api private
|
|
251
570
|
def full_prefixed_key(key)
|
|
252
571
|
p_key = if env_prefix.empty?
|
|
253
572
|
[key.to_s]
|
|
@@ -257,6 +576,11 @@ module BBK
|
|
|
257
576
|
normalize_key(p_key)
|
|
258
577
|
end
|
|
259
578
|
|
|
579
|
+
# Генерирует варианты ключей с разными комбинациями префиксов.
|
|
580
|
+
#
|
|
581
|
+
# @param key [String] Базовый ключ
|
|
582
|
+
# @return [Enumerator] Перечислитель вариантов ключей
|
|
583
|
+
# @api private
|
|
260
584
|
def sub_prefixed_keys(key)
|
|
261
585
|
Enumerator.new do |yielder|
|
|
262
586
|
@prefixes.size.downto(0).each do |last_index|
|
|
@@ -265,6 +589,20 @@ module BBK
|
|
|
265
589
|
end
|
|
266
590
|
end
|
|
267
591
|
|
|
592
|
+
# Обрабатывает один конфигурационный элемент: читает значение из источника.
|
|
593
|
+
#
|
|
594
|
+
# Логика обработки:
|
|
595
|
+
# - Если значение присутствует или указан тип — обрабатывает значение
|
|
596
|
+
# - Для файловых параметров — записывает значение в файл
|
|
597
|
+
# - Для типизированных — применяет кастер типа
|
|
598
|
+
# - Если значение отсутствует и параметр обязательный — выбрасывает ошибку
|
|
599
|
+
# - Если значение отсутствует и параметр опциональный — использует дефолт
|
|
600
|
+
#
|
|
601
|
+
# @param source [Hash{String=>String}, #fetch] Источник значений (объект с методом #fetch, например ENV)
|
|
602
|
+
# @param item [Hash] Конфигурационный элемент из хранилища
|
|
603
|
+
# @return [void]
|
|
604
|
+
# @raise [RuntimeError] Если обязательный параметр отсутствует
|
|
605
|
+
# @api private
|
|
268
606
|
def process(source, item)
|
|
269
607
|
content = source.fetch(item[:env], item[:default])
|
|
270
608
|
|
|
@@ -305,10 +643,21 @@ module BBK
|
|
|
305
643
|
raise
|
|
306
644
|
end
|
|
307
645
|
|
|
646
|
+
# Выбрасывает ошибку об отсутствии обязательного параметра.
|
|
647
|
+
#
|
|
648
|
+
# @param item [Hash] Конфигурационный элемент
|
|
649
|
+
# @raise [RuntimeError] Всегда выбрасывает ошибку
|
|
650
|
+
# @api private
|
|
308
651
|
def required!(item)
|
|
309
652
|
raise "ENV [#{item[:env]}] is required!"
|
|
310
653
|
end
|
|
311
654
|
|
|
655
|
+
# Формирует строку вывода для файлового параметра.
|
|
656
|
+
#
|
|
657
|
+
# @param item [Hash] Конфигурационный элемент
|
|
658
|
+
# @param padding [String] Отступ для форматирования
|
|
659
|
+
# @return [String] Форматированная строка
|
|
660
|
+
# @api private
|
|
312
661
|
def print_file_item(item, padding)
|
|
313
662
|
line = "#{padding}File #{wrap_required(item)}"
|
|
314
663
|
line = if item[:desc].present?
|
|
@@ -320,11 +669,19 @@ module BBK
|
|
|
320
669
|
"#{line}\n#{padding * 2}-> #{item[:file].inspect}"
|
|
321
670
|
end
|
|
322
671
|
|
|
672
|
+
# Формирует строку вывода для обычного параметра.
|
|
673
|
+
#
|
|
674
|
+
# @param item [Hash] Конфигурационный элемент
|
|
675
|
+
# @param padding [String] Отступ для форматирования
|
|
676
|
+
# @return [String] Форматированная строка
|
|
677
|
+
# @api private
|
|
323
678
|
def print_item(item, padding)
|
|
324
679
|
line = padding + wrap_required(item)
|
|
325
680
|
if item[:default].present?
|
|
326
681
|
def_value = if item[:secure]
|
|
327
682
|
FILTERED_VALUE
|
|
683
|
+
elsif item[:default].respond_to?(:secure_inspect)
|
|
684
|
+
item[:default].secure_inspect
|
|
328
685
|
else
|
|
329
686
|
item[:default]
|
|
330
687
|
end
|
|
@@ -338,12 +695,22 @@ module BBK
|
|
|
338
695
|
end
|
|
339
696
|
value = if item[:secure]
|
|
340
697
|
FILTERED_VALUE
|
|
698
|
+
elsif item[:value].respond_to?(:secure_inspect)
|
|
699
|
+
item[:value].secure_inspect
|
|
341
700
|
else
|
|
342
701
|
item[:value].inspect
|
|
343
702
|
end
|
|
344
703
|
"#{line}\n#{padding * 2}-> #{value}"
|
|
345
704
|
end
|
|
346
705
|
|
|
706
|
+
# Оборачивает имя переменной в скобки в зависимости от обязательности.
|
|
707
|
+
#
|
|
708
|
+
# Обязательные параметры выводятся в угловых скобках: <ИМЯ>
|
|
709
|
+
# Опциональные параметры выводятся в квадратных скобках: [ИМЯ]
|
|
710
|
+
#
|
|
711
|
+
# @param item [Hash] Конфигурационный элемент
|
|
712
|
+
# @return [String] Имя переменной в скобках
|
|
713
|
+
# @api private
|
|
347
714
|
def wrap_required(item)
|
|
348
715
|
if item[:required]
|
|
349
716
|
"<#{item[:env]}>"
|
|
@@ -354,5 +721,4 @@ module BBK
|
|
|
354
721
|
|
|
355
722
|
end
|
|
356
723
|
end
|
|
357
|
-
end
|
|
358
|
-
|
|
724
|
+
end
|
data/lib/bbk/utils/env_helper.rb
CHANGED
|
@@ -4,21 +4,119 @@ require 'uri'
|
|
|
4
4
|
|
|
5
5
|
module BBK
|
|
6
6
|
module Utils
|
|
7
|
+
# Вспомогательный модуль для сборки и нормализации переменных окружения
|
|
8
|
+
# при подключении к внешним сервисам.
|
|
9
|
+
#
|
|
10
|
+
# Предоставляет методы для конструирования URL-подключений из переменных окружения
|
|
11
|
+
# с интеллектуальными значениями по умолчанию и механизмом переопределения.
|
|
12
|
+
# Поддерживает базы данных, очереди сообщений и сервисы трейсинга.
|
|
13
|
+
#
|
|
14
|
+
# @example Базовое использование для конфигурации базы данных
|
|
15
|
+
# env = {
|
|
16
|
+
# 'DATABASE_URL' => 'postgres://old:pass@oldhost:5432/olddb',
|
|
17
|
+
# 'DATABASE_HOST' => 'newhost',
|
|
18
|
+
# 'DATABASE_NAME' => 'newdb'
|
|
19
|
+
# }
|
|
20
|
+
# BBK::Utils::EnvHelper.prepare_database_envs(env)
|
|
21
|
+
# # => env['DATABASE_URL'] = 'postgres://old:pass@newhost:5432/newdb'
|
|
22
|
+
# # => env['DATABASE_HOST'] = 'newhost'
|
|
23
|
+
# # => env['DATABASE_NAME'] = 'newdb'
|
|
24
|
+
#
|
|
25
|
+
# @note Все методы изменяют переданный хэш env in-place и возвращают его
|
|
7
26
|
module EnvHelper
|
|
8
27
|
|
|
28
|
+
# @return [String] Префикс по умолчанию для переменных окружения, связанных с базой данных
|
|
9
29
|
DEFAULT_DATABASE_PREFIX = 'DATABASE'
|
|
10
30
|
|
|
31
|
+
# Подготавливает переменные окружения для подключения к базе данных.
|
|
32
|
+
#
|
|
33
|
+
# Собирает URL подключения к БД из отдельных переменных окружения или
|
|
34
|
+
# переопределяет компоненты существующего URL. После сборки URL раскладывает
|
|
35
|
+
# его обратно в индивидуальные переменные окружения.
|
|
36
|
+
#
|
|
37
|
+
# Поддерживаемые переменные окружения (с префиксом):
|
|
38
|
+
# - {prefix}_URL - базовый URL (опционально, используется как шаблон)
|
|
39
|
+
# - {prefix}_ADAPTER - адаптер/схема БД (по умолчанию: 'postgresql')
|
|
40
|
+
# - {prefix}_HOST - хост БД (по умолчанию: 'db')
|
|
41
|
+
# - {prefix}_PORT - порт БД (по умолчанию: 5432)
|
|
42
|
+
# - {prefix}_USER - пользователь БД (по умолчанию: 'postgres')
|
|
43
|
+
# - {prefix}_PASS - пароль БД (по умолчанию: nil)
|
|
44
|
+
# - {prefix}_NAME - имя БД/путь
|
|
45
|
+
# - {prefix}_POOL - размер пула соединений. Используется **только если в {prefix}_URL присутствует query-строка** (не обязательно содержащая параметр `pool`). Если query-строки нет, значение игнорируется.
|
|
46
|
+
#
|
|
47
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV (изменяется in-place)
|
|
48
|
+
# @param prefix [String] Префикс для имен переменных окружения
|
|
49
|
+
# @return [Hash{String=>String}, ENV] Тот же объект env (изменён in-place)
|
|
50
|
+
#
|
|
51
|
+
# @example Только с URL
|
|
52
|
+
# env = { 'DATABASE_URL' => 'postgres://user:pass@host:5432/mydb' }
|
|
53
|
+
# prepare_database_envs(env)
|
|
54
|
+
# # => env['DATABASE_HOST'] = 'host', env['DATABASE_PORT'] = '5432', и т.д.
|
|
55
|
+
#
|
|
56
|
+
# @example С URL и переопределениями
|
|
57
|
+
# env = { 'DATABASE_URL' => 'postgres://user:pass@host:5432/mydb', 'DATABASE_HOST' => 'newhost' }
|
|
58
|
+
# prepare_database_envs(env)
|
|
59
|
+
# # => env['DATABASE_URL'] = 'postgres://user:pass@newhost:5432/mydb'
|
|
60
|
+
#
|
|
61
|
+
# @example Только с индивидуальными переменными
|
|
62
|
+
# env = { 'DATABASE_HOST' => 'myhost', 'DATABASE_NAME' => 'mydb' }
|
|
63
|
+
# prepare_database_envs(env)
|
|
64
|
+
# # => env['DATABASE_URL'] = 'postgresql://postgres@myhost:5432/mydb'
|
|
11
65
|
def self.prepare_database_envs(env, prefix: DEFAULT_DATABASE_PREFIX)
|
|
12
66
|
uri = build_uri_with_defaults(env, prefix: prefix)
|
|
13
67
|
apply_env_from_uri(env, uri, prefix: prefix)
|
|
14
68
|
env
|
|
15
69
|
end
|
|
16
70
|
|
|
71
|
+
# Подготавливает переменные окружения для подключения к очереди сообщений.
|
|
72
|
+
#
|
|
73
|
+
# Собирает URL для MQ из переменных окружения с поддержкой нескольких хостов (кластер).
|
|
74
|
+
# Хосты могут быть указаны в виде списка, разделенного точкой с запятой или вертикальной чертой,
|
|
75
|
+
# в переменной MQ_HOST.
|
|
76
|
+
#
|
|
77
|
+
# Поддерживаемые переменные окружения:
|
|
78
|
+
# - MQ_URL - базовый URL-шаблон (опционально, используется первый, если несколько)
|
|
79
|
+
# - MQ_HOST - хост(ы), могут быть разделены ';' или '|' (по умолчанию: 'mq')
|
|
80
|
+
# - MQ_PORT - порт (по умолчанию: 5671)
|
|
81
|
+
# - MQ_USER - имя пользователя
|
|
82
|
+
# - MQ_PASS - пароль
|
|
83
|
+
# - MQ_VHOST - виртуальный хост (по умолчанию: '/')
|
|
84
|
+
#
|
|
85
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV (изменяется in-place)
|
|
86
|
+
# @return [Hash{String=>String}, ENV] Тот же объект env (изменён in-place)
|
|
87
|
+
#
|
|
88
|
+
# @example Один хост
|
|
89
|
+
# env = { 'MQ_HOST' => 'rabbitmq', 'MQ_USER' => 'guest' }
|
|
90
|
+
# prepare_mq_envs(env)
|
|
91
|
+
# # => env['MQ_URL'] = 'amqps://guest@rabbitmq:5671/'
|
|
92
|
+
#
|
|
93
|
+
# @example Несколько хостов (кластер)
|
|
94
|
+
# env = { 'MQ_HOST' => 'mq1;mq2;mq3', 'MQ_USER' => 'guest' }
|
|
95
|
+
# prepare_mq_envs(env)
|
|
96
|
+
# # => env['MQ_URL'] = 'amqps://guest@mq1:5671/;amqps://guest@mq2:5671/;amqps://guest@mq3:5671/'
|
|
97
|
+
# # => env['MQ_HOST'] = 'mq1;mq2;mq3'
|
|
17
98
|
def self.prepare_mq_envs(env)
|
|
18
99
|
apply_mq_env_from_uri(env, build_mq_uri_with_defaults(env))
|
|
19
100
|
env
|
|
20
101
|
end
|
|
21
102
|
|
|
103
|
+
# Подготавливает переменные окружения для Jaeger трейсинга.
|
|
104
|
+
#
|
|
105
|
+
# Собирает URL подключения к Jaeger из переменных окружения.
|
|
106
|
+
#
|
|
107
|
+
# Поддерживаемые переменные окружения:
|
|
108
|
+
# - JAEGER_URL - базовый URL (опционально)
|
|
109
|
+
# - JAEGER_SENDER - протокол/схема отправки (по умолчанию: 'udp')
|
|
110
|
+
# - JAEGER_HOST - хост Jaeger агента (по умолчанию: 'jaeger')
|
|
111
|
+
# - JAEGER_PORT - порт Jaeger агента (по умолчанию: 6831)
|
|
112
|
+
#
|
|
113
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV (изменяется in-place)
|
|
114
|
+
# @return [Hash{String=>String}, ENV] Тот же объект env (изменён in-place)
|
|
115
|
+
#
|
|
116
|
+
# @example
|
|
117
|
+
# env = { 'JAEGER_HOST' => 'jaeger-agent' }
|
|
118
|
+
# prepare_jaeger_envs(env)
|
|
119
|
+
# # => env['JAEGER_URL'] = 'udp://jaeger-agent:6831'
|
|
22
120
|
def self.prepare_jaeger_envs(env)
|
|
23
121
|
jaeger_uri = ::URI.parse(env['JAEGER_URL'] || '').tap do |uri|
|
|
24
122
|
uri.scheme = env.fetch('JAEGER_SENDER', uri.scheme) || 'udp'
|
|
@@ -32,6 +130,18 @@ module BBK
|
|
|
32
130
|
env
|
|
33
131
|
end
|
|
34
132
|
|
|
133
|
+
# Собирает объект URI из переменных окружения со значениями по умолчанию.
|
|
134
|
+
# При отсутствии {prefix}_URL используется пустой URI (URI.parse('')).
|
|
135
|
+
#
|
|
136
|
+
# @note Приоритет для каждого компонента:
|
|
137
|
+
# 1. Индивидуальная переменная окружения (например, DATABASE_HOST)
|
|
138
|
+
# 2. Компонент из базового URL (например, host из DATABASE_URL)
|
|
139
|
+
# 3. Значение по умолчанию (например, 'db')
|
|
140
|
+
#
|
|
141
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV
|
|
142
|
+
# @param prefix [String] Префикс для имен переменных окружения
|
|
143
|
+
# @return [URI::Generic] Сконструированный объект URI
|
|
144
|
+
# @api private
|
|
35
145
|
def self.build_uri_with_defaults(env, prefix: DEFAULT_DATABASE_PREFIX)
|
|
36
146
|
::URI.parse(env[prefixed_key(prefix, 'URL')] || '').then do |uri|
|
|
37
147
|
result = uri.clone
|
|
@@ -54,6 +164,13 @@ module BBK
|
|
|
54
164
|
end
|
|
55
165
|
end
|
|
56
166
|
|
|
167
|
+
# Раскладывает URI в индивидуальные переменные окружения.
|
|
168
|
+
#
|
|
169
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV (изменяется in-place)
|
|
170
|
+
# @param uri [URI::Generic] Объект URI для декомпозиции
|
|
171
|
+
# @param prefix [String] Префикс для имен переменных окружения
|
|
172
|
+
# @return [void]
|
|
173
|
+
# @api private
|
|
57
174
|
def self.apply_env_from_uri(env, uri, prefix: DEFAULT_DATABASE_PREFIX)
|
|
58
175
|
env[prefixed_key(prefix, 'URL')] = uri.to_s
|
|
59
176
|
env[prefixed_key(prefix, 'ADAPTER')] = uri.scheme
|
|
@@ -69,11 +186,16 @@ module BBK
|
|
|
69
186
|
end
|
|
70
187
|
end
|
|
71
188
|
|
|
189
|
+
# Собирает объекты URI для MQ из переменных окружения с поддержкой нескольких хостов.
|
|
190
|
+
#
|
|
191
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV
|
|
192
|
+
# @return [Array<URI>] Массив объектов URI (по одному на каждый хост)
|
|
193
|
+
# @api private
|
|
72
194
|
def self.build_mq_uri_with_defaults(env)
|
|
73
|
-
#
|
|
195
|
+
# Только первый MQ_URL выбирается как шаблон, если их несколько
|
|
74
196
|
url = [env.fetch('MQ_URL', '').split(/[;|]/)].flatten.select(&:present?).first || ''
|
|
75
197
|
|
|
76
|
-
#
|
|
198
|
+
# Все хосты в виде списка заполняют шаблон URL
|
|
77
199
|
hosts = [env.fetch('MQ_HOST',
|
|
78
200
|
URI.parse(url).hostname || 'mq').split(/[;|]/)].flatten.select(&:present?).uniq
|
|
79
201
|
|
|
@@ -95,6 +217,12 @@ module BBK
|
|
|
95
217
|
end
|
|
96
218
|
end
|
|
97
219
|
|
|
220
|
+
# Раскладывает URI для MQ в переменные окружения.
|
|
221
|
+
#
|
|
222
|
+
# @param env [Hash{String=>String}, ENV] Хэш переменных окружения или объект ENV (изменяется in-place)
|
|
223
|
+
# @param uris [Array<URI>] Массив объектов URI
|
|
224
|
+
# @return [void]
|
|
225
|
+
# @api private
|
|
98
226
|
def self.apply_mq_env_from_uri(env, uris)
|
|
99
227
|
uri = uris.first
|
|
100
228
|
|
|
@@ -111,11 +239,16 @@ module BBK
|
|
|
111
239
|
env['MQ_VHOST'] = vhost
|
|
112
240
|
end
|
|
113
241
|
|
|
242
|
+
# Конструирует имя переменной окружения с префиксом.
|
|
243
|
+
#
|
|
244
|
+
# @param prefix [String] Префикс (например, 'DATABASE')
|
|
245
|
+
# @param name [String] Имя переменной (например, 'HOST')
|
|
246
|
+
# @return [String] Объединенное имя (например, 'DATABASE_HOST')
|
|
247
|
+
# @api private
|
|
114
248
|
def self.prefixed_key(prefix, name)
|
|
115
249
|
[prefix, name].select(&:present?).join('_')
|
|
116
250
|
end
|
|
117
251
|
|
|
118
252
|
end
|
|
119
253
|
end
|
|
120
|
-
end
|
|
121
|
-
|
|
254
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bbk-utils
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.6.
|
|
4
|
+
version: 1.1.6.409139
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samoilenko Yuri
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|