sync_stage 0.1.0
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 +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: []
|