sync_stage 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/sync_stage +87 -0
- data/lib/config/sync_stage.yml +13 -0
- data/lib/sync_stage.rb +194 -0
- metadata +48 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4e34cfd09708a90565acd4bdb43e1f3830033afc
|
4
|
+
data.tar.gz: 9929baa91e3561aa29aa5d37d06a151aa1cc0e4e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2f628cf1467eb82d12da6dc5b1e30d5b2f707bdeb8f9609b638d0a99d473b555f672c5dffc15929ac1ebc97de51badee3369ded72d1f76b61cc1759611e8592d
|
7
|
+
data.tar.gz: f504916ed256d5e270ca2f955281afc94104c3892ac5461541f0262c2034a0cf73dbec9b5c03ec2f7a18e9b87f0a02c06ad22d93dc37869bc8c550e572db9aa0
|
data/bin/sync_stage
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'sync_stage'
|
4
|
+
require 'getoptlong'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
opts = GetoptLong.new(
|
8
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
9
|
+
[ '--init', '-i', GetoptLong::NO_ARGUMENT ],
|
10
|
+
[ '--run', '-r', GetoptLong::NO_ARGUMENT ],
|
11
|
+
[ '--restore', GetoptLong::NO_ARGUMENT ],
|
12
|
+
[ '--explain', GetoptLong::NO_ARGUMENT],
|
13
|
+
[ '--app', '-a', GetoptLong::REQUIRED_ARGUMENT ]
|
14
|
+
)
|
15
|
+
|
16
|
+
app = nil
|
17
|
+
init = nil
|
18
|
+
run = nil
|
19
|
+
restore = nil
|
20
|
+
explain = nil
|
21
|
+
|
22
|
+
if ARGV.length == 0
|
23
|
+
puts "missing argument try --help"
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.each do |opt, arg|
|
27
|
+
case opt
|
28
|
+
when '--help'
|
29
|
+
puts <<-EOF
|
30
|
+
sync_stage [OPTION]
|
31
|
+
|
32
|
+
-h, --help:
|
33
|
+
show help
|
34
|
+
|
35
|
+
--init, -i:
|
36
|
+
initializes sync_stage config in current directory
|
37
|
+
or in --dir if --dir is given
|
38
|
+
|
39
|
+
--explain:
|
40
|
+
print out what would happen, but dont actually run the commands
|
41
|
+
|
42
|
+
--run, -r:
|
43
|
+
actually start the dump, pack, copy over to destination
|
44
|
+
|
45
|
+
|
46
|
+
--app DIR, -a DIR:
|
47
|
+
use given Directory
|
48
|
+
|
49
|
+
--restore:
|
50
|
+
pg_restore the database and unpack shared/public
|
51
|
+
on destination system
|
52
|
+
|
53
|
+
EOF
|
54
|
+
exit 0
|
55
|
+
when '--app'
|
56
|
+
app = arg
|
57
|
+
when '--init'
|
58
|
+
init = true
|
59
|
+
when '--run'
|
60
|
+
run = true
|
61
|
+
when '--restore'
|
62
|
+
restore = true
|
63
|
+
when '--explain'
|
64
|
+
explain = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
if init && run
|
70
|
+
puts "incompatible arguments -i and -r"
|
71
|
+
exit 0
|
72
|
+
end
|
73
|
+
|
74
|
+
if init
|
75
|
+
cfg = OpenStruct.new(app: app||Dir.pwd, init: true)
|
76
|
+
st = SyncStage::Worker.new(cfg)
|
77
|
+
exit 0
|
78
|
+
end
|
79
|
+
|
80
|
+
if app && !run
|
81
|
+
puts "missing argument -r to run"
|
82
|
+
end
|
83
|
+
|
84
|
+
if run
|
85
|
+
cfg = OpenStruct.new(app: app||Dir.pwd, run: run, restore: restore, explain: explain)
|
86
|
+
st = SyncStage::Worker.new(cfg)
|
87
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
:source:
|
2
|
+
:host: www.example.com
|
3
|
+
:user: deploymentuser
|
4
|
+
:db: app_production
|
5
|
+
:dbuser: user
|
6
|
+
:shared_dir: /var/www/www.example.com/shared
|
7
|
+
|
8
|
+
:destination:
|
9
|
+
:host: staging.example.com
|
10
|
+
:user: deploymentuser
|
11
|
+
:db: app_staging
|
12
|
+
:dbuser: user
|
13
|
+
:shared_dir: /var/www/staging.example.com/shared
|
data/lib/sync_stage.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
module SyncStage
|
7
|
+
class Worker
|
8
|
+
|
9
|
+
def initialize(cfg)
|
10
|
+
s = Time.now
|
11
|
+
Dir.chdir(cfg.app) do
|
12
|
+
if !File.exist?('sync_stage.yml')
|
13
|
+
if ! cfg.init
|
14
|
+
puts "Directory not initialized - try argument --init or see --help"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
if cfg.init
|
18
|
+
create_example_config(cfg.app)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
read_config
|
22
|
+
end
|
23
|
+
end
|
24
|
+
if cfg.explain
|
25
|
+
explain(cfg.restore)
|
26
|
+
exit 0
|
27
|
+
end
|
28
|
+
if cfg.run
|
29
|
+
run(cfg.restore)
|
30
|
+
end
|
31
|
+
duration = Time.now - s
|
32
|
+
puts "synced data \nfrom #{@config[:source].fetch(:host)} to #{@config[:destination].fetch(:host)} \n
|
33
|
+
done in #{duration.ceil} seconds."
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def explain(restore)
|
39
|
+
puts "sync_stage would use following settings: \n\n"
|
40
|
+
pp @config
|
41
|
+
|
42
|
+
cmds = []
|
43
|
+
cmds.push(ssh_cmd(@config[:source]) << "'" << pg_dump_cmd(@config[:source]) << "'")
|
44
|
+
cmds.push(ssh_cmd(@config[:source]) << "'" << pack_assets_cmd(@config[:source]) << "'")
|
45
|
+
cmds.push(copy_db_cmd(@config[:source], @config[:destination]))
|
46
|
+
cmds.push(copy_assets_cmd(@config[:source], @config[:destination]))
|
47
|
+
if restore
|
48
|
+
cmds.push(ssh_cmd(@config[:destination]) << "-t '" <<
|
49
|
+
pg_restore_cmd(@config[:source], @config[:destination]) << "'")
|
50
|
+
cmds.push(ssh_cmd(@config[:destination]) << "'" <<
|
51
|
+
unpack_assets_cmd(@config[:source], @config[:destination]) << "'")
|
52
|
+
end
|
53
|
+
puts "\nand run the following commands in order: \n\n"
|
54
|
+
cmds.each_with_index do |c,i|
|
55
|
+
puts "#{i} $: " << c
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def run(restore)
|
61
|
+
puts "this could take a while....\n"
|
62
|
+
execute_db_dump
|
63
|
+
execute_asset_packing
|
64
|
+
execute_db_copying
|
65
|
+
execute_asset_copying
|
66
|
+
if restore
|
67
|
+
execute_db_restoring
|
68
|
+
execute_asset_unpacking
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def execute_db_dump
|
73
|
+
ret = system(ssh_cmd(@config[:source]) << "'" << pg_dump_cmd(@config[:source]) << "'")
|
74
|
+
if ret
|
75
|
+
puts "done dumping database"
|
76
|
+
else
|
77
|
+
raise "error dumping database"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def execute_asset_packing
|
82
|
+
ret = system(ssh_cmd(@config[:source]) << "'" << pack_assets_cmd(@config[:source]) << "'")
|
83
|
+
if ret
|
84
|
+
puts "done packing shared directory"
|
85
|
+
else
|
86
|
+
raise "error packing shared directory"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def execute_db_copying
|
91
|
+
ret = system(copy_db_cmd(@config[:source], @config[:destination]))
|
92
|
+
if ret
|
93
|
+
puts "done copying database over"
|
94
|
+
else
|
95
|
+
raise "error copying database over"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def execute_asset_copying
|
100
|
+
puts "start to copy over shared dir... be patient..."
|
101
|
+
ret = system(copy_assets_cmd(@config[:source], @config[:destination]))
|
102
|
+
if ret
|
103
|
+
puts "done copying assets"
|
104
|
+
else
|
105
|
+
raise "error copying assets over"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def execute_db_restoring
|
110
|
+
ret = system(ssh_cmd(@config[:destination]) << " -t '" <<
|
111
|
+
pg_restore_cmd(@config[:source], @config[:destination]) << "'")
|
112
|
+
if ret
|
113
|
+
puts "done restoring database"
|
114
|
+
else
|
115
|
+
raise "error restoring database"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def execute_asset_unpacking
|
120
|
+
ret = system(ssh_cmd(@config[:destination]) << "'" << unpack_assets_cmd(@config[:source], @config[:destination]) << "'")
|
121
|
+
if ret
|
122
|
+
puts "done unpacking shared dir"
|
123
|
+
else
|
124
|
+
raise "error unpacking shared dir"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def pg_dump_cmd(opts)
|
129
|
+
str = "pg_dump -U #{opts.fetch(:dbuser)} -h localhost -Fc #{opts.fetch(:db)} -f ~/#{opts.fetch(:db)}.sql"
|
130
|
+
str
|
131
|
+
end
|
132
|
+
|
133
|
+
def pack_assets_cmd(opts)
|
134
|
+
str = "cd #{opts.fetch(:shared_dir)} && tar cvfzp ~/#{opts.fetch(:host)}-shared.tgz ./public"
|
135
|
+
str
|
136
|
+
end
|
137
|
+
|
138
|
+
def ssh_cmd(opts)
|
139
|
+
"ssh -l #{opts.fetch(:user)} #{opts.fetch(:host)} "
|
140
|
+
end
|
141
|
+
|
142
|
+
def copy_db_cmd(from_opts, to_opts)
|
143
|
+
str = "scp #{from_opts.fetch(:user)}@#{from_opts.fetch(:host)}:~/#{from_opts.fetch(:db)}.sql "
|
144
|
+
str << " #{to_opts.fetch(:user)}@#{to_opts.fetch(:host)}:~/"
|
145
|
+
str
|
146
|
+
end
|
147
|
+
|
148
|
+
def copy_assets_cmd(from_opts, to_opts)
|
149
|
+
str = "scp #{from_opts.fetch(:user)}@#{from_opts.fetch(:host)}:~/#{from_opts.fetch(:host)}-shared.tgz "
|
150
|
+
str << " #{to_opts.fetch(:user)}@#{to_opts.fetch(:host)}:#{to_opts.fetch(:shared_dir)}/"
|
151
|
+
str
|
152
|
+
end
|
153
|
+
|
154
|
+
def pg_restore_cmd(src, dest)
|
155
|
+
str = "sudo -u postgres pg_restore -U postgres -v -d #{dest.fetch(:db)} -c #{src.fetch(:db)}.sql"
|
156
|
+
str
|
157
|
+
end
|
158
|
+
|
159
|
+
def unpack_assets_cmd(src, dest)
|
160
|
+
str = "cd #{dest.fetch(:shared_dir)} &&
|
161
|
+
mv public public-#{Time.now.to_i} &&
|
162
|
+
tar xvfzp #{src.fetch(:host)}-shared.tgz"
|
163
|
+
str
|
164
|
+
end
|
165
|
+
|
166
|
+
def create_example_config(dir)
|
167
|
+
puts Dir.pwd
|
168
|
+
_example = YAML::load_file(File.join(File.dirname(__FILE__),'config', 'sync_stage.yml'))
|
169
|
+
File.open('sync_stage.yml', 'w') do |f|
|
170
|
+
f.puts YAML::dump(_example)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def read_config
|
175
|
+
@config = YAML::load_file('sync_stage.yml')
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
# pack the assets
|
182
|
+
#ret = system(ssh_cmd(PRODUCTION) << "'" << pack_assets_cmd(PRODUCTION) << "'")
|
183
|
+
#ret = system(copy_assets_cmd(PRODUCTION, STAGING))
|
184
|
+
|
185
|
+
# dump the database
|
186
|
+
#ret = system(ssh_cmd(PRODUCTION) << "'" << pg_dump_cmd(PRODUCTION) << "'")
|
187
|
+
|
188
|
+
# copy db-dump to other host
|
189
|
+
#ret = system(copy_db_cmd(PRODUCTION, STAGING))
|
190
|
+
|
191
|
+
# restore db from dump
|
192
|
+
#puts "you need to be a sudoer"
|
193
|
+
#ret = system(ssh_cmd(STAGING) << " -t '" << pg_restore_cmd(PRODUCTION, STAGING) << "'")
|
194
|
+
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sync_stage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- rene paulokat
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-11 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: dumps and restores postgres database and packs shared/public over to
|
14
|
+
staging server
|
15
|
+
email: rene@so36.net
|
16
|
+
executables:
|
17
|
+
- sync_stage
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/sync_stage
|
22
|
+
- lib/config/sync_stage.yml
|
23
|
+
- lib/sync_stage.rb
|
24
|
+
homepage: https://github.com/erpe/sync_stage
|
25
|
+
licenses:
|
26
|
+
- GPLv3
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 2.4.5
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: Sync your Rails-App data back from production to staging
|
48
|
+
test_files: []
|