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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64b2a2381ebeca46d78d55e1c60ae743574cba05e521dab121f58b633ab7020e
4
- data.tar.gz: 83548d76917b9c7db035133e0131ec0dfe0934db80893d9e22cd7a7eaa8582c8
3
+ metadata.gz: bfa5eb9e2309dbcb2cf03355c6f5e138789f8fe9e2b3c7ab670de90d6d3ac55a
4
+ data.tar.gz: 4cff866be86f922c0ac2e008cec177e674ee3a28b4d884e501809740e9eb169d
5
5
  SHA512:
6
- metadata.gz: 438461a1fced07b637c5a582b7a058ec6bd79a541e69433a4a5907bfd71da7207803323b11dcffd409130669e438ddd81b4faff20a0c8538594d8fd6ec801dda
7
- data.tar.gz: 9c62f0ad4172188406b59151fc52fa9164fd5bc05cd4ea44134b5c3fa6e5ac2ef352f5c07c842328ba76fe750b9ab1c59d792c9cb4197291ab049c5999073aec
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` добавить источник данных. Сейчас доступны 2 источника:
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 2 source types now:
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Gorynich
2
- VERSION = '1.1.1'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -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.1.1.148381
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-06-05 00:00:00.000000000 Z
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