dustcart 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/.gitignore +11 -0
- data/.reek +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -0
- data/Gemfile +13 -0
- data/Guardfile +47 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +7 -0
- data/dustcart.gemspec +33 -0
- data/exe/dustcart +5 -0
- data/lib/dustcart.rb +11 -0
- data/lib/dustcart/cli.rb +45 -0
- data/lib/dustcart/dsl.rb +55 -0
- data/lib/dustcart/group.rb +71 -0
- data/lib/dustcart/input/base.rb +24 -0
- data/lib/dustcart/input/directory.rb +29 -0
- data/lib/dustcart/input/file.rb +29 -0
- data/lib/dustcart/output/amazon_s3.rb +66 -0
- data/lib/dustcart/output/base.rb +16 -0
- data/lib/dustcart/resource_base.rb +59 -0
- data/lib/dustcart/version.rb +3 -0
- data/lib/helper/zip_file_generator.rb +57 -0
- metadata +211 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 56a519e271c581bc5611287d4cd8f9005f295ae1
|
4
|
+
data.tar.gz: 7bee7c8fe6fca08a01bc7d28ad4eafabb35c7daa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa24717a0ae6b4686ffa005fad63f0c9148bbab6da9e9d2db67fdd12f439c64a528539bed6a7ef097d689e619a2235fe4f2d2317bf59bcdec1dfb09dacbd6f83
|
7
|
+
data.tar.gz: 883e8dbfe5d7ad4fa2ecf233466532cc5bdfbf220fc3e79949daba64f0cbe2ecbc04c0907d51381b40625f4a92a33d912c761a16542adcdf1b562ab98374e854
|
data/.gitignore
ADDED
data/.reek
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.0
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in dustcart.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem 'guard'
|
8
|
+
gem 'guard-rspec'
|
9
|
+
gem 'guard-rubocop'
|
10
|
+
gem 'terminal-notifier-guard'
|
11
|
+
gem 'listen', '3.1.1'
|
12
|
+
gem 'ruby_dep', '1.3.1'
|
13
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
28
|
+
require 'guard/rspec/dsl'
|
29
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
30
|
+
|
31
|
+
# Feel free to open issues for suggestions and improvements
|
32
|
+
|
33
|
+
# RSpec files
|
34
|
+
rspec = dsl.rspec
|
35
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
+
watch(rspec.spec_files)
|
38
|
+
|
39
|
+
# Ruby files
|
40
|
+
ruby = dsl.ruby
|
41
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
+
end
|
43
|
+
|
44
|
+
guard :rubocop do
|
45
|
+
watch(/.+\.rb$/)
|
46
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
47
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Dustcart
|
2
|
+
|
3
|
+
[](https://circleci.com/gh/tamano/dustcart)
|
4
|
+
[](https://codeclimate.com/github/tamano/dustcart)
|
5
|
+
[](https://codeclimate.com/github/tamano/dustcart/coverage)
|
6
|
+
[](https://codeclimate.com/github/tamano/dustcart)
|
7
|
+
|
8
|
+
Dustcart is simple server backup tool inspired by [backup](https://github.com/backup/backup)
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Install it yourself as:
|
13
|
+
|
14
|
+
$ gem install dustcart
|
15
|
+
|
16
|
+
## Basic usage
|
17
|
+
|
18
|
+
Create your configuration file.
|
19
|
+
|
20
|
+
- The file instructs which file/directory to backup and to which S3 bucket.
|
21
|
+
- This file would contain sensitive information (such as AWS credential), so it should be have file mode `600`.
|
22
|
+
- Sample is [here](https://github.com/tamano/dustcart/blob/master/spec/sample_instructions/backup_all.rb)
|
23
|
+
|
24
|
+
Then Kick command:
|
25
|
+
|
26
|
+
$ dustcart exec -f YOUR_CONFIGURATION_FILE
|
27
|
+
|
28
|
+
- `-f YOUR_CONFIGURATION_FILE` can be omitted. In that case, `~/.dustcart/default.rb` will be used.
|
29
|
+
|
30
|
+
## Details
|
31
|
+
|
32
|
+
Please read the [sample file](https://github.com/tamano/dustcart/blob/master/spec/sample_instructions/backup_all.rb).
|
33
|
+
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/tamano/dustcart.
|
38
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'dustcart'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/circle.yml
ADDED
data/dustcart.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dustcart/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'dustcart'
|
8
|
+
spec.version = Dustcart::VERSION
|
9
|
+
spec.authors = ['Yuya TAMANO']
|
10
|
+
spec.email = ['everfree.main@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'S3 integrated backup tool.'
|
13
|
+
spec.description = 'CLI tool to send files/db_dump to S3.'
|
14
|
+
spec.homepage = 'https://github.com/tamano/dustcart'
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
25
|
+
spec.add_development_dependency 'reek'
|
26
|
+
spec.add_development_dependency 'rubocop'
|
27
|
+
spec.add_development_dependency 'simplecov'
|
28
|
+
|
29
|
+
spec.add_dependency 'thor'
|
30
|
+
spec.add_dependency 'unindent'
|
31
|
+
spec.add_dependency 'aws-sdk', '~> 2'
|
32
|
+
spec.add_dependency 'rubyzip'
|
33
|
+
end
|
data/exe/dustcart
ADDED
data/lib/dustcart.rb
ADDED
data/lib/dustcart/cli.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'unindent'
|
5
|
+
|
6
|
+
module Dustcart
|
7
|
+
# command facade
|
8
|
+
class CLI < Thor
|
9
|
+
desc 'exec', 'execute backup.'
|
10
|
+
option :instruction_file, type: :string, required: false, aliases: '-f'
|
11
|
+
def exec
|
12
|
+
instruction_file = (options[:instruction_file] || "#{Dir.home}/.dustcart/default.rb")
|
13
|
+
|
14
|
+
begin
|
15
|
+
check_file(instruction_file)
|
16
|
+
rescue => error
|
17
|
+
puts "ERROR: #{error.message}"
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
dsl = DSL.new
|
22
|
+
dsl.load(instruction_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'version', 'show version information.'
|
26
|
+
def version
|
27
|
+
puts Dustcart::VERSION
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def check_file(file)
|
33
|
+
raise <<-EOS.unindent unless File.exist?(file)
|
34
|
+
The instruction file (#{file}) doesn't exists.
|
35
|
+
EOS
|
36
|
+
|
37
|
+
mode = format('%o', File.stat(file).mode)[-3, 3]
|
38
|
+
|
39
|
+
raise <<-EOS.unindent unless mode == '600'
|
40
|
+
The instruction file (#{file}) has too open permission.
|
41
|
+
Make sure its permission is 600.
|
42
|
+
EOS
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/dustcart/dsl.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Dustcart
|
2
|
+
# DSL for instruction file
|
3
|
+
class DSL
|
4
|
+
attr_reader :dump_base
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
end
|
8
|
+
|
9
|
+
def load(path)
|
10
|
+
load_from(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def load_from(path)
|
16
|
+
instance_eval(File.read(path), path) if path
|
17
|
+
end
|
18
|
+
|
19
|
+
def dump_site(path)
|
20
|
+
raise 'dump_site has already set.' if @_temp_dir
|
21
|
+
|
22
|
+
path.chomp!('/')
|
23
|
+
time_str = Time.now.strftime('%Y%m%d%H%M%S')
|
24
|
+
@_temp_dir = "#{path}/#{time_str}"
|
25
|
+
@dump_base = path
|
26
|
+
end
|
27
|
+
|
28
|
+
def temp_dir
|
29
|
+
return @_temp_dir if @_temp_dir
|
30
|
+
|
31
|
+
time_str = Time.now.strftime('%Y%m%d%H%M%S')
|
32
|
+
@_temp_dir = "/tmp/#{time_str}"
|
33
|
+
@dump_base = '/tmp'
|
34
|
+
end
|
35
|
+
|
36
|
+
def group(*args, &block)
|
37
|
+
size = args.size
|
38
|
+
raise ArgumentError, "wrong number of arguments (#{size} for 1)" unless size == 1
|
39
|
+
|
40
|
+
method = args.first
|
41
|
+
|
42
|
+
group = Group.new(method, temp_dir)
|
43
|
+
group.instance_eval(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def cleanup(target)
|
47
|
+
raise "target(#{target}) is not available." unless [:all, :except_latest].include?(target)
|
48
|
+
|
49
|
+
Dir.glob("#{dump_base}/*").each do |file|
|
50
|
+
next if target == :except_latest && file.start_with?(temp_dir)
|
51
|
+
FileUtils.rm_rf(file)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Dustcart
|
2
|
+
# resource group
|
3
|
+
class Group
|
4
|
+
INPUT_RESOURCES = [
|
5
|
+
'dustcart/input/base',
|
6
|
+
'dustcart/input/directory',
|
7
|
+
'dustcart/input/file'
|
8
|
+
].freeze
|
9
|
+
|
10
|
+
OUTPUT_RESOURCES = [
|
11
|
+
'dustcart/output/base',
|
12
|
+
'dustcart/output/amazon_s3'
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
def initialize(group_class, dir)
|
16
|
+
@temp_dir = dir
|
17
|
+
initialize_classes(group_class)
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(method, *args, &block)
|
21
|
+
super unless args.size == 1
|
22
|
+
name = args[0]
|
23
|
+
|
24
|
+
begin
|
25
|
+
klass = get_class(method)
|
26
|
+
rescue NameError
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
resource = klass.new(@temp_dir, name, &block)
|
31
|
+
resource.precheck
|
32
|
+
resource.run
|
33
|
+
end
|
34
|
+
|
35
|
+
# ignore :reek:UtilityFunction
|
36
|
+
def respond_to_missing?(method, *)
|
37
|
+
get_class(method)
|
38
|
+
true
|
39
|
+
rescue NameError
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# ignore :reek:UtilityFunction
|
46
|
+
def to_camel_case(str)
|
47
|
+
str.split('_').map(&:capitalize).join
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_class(method)
|
51
|
+
@group_type.const_get(to_camel_case(method.to_s))
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize_classes(group_class)
|
55
|
+
case group_class
|
56
|
+
when :input
|
57
|
+
require_files(INPUT_RESOURCES)
|
58
|
+
@group_type = Resource::Input
|
59
|
+
when :output
|
60
|
+
require_files(OUTPUT_RESOURCES)
|
61
|
+
@group_type = Resource::Output
|
62
|
+
else
|
63
|
+
raise "invalid group type (#{group_class})"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def require_files(files)
|
68
|
+
files.each { |file| require file }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Dustcart
|
2
|
+
module Resource
|
3
|
+
module Input
|
4
|
+
# base class for input
|
5
|
+
class Base < Resource::Base
|
6
|
+
attr_reader :from
|
7
|
+
alias_method :to_dir, :dump_dir
|
8
|
+
|
9
|
+
def initialize(to_dir, from, &block)
|
10
|
+
super(to_dir, &block)
|
11
|
+
@from = from
|
12
|
+
end
|
13
|
+
|
14
|
+
def precheck
|
15
|
+
super
|
16
|
+
|
17
|
+
raise <<-EOS.unindent unless Object::File.exists?(from)
|
18
|
+
target(#{from}) does not exists
|
19
|
+
EOS
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dustcart
|
2
|
+
module Resource
|
3
|
+
module Input
|
4
|
+
# input: directory
|
5
|
+
class Directory < Base
|
6
|
+
define_attribute :label
|
7
|
+
|
8
|
+
def precheck
|
9
|
+
super
|
10
|
+
|
11
|
+
raise <<-EOS.unindent unless Object::File.directory?(from)
|
12
|
+
target(#{from}) is not a directory
|
13
|
+
EOS
|
14
|
+
|
15
|
+
raise <<-EOS.unindent if attributes.key?(:label) && label !~ /^\w+$/
|
16
|
+
label should be word characters ([a-zA-Z0-9_]+)
|
17
|
+
EOS
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
super
|
22
|
+
|
23
|
+
target = "#{to_dir}/#{label}"
|
24
|
+
FileUtils.cp_r(from, target)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dustcart
|
2
|
+
module Resource
|
3
|
+
module Input
|
4
|
+
# input: file
|
5
|
+
class File < Base
|
6
|
+
define_attribute :label
|
7
|
+
|
8
|
+
def precheck
|
9
|
+
super
|
10
|
+
|
11
|
+
raise <<-EOS.unindent unless Object::File.file?(from)
|
12
|
+
target(#{from}) is not a regular file
|
13
|
+
EOS
|
14
|
+
|
15
|
+
raise <<-EOS.unindent if attributes.key?(:label) && label !~ /^\w+$/
|
16
|
+
label should be word characters ([a-zA-Z0-9_]+)
|
17
|
+
EOS
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
super
|
22
|
+
|
23
|
+
target = "#{to_dir}/#{label}"
|
24
|
+
FileUtils.cp(from, target)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'helper/zip_file_generator'
|
3
|
+
|
4
|
+
module Dustcart
|
5
|
+
module Resource
|
6
|
+
module Output
|
7
|
+
# output: S3
|
8
|
+
# ignore :reek:UncommunicativeModuleName
|
9
|
+
class AmazonS3 < Base
|
10
|
+
define_attribute :access_key_id
|
11
|
+
define_attribute :secret_access_key
|
12
|
+
define_attribute :region
|
13
|
+
define_attribute :bucket
|
14
|
+
|
15
|
+
attr_reader :zip_file_name
|
16
|
+
|
17
|
+
def initialize(from_dir, mode, &block)
|
18
|
+
super(from_dir, mode, &block)
|
19
|
+
|
20
|
+
@zip_file_name = "#{from_dir}.zip"
|
21
|
+
end
|
22
|
+
|
23
|
+
def precheck
|
24
|
+
super
|
25
|
+
|
26
|
+
raise <<-EOS.unindent unless mode == :all
|
27
|
+
mode (#{mode}) unknown.
|
28
|
+
:all is the only available mode now.
|
29
|
+
EOS
|
30
|
+
|
31
|
+
[:access_key_id, :secret_access_key, :region, :bucket].each do |key|
|
32
|
+
raise <<-EOS.unindent unless attributes.key?(key)
|
33
|
+
#{key} is required.
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
super
|
40
|
+
|
41
|
+
generate_zip_file
|
42
|
+
upload_zip_file
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def generate_zip_file
|
48
|
+
zf = ZipFileGenerator.new(from_dir, zip_file_name)
|
49
|
+
zf.write
|
50
|
+
end
|
51
|
+
|
52
|
+
def upload_zip_file
|
53
|
+
resource = Aws::S3::Resource.new(
|
54
|
+
access_key_id: access_key_id,
|
55
|
+
secret_access_key: secret_access_key,
|
56
|
+
region: region
|
57
|
+
)
|
58
|
+
|
59
|
+
obj_name = File.basename(zip_file_name)
|
60
|
+
obj = resource.bucket(bucket).object(obj_name)
|
61
|
+
obj.upload_file(zip_file_name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dustcart
|
2
|
+
module Resource
|
3
|
+
module Output
|
4
|
+
# base class for input
|
5
|
+
class Base < Resource::Base
|
6
|
+
attr_reader :mode
|
7
|
+
alias_method :from_dir, :dump_dir
|
8
|
+
|
9
|
+
def initialize(from_dir, mode, &block)
|
10
|
+
super(from_dir, &block)
|
11
|
+
@mode = mode
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Dustcart
|
2
|
+
module Resource
|
3
|
+
# base class for resources
|
4
|
+
class Base
|
5
|
+
attr_reader :dump_dir
|
6
|
+
attr_reader :attributes
|
7
|
+
|
8
|
+
@defined_attributes ||= {}
|
9
|
+
|
10
|
+
def initialize(dir, &block)
|
11
|
+
@dump_dir = dir
|
12
|
+
@attributes ||= {}
|
13
|
+
instance_eval(&block) if block
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(method, *args, &block)
|
17
|
+
method = method.to_sym
|
18
|
+
|
19
|
+
if self.class.defined_attributes.key?(method)
|
20
|
+
case args.size
|
21
|
+
when 0
|
22
|
+
return @attributes[method]
|
23
|
+
when 1
|
24
|
+
return @attributes[method] = args.first
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def respond_to_missing?(method, *)
|
32
|
+
self.class.defined_attributes.key?(method) || super
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
FileUtils.mkdir_p(dump_dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
def precheck
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
attr_reader :defined_attributes
|
44
|
+
|
45
|
+
def inherited(subclass)
|
46
|
+
subclass.instance_variable_set(
|
47
|
+
:@defined_attributes,
|
48
|
+
defined_attributes.dup
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def define_attribute(name)
|
53
|
+
name = name.to_sym
|
54
|
+
@defined_attributes[name] = nil unless @defined_attributes.key?(name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Original: https://github.com/EagleSHCN/rubyzip/blob/master/samples/example_recursive.rb
|
2
|
+
require 'zip'
|
3
|
+
|
4
|
+
# This is a simple example which uses rubyzip to
|
5
|
+
# recursively generate a zip file from the contents of
|
6
|
+
# a specified directory. The directory itself is not
|
7
|
+
# included in the archive, rather just its contents.
|
8
|
+
#
|
9
|
+
# Usage:
|
10
|
+
# directoryToZip = "/tmp/input"
|
11
|
+
# output_file = "/tmp/out.zip"
|
12
|
+
# zf = ZipFileGenerator.new(directory_to_zip, output_file)
|
13
|
+
# zf.write()
|
14
|
+
class ZipFileGenerator
|
15
|
+
# Initialize with the directory to zip and the location of the output archive.
|
16
|
+
def initialize(input_dir, output_file)
|
17
|
+
@input_dir = input_dir
|
18
|
+
@output_file = output_file
|
19
|
+
end
|
20
|
+
|
21
|
+
# Zip the input directory.
|
22
|
+
def write
|
23
|
+
entries = Dir.entries(@input_dir) - %w(. ..)
|
24
|
+
|
25
|
+
::Zip::File.open(@output_file, ::Zip::File::CREATE) do |io|
|
26
|
+
write_entries entries, '', io
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# A helper method to make the recursion work.
|
33
|
+
def write_entries(entries, path, io)
|
34
|
+
entries.each do |entry|
|
35
|
+
zip_file_path = path == '' ? entry : File.join(path, entry)
|
36
|
+
disk_file_path = File.join(@input_dir, zip_file_path)
|
37
|
+
puts "Deflating #{disk_file_path}"
|
38
|
+
|
39
|
+
if File.directory? disk_file_path
|
40
|
+
recursively_deflate_directory(disk_file_path, io, zip_file_path)
|
41
|
+
else
|
42
|
+
put_into_archive(disk_file_path, io, zip_file_path)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def recursively_deflate_directory(disk_file_path, io, zip_file_path)
|
48
|
+
io.mkdir zip_file_path
|
49
|
+
subdir = Dir.entries(disk_file_path) - %w(. ..)
|
50
|
+
write_entries subdir, zip_file_path, io
|
51
|
+
end
|
52
|
+
|
53
|
+
# ignore :reek:UtilityFunction
|
54
|
+
def put_into_archive(disk_file_path, io, zip_file_path)
|
55
|
+
io.add(zip_file_path, disk_file_path)
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dustcart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yuya TAMANO
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: reek
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: thor
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: unindent
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: aws-sdk
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '2'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '2'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubyzip
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: CLI tool to send files/db_dump to S3.
|
154
|
+
email:
|
155
|
+
- everfree.main@gmail.com
|
156
|
+
executables:
|
157
|
+
- dustcart
|
158
|
+
extensions: []
|
159
|
+
extra_rdoc_files: []
|
160
|
+
files:
|
161
|
+
- ".gitignore"
|
162
|
+
- ".reek"
|
163
|
+
- ".rspec"
|
164
|
+
- ".rubocop.yml"
|
165
|
+
- ".ruby-version"
|
166
|
+
- Gemfile
|
167
|
+
- Guardfile
|
168
|
+
- README.md
|
169
|
+
- Rakefile
|
170
|
+
- bin/console
|
171
|
+
- bin/setup
|
172
|
+
- circle.yml
|
173
|
+
- dustcart.gemspec
|
174
|
+
- exe/dustcart
|
175
|
+
- lib/dustcart.rb
|
176
|
+
- lib/dustcart/cli.rb
|
177
|
+
- lib/dustcart/dsl.rb
|
178
|
+
- lib/dustcart/group.rb
|
179
|
+
- lib/dustcart/input/base.rb
|
180
|
+
- lib/dustcart/input/directory.rb
|
181
|
+
- lib/dustcart/input/file.rb
|
182
|
+
- lib/dustcart/output/amazon_s3.rb
|
183
|
+
- lib/dustcart/output/base.rb
|
184
|
+
- lib/dustcart/resource_base.rb
|
185
|
+
- lib/dustcart/version.rb
|
186
|
+
- lib/helper/zip_file_generator.rb
|
187
|
+
homepage: https://github.com/tamano/dustcart
|
188
|
+
licenses:
|
189
|
+
- MIT
|
190
|
+
metadata: {}
|
191
|
+
post_install_message:
|
192
|
+
rdoc_options: []
|
193
|
+
require_paths:
|
194
|
+
- lib
|
195
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: '0'
|
205
|
+
requirements: []
|
206
|
+
rubyforge_project:
|
207
|
+
rubygems_version: 2.4.5
|
208
|
+
signing_key:
|
209
|
+
specification_version: 4
|
210
|
+
summary: S3 integrated backup tool.
|
211
|
+
test_files: []
|