gorynich 1.1.1.148381 → 1.2.0.180668
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 +13 -11
- data/lib/gorynich/fetcher.rb +2 -1
- data/lib/gorynich/fetchers/consul_secure.rb +38 -0
- data/lib/gorynich/version.rb +1 -1
- data/spec/lib/gorynich/fetchers/consul_secure_spec.rb +45 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfa5eb9e2309dbcb2cf03355c6f5e138789f8fe9e2b3c7ab670de90d6d3ac55a
|
|
4
|
+
data.tar.gz: 4cff866be86f922c0ac2e008cec177e674ee3a28b4d884e501809740e9eb169d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ad533e8db97798dd44be95f527eff513f1b641a0f7bc90f6b4b7caed6ce2f104c1be1739233bc11ede063671f72634b988c56775c819dcf9276d0fbeb9341d0
|
|
7
|
+
data.tar.gz: 12464ea4be054bb26aa9c3f6934bbe1eadcb5cbc1573aabee6a13cae93b35b8aea1998113d0e485ef4c344f72e904ec5eaf3f5a44f8934ae44163ab14dd12f62
|
data/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
`Gorynich` - это гем для реализации [мультитенантности](https://ru.wikipedia.org/wiki/Мультиарендность) (мультиарендности) в Ruby on Rails приложении. Позволяет обеспечить строгую изоляцию данных в нескольких СУБД, поддерживаемых в ActiveRecord.
|
|
18
18
|
|
|
19
|
-
Поскольку мультитенантное приложение тесно связано с разделением данных, которые в свою очередь могут находиться в разных источниках (СУБД, S3, Redis и пр.), а также с их обработкой в разных подсистемах (ActiveJob, ActionCable), мы выбрали название ["Горыныч"](https://ru.wikipedia.org/wiki/Змей_Горыныч), чтобы подчеркнуть ~многоголовость~ многогранность интеграций.
|
|
19
|
+
Поскольку мультитенантное приложение тесно связано с разделением данных, которые в свою очередь могут находиться в разных источниках (СУБД, S3, Redis и пр.), а также с их обработкой в разных подсистемах (ActiveJob, ActionCable), мы выбрали название ["Горыныч"](https://ru.wikipedia.org/wiki/Змей_Горыныч), чтобы подчеркнуть ~многоголовость~ многогранность интеграций.
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -66,14 +66,14 @@ gem 'gorynich'
|
|
|
66
66
|
```sh
|
|
67
67
|
bundle install # для установки гема / gem installation
|
|
68
68
|
|
|
69
|
-
rails generate gorynich:install # для добавления шаблонов конфигурации / install configuration templates
|
|
69
|
+
rails generate gorynich:install # для добавления шаблонов конфигурации / install configuration templates
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
## Что такое тенант? / What tenant is?
|
|
73
73
|
|
|
74
74
|
Тенант (в данном случае) - это активное подключение к СУБД, а также доступный в любом месте объект `Gorynich::Current`, в котором находятся параметры текущего тенанта. К нему можно обратиться в любом месте.
|
|
75
75
|
|
|
76
|
-
---
|
|
76
|
+
---
|
|
77
77
|
|
|
78
78
|
In this case tenant is an active connection to the DBMS, as well as a `Gorynich::Current` object available anywhere, which contains the parameters of the current tenant. You can refer to it anywhere, for example when sending emails:
|
|
79
79
|
|
|
@@ -94,7 +94,7 @@ end
|
|
|
94
94
|
|
|
95
95
|
Например, при отправке писем изнутри ActiveJob использование выглядит так:
|
|
96
96
|
|
|
97
|
-
---
|
|
97
|
+
---
|
|
98
98
|
|
|
99
99
|
Before request processing [Gorynich::Rack::RackMiddleware](./lib/gorynich/head/rack_middleware.rb) ActiveRecord connection switching to apropriate database. Additional tenant properties available in any part of application through [ActiveSupport::CurrentAttributes](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html) as `Gorynich::Current` instance. ActionCable, ActiveJob and other "heads" also uses `Gorynich::Current` to store context and evaluate it later.
|
|
100
100
|
|
|
@@ -130,19 +130,21 @@ end
|
|
|
130
130
|
|
|
131
131
|
## Использование / Usage
|
|
132
132
|
|
|
133
|
-
### Настройка источника данных / Configuration source
|
|
133
|
+
### Настройка источника данных / Configuration source
|
|
134
134
|
|
|
135
|
-
Для использования необходимо в файле `config/application.rb` добавить источник данных. Сейчас доступны
|
|
135
|
+
Для использования необходимо в файле `config/application.rb` добавить источник данных. Сейчас доступны 3 источника:
|
|
136
136
|
|
|
137
137
|
---
|
|
138
138
|
|
|
139
|
-
Now you need to select configuration source in `config/application.rb`. Yuo can choose from
|
|
139
|
+
Now you need to select configuration source in `config/application.rb`. Yuo can choose from 3 source types now:
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
```ruby
|
|
143
143
|
Gorynich::Fetchers::File.new(file_path: [FILE_PATH]) # из файла / from file
|
|
144
144
|
|
|
145
145
|
Gorynich::Fetchers::Consul.new(storage: [CONSUL_KEY], **options) # из консула / from consul (options - from Dimplomat gem https://github.com/WeAreFarmGeek/diplomat)
|
|
146
|
+
|
|
147
|
+
Gorynich::Fetchers::ConsulSecure.new(storage: [CONSUL_KEY], file_path: [FILE_PATH], **options) # из консула с сохранением в файл (при недоступности консула будет читать из файла) / from consul with saving to a file (if unavailable, consul will read from the file) (options - from Dimplomat gem https://github.com/WeAreFarmGeek/diplomat)
|
|
146
148
|
```
|
|
147
149
|
|
|
148
150
|
Пример / Example:
|
|
@@ -214,7 +216,7 @@ TENANT=tenant rails gc # default tenant name id 'default'
|
|
|
214
216
|
|
|
215
217
|
Для создания статичного файла `database.yml` из источника данных (Fetcher) используйте:
|
|
216
218
|
|
|
217
|
-
---
|
|
219
|
+
---
|
|
218
220
|
|
|
219
221
|
For static `database.yml` generation from configured source (Fetcher) use:
|
|
220
222
|
|
|
@@ -228,7 +230,7 @@ rails gc:db:prepare
|
|
|
228
230
|
|
|
229
231
|
Первый, самый простой способ работы, подходящий для локальной разработки, это статическая генерация `database.yml`.
|
|
230
232
|
|
|
231
|
-
---
|
|
233
|
+
---
|
|
232
234
|
|
|
233
235
|
First and most simple using of Gorynich handy for local development is static `database.yml` generation.
|
|
234
236
|
|
|
@@ -240,7 +242,7 @@ rails gc:db:prepare
|
|
|
240
242
|
|
|
241
243
|
2. Полуавтоматический режим / Semi-automated mode
|
|
242
244
|
|
|
243
|
-
Второй вариант - это создание конфигурации `database.yml` при старте Rails приложения - данные будут прочитаны из настроенного источника. В этом случае конфигурация СУБД может изменяться только при перезапуске приложения, но остальные настройки, такие как привязка тенантов к доменам и secrets, будут подхватываться "на лету" непосредственно во время работы приложения. Rake-задачи `db:create`, `db:migrate` работают для всех тенантов на момент запуска.
|
|
245
|
+
Второй вариант - это создание конфигурации `database.yml` при старте Rails приложения - данные будут прочитаны из настроенного источника. В этом случае конфигурация СУБД может изменяться только при перезапуске приложения, но остальные настройки, такие как привязка тенантов к доменам и secrets, будут подхватываться "на лету" непосредственно во время работы приложения. Rake-задачи `db:create`, `db:migrate` работают для всех тенантов на момент запуска.
|
|
244
246
|
|
|
245
247
|
---
|
|
246
248
|
|
|
@@ -353,7 +355,7 @@ config.telegram_updates_controller.session_store = :redis_cache_store, {
|
|
|
353
355
|
}
|
|
354
356
|
```
|
|
355
357
|
|
|
356
|
-
### Shrine
|
|
358
|
+
### Shrine
|
|
357
359
|
|
|
358
360
|
```ruby
|
|
359
361
|
#lib/shrine/plugins/tenant_location.rb
|
data/lib/gorynich/fetcher.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative 'fetchers/file'
|
|
2
2
|
require_relative 'fetchers/consul'
|
|
3
|
+
require_relative 'fetchers/consul_secure'
|
|
3
4
|
|
|
4
5
|
module Gorynich
|
|
5
6
|
class Fetcher
|
|
@@ -32,7 +33,7 @@ module Gorynich
|
|
|
32
33
|
elsif @fetcher.is_a?(Array)
|
|
33
34
|
result = {}
|
|
34
35
|
@fetcher.each do |f|
|
|
35
|
-
result =
|
|
36
|
+
result =
|
|
36
37
|
begin
|
|
37
38
|
f.fetch
|
|
38
39
|
rescue ::StandardError
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Gorynich
|
|
2
|
+
module Fetchers
|
|
3
|
+
class ConsulSecure
|
|
4
|
+
attr_reader :storage, :file_path, :consul_opts
|
|
5
|
+
|
|
6
|
+
def initialize(storage:, file_path:, **opts)
|
|
7
|
+
@storage = storage
|
|
8
|
+
@file_path = file_path
|
|
9
|
+
@consul_opts = opts
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def fetch
|
|
13
|
+
cfg = Consul.new(storage: storage, **consul_opts).fetch
|
|
14
|
+
return from_file if cfg.empty?
|
|
15
|
+
|
|
16
|
+
save_to_file(cfg)
|
|
17
|
+
|
|
18
|
+
cfg
|
|
19
|
+
rescue ::StandardError
|
|
20
|
+
from_file
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def save_to_file(cfg)
|
|
26
|
+
envs = ::Dir.glob(::Rails.root.join('config/environments/*.rb').to_s).map { |f| ::File.basename(f, '.rb') }
|
|
27
|
+
|
|
28
|
+
::File.open(file_path, 'w') do |f|
|
|
29
|
+
f << cfg.deep_transform_keys(&:downcase).select { |k, _v| envs.include?(k) }.to_yaml.gsub('---', '')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def from_file
|
|
34
|
+
File.new(file_path: file_path).fetch
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/gorynich/version.rb
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
RSpec.describe Gorynich::Fetchers::ConsulSecure do
|
|
2
|
+
let(:storage) { Faker::Lorem.word }
|
|
3
|
+
let(:file_path) { "#{RSPEC_ROOT}/fixtures/fetchers/file_config.yml" }
|
|
4
|
+
let(:file_like_object) { double("file like object") }
|
|
5
|
+
|
|
6
|
+
context '#fetch' do
|
|
7
|
+
let(:consul_host) { Faker::Internet.url }
|
|
8
|
+
let(:consul_opts) { { http_addr: consul_host } }
|
|
9
|
+
|
|
10
|
+
def consul_request(response, code = 200)
|
|
11
|
+
stub_request(:get, "#{consul_host}/v1/kv/#{storage}?recurse=true")
|
|
12
|
+
.to_return(
|
|
13
|
+
status: code,
|
|
14
|
+
body: response
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
subject { described_class.new(storage: storage, file_path: file_path, **consul_opts) }
|
|
19
|
+
|
|
20
|
+
describe 'when consul return data' do
|
|
21
|
+
let(:response) { [{ 'Key' => "#{storage}/test_key", 'Value' => Base64.encode64('test') }].to_json }
|
|
22
|
+
|
|
23
|
+
before(:each) do
|
|
24
|
+
consul_request(response)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it do
|
|
28
|
+
allow(File).to receive(:open).with(file_path, 'w').and_return(file_like_object)
|
|
29
|
+
expect(subject.fetch).to eq({ 'test_key' => 'test' })
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe 'when http error' do
|
|
34
|
+
before(:each) do
|
|
35
|
+
consul_request([], 500)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it do
|
|
39
|
+
result = subject.fetch
|
|
40
|
+
expect(result.class).to eq(Hash)
|
|
41
|
+
expect(result).to include('development', 'test')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gorynich
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0.180668
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Poliev Alexey
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2023-
|
|
12
|
+
date: 2023-08-25 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: diplomat
|
|
@@ -286,6 +286,7 @@ files:
|
|
|
286
286
|
- lib/gorynich/engine.rb
|
|
287
287
|
- lib/gorynich/fetcher.rb
|
|
288
288
|
- lib/gorynich/fetchers/consul.rb
|
|
289
|
+
- lib/gorynich/fetchers/consul_secure.rb
|
|
289
290
|
- lib/gorynich/fetchers/file.rb
|
|
290
291
|
- lib/gorynich/head.rb
|
|
291
292
|
- lib/gorynich/head/action_cable.rb
|
|
@@ -358,6 +359,7 @@ files:
|
|
|
358
359
|
- spec/fixtures/test_database.yml
|
|
359
360
|
- spec/lib/gorynich/config_spec.rb
|
|
360
361
|
- spec/lib/gorynich/fetcher_spec.rb
|
|
362
|
+
- spec/lib/gorynich/fetchers/consul_secure_spec.rb
|
|
361
363
|
- spec/lib/gorynich/fetchers/consul_spec.rb
|
|
362
364
|
- spec/lib/gorynich/fetchers/file_spec.rb
|
|
363
365
|
- spec/lib/gorynich/version_spec.rb
|
|
@@ -450,6 +452,7 @@ test_files:
|
|
|
450
452
|
- spec/fixtures/test_database.yml
|
|
451
453
|
- spec/lib/gorynich/config_spec.rb
|
|
452
454
|
- spec/lib/gorynich/fetcher_spec.rb
|
|
455
|
+
- spec/lib/gorynich/fetchers/consul_secure_spec.rb
|
|
453
456
|
- spec/lib/gorynich/fetchers/consul_spec.rb
|
|
454
457
|
- spec/lib/gorynich/fetchers/file_spec.rb
|
|
455
458
|
- spec/lib/gorynich/version_spec.rb
|