lhm-shopify 3.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +34 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +183 -0
- data/.travis.yml +21 -0
- data/CHANGELOG.md +216 -0
- data/Gemfile +5 -0
- data/LICENSE +27 -0
- data/README.md +284 -0
- data/Rakefile +22 -0
- data/bin/.gitkeep +0 -0
- data/dbdeployer/config.json +32 -0
- data/dbdeployer/install.sh +64 -0
- data/dev.yml +20 -0
- data/gemfiles/ar-2.3_mysql.gemfile +6 -0
- data/gemfiles/ar-3.2_mysql.gemfile +5 -0
- data/gemfiles/ar-3.2_mysql2.gemfile +5 -0
- data/gemfiles/ar-4.0_mysql2.gemfile +5 -0
- data/gemfiles/ar-4.1_mysql2.gemfile +5 -0
- data/gemfiles/ar-4.2_mysql2.gemfile +5 -0
- data/gemfiles/ar-5.0_mysql2.gemfile +5 -0
- data/lhm.gemspec +34 -0
- data/lib/lhm.rb +131 -0
- data/lib/lhm/atomic_switcher.rb +52 -0
- data/lib/lhm/chunk_finder.rb +32 -0
- data/lib/lhm/chunk_insert.rb +51 -0
- data/lib/lhm/chunker.rb +87 -0
- data/lib/lhm/cleanup/current.rb +74 -0
- data/lib/lhm/command.rb +48 -0
- data/lib/lhm/entangler.rb +117 -0
- data/lib/lhm/intersection.rb +51 -0
- data/lib/lhm/invoker.rb +98 -0
- data/lib/lhm/locked_switcher.rb +74 -0
- data/lib/lhm/migration.rb +43 -0
- data/lib/lhm/migrator.rb +237 -0
- data/lib/lhm/printer.rb +59 -0
- data/lib/lhm/railtie.rb +9 -0
- data/lib/lhm/sql_helper.rb +77 -0
- data/lib/lhm/sql_retry.rb +61 -0
- data/lib/lhm/table.rb +121 -0
- data/lib/lhm/table_name.rb +23 -0
- data/lib/lhm/test_support.rb +35 -0
- data/lib/lhm/throttler.rb +36 -0
- data/lib/lhm/throttler/slave_lag.rb +145 -0
- data/lib/lhm/throttler/threads_running.rb +53 -0
- data/lib/lhm/throttler/time.rb +29 -0
- data/lib/lhm/timestamp.rb +11 -0
- data/lib/lhm/version.rb +6 -0
- data/shipit.rubygems.yml +0 -0
- data/spec/.lhm.example +4 -0
- data/spec/README.md +58 -0
- data/spec/fixtures/bigint_table.ddl +4 -0
- data/spec/fixtures/composite_primary_key.ddl +7 -0
- data/spec/fixtures/custom_primary_key.ddl +6 -0
- data/spec/fixtures/destination.ddl +6 -0
- data/spec/fixtures/lines.ddl +7 -0
- data/spec/fixtures/origin.ddl +6 -0
- data/spec/fixtures/permissions.ddl +5 -0
- data/spec/fixtures/small_table.ddl +4 -0
- data/spec/fixtures/tracks.ddl +5 -0
- data/spec/fixtures/users.ddl +14 -0
- data/spec/fixtures/wo_id_int_column.ddl +6 -0
- data/spec/integration/atomic_switcher_spec.rb +93 -0
- data/spec/integration/chunk_insert_spec.rb +29 -0
- data/spec/integration/chunker_spec.rb +185 -0
- data/spec/integration/cleanup_spec.rb +136 -0
- data/spec/integration/entangler_spec.rb +66 -0
- data/spec/integration/integration_helper.rb +237 -0
- data/spec/integration/invoker_spec.rb +33 -0
- data/spec/integration/lhm_spec.rb +585 -0
- data/spec/integration/lock_wait_timeout_spec.rb +30 -0
- data/spec/integration/locked_switcher_spec.rb +50 -0
- data/spec/integration/sql_retry/lock_wait_spec.rb +125 -0
- data/spec/integration/sql_retry/lock_wait_timeout_test_helper.rb +101 -0
- data/spec/integration/table_spec.rb +91 -0
- data/spec/test_helper.rb +32 -0
- data/spec/unit/atomic_switcher_spec.rb +31 -0
- data/spec/unit/chunk_finder_spec.rb +73 -0
- data/spec/unit/chunk_insert_spec.rb +44 -0
- data/spec/unit/chunker_spec.rb +166 -0
- data/spec/unit/entangler_spec.rb +124 -0
- data/spec/unit/intersection_spec.rb +51 -0
- data/spec/unit/lhm_spec.rb +29 -0
- data/spec/unit/locked_switcher_spec.rb +51 -0
- data/spec/unit/migrator_spec.rb +146 -0
- data/spec/unit/printer_spec.rb +97 -0
- data/spec/unit/sql_helper_spec.rb +32 -0
- data/spec/unit/table_name_spec.rb +39 -0
- data/spec/unit/table_spec.rb +47 -0
- data/spec/unit/throttler/slave_lag_spec.rb +317 -0
- data/spec/unit/throttler/threads_running_spec.rb +64 -0
- data/spec/unit/throttler_spec.rb +124 -0
- data/spec/unit/unit_helper.rb +13 -0
- metadata +239 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2011 - 2013, SoundCloud, Rany Keddo, Tobias Bielohlawek, Tobias Schmidt
|
2
|
+
|
3
|
+
All rights reserved.
|
4
|
+
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
- Redistributions of source code must retain the above copyright notice, this
|
9
|
+
list of conditions and the following disclaimer.
|
10
|
+
- Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
- Neither the name of the SoundCloud nor the names of its contributors may be
|
14
|
+
used to endorse or promote products derived from this software without
|
15
|
+
specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
21
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
data/README.md
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
# Large Hadron Migrator
|
2
|
+
|
3
|
+
[![Tests](https://github.com/Shopify/lhm/actions/workflows/test.yml/badge.svg)](https://github.com/Shopify/lhm/actions/workflows/test.yml)
|
4
|
+
|
5
|
+
This is the Shopify fork of [SoundCloud's LHM](https://github.com/soundcloud/lhm). The
|
6
|
+
following description, originally from SoundCloud (with minor updates by Shopify),
|
7
|
+
gives some of the flavor around its original creation, and its choice of name...
|
8
|
+
|
9
|
+
Rails-style database migrations are a useful way to evolve your database schema in
|
10
|
+
an agile manner. Most Rails projects start like this, and at first, making
|
11
|
+
changes is fast and easy.
|
12
|
+
|
13
|
+
That is, until your tables grow to millions or billions of records. At this point,
|
14
|
+
the locking nature of `ALTER TABLE` may take your site down for hours or more
|
15
|
+
while critical tables are migrated. In order to avoid this, developers begin
|
16
|
+
to design around the problem by introducing join tables or moving the data
|
17
|
+
into another layer. Development gets less and less agile as tables grow and
|
18
|
+
grow. To make the problem worse, adding or changing indices to optimize data
|
19
|
+
access becomes just as difficult.
|
20
|
+
|
21
|
+
*Side effects may include black holes and universe implosion.*
|
22
|
+
|
23
|
+
There are few things that can be done at the server or engine level. It is
|
24
|
+
possible to change default values in an `ALTER TABLE` without locking the
|
25
|
+
table. InnoDB provides facilities for online index creation, but that only
|
26
|
+
solves half the problem.
|
27
|
+
|
28
|
+
At SoundCloud we started having migration pains quite a while ago, and after
|
29
|
+
looking around for third party solutions, we decided to create our
|
30
|
+
own. We called it **Large Hadron Migrator**, and it is a Ruby Gem that provides
|
31
|
+
facilities for online ActiveRecord migrations.
|
32
|
+
|
33
|
+
![The Large Hadron Collider at CERN](http://farm4.static.flickr.com/3093/2844971993_17f2ddf2a8_z.jpg)
|
34
|
+
|
35
|
+
The [Large Hadron Collider](http://en.wikipedia.org/wiki/Large_Hadron_Collider) at [CERN](https://en.wikipedia.org/wiki/CERN) near Geneva, Switzerland.
|
36
|
+
|
37
|
+
## The idea
|
38
|
+
|
39
|
+
The basic idea is to perform the migration online while the system is live,
|
40
|
+
without locking the table. In contrast to [OAK][0] and the [facebook tool][1], we
|
41
|
+
only use a copy table and triggers.
|
42
|
+
|
43
|
+
LHM is a test-driven Ruby solution which can easily be dropped into an ActiveRecord
|
44
|
+
migration. It presumes a single auto-incremented numeric primary key called `id` as
|
45
|
+
per the Rails convention. Unlike [Matt Freels's `table_migrator` solution][2],
|
46
|
+
it does not require the presence of an indexed `updated_at` column.
|
47
|
+
|
48
|
+
## Requirements
|
49
|
+
|
50
|
+
LHM currently only works with MySQL databases and requires an established
|
51
|
+
ActiveRecord connection.
|
52
|
+
|
53
|
+
## Limitations
|
54
|
+
|
55
|
+
Due to the Chunker implementation, LHM requires that the table to migrate has a
|
56
|
+
a single integer numeric key column named `id`.
|
57
|
+
|
58
|
+
## Installation
|
59
|
+
|
60
|
+
Install it via `gem install lhm` or by adding `gem "lhm"` to your `Gemfile`.
|
61
|
+
|
62
|
+
## Usage
|
63
|
+
|
64
|
+
You can invoke LHM directly from a plain Ruby file after connecting ActiveRecord
|
65
|
+
to your MySQL instance:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
require 'lhm'
|
69
|
+
|
70
|
+
ActiveRecord::Base.establish_connection(
|
71
|
+
:adapter => 'mysql',
|
72
|
+
:host => '127.0.0.1',
|
73
|
+
:database => 'lhm'
|
74
|
+
)
|
75
|
+
|
76
|
+
# and migrate
|
77
|
+
Lhm.change_table :users do |m|
|
78
|
+
m.add_column :arbitrary, "INT(12)"
|
79
|
+
m.add_index [:arbitrary_id, :created_at]
|
80
|
+
m.ddl("alter table %s add column flag tinyint(1)" % m.name)
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
To use LHM from an `ActiveRecord::Migration` in a Rails project, add it to your
|
85
|
+
`Gemfile`, then invoke as follows:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
require 'lhm'
|
89
|
+
|
90
|
+
class MigrateUsers < ActiveRecord::Migration
|
91
|
+
def self.up
|
92
|
+
Lhm.change_table :users do |m|
|
93
|
+
m.add_column :arbitrary, "INT(12)"
|
94
|
+
m.add_index [:arbitrary_id, :created_at]
|
95
|
+
m.ddl("alter table %s add column flag tinyint(1)" % m.name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.down
|
100
|
+
Lhm.change_table :users do |m|
|
101
|
+
m.remove_index [:arbitrary_id, :created_at]
|
102
|
+
m.remove_column :arbitrary
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
**Note:** LHM does not delete the old, leftover table. This is intentional, in order
|
109
|
+
to prevent accidental data loss. After successful or failed LHM migrations, these leftover
|
110
|
+
tables must be cleaned up.
|
111
|
+
|
112
|
+
## Throttler
|
113
|
+
|
114
|
+
LHM uses a throttling mechanism to read data in your original table. By default, 2,000 rows are read each 0.1 second. If you want to change that behaviour, you can pass an instance of a throttler with the `throttler` option. In this example, 1,000 rows will be read with a 10 second delay between each processing:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
my_throttler = Lhm::Throttler::Time.new(stride: 1000, delay: 10)
|
118
|
+
|
119
|
+
Lhm.change_table :users, throttler: my_throttler do |m|
|
120
|
+
...
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
### SlaveLag Throttler
|
125
|
+
|
126
|
+
Lhm uses by default the time throttler, however a better solution is to throttle the copy of the data
|
127
|
+
depending on the time that the slaves are behind. To use the SlaveLag throttler:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Lhm.change_table :users, throttler: :slave_lag_throttler do |m|
|
131
|
+
...
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
Or to set that as default throttler, use the following (for instance in a Rails initializer):
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
Lhm.setup_throttler(:slave_lag_throttler)
|
139
|
+
```
|
140
|
+
|
141
|
+
### ThreadsRunning Throttler
|
142
|
+
|
143
|
+
If you don't have access to connect directly to your replicas, you can also
|
144
|
+
throttle based on the number of threads running in MySQL, as a proxy for "is
|
145
|
+
this operation causing excessive load":
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
Lhm.change_table :users, throttler: :threads_running_throttler do |m|
|
149
|
+
...
|
150
|
+
end
|
151
|
+
```
|
152
|
+
|
153
|
+
Or to set that as default throttler, use the following (for instance in a Rails initializer):
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
Lhm.setup_throttler(:threads_running_throttler)
|
157
|
+
```
|
158
|
+
|
159
|
+
## Table rename strategies
|
160
|
+
|
161
|
+
There are two different table rename strategies available: `LockedSwitcher` and
|
162
|
+
`AtomicSwitcher`.
|
163
|
+
|
164
|
+
The `LockedSwitcher` strategy locks the table being migrated and issues two `ALTER TABLE` statements. The `AtomicSwitcher` uses a single atomic `RENAME TABLE` query and is the favored solution.
|
165
|
+
|
166
|
+
LHM chooses `AtomicSwitcher` if no strategy is specified, **unless** your version of MySQL is
|
167
|
+
affected by [binlog bug #39675](http://bugs.mysql.com/bug.php?id=39675). If your version is
|
168
|
+
affected, LHM will raise an error if you don't specify a strategy. You're recommended
|
169
|
+
to use the `LockedSwitcher` in these cases to avoid replication issues.
|
170
|
+
|
171
|
+
To specify the strategy in your migration:
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
Lhm.change_table :users, :atomic_switch => true do |m|
|
175
|
+
...
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
## Limiting the data that is migrated
|
180
|
+
|
181
|
+
For instances where you want to limit the data that is migrated to the new
|
182
|
+
table by some conditions, you may tell the migration to filter by a set of
|
183
|
+
conditions:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
Lhm.change_table(:sounds) do |m|
|
187
|
+
m.filter("inner join users on users.`id` = sounds.`user_id` and sounds.`public` = 1")
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
Note that this SQL will be inserted into the copy directly after the `FROM` clause
|
192
|
+
so be sure to use `INNER JOIN` or `OUTER JOIN` syntax and not comma-joins. These
|
193
|
+
conditions will not affect the triggers, so any modifications to the table
|
194
|
+
during the run will happen on the new table as well.
|
195
|
+
|
196
|
+
## Cleaning up after an interrupted Lhm run
|
197
|
+
|
198
|
+
If an LHM migration is interrupted, it may leave behind the temporary tables
|
199
|
+
and/or triggers used in the migration. If the migration is re-started, the
|
200
|
+
unexpected presence of these tables will cause an error.
|
201
|
+
|
202
|
+
In this case, `Lhm.cleanup` can be used to drop any orphaned LHM temporary tables or triggers.
|
203
|
+
|
204
|
+
To see what LHM tables/triggers are found:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
Lhm.cleanup
|
208
|
+
```
|
209
|
+
|
210
|
+
To remove any LHM tables/triggers found:
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
Lhm.cleanup(true)
|
214
|
+
```
|
215
|
+
|
216
|
+
Optionally, only remove tables up to a specific time, if you want to retain previous migrations.
|
217
|
+
|
218
|
+
Rails:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
Lhm.cleanup(true, until: 1.day.ago)
|
222
|
+
```
|
223
|
+
|
224
|
+
Ruby:
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
Lhm.cleanup(true, until: Time.now - 86400)
|
228
|
+
```
|
229
|
+
|
230
|
+
## Contributing
|
231
|
+
|
232
|
+
To run the tests:
|
233
|
+
|
234
|
+
```bash
|
235
|
+
bundle exec rake unit # unit tests
|
236
|
+
bundle exec rake integration # integration tests
|
237
|
+
bundle exec rake unit # all tests
|
238
|
+
```
|
239
|
+
|
240
|
+
You can run an individual test as follows:
|
241
|
+
|
242
|
+
```bash
|
243
|
+
bundle exec rake unit TEST=spec/integration/atomic_switcher_spec.rb
|
244
|
+
```
|
245
|
+
|
246
|
+
You can check the code coverage reporting for an individual test as follows:
|
247
|
+
|
248
|
+
```bash
|
249
|
+
rm -rf coverage
|
250
|
+
COV=1 bundle exec rake unit TEST=spec/integration/atomic_switcher_spec.rb
|
251
|
+
open coverage/index.html
|
252
|
+
```
|
253
|
+
|
254
|
+
To check the code coverage for all tests:
|
255
|
+
|
256
|
+
```bash
|
257
|
+
rm -rf coverage
|
258
|
+
COV=1 bundle exec rake unit && bundle exec rake integration
|
259
|
+
open coverage/index.html
|
260
|
+
```
|
261
|
+
|
262
|
+
### dbdeployer
|
263
|
+
|
264
|
+
The integration tests rely on a replicated configuration for MySQL. We're using
|
265
|
+
[`dbdeployer`](https://github.com/datacharmer/dbdeployer) to manage the test nodes
|
266
|
+
required to set up these configurations.
|
267
|
+
|
268
|
+
## License
|
269
|
+
|
270
|
+
The license is included as [LICENSE](LICENSE) in this directory.
|
271
|
+
|
272
|
+
## Similar solutions
|
273
|
+
|
274
|
+
* [OAK: online alter table][0]
|
275
|
+
* [Facebook][1]
|
276
|
+
* [Twitter][2]
|
277
|
+
* [pt-online-schema-change][3]
|
278
|
+
|
279
|
+
[0]: http://openarkkit.googlecode.com
|
280
|
+
[1]: http://www.facebook.com/note.php?note\_id=430801045932
|
281
|
+
[2]: https://github.com/freels/table_migrator
|
282
|
+
[3]: http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html
|
283
|
+
[4]: https://travis-ci.org/soundcloud/lhm
|
284
|
+
[5]: https://travis-ci.org/soundcloud/lhm.svg?branch=master
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
Rake::TestTask.new('unit') do |t|
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.libs << 'spec'
|
10
|
+
t.test_files = FileList['spec/unit/**/*_spec.rb']
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
Rake::TestTask.new('integration') do |t|
|
15
|
+
t.libs << 'lib'
|
16
|
+
t.libs << 'spec'
|
17
|
+
t.test_files = FileList['spec/integration/**/*_spec.rb']
|
18
|
+
t.verbose = true
|
19
|
+
end
|
20
|
+
|
21
|
+
task :specs => [:unit, :integration]
|
22
|
+
task :default => :specs
|
data/bin/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"version": "1.8.0",
|
3
|
+
"sandbox-home": "./dbdeployer/sandboxes",
|
4
|
+
"sandbox-binary": "./dbdeployer/binaries",
|
5
|
+
"use-sandbox-catalog": true,
|
6
|
+
"master-slave-base-port": 11000,
|
7
|
+
"group-replication-base-port": 12000,
|
8
|
+
"group-replication-sp-base-port": 13000,
|
9
|
+
"fan-in-replication-base-port": 14000,
|
10
|
+
"all-masters-replication-base-port": 15000,
|
11
|
+
"multiple-base-port": 16000,
|
12
|
+
"group-port-delta": 125,
|
13
|
+
"mysqlx-port-delta": 10000,
|
14
|
+
"master-name": "master",
|
15
|
+
"master-abbr": "m",
|
16
|
+
"node-prefix": "node",
|
17
|
+
"slave-prefix": "slave",
|
18
|
+
"slave-abbr": "s",
|
19
|
+
"sandbox-prefix": "msb_",
|
20
|
+
"master-slave-prefix": "rsandbox_",
|
21
|
+
"group-prefix": "group_msb_",
|
22
|
+
"group-sp-prefix": "group_sp_msb_",
|
23
|
+
"multiple-prefix": "multi_msb_",
|
24
|
+
"fan-in-prefix": "fan_in_msb_",
|
25
|
+
"all-masters-prefix": "all_masters_msb_",
|
26
|
+
"reserved-ports": [
|
27
|
+
1186,
|
28
|
+
3306,
|
29
|
+
33060
|
30
|
+
],
|
31
|
+
"timestamp": "Mon Jul 16 17:36:55 AST 2018"
|
32
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
set -e
|
2
|
+
mkdir -p ./dbdeployer/sandboxes
|
3
|
+
mkdir -p ./dbdeployer/binaries
|
4
|
+
|
5
|
+
if [ -z "$(uname | grep Darwin)" ]; then
|
6
|
+
OS=linux
|
7
|
+
set -x
|
8
|
+
else
|
9
|
+
OS=osx
|
10
|
+
fi
|
11
|
+
|
12
|
+
echo "Checking if dbdeployer is installed"
|
13
|
+
if ! [ -x "$(command -v ./bin/dbdeployer)" ]; then
|
14
|
+
echo "Not installed...starting install"
|
15
|
+
VERSION=1.56.0
|
16
|
+
origin=https://github.com/datacharmer/dbdeployer/releases/download/v$VERSION
|
17
|
+
filename=dbdeployer-$VERSION.$OS
|
18
|
+
wget -q $origin/$filename.tar.gz
|
19
|
+
tar -xzf $filename.tar.gz
|
20
|
+
chmod +x $filename
|
21
|
+
sudo mv $filename ./bin/dbdeployer
|
22
|
+
rm $filename.tar.gz
|
23
|
+
else
|
24
|
+
echo "Installation found!"
|
25
|
+
fi
|
26
|
+
|
27
|
+
|
28
|
+
echo "Checking if mysql 5.7.22 is available for dbdeployer"
|
29
|
+
if [ -z "$(./bin/dbdeployer --config ./dbdeployer/config.json --sandbox-binary "./dbdeployer/binaries" available | grep 5.7.22)" ]; then
|
30
|
+
echo "Not found..."
|
31
|
+
|
32
|
+
if [ "$OS" = "linux" ]; then
|
33
|
+
MYSQL_FILE=mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz
|
34
|
+
else
|
35
|
+
MYSQL_FILE=mysql-5.7.22-macos10.13-x86_64.tar.gz
|
36
|
+
fi
|
37
|
+
|
38
|
+
if [ ! -f $MYSQL_FILE ]; then
|
39
|
+
echo "Downloading $MYSQL_FILE...(this may take a while)"
|
40
|
+
wget -q "https://dev.mysql.com/get/Downloads/MySQL-5.7/$MYSQL_FILE"
|
41
|
+
fi
|
42
|
+
|
43
|
+
echo "Setting up..."
|
44
|
+
./bin/dbdeployer unpack $MYSQL_FILE --verbosity 0 --config ./dbdeployer/config.json --sandbox-binary "./dbdeployer/binaries"
|
45
|
+
rm $MYSQL_FILE
|
46
|
+
else
|
47
|
+
echo "mysql 5.7.22 found!"
|
48
|
+
fi
|
49
|
+
|
50
|
+
echo "Forcing new replication setup..."
|
51
|
+
./bin/dbdeployer deploy replication 5.7.22 --nodes 2 --force --config ./dbdeployer/config.json --sandbox-binary "./dbdeployer/binaries" --sandbox-home "./dbdeployer/sandboxes"
|
52
|
+
./bin/dbdeployer global status --config ./dbdeployer/config.json --sandbox-binary "./dbdeployer/binaries" --sandbox-home "./dbdeployer/sandboxes"
|
53
|
+
|
54
|
+
echo "Setting up database.yml"
|
55
|
+
DATABASE_YML=spec/integration/database.yml
|
56
|
+
echo "master:" > $DATABASE_YML
|
57
|
+
cat ./dbdeployer/sandboxes/rsandbox_5_7_22/master/my.sandbox.cnf | grep -A 4 client | tail -n 4 | sed -e 's/ * = /: /' -e 's/^/ /' >> $DATABASE_YML
|
58
|
+
|
59
|
+
echo "slave:" >> $DATABASE_YML
|
60
|
+
cat ./dbdeployer/sandboxes/rsandbox_5_7_22/node1/my.sandbox.cnf | grep -A 4 client | tail -n 4 | sed -e 's/ * = /: /' -e 's/^/ /' >> $DATABASE_YML
|
61
|
+
|
62
|
+
cat $DATABASE_YML
|
63
|
+
|
64
|
+
echo "You are ready to run the integration test suite..."
|
data/dev.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
name: lhm
|
2
|
+
up:
|
3
|
+
- homebrew:
|
4
|
+
- mysql-client@5.7:
|
5
|
+
or: [mysql@5.7]
|
6
|
+
conflicts: [shopify/shopify/mysql-client, mysql-connector-c, mysql, mysql-client]
|
7
|
+
- wget
|
8
|
+
- ruby: 2.6.5
|
9
|
+
- bundler
|
10
|
+
- custom:
|
11
|
+
name: Database
|
12
|
+
met?: test -f spec/integration/database.yml && test "$(./dbdeployer/sandboxes/rsandbox_5_7_22/status_all | grep on\ | wc -l | xargs echo)" = "2"
|
13
|
+
meet: ./dbdeployer/install.sh
|
14
|
+
down: ./dbdeployer/sandboxes/rsandbox_5_7_22/stop_all
|
15
|
+
|
16
|
+
commands:
|
17
|
+
unit: bundle exec rake unit
|
18
|
+
int: bundle exec rake integration
|
19
|
+
test: bundle exec rake unit && bundle exec rake integration
|
20
|
+
cov: rm -rf coverage; COV=1 bundle exec rake unit && bundle exec rake integration; open coverage/index.html
|