multitenancy_tools 0.1.12 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Dockerfile +8 -0
- data/README.md +23 -0
- data/lib/multitenancy_tools.rb +2 -0
- data/lib/multitenancy_tools/dump/data_only.rb +38 -0
- data/lib/multitenancy_tools/dump/schema_only.rb +36 -0
- data/lib/multitenancy_tools/dump_cleaner.rb +24 -1
- data/lib/multitenancy_tools/schema_dumper.rb +10 -11
- data/lib/multitenancy_tools/table_dumper.rb +11 -12
- data/lib/multitenancy_tools/version.rb +1 -1
- data/multitenancy_tools.gemspec +1 -1
- data/scripts/bash +37 -0
- data/scripts/setup +5 -0
- metadata +12 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 29487300a4a2beaeeb630c17072466accc69b6c1a9b66be2a1860027174be30e
|
4
|
+
data.tar.gz: 33309996f228140ccbbcb81f3ef01bfec3d11290e5af40a8e2f717ccf6f07bda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 346288f4a1b022de75b601a2638fa772e6f69ded6ede08fc56a1219e9ca63f4d9d606479b145110dee3f2898ee095581a4f4f52ea117befe6f4b5929cfb15c32
|
7
|
+
data.tar.gz: 348d188521cd848777b2246974c3456edd3bd479dd51d0dd8374b55f86292fff2d37df30774f9a471188720a6dde49952891cbf41b7d115ee6de2f8f4b993296
|
data/Dockerfile
ADDED
data/README.md
CHANGED
@@ -40,6 +40,13 @@ dumper = MultitenancyTools::SchemaDumper.new('database name', 'schema name')
|
|
40
40
|
dumper.dump_to('path/to/file.sql')
|
41
41
|
```
|
42
42
|
|
43
|
+
#### Dumping from a different host and using a different username
|
44
|
+
```ruby
|
45
|
+
options = { host: 'db-on-docker', username: 'non-root-user' }
|
46
|
+
dumper = MultitenancyTools::SchemaDumper.new('database name', 'schema name', options)
|
47
|
+
dupmer.dump_to('path/to/file.sql')
|
48
|
+
```
|
49
|
+
|
43
50
|
### Dumping the content of a table to a SQL file
|
44
51
|
|
45
52
|
Like `SchemaDumper`, this tool also requires `pg_dump` to be on the `PATH`:
|
@@ -49,6 +56,13 @@ dumper = MultitenancyTools::TableDumper.new('database name', 'schema name', 'tab
|
|
49
56
|
dumper.dump_to('path/to/file.sql')
|
50
57
|
```
|
51
58
|
|
59
|
+
#### Dumping from a different host and using a different username
|
60
|
+
```ruby
|
61
|
+
options = { host: 'db-on-docker', username: 'non-root-user' }
|
62
|
+
dumper = MultitenancyTools::TableDumper.new('database name', 'schema name', 'table_name', options)
|
63
|
+
dupmer.dump_to('path/to/file.sql')
|
64
|
+
```
|
65
|
+
|
52
66
|
### Creating a new PostgreSQL schema using a SQL file as template
|
53
67
|
|
54
68
|
After using `SchemaDumper` to create the SQL template, you can use the following
|
@@ -72,6 +86,15 @@ this database *will be destroyed and recreated* on test execution.
|
|
72
86
|
You can use `bin/console` to get an interactive prompt that will allow you to
|
73
87
|
experiment.
|
74
88
|
|
89
|
+
You can also run this project using docker in your local environment. Just
|
90
|
+
ensure that you have:
|
91
|
+
|
92
|
+
* Docker equal or greater than 18.09.1
|
93
|
+
|
94
|
+
Then, build *Multitenancy Tools* image running `scripts/setup`
|
95
|
+
|
96
|
+
In order to access it's console, run `scripts/bash`
|
97
|
+
|
75
98
|
## Releasing a new version
|
76
99
|
|
77
100
|
If you are the maintainer of this project:
|
data/lib/multitenancy_tools.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'multitenancy_tools/version'
|
2
2
|
require 'multitenancy_tools/errors'
|
3
3
|
require 'multitenancy_tools/dump_cleaner'
|
4
|
+
require 'multitenancy_tools/dump/data_only'
|
5
|
+
require 'multitenancy_tools/dump/schema_only'
|
4
6
|
require 'multitenancy_tools/schema_dumper'
|
5
7
|
require 'multitenancy_tools/schema_creator'
|
6
8
|
require 'multitenancy_tools/table_dumper'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module MultitenancyTools
|
4
|
+
module Dump
|
5
|
+
class DataOnly
|
6
|
+
def initialize(options)
|
7
|
+
@schema = options.fetch(:schema)
|
8
|
+
@db = options.fetch(:database)
|
9
|
+
@host = options.fetch(:host, nil)
|
10
|
+
@user = options.fetch(:username, nil)
|
11
|
+
@table = options.fetch(:table)
|
12
|
+
end
|
13
|
+
|
14
|
+
def dump
|
15
|
+
Open3.capture3(dump_args.shelljoin)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def dump_args
|
21
|
+
args = [
|
22
|
+
'pg_dump',
|
23
|
+
'--table', "#{@schema}.#{@table}",
|
24
|
+
'--no-privileges',
|
25
|
+
'--no-tablespaces',
|
26
|
+
'--no-owner',
|
27
|
+
'--dbname', @db,
|
28
|
+
'--data-only',
|
29
|
+
'--inserts'
|
30
|
+
]
|
31
|
+
|
32
|
+
args << ['--host', @host] if @host.present?
|
33
|
+
args << ['--username', @user] if @user.present?
|
34
|
+
args.flatten
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module MultitenancyTools
|
4
|
+
module Dump
|
5
|
+
class SchemaOnly
|
6
|
+
def initialize(options)
|
7
|
+
@schema = options.fetch(:schema)
|
8
|
+
@database = options.fetch(:database)
|
9
|
+
@host = options.fetch(:host, nil)
|
10
|
+
@user = options.fetch(:username, nil)
|
11
|
+
end
|
12
|
+
|
13
|
+
def dump
|
14
|
+
Open3.capture3(dump_args.shelljoin)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def dump_args
|
20
|
+
args = [
|
21
|
+
'pg_dump',
|
22
|
+
'--schema', @schema,
|
23
|
+
'--schema-only',
|
24
|
+
'--no-privileges',
|
25
|
+
'--no-tablespaces',
|
26
|
+
'--no-owner',
|
27
|
+
'--dbname', @database,
|
28
|
+
]
|
29
|
+
|
30
|
+
args << ['--host', @host] if @host.present?
|
31
|
+
args << ['--username', @user] if @user.present?
|
32
|
+
args.flatten
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -3,7 +3,8 @@ module MultitenancyTools
|
|
3
3
|
# be present on dumps generated by {SchemaDumper} and {TableDumper}.
|
4
4
|
class DumpCleaner
|
5
5
|
# @param [String] sql
|
6
|
-
def initialize(sql)
|
6
|
+
def initialize(sql, schema_name = '')
|
7
|
+
@schema_name = schema_name
|
7
8
|
@sql = sql.dup
|
8
9
|
end
|
9
10
|
|
@@ -17,7 +18,29 @@ module MultitenancyTools
|
|
17
18
|
@sql.gsub!(/SET lock_timeout .*;\n/, '')
|
18
19
|
@sql.gsub!(/^--(?:.*)\n+/, '')
|
19
20
|
@sql.gsub!(/\n+/, "\n")
|
21
|
+
clean_schema_names!
|
22
|
+
clean_catalog_overwrites!
|
20
23
|
@sql
|
21
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Matches namespaces containing the given schema_name
|
29
|
+
#
|
30
|
+
# For instance:
|
31
|
+
# CREATE TABLE schema1.posts ();
|
32
|
+
#
|
33
|
+
# Will be replaced by:
|
34
|
+
# CREATE TABLE posts ();
|
35
|
+
def clean_schema_names!
|
36
|
+
return if @schema_name.blank?
|
37
|
+
|
38
|
+
@sql.gsub!(/\b#{@schema_name}\.([\S\D]*)/, '\1')
|
39
|
+
end
|
40
|
+
|
41
|
+
# Removes system administrators configs overwrites
|
42
|
+
def clean_catalog_overwrites!
|
43
|
+
@sql.gsub!(/SELECT pg_catalog\.set_config.*;\n/, '')
|
44
|
+
end
|
22
45
|
end
|
23
46
|
end
|
@@ -21,9 +21,11 @@ module MultitenancyTools
|
|
21
21
|
class SchemaDumper
|
22
22
|
# @param database [String] database name
|
23
23
|
# @param schema [String] schema name
|
24
|
-
def initialize(database, schema)
|
24
|
+
def initialize(database, schema, options = {})
|
25
25
|
@database = database
|
26
26
|
@schema = schema
|
27
|
+
@host = options.fetch(:host, '')
|
28
|
+
@username = options.fetch(:username, '')
|
27
29
|
end
|
28
30
|
|
29
31
|
# Generates a dump an writes it into a file. Please see {IO.new} for open
|
@@ -34,20 +36,17 @@ module MultitenancyTools
|
|
34
36
|
# @param file [String] file path
|
35
37
|
# @param mode [String] IO open mode
|
36
38
|
def dump_to(file, mode: 'w')
|
37
|
-
stdout, stderr, status =
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
'--no-owner',
|
44
|
-
'--dbname', @database
|
45
|
-
)
|
39
|
+
stdout, stderr, status = Dump::SchemaOnly.new(
|
40
|
+
schema: @schema,
|
41
|
+
host: @host,
|
42
|
+
username: @username,
|
43
|
+
database: @database
|
44
|
+
).dump
|
46
45
|
|
47
46
|
fail(PgDumpError, stderr) unless status.success?
|
48
47
|
|
49
48
|
File.open(file, mode) do |f|
|
50
|
-
f.write DumpCleaner.new(stdout).clean
|
49
|
+
f.write DumpCleaner.new(stdout, @schema).clean
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
@@ -20,10 +20,12 @@ module MultitenancyTools
|
|
20
20
|
# @param database [String] database name
|
21
21
|
# @param schema [String] schema name
|
22
22
|
# @param table [String] table name
|
23
|
-
def initialize(database, schema, table)
|
23
|
+
def initialize(database, schema, table, options = {})
|
24
24
|
@database = database
|
25
25
|
@schema = schema
|
26
26
|
@table = table
|
27
|
+
@host = options.fetch(:host, '')
|
28
|
+
@username = options.fetch(:username, '')
|
27
29
|
end
|
28
30
|
|
29
31
|
# Generates a dump an writes it into a file. Please see {IO.new} for open
|
@@ -34,21 +36,18 @@ module MultitenancyTools
|
|
34
36
|
# @param file [String] file path
|
35
37
|
# @param mode [String] IO open mode
|
36
38
|
def dump_to(file, mode: 'w')
|
37
|
-
stdout, stderr, status =
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
'--inserts',
|
45
|
-
'--dbname', @database
|
46
|
-
)
|
39
|
+
stdout, stderr, status = Dump::DataOnly.new(
|
40
|
+
table: @table,
|
41
|
+
schema: @schema,
|
42
|
+
database: @database,
|
43
|
+
host: @host,
|
44
|
+
username: @username
|
45
|
+
).dump
|
47
46
|
|
48
47
|
fail(PgDumpError, stderr) unless status.success?
|
49
48
|
|
50
49
|
File.open(file, mode) do |f|
|
51
|
-
f.write DumpCleaner.new(stdout).clean
|
50
|
+
f.write DumpCleaner.new(stdout, @schema).clean
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
data/multitenancy_tools.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
|
23
23
|
spec.add_dependency 'activerecord', '~> 4.2.0'
|
24
24
|
spec.add_dependency 'activesupport', '~> 4.2.0'
|
25
|
-
spec.add_dependency 'pg'
|
25
|
+
spec.add_dependency 'pg', '< 1'
|
26
26
|
|
27
27
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
28
28
|
spec.add_development_dependency 'rake', '~> 10.0'
|
data/scripts/bash
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
export POSTGRES_CONTAINER_NAME="postgres"
|
6
|
+
|
7
|
+
# removed old pg containers running in your machine
|
8
|
+
# searches for containers with name "postgres"
|
9
|
+
remove_old_pg_container() {
|
10
|
+
container_id=$(docker ps -a --filter name="^$POSTGRES_CONTAINER_NAME$" --format {{.ID}})
|
11
|
+
|
12
|
+
if [ "$container_id" ]; then
|
13
|
+
docker stop $container_id
|
14
|
+
docker rm $container_id
|
15
|
+
fi
|
16
|
+
}
|
17
|
+
|
18
|
+
# destroys previous postgres containers and starts a new one
|
19
|
+
# with fresh data. This prevents problems in running it with
|
20
|
+
# a prepoulated volume containing old tables.
|
21
|
+
setup_db_container() {
|
22
|
+
remove_old_pg_container
|
23
|
+
|
24
|
+
docker run --detach \
|
25
|
+
--publish 5432:5432 \
|
26
|
+
--hostname $POSTGRES_CONTAINER_NAME \
|
27
|
+
--name $POSTGRES_CONTAINER_NAME postgres:9.3
|
28
|
+
}
|
29
|
+
|
30
|
+
# ignores docker containers IDs outputs to stdout
|
31
|
+
setup_db_container &>/dev/null
|
32
|
+
|
33
|
+
# brings up main container with multitenancy tools environment
|
34
|
+
docker run -it \
|
35
|
+
-v $PWD:/mtools \
|
36
|
+
--workdir /mtools --user $EUID \
|
37
|
+
--link $POSTGRES_CONTAINER_NAME mtools bash
|
data/scripts/setup
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multitenancy_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lenon Marcel
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2019-02-15 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activerecord
|
@@ -45,16 +45,16 @@ dependencies:
|
|
45
45
|
name: pg
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
|
-
- - "
|
48
|
+
- - "<"
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: '
|
50
|
+
version: '1'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- - "
|
55
|
+
- - "<"
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: '
|
57
|
+
version: '1'
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: bundler
|
60
60
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,6 +138,7 @@ files:
|
|
138
138
|
- ".gitignore"
|
139
139
|
- ".rspec"
|
140
140
|
- ".travis.yml"
|
141
|
+
- Dockerfile
|
141
142
|
- Gemfile
|
142
143
|
- LICENSE.txt
|
143
144
|
- README.md
|
@@ -145,6 +146,8 @@ files:
|
|
145
146
|
- bin/console
|
146
147
|
- bin/setup
|
147
148
|
- lib/multitenancy_tools.rb
|
149
|
+
- lib/multitenancy_tools/dump/data_only.rb
|
150
|
+
- lib/multitenancy_tools/dump/schema_only.rb
|
148
151
|
- lib/multitenancy_tools/dump_cleaner.rb
|
149
152
|
- lib/multitenancy_tools/errors.rb
|
150
153
|
- lib/multitenancy_tools/extensions_dumper.rb
|
@@ -157,6 +160,8 @@ files:
|
|
157
160
|
- lib/multitenancy_tools/table_dumper.rb
|
158
161
|
- lib/multitenancy_tools/version.rb
|
159
162
|
- multitenancy_tools.gemspec
|
163
|
+
- scripts/bash
|
164
|
+
- scripts/setup
|
160
165
|
homepage: https://github.com/locaweb/multitenancy_tools
|
161
166
|
licenses:
|
162
167
|
- MIT
|
@@ -176,10 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
181
|
- !ruby/object:Gem::Version
|
177
182
|
version: '0'
|
178
183
|
requirements: []
|
179
|
-
|
180
|
-
rubygems_version: 2.4.5.1
|
184
|
+
rubygems_version: 3.0.2
|
181
185
|
signing_key:
|
182
186
|
specification_version: 4
|
183
187
|
summary: A collection of tools for multitenant Ruby/Rails apps
|
184
188
|
test_files: []
|
185
|
-
has_rdoc:
|