snapshotar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b7518a6186d705c241f358e230cff6743b69b36
4
+ data.tar.gz: 319fcc1e61c96ad015507bb9b2da001c59c1ba51
5
+ SHA512:
6
+ metadata.gz: a312f9567fd4a600df243ac3547d134fbac3a2a4c533f5a302a441bd7c07917dfa1e63cd36703b620b08f5a4411451c1ca41d23595ada61c43cb632996270963
7
+ data.tar.gz: e19decc5f4d9c7017d7b641053323d68958b5e4e3ae51652825f5bea8b188016f0d10d3d4a3eae06470ec03de94163c7e93690f15244759c0cdfe55c661222c3
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .env
19
+ uploads
data/.respec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+
7
+ # uncomment this line if your project needs to run something other than `rake`:
8
+ # script: bundle exec rspec spec
9
+ services:
10
+ - mongodb
11
+ env:
12
+ global:
13
+ - S3_ENABLED=false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in snapshotar.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Benjamin Müller
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ [![Build Status](https://travis-ci.org/elchbenny/snapshotar.svg?branch=master)](https://travis-ci.org/elchbenny/snapshotar)
2
+ [![Code Climate](https://codeclimate.com/github/elchbenny/snapshotar.png)](https://codeclimate.com/github/elchbenny/snapshotar)
3
+
4
+
5
+ # Snapshotar
6
+
7
+ Make a snapshot of your staging environment and pull back on your dev machine.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'snapshotar'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install snapshotar
22
+
23
+ ## What snapshotar can...
24
+
25
+ 1. serializing your rails models to json
26
+ 2. handling *carrierwave* attachments
27
+ 3. storing serialized dataset locally or to amazon s3
28
+ 4. listing available snapshots
29
+ 5. deserialize snapshot and load back to database
30
+
31
+ ## Why snapshotar?
32
+
33
+ instead of...
34
+
35
+ - **database backup?** Because image attachments causing trouble!!
36
+ - **fixtures/factories/fakers?** Because this requires coding. Let the
37
+ others fill up your app with sample data.
38
+
39
+ ## When to use snapshotar?
40
+
41
+ - For testing and development!!
42
+ - definitely *NOT* for production backups
43
+
44
+ ## Requirements
45
+
46
+ - Ruby >= 1.9.3
47
+ - Rails ?
48
+
49
+ ## Usage
50
+
51
+ - one option for snapshotar is **rake**
52
+
53
+ - you can also integrate snapshotar into your administration backend and let app
54
+ users create snapshots.
55
+
56
+ ## Configuration Options
57
+
58
+ ## Testing
59
+ This repository is under continuous integration testing on travis-ci.org.
60
+
61
+ Amazon S3 related functionalities are not tested in CI as an official account at
62
+ amazon would be required. AWS S3 tests can be run locally by providing a *.env* file
63
+ in the projects root directory with the following keys:
64
+
65
+ AWS_ACCESS_KEY_ID=<your id>
66
+ AWS_SECRET_ACCESS_KEY=<your secret>
67
+ AWS_SNAPSHOTAR_BUCKET=<a bucket name>
68
+
69
+ RACK_ENV=test
70
+
71
+ S3_ENABLED=true
72
+
73
+ ## Contributing
74
+
75
+ 1. Fork it
76
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
77
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
78
+ 4. Push to the branch (`git push origin my-new-feature`)
79
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ # If you want to make this the default task
7
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ module Snapshotar
2
+
3
+ ##
4
+ # Configuration Class
5
+ class Configuration
6
+
7
+ ##
8
+ # Where to store your snapshots?
9
+ # - +:s3+ for amazon s3 service
10
+ # - +:file+ local directory
11
+ attr_accessor :storage_type
12
+
13
+ ##
14
+ # Provide the models and their attributes to seralize like this:
15
+ # [[ModelName1, :attribute1, :attribute2,...],[ModelName2, :attribute1]]
16
+ #
17
+ attr_accessor :models
18
+
19
+ def initialize #:nodoc:
20
+ @storage_type = :file
21
+ @models = []
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,103 @@
1
+ require "snapshotar/storage/s3_storage"
2
+ require "snapshotar/storage/file_storage"
3
+ require "json"
4
+ require "jbuilder"
5
+
6
+ module Snapshotar
7
+
8
+ class Core
9
+
10
+ def initialize #:nodoc:
11
+ storage_class = Snapshotar::Storage::S3Storage if Snapshotar.configuration.storage_type == :s3
12
+ storage_class = Snapshotar::Storage::FileStorage if Snapshotar.configuration.storage_type == :file
13
+
14
+ @storage = storage_class.new
15
+ end
16
+
17
+ ##
18
+ # List all available snapshots.
19
+ #
20
+ # returns:: array of filenames
21
+ #
22
+ def list
23
+ @storage.index
24
+ end
25
+
26
+ ##
27
+ # Performs a snapshot
28
+ #
29
+ # Params::
30
+ # +filename+:: filename to create or nil to let snapshotar create something
31
+ # like +snapshotar_dump_<timestamp>.json+
32
+ #
33
+ # returns:: +filename+
34
+ #
35
+ def export(filename = nil)
36
+ filename ||= "snapshotar_dump_#{Time.now.to_i}.json"
37
+
38
+ serialized = Jbuilder.encode do |json|
39
+ Snapshotar.configuration.models.each do |m|
40
+ model_name = m.first.name
41
+ json.set! model_name do
42
+ json.array! m.first.all do |itm|
43
+ m[1..-1].each do |attr|
44
+
45
+ next unless itm.respond_to?(attr.to_sym)
46
+
47
+ # replace uploads by their url
48
+ if itm.send(attr.to_sym).respond_to?(:url)
49
+ json.set! "#{attr}_url".to_sym, itm.send(attr.to_sym).url
50
+ else
51
+ json.set! attr.to_sym, itm[attr]
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ @storage.create(filename,serialized)
60
+
61
+ return filename
62
+ end
63
+
64
+ # Load a snapshot.
65
+ #
66
+ # Params::
67
+ # +filename+:: name of the snapshot to load
68
+ #
69
+ def import(filename)
70
+ tree = JSON.load @storage.show(filename)
71
+
72
+ tree.each do |key,value|
73
+ clazz = key.constantize
74
+
75
+ value.each do |itm|
76
+ item_params = {}
77
+ itm.each do |itm_key,itm_value|
78
+ # handle url paths separatley
79
+ if itm_key.to_s.end_with?("_url")
80
+ orig_key = itm_key.to_s[0..-5].to_sym
81
+ item_params[orig_key] = File.open(itm_value)
82
+ else
83
+ item_params[itm_key] = itm_value
84
+ end
85
+ end
86
+ clazz.create(item_params)
87
+ end
88
+ end
89
+ end
90
+
91
+ ##
92
+ # delete a snapshot.
93
+ #
94
+ # Params::
95
+ # +filename+:: name of the snapshot to delete
96
+ #
97
+ def delete(filename)
98
+
99
+ @storage.delete(filename)
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,67 @@
1
+ module Snapshotar
2
+ module Storage
3
+
4
+ class FileStorage
5
+
6
+ ##
7
+ # Use this property to specify the local path where snapshots are stored.
8
+ # Default:: +tmp/+
9
+ #
10
+ attr_accessor :base_path
11
+
12
+ def initialize(path = nil) #:nodoc:
13
+ @base_path = path || "tmp"
14
+
15
+ # create tmp dir if it's not existent
16
+ unless File.directory?(@base_path)
17
+ FileUtils.mkdir_p(@base_path)
18
+ end
19
+ end
20
+
21
+ ##
22
+ # lists available snapshots in this storage.
23
+ #
24
+ # returns:: array of filenames
25
+ #
26
+ def index
27
+ Dir["#{@base_path}/*.json"].map{|p| File.basename(p)}
28
+ end
29
+
30
+ ##
31
+ # loads a snapshot specified by the given +filename+.
32
+ #
33
+ # Params::
34
+ # +filename+:: name of the snapshot to load
35
+ #
36
+ # returns:: still seralized json
37
+ #
38
+ def show(filename)
39
+ File.read File.join(@base_path, filename)
40
+ end
41
+
42
+ ##
43
+ # creates a snapshot specified by the given +filename+ with data provided
44
+ #
45
+ # Params::
46
+ # +filename+:: name of the snapshot to create
47
+ # +serialized_tree+:: json serialized data
48
+ #
49
+ def create(filename,serialized_tree)
50
+ File.open(File.join(@base_path, filename),"w") do |f|
51
+ f.write(serialized_tree)
52
+ end
53
+ end
54
+
55
+ ##
56
+ # deletes a snapshot specified by the given +filename+.
57
+ #
58
+ # Params::
59
+ # +filename+:: name of the snapshot to delete
60
+ #
61
+ def delete(filename)
62
+ File.delete File.join(@base_path, filename)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,70 @@
1
+ require "aws-sdk"
2
+
3
+ module Snapshotar
4
+ module Storage
5
+
6
+ ##
7
+ # This snapshot storage type connects to amazon s3 via *aws-sdk gem*.
8
+ class S3Storage
9
+
10
+ def initialize #:nodoc:
11
+
12
+ raise ArgumentError, "You should set ENV['AWS_ACCESS_KEY_ID'] to a valid value" unless ENV['AWS_ACCESS_KEY_ID']
13
+ raise ArgumentError, "You should set ENV['AWS_SECRET_ACCESS_KEY'] to a valid value" unless ENV['AWS_SECRET_ACCESS_KEY']
14
+ raise ArgumentError, "You should set ENV['AWS_SNAPSHOTAR_BUCKET'] to a aws bucket name used only for snapshotting" unless ENV['AWS_SNAPSHOTAR_BUCKET']
15
+
16
+ p "Running S3 with key: #{ENV['AWS_ACCESS_KEY_ID']}, secret: #{ENV['AWS_SECRET_ACCESS_KEY']}, bucket: #{ENV['AWS_SNAPSHOTAR_BUCKET']}"
17
+
18
+ @s3 = AWS::S3.new(
19
+ access_key_id: ENV['AWS_ACCESS_KEY_ID'],
20
+ secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
21
+ region: ENV['AWS_REGION'])
22
+
23
+ @bucket = @s3.buckets[ENV['AWS_SNAPSHOTAR_BUCKET']]
24
+ end
25
+
26
+ ##
27
+ # lists available snapshots in this storage.
28
+ #
29
+ # returns:: array of filenames
30
+ #
31
+ def index
32
+ @bucket.objects.map{|obj| obj.key}
33
+ end
34
+
35
+ ##
36
+ # loads a snapshot specified by the given +filename+.
37
+ #
38
+ # Params::
39
+ # +filename+:: name of the snapshot to load
40
+ #
41
+ # returns:: still seralized json
42
+ #
43
+ def show(filename)
44
+ @bucket.objects[filename]
45
+ end
46
+
47
+ ##
48
+ # creates a snapshot specified by the given +filename+ with data provided
49
+ #
50
+ # Params::
51
+ # +filename+:: name of the snapshot to create
52
+ # +serialized_tree+:: json serialized data
53
+ #
54
+ def create(filename,serialized_tree)
55
+ @bucket.objects[filename].write(serialized_tree)
56
+ end
57
+
58
+ ##
59
+ # deletes a snapshot specified by the given +filename+.
60
+ #
61
+ # Params::
62
+ # +filename+:: name of the snapshot to delete
63
+ #
64
+ def delete(filename)
65
+ @bucket.objects[filename].delete
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,53 @@
1
+ module Snapshotar
2
+ module Storage
3
+
4
+ class StorageTemplate
5
+
6
+ def initialize #:nodoc:
7
+ end
8
+
9
+ ##
10
+ # lists available snapshots in this storage.
11
+ #
12
+ # returns:: array of filenames
13
+ #
14
+ def index
15
+
16
+ end
17
+
18
+ ##
19
+ # loads a snapshot specified by the given +filename+.
20
+ #
21
+ # Params::
22
+ # +filename+:: name of the snapshot to load
23
+ #
24
+ # returns:: still seralized json
25
+ #
26
+ def show(filename)
27
+
28
+ end
29
+
30
+ ##
31
+ # creates a snapshot specified by the given +filename+ with data provided
32
+ #
33
+ # Params::
34
+ # +filename+:: name of the snapshot to create
35
+ # +serialized_tree+:: json serialized data
36
+ #
37
+ def create(filename,serialized_tree)
38
+
39
+ end
40
+
41
+ ##
42
+ # deletes a snapshot specified by the given +filename+.
43
+ #
44
+ # Params::
45
+ # +filename+:: name of the snapshot to delete
46
+ #
47
+ def delete(filename)
48
+
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,50 @@
1
+ require "rake"
2
+
3
+ namespace :snapshotar do
4
+
5
+ desc "list available snapshots"
6
+ task list: :environment do
7
+
8
+ file = ARGV.last
9
+ task file.to_sym do ; end
10
+
11
+ p "# Snapshotar: Listing available snapshots"
12
+ p Snapshotar.list
13
+ end
14
+
15
+ desc "create a snapshots"
16
+ task create: :environment do
17
+
18
+ file = ARGV.last
19
+ task file.to_sym do ; end
20
+
21
+ file = nil if file.downcase == "snapshotar:create"
22
+
23
+ p "# Snapshotar: Creating snapshots #{file}"
24
+ p Snapshotar.create(file)
25
+ end
26
+
27
+ desc "load a snapshots"
28
+ task load: :environment do
29
+
30
+ file = ARGV.last
31
+ task file.to_sym do ; end
32
+
33
+ file = nil if file.downcase == "snapshotar:load"
34
+
35
+ p "# Snapshotar: Loading snapshot #{file}"
36
+ p Snapshotar.load(file)
37
+ end
38
+
39
+ desc "delete a snapshots"
40
+ task delete: :environment do
41
+
42
+ file = ARGV.last
43
+ task file.to_sym do ; end
44
+
45
+ file = nil if file.downcase == "snapshotar:delete"
46
+
47
+ p "# Snapshotar: Listing deleting snapshot #{file}"
48
+ p Snapshotar.delete(file)
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module Snapshotar
2
+ VERSION = "0.0.1"
3
+ end
data/lib/snapshotar.rb ADDED
@@ -0,0 +1,65 @@
1
+ require "snapshotar/configuration"
2
+ require "snapshotar/version"
3
+ require "snapshotar/core"
4
+ require "snapshotar/tasks"
5
+
6
+ ##
7
+ # Make a snapshot of your staging environment and pull back on your dev machine.
8
+
9
+ module Snapshotar
10
+
11
+ class << self
12
+
13
+ ##
14
+ # Configuration object. Create a *snapshotar.rb* initializer under
15
+ # config/initializers and add your configuation inside:
16
+ #
17
+ # Snapshotar.configure do |config|
18
+ # config.storage_type = :file # :s3
19
+ #
20
+ # config.models << [Event, :name, :date]
21
+ # config.models << [Artist, :name]
22
+ # end
23
+ attr_accessor :configuration
24
+ end
25
+
26
+ def self.configuration
27
+ @configuration ||= Configuration.new
28
+ end
29
+
30
+ def self.configure
31
+ yield(configuration) if block_given?
32
+ end
33
+
34
+ def self.core
35
+ @core ||= Core.new
36
+ end
37
+
38
+ ##
39
+ # List available snapshots
40
+ #
41
+ def self.list
42
+ self.core.list
43
+ end
44
+
45
+ ##
46
+ # Create a snapshot
47
+ #
48
+ def self.create(name = nil)
49
+ self.core.export(name)
50
+ end
51
+
52
+ ##
53
+ # Load a snapshot
54
+ #
55
+ def self.load(name)
56
+ self.core.import(name)
57
+ end
58
+
59
+ ##
60
+ # Delete a snapshot
61
+ #
62
+ def self.delete(name)
63
+ self.core.delete(name)
64
+ end
65
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'snapshotar/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "snapshotar"
8
+ spec.version = Snapshotar::VERSION
9
+ spec.authors = ["Benjamin Müller"]
10
+ spec.email = ["benjamin@boxar.de"]
11
+ spec.description = %q{Make a snapshot of your rails database by serializing all objects.}
12
+ spec.summary = %q{In contrast to a database backup, snapshotAR is able to manage image references made with paperclip or carrierwave correctly. You are able to save your entire application or only parts of it and e.g. seed your test environments. }
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib","tasks"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "dotenv"
25
+ spec.add_development_dependency 'mongoid', '~> 4.0.0'
26
+ spec.add_development_dependency 'carrierwave-mongoid'
27
+
28
+ spec.add_dependency 'aws-sdk', '~> 1.0'
29
+ spec.add_dependency 'jbuilder'
30
+ end
data/snapshotar.png ADDED
Binary file
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Snapshotar::Storage::FileStorage do
4
+
5
+ context "local file storage" do
6
+
7
+ before(:all) do
8
+ Mongoid.purge!
9
+
10
+ # setup configuration
11
+ Snapshotar.configure do |config|
12
+
13
+ config.storage_type = :file
14
+
15
+ # serialization
16
+ config.models << [Artist, :name, :avatar]
17
+ end
18
+
19
+ # create models with images attached
20
+ artist = Artist.create({name: "Artist 3"})
21
+ artist.avatar.store!(File.open("snapshotar.png"))
22
+ artist.save
23
+
24
+ @snapshotar = Snapshotar::Core.new
25
+ end
26
+
27
+ after(:all) do
28
+ # clean up files
29
+ FileUtils.rm_rf(Dir["tmp"])
30
+
31
+ Mongoid.purge!
32
+ end
33
+
34
+ it "should create image models" do
35
+ expect(Artist.count).to eq 1
36
+ p Artist.first.avatar.path
37
+ end
38
+
39
+ it "should export successfully" do
40
+ filename = @snapshotar.export
41
+
42
+ expect(@snapshotar.list).to include(filename)
43
+
44
+ # clean up
45
+ @snapshotar.delete(filename)
46
+ end
47
+
48
+ it "should reimport with images" do
49
+ # export sample
50
+ filename = @snapshotar.export
51
+
52
+ # clear db
53
+ Mongoid.purge!
54
+
55
+ expect(Artist.count).to eq 0
56
+
57
+ # # reimport
58
+ @snapshotar.import(filename)
59
+
60
+ expect(Artist.count).to eq 1
61
+ expect(Artist.first.avatar.path).not_to be_nil
62
+
63
+ # clean up
64
+ @snapshotar.delete(filename)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,14 @@
1
+ test:
2
+ sessions:
3
+ default:
4
+ database: snapshotar_test
5
+ hosts:
6
+ - <%= ENV['WERCKER_MONGODB_HOST'] || 'localhost:27017' %>
7
+ options:
8
+ # consistency: :strong
9
+ # In the test environment we lower the retries and retry interval to
10
+ # low amounts for fast failures.
11
+ max_retries: 1
12
+ retry_interval: 0
13
+ options:
14
+ raise_not_found_error: false
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ #:nodoc:
4
+ describe Snapshotar::Core do
5
+
6
+ context "listing snapshots" do
7
+
8
+ before(:all) do
9
+ Snapshotar.configure do |config|
10
+ # lets use default values
11
+ config.storage_type = :file
12
+ config.models = []
13
+ end
14
+ end
15
+
16
+ it "should load default config" do
17
+ expect(Snapshotar.configuration).not_to be_nil
18
+
19
+ expect(Snapshotar.configuration.storage_type).to eq :file
20
+ expect(Snapshotar.configuration.models).to be_empty
21
+ end
22
+
23
+ end
24
+ end
data/spec/core_spec.rb ADDED
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+ require 'jbuilder'
3
+
4
+ #:nodoc:
5
+ describe Snapshotar::Core do
6
+
7
+ context "listing snapshots" do
8
+
9
+ before(:all) do
10
+
11
+ # clear db
12
+ Mongoid.purge!
13
+
14
+ # setup configuration
15
+ Snapshotar.configure do |config|
16
+
17
+ config.storage_type = :file
18
+
19
+ # serialization
20
+ config.models << [Event, :name, :date]
21
+ config.models << [Artist, :name]
22
+
23
+ end
24
+
25
+ # create sample data
26
+ Event.create({name: "Event 1", date: Date.new})
27
+ Event.create({name: "Event 2", date: Date.new})
28
+
29
+ Artist.create({name: "Artist 1"})
30
+ Artist.create({name: "Artist 2"})
31
+ end
32
+
33
+ after(:all) do
34
+ # clean up
35
+ FileUtils.rm_rf(Dir["tmp"])
36
+ Mongoid.purge!
37
+ end
38
+
39
+ it "should list snapshots" do
40
+ expect(Snapshotar.list).to be_empty
41
+ end
42
+
43
+ it "should have one Event" do
44
+ expect(Event.count).to eq 2
45
+ expect(Artist.count).to eq 2
46
+ end
47
+
48
+ it "should correctly read config models" do
49
+
50
+ serialized = Jbuilder.encode do |json|
51
+ Snapshotar.configuration.models.each do |m|
52
+ model_name = m.first.name
53
+ json.set! model_name do
54
+ json.array! m.first.all, *m[1..-1]
55
+ end
56
+ end
57
+ end
58
+
59
+ # p "serialized: #{serialized}"
60
+ end
61
+
62
+ it "should export models" do
63
+ filename = Snapshotar.create
64
+ expect(Snapshotar.list).to include(filename)
65
+
66
+ # clean up
67
+ Snapshotar.delete(filename)
68
+ end
69
+
70
+ it "should import models" do
71
+ # export sample
72
+ filename = Snapshotar.create
73
+
74
+ # clear db
75
+ Mongoid.purge!
76
+
77
+ expect(Event.count).to eq 0
78
+ expect(Artist.count).to eq 0
79
+
80
+ # reimport
81
+ Snapshotar.load(filename)
82
+
83
+ expect(Event.count).to eq 2
84
+ expect(Artist.count).to eq 2
85
+
86
+ # clean up
87
+ Snapshotar.delete(filename)
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe Snapshotar::Storage::FileStorage do
5
+
6
+ TMP_DIR = "tmp"
7
+
8
+ context "local file storage" do
9
+
10
+ before(:all) do
11
+ @fileStorage = described_class.new(TMP_DIR)
12
+
13
+ # write a test file
14
+ f = File.open(File.join(TMP_DIR,"test.json"), "w+")
15
+ f.close
16
+
17
+ end
18
+
19
+ after(:all) do
20
+
21
+ # clean up
22
+ File.delete(File.join(TMP_DIR,"test.json"))
23
+ end
24
+
25
+ it "should initialize correctly" do
26
+ end
27
+
28
+ it "should list objects" do
29
+
30
+ expect(@fileStorage.index).not_to be_empty
31
+ expect(@fileStorage.index.count).to eq 1
32
+ end
33
+
34
+ it "should show one element" do
35
+
36
+ expect(@fileStorage.show(@fileStorage.index.first)).not_to be_nil
37
+ end
38
+
39
+ it "should create an element" do
40
+
41
+ @fileStorage.create("zz_testdump.json",{"test" => "this is a test object"}.to_json)
42
+
43
+ expect(JSON.load(@fileStorage.show("zz_testdump.json"))).to have_key("test")
44
+
45
+ @fileStorage.delete("zz_testdump.json")
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,10 @@
1
+ # this is a sample model for testing purpose
2
+ require_relative './image_uploader'
3
+
4
+ class Artist #:nodoc:
5
+ include Mongoid::Document
6
+
7
+ mount_uploader :avatar, ImageUploader
8
+
9
+ field :name, type: String
10
+ end
@@ -0,0 +1,8 @@
1
+ # this is a sample model for testing purpose
2
+
3
+ class Event #:nodoc:
4
+ include Mongoid::Document
5
+
6
+ field :name, type: String
7
+ field :date, type: Date
8
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ require 'carrierwave/mongoid'
3
+
4
+ class ImageUploader < CarrierWave::Uploader::Base
5
+
6
+ # Include RMagick or MiniMagick support:
7
+ # include CarrierWave::RMagick
8
+ # include CarrierWave::MiniMagick
9
+
10
+ # Choose what kind of storage to use for this uploader:
11
+ # storage :fog
12
+ storage = :file
13
+ enable_processing = false
14
+
15
+ # Override the directory where uploaded files will be stored.
16
+ # This is a sensible default for uploaders that are meant to be mounted:
17
+ def store_dir
18
+ "tmp/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
19
+ end
20
+
21
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ #:nodoc:
4
+ describe Snapshotar::Storage::S3Storage do
5
+
6
+ context "setup s3 connection", require_s3: true do
7
+
8
+ before(:all) do
9
+ @s3Storage = described_class.new
10
+ end
11
+
12
+ it "should initialize correctly" do
13
+ end
14
+
15
+ it "should list objects" do
16
+ expect(@s3Storage.index).not_to be_empty
17
+ end
18
+
19
+ it "should show one element" do
20
+ expect(@s3Storage.show(@s3Storage.index.first)).not_to be_nil
21
+ end
22
+
23
+ it "should create an element" do
24
+ @s3Storage.create("zz_testdump.json",{"test" => "this is a test object"}.to_json)
25
+
26
+ expect(JSON.load(@s3Storage.show(@s3Storage.index.last))).to have_key("test")
27
+
28
+ @s3Storage.delete("zz_testdump.json")
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'dotenv'
5
+ Dotenv.load
6
+
7
+ require 'snapshotar'
8
+ require 'mongoid'
9
+
10
+ Mongoid.load!('spec/config/mongoid.yml')
11
+
12
+ require 'carrierwave/mongoid'
13
+
14
+ CarrierWave.configure do |config|
15
+ config.root = Dir.pwd
16
+ config.asset_host = Dir.pwd
17
+ end
18
+
19
+ require 'models/event'
20
+ require 'models/artist'
21
+
22
+
23
+ RSpec.configure do |config|
24
+
25
+ config.tty = true
26
+
27
+ if ENV['S3_ENABLED']=="false"
28
+ p "Skipping S3 Tests"
29
+ config.filter_run_excluding require_s3: true
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: snapshotar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin Müller
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-12 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.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '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: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dotenv
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: mongoid
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 4.0.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 4.0.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: carrierwave-mongoid
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: aws-sdk
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: jbuilder
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
+ description: Make a snapshot of your rails database by serializing all objects.
126
+ email:
127
+ - benjamin@boxar.de
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - .respec
134
+ - .travis.yml
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - lib/snapshotar.rb
140
+ - lib/snapshotar/configuration.rb
141
+ - lib/snapshotar/core.rb
142
+ - lib/snapshotar/storage/file_storage.rb
143
+ - lib/snapshotar/storage/s3_storage.rb
144
+ - lib/snapshotar/storage/storage_template.rb
145
+ - lib/snapshotar/tasks.rb
146
+ - lib/snapshotar/version.rb
147
+ - snapshotar.gemspec
148
+ - snapshotar.png
149
+ - spec/carrierwave_spec.rb
150
+ - spec/config/mongoid.yml
151
+ - spec/config_spec.rb
152
+ - spec/core_spec.rb
153
+ - spec/file_storage_spec.rb
154
+ - spec/models/artist.rb
155
+ - spec/models/event.rb
156
+ - spec/models/image_uploader.rb
157
+ - spec/s3_storage_spec.rb
158
+ - spec/spec_helper.rb
159
+ homepage: ''
160
+ licenses:
161
+ - MIT
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ - tasks
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubyforge_project:
180
+ rubygems_version: 2.4.1
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: In contrast to a database backup, snapshotAR is able to manage image references
184
+ made with paperclip or carrierwave correctly. You are able to save your entire application
185
+ or only parts of it and e.g. seed your test environments.
186
+ test_files:
187
+ - spec/carrierwave_spec.rb
188
+ - spec/config/mongoid.yml
189
+ - spec/config_spec.rb
190
+ - spec/core_spec.rb
191
+ - spec/file_storage_spec.rb
192
+ - spec/models/artist.rb
193
+ - spec/models/event.rb
194
+ - spec/models/image_uploader.rb
195
+ - spec/s3_storage_spec.rb
196
+ - spec/spec_helper.rb