snapshot_reload 1.0.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.
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rvmrc +48 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +69 -0
- data/LICENSE.txt +22 -0
- data/README.md +114 -0
- data/README.rdoc +19 -0
- data/Rakefile +66 -0
- data/bin/snapshot_reload +70 -0
- data/features/snapshot_live.feature +29 -0
- data/features/snapshot_reload.feature +171 -0
- data/features/step_definitions/snapshot_live_steps.rb +4 -0
- data/features/step_definitions/snapshot_reload_steps.rb +1 -0
- data/features/support/env.rb +17 -0
- data/lib/snapshot_reload.rb +129 -0
- data/lib/snapshot_reload/String.rb +25 -0
- data/lib/snapshot_reload/defaults.rb +18 -0
- data/lib/snapshot_reload/errors.rb +31 -0
- data/lib/snapshot_reload/fetch.rb +161 -0
- data/lib/snapshot_reload/reload.rb +69 -0
- data/lib/snapshot_reload/validate.rb +111 -0
- data/lib/snapshot_reload/version.rb +18 -0
- data/snapshot_reload.gemspec +25 -0
- data/spec/snapshot_reload_spec.rb +109 -0
- data/spec/spec_helper.rb +1 -0
- metadata +178 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Issue the actual commands to drop, create, and load the database
|
4
|
+
|
5
|
+
+Copyright:+ (c) 2012, Novu, LLC
|
6
|
+
+License:+ All rights reserved. For internal and private use only.
|
7
|
+
+Author:+ Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
=end
|
10
|
+
|
11
|
+
require 'methadone'
|
12
|
+
|
13
|
+
module SnapshotReload
|
14
|
+
class SnapshotReload
|
15
|
+
include Methadone::CLILogging
|
16
|
+
# include Methadone::CLILogger
|
17
|
+
include Methadone::SH
|
18
|
+
|
19
|
+
def reload
|
20
|
+
drop_db
|
21
|
+
create_db
|
22
|
+
load_db
|
23
|
+
end
|
24
|
+
|
25
|
+
def drop_db
|
26
|
+
mysqladmin_go("drop")
|
27
|
+
end # method drop
|
28
|
+
|
29
|
+
def create_db
|
30
|
+
mysqladmin_go("create")
|
31
|
+
end
|
32
|
+
|
33
|
+
def mysqladmin_go(command)
|
34
|
+
return false unless "drop create".include?(command)
|
35
|
+
passopt = (@password.nil? or @password.empty?) ? '' : "--password=#{@password}"
|
36
|
+
cmd = "mysqladmin --host=#{@host} --user=#{@username} #{passopt} --force #{command} #{@database}"
|
37
|
+
run_it(cmd)
|
38
|
+
end # mysqladmin_go method
|
39
|
+
|
40
|
+
def load_db
|
41
|
+
passopt = (@password.nil? or @password.empty?) ? '' : "--password=#{@password}"
|
42
|
+
fetch_snapshot
|
43
|
+
cmd = "gunzip < #{self.sql_file} | mysql --host=#{@host} --user=#{@username} #{passopt} #{@database}"
|
44
|
+
run_it(cmd)
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_it(cmd)
|
48
|
+
info("Dry-run, no commands will be executed.") if @dry_run and @verbose
|
49
|
+
info("Command issued: #{cmd}") if @verbose
|
50
|
+
unless @dry_run
|
51
|
+
sh cmd do |stdout, stderr, retval|
|
52
|
+
if retval != 0
|
53
|
+
unless cmd.match("mysqladmin.*drop") and stderr.match("database doesn't exist")
|
54
|
+
fatal("mysqladmin drop command failed:")
|
55
|
+
fatal(stdout)
|
56
|
+
fatal(stderr)
|
57
|
+
exit(EDROPFAILED)
|
58
|
+
else
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Methods to validate input
|
4
|
+
|
5
|
+
+Copyright:+ (c) 2012, Novu, LLC
|
6
|
+
+License:+ All rights reserved. For internal and private use only.
|
7
|
+
+Author:+ Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
=end
|
10
|
+
require 'methadone'
|
11
|
+
|
12
|
+
module SnapshotReload
|
13
|
+
|
14
|
+
class SnapshotReload
|
15
|
+
include Methadone::CLILogging
|
16
|
+
|
17
|
+
|
18
|
+
def validate_configuration(config_file)
|
19
|
+
|
20
|
+
unless File.exists?(config_file)
|
21
|
+
fatal("#{config_file} file does not exist")
|
22
|
+
exit(ENOCONFIG)
|
23
|
+
end
|
24
|
+
|
25
|
+
config = YAML.load(File.read(config_file))
|
26
|
+
unless config.class == Hash
|
27
|
+
fatal("#{config_file} is not YAML")
|
28
|
+
exit(ECONFIGNOTYAML)
|
29
|
+
end
|
30
|
+
|
31
|
+
debug("Config: #{config.to_s}")
|
32
|
+
|
33
|
+
config
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_environment(env,config)
|
37
|
+
env ||= ENV['RAILS_ENV'] ||= DEFAULT_ENVIRONMENT
|
38
|
+
unless config.has_key?(env)
|
39
|
+
fatal("#{env} not found in configuration")
|
40
|
+
exit(ENOENVINCONFIG)
|
41
|
+
end
|
42
|
+
|
43
|
+
debug("Env: #{env}")
|
44
|
+
env
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_source(source)
|
48
|
+
source ||= DEFAULT_S3_SOURCE
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_aws(aws_conf, aws_key = nil, aws_secret = nil)
|
52
|
+
|
53
|
+
# DONE: fix scenarios so they run this code (pass in an S3 source!!)
|
54
|
+
|
55
|
+
# aws_key and/or aws_secret were not nil -- therefore specified on the command line
|
56
|
+
|
57
|
+
# **Both** aws_key and aws_secret must be given.
|
58
|
+
# if only one but not the other is given, it's an error
|
59
|
+
|
60
|
+
debug("Is aws_key present? #{aws_key.present? ? "yes" : "no"} key: #{aws_key}")
|
61
|
+
debug("Is aws_secret present? #{aws_secret.present? ? "yes" : "no"} secret: #{aws_secret}")
|
62
|
+
|
63
|
+
if (aws_key.present? ^ aws_secret.present?) # exclusive or, one must be true, but not the other
|
64
|
+
fatal("Must provide *both* aws-key and aws-secret")
|
65
|
+
exit(EMISSINGKEYORSECRET)
|
66
|
+
end
|
67
|
+
|
68
|
+
if aws_key.nil? and aws_secret.nil?
|
69
|
+
|
70
|
+
aws_conf ||= DEFAULT_AWS_CREDS
|
71
|
+
|
72
|
+
if File.exists?(aws_conf)
|
73
|
+
File.open(aws_conf, 'r') do |awsfile|
|
74
|
+
awsfile.each_line do |line|
|
75
|
+
m = line.match('^access_key\s*=\s*(.*)$')
|
76
|
+
aws_key = m[1] if m
|
77
|
+
|
78
|
+
m = line.match('^secret_key\s*=\s*(.*)$')
|
79
|
+
debug("secret_key match -> #{m[0]} -> #{m[1]}") if m
|
80
|
+
aws_secret = m[1] if m
|
81
|
+
end
|
82
|
+
end
|
83
|
+
else
|
84
|
+
fatal("#{aws_conf} does not exist!")
|
85
|
+
exit(ENOCRED)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
debug("key: #{aws_key}\nsecret: #{aws_secret}")
|
91
|
+
[ aws_key, aws_secret ]
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def check_field(conf,env,field,required=true)
|
96
|
+
if conf[env].has_key?(field)
|
97
|
+
conf[env][field]
|
98
|
+
else
|
99
|
+
if required
|
100
|
+
fatal("Must provide #{field} in configuration")
|
101
|
+
exit(ENOFIELD)
|
102
|
+
else
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end # class
|
109
|
+
|
110
|
+
end # module
|
111
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Set Application version info
|
4
|
+
|
5
|
+
+Copyright:+ (c) 2012 Novu, LLC
|
6
|
+
+License:+ All rights reserved. For internal and private use only.
|
7
|
+
+Author:+ Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
=end
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
module SnapshotReload
|
14
|
+
VERSION = "1.0.0"
|
15
|
+
SUMMARY = %q{Redeploy the obfuscated data from production to other servers}
|
16
|
+
DESCRIPTION = %q{Take the obfuscated production data from it's nightly backup and place it into a working database. This script is run nightly to put obfuscated data into the Q* test server environments.}
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'snapshot_reload/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "snapshot_reload"
|
8
|
+
gem.version = SnapshotReload::VERSION
|
9
|
+
gem.authors = ["Tamara Temple"]
|
10
|
+
gem.email = ["tamara.temple@novu.com"]
|
11
|
+
gem.description = SnapshotReload::DESCRIPTION
|
12
|
+
gem.summary = SnapshotReload::SUMMARY
|
13
|
+
gem.homepage = "https://sites.google.com/a/novu.com/hq/home/technology-operations/systems-engineering/database-refresh-script"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.add_development_dependency('rdoc')
|
20
|
+
gem.add_development_dependency('aruba')
|
21
|
+
gem.add_development_dependency('rake', '~> 0.9.2')
|
22
|
+
gem.add_development_dependency('rspec')
|
23
|
+
gem.add_dependency('methadone', '~> 1.2.3')
|
24
|
+
gem.add_dependency('fog') # for AWS S3 access
|
25
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
module SnapshotReload
|
5
|
+
|
6
|
+
describe "SnapshotReload" do
|
7
|
+
before(:each) do
|
8
|
+
@x_yml = "/tmp/x.yml"
|
9
|
+
x_yml_file = File.open(@x_yml,'w')
|
10
|
+
x_yml_file.puts <<-END
|
11
|
+
qa:
|
12
|
+
adapter: mysql2
|
13
|
+
host: localhost
|
14
|
+
database: novuqa
|
15
|
+
username: novuadmin
|
16
|
+
password:
|
17
|
+
other:
|
18
|
+
adapter: mysql2
|
19
|
+
host: localhost
|
20
|
+
database: novuqa
|
21
|
+
username: novuadmin
|
22
|
+
password:
|
23
|
+
END
|
24
|
+
x_yml_file.close
|
25
|
+
|
26
|
+
@aws_conf = "/tmp/aws_conf"
|
27
|
+
aws_conf_file = File.open(@aws_conf, 'w')
|
28
|
+
aws_conf_file.puts <<-END
|
29
|
+
access_key = 12345
|
30
|
+
secret_key = 67890
|
31
|
+
END
|
32
|
+
aws_conf_file.close
|
33
|
+
|
34
|
+
@options = Hash.new
|
35
|
+
@options[:e] = @options['e'] = @options[:env] = @options['env'] = DEFAULT_ENVIRONMENT
|
36
|
+
@options[:s] = @options['s'] = @options[:source] = @options['source'] = 'testdata/novu_2012-12-11.sql.gz'
|
37
|
+
# @options[:s] = @options['s'] = @options[:source] = @options['source'] = 'xxx'
|
38
|
+
@options[:c] = @options['c'] = @options[:"aws-conf"] = @options['aws-conf'] = @aws_conf
|
39
|
+
@options[:n] = @options['n'] = @options[:"dry-run"] = @options['dry-run'] = true
|
40
|
+
@options[:v] = @options['v'] = @options[:verbose] = @options['verbose'] = false
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
it "can be instantiated" do
|
45
|
+
SnapshotReload.new(@x_yml,@options).should be_an_instance_of(SnapshotReload)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns a hash for #config" do
|
49
|
+
SnapshotReload.new(@x_yml,@options).config.should be_an_instance_of(Hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "environment is qa" do
|
53
|
+
SnapshotReload.new(@x_yml,@options).env.should eq('qa')
|
54
|
+
end
|
55
|
+
|
56
|
+
it "responds to drop_db" do
|
57
|
+
SnapshotReload.new(@x_yml,@options).respond_to?('drop_db').should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "responds to create_db" do
|
61
|
+
SnapshotReload.new(@x_yml,@options).respond_to?('create_db').should be_true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "responds to mysqladmin_go" do
|
65
|
+
SnapshotReload.new(@x_yml,@options).respond_to?('mysqladmin_go').should be_true
|
66
|
+
end
|
67
|
+
|
68
|
+
it "responds to load_db" do
|
69
|
+
SnapshotReload.new(@x_yml,@options).respond_to?('load_db').should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
it "responds to fetch_snapshot" do
|
74
|
+
SnapshotReload.new(@x_yml,@options).respond_to?('fetch_snapshot').should be_true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "sets @sql_file" do
|
78
|
+
@sn = SnapshotReload.new(@x_yml,@options)
|
79
|
+
@sn.fetch_snapshot
|
80
|
+
@sn.sql_file.should eq("testdata/novu_2012-12-11.sql.gz")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "responds to run_it" do
|
84
|
+
SnapshotReload.new(@x_yml,@options).respond_to?('run_it').should be_true
|
85
|
+
end
|
86
|
+
|
87
|
+
it "emulates drop command" do
|
88
|
+
SnapshotReload.new(@x_yml,@options).drop_db.should be_true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "emulates create command" do
|
92
|
+
SnapshotReload.new(@x_yml,@options).create_db.should be_true
|
93
|
+
end
|
94
|
+
|
95
|
+
it "emulates load command" do
|
96
|
+
@sn = SnapshotReload.new(@x_yml,@options)
|
97
|
+
@sn.load_db.should be_true
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
after(:each) do
|
103
|
+
File.unlink(@x_yml)
|
104
|
+
File.unlink(@aws_conf)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'snapshot_reload'
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snapshot_reload
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tamara Temple
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rdoc
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: aruba
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.2
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.2
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: methadone
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.2.3
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.2.3
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: fog
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Take the obfuscated production data from it's nightly backup and place
|
111
|
+
it into a working database. This script is run nightly to put obfuscated data into
|
112
|
+
the Q* test server environments.
|
113
|
+
email:
|
114
|
+
- tamara.temple@novu.com
|
115
|
+
executables:
|
116
|
+
- snapshot_reload
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- .gitignore
|
121
|
+
- .rspec
|
122
|
+
- .rvmrc
|
123
|
+
- Gemfile
|
124
|
+
- Gemfile.lock
|
125
|
+
- LICENSE.txt
|
126
|
+
- README.md
|
127
|
+
- README.rdoc
|
128
|
+
- Rakefile
|
129
|
+
- bin/snapshot_reload
|
130
|
+
- features/snapshot_live.feature
|
131
|
+
- features/snapshot_reload.feature
|
132
|
+
- features/step_definitions/snapshot_live_steps.rb
|
133
|
+
- features/step_definitions/snapshot_reload_steps.rb
|
134
|
+
- features/support/env.rb
|
135
|
+
- lib/snapshot_reload.rb
|
136
|
+
- lib/snapshot_reload/String.rb
|
137
|
+
- lib/snapshot_reload/defaults.rb
|
138
|
+
- lib/snapshot_reload/errors.rb
|
139
|
+
- lib/snapshot_reload/fetch.rb
|
140
|
+
- lib/snapshot_reload/reload.rb
|
141
|
+
- lib/snapshot_reload/validate.rb
|
142
|
+
- lib/snapshot_reload/version.rb
|
143
|
+
- snapshot_reload.gemspec
|
144
|
+
- spec/snapshot_reload_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
homepage: https://sites.google.com/a/novu.com/hq/home/technology-operations/systems-engineering/database-refresh-script
|
147
|
+
licenses: []
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 1.8.24
|
167
|
+
signing_key:
|
168
|
+
specification_version: 3
|
169
|
+
summary: Redeploy the obfuscated data from production to other servers
|
170
|
+
test_files:
|
171
|
+
- features/snapshot_live.feature
|
172
|
+
- features/snapshot_reload.feature
|
173
|
+
- features/step_definitions/snapshot_live_steps.rb
|
174
|
+
- features/step_definitions/snapshot_reload_steps.rb
|
175
|
+
- features/support/env.rb
|
176
|
+
- spec/snapshot_reload_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
178
|
+
has_rdoc:
|