cabinet 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ module Cabinet
2
+ class Instance
3
+ attr_accessor :connection, :directory
4
+
5
+ def initialize(provider, auth={})
6
+ fog_config = auth.merge({:provider => fog_provider(provider)})
7
+ self.connection = Fog::Storage.new(fog_config)
8
+ end
9
+
10
+ def directory=(name)
11
+ @directory = connection.directories.get(name) || connection.directories.create(:key => name)
12
+ end
13
+
14
+ alias :container= :directory=
15
+ alias :bucket= :directory=
16
+
17
+ def get(name)
18
+ file(name).body
19
+ end
20
+
21
+ def list(regexp=/.*/)
22
+ directory.files.reload
23
+ directory.files.select{|f| f.key.match(regexp)}.to_a.map(&:key)
24
+ end
25
+
26
+ def put(name, content)
27
+ content = content.to_s
28
+
29
+ begin
30
+ directory.files.create(:key => name, :body => content).content_length == content.length
31
+ rescue
32
+ false
33
+ end
34
+ end
35
+
36
+ def touch(name)
37
+ (exists?(name) ? put(name, get(name)) : put(name, "")) and !!reload(name)
38
+ end
39
+
40
+ def append(name, new_content)
41
+ content = exists?(name) ? get(name) + new_content : new_content
42
+ put(name, content) and !!reload(name)
43
+ end
44
+
45
+ def delete(name_or_regexp)
46
+ @file = nil
47
+
48
+ directory.files.reload
49
+
50
+ if name_or_regexp.class == Regexp
51
+ directory.files.select{|f| f.key.match(name_or_regexp)}.each do |file|
52
+ file.destroy
53
+ end
54
+ else
55
+ directory.files.get(name_or_regexp).destroy
56
+ end
57
+
58
+ true
59
+ end
60
+
61
+ def copy_to(klass, name)
62
+ klass.put(name, get(name))
63
+ end
64
+
65
+ def exists?(name)
66
+ !!file(name)
67
+ end
68
+
69
+ def modified(name)
70
+ file(name).last_modified + 0 if exists?(name)
71
+ end
72
+
73
+ def compress(name, content)
74
+ name = name.gsub(/(.+?)(\.gz)?$/, '\1.gz')
75
+ tmp = "/tmp/cabinet-tmp-#{name}-#{Time.now}"
76
+
77
+ File.open(tmp, 'w') do |f|
78
+ gz = Zlib::GzipWriter.new(f)
79
+ gz.write content
80
+ gz.close
81
+ end
82
+
83
+ put(name, File.read(tmp)) and (File.unlink(tmp) == 1)
84
+ end
85
+
86
+ def decompress(name)
87
+ Zlib::GzipReader.new(StringIO.new(get(name))).read
88
+ end
89
+
90
+ private
91
+ def file(name)
92
+ raise 'No directory specified' unless directory
93
+
94
+ if @file && @file.key == name
95
+ @file
96
+ else
97
+ reload(name)
98
+ end
99
+ end
100
+
101
+ def reload(name)
102
+ directory.files.reload
103
+ @file = directory.files.get(name)
104
+ end
105
+
106
+ def fog_provider(provider)
107
+ case provider.to_s.downcase
108
+ when 'aws', 's3', 'amazon'
109
+ 'AWS'
110
+ when 'rackspace', 'cloudfiles', 'cloud_files'
111
+ 'Rackspace'
112
+ when 'google', 'google_storage'
113
+ 'Google'
114
+ when 'local', 'localhost', 'filesystem'
115
+ 'Local'
116
+ else
117
+ raise ArgumentError, "#{provider} is not a valid provider"
118
+ end
119
+ end
120
+ end
121
+ end
@@ -1,3 +1,3 @@
1
1
  module Cabinet
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/cabinet.rb CHANGED
@@ -1,7 +1,19 @@
1
1
  require 'pathname'
2
+ require 'fog'
2
3
 
3
- module Cabinet; end
4
+ module Cabinet
5
+ def self.cloud(provider, options={})
6
+ self.init(provider, options)
7
+ end
8
+
9
+ def self.local(path='/')
10
+ self.init(:local, {:local_root => path})
11
+ end
12
+
13
+ def self.init(*args)
14
+ Cabinet::Instance.new(*args)
15
+ end
16
+ end
4
17
 
5
18
  dir = Pathname(__FILE__).dirname.expand_path
6
- require dir + 'cabinet/cloud'
7
- require dir + 'cabinet/local'
19
+ require dir + 'cabinet/instance'
@@ -0,0 +1,118 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe Cabinet::Instance do
4
+ before(:all) do
5
+ @local = Cabinet.local
6
+ @local.directory = '/tmp/cabinet_test'
7
+
8
+ @file_name = Forgery(:basic).text
9
+ @file_content = Forgery(:lorem_ipsum).text(:paragraphs, 10)
10
+ end
11
+
12
+ after(:all) do
13
+ @local.delete(/.*/)
14
+ end
15
+
16
+ it "creates files" do
17
+ @local.put(@file_name, @file_content).should == true
18
+ end
19
+
20
+ it "confirms that files exists" do
21
+ @local.exists?(@file_name).should == true
22
+ end
23
+
24
+ it "confirms that files don't exist" do
25
+ @local.exists?(@file_content).should == false
26
+ end
27
+
28
+ it "reads file content" do
29
+ @local.get(@file_name).should == @file_content
30
+ end
31
+
32
+ it "fetches last modified timestamp" do
33
+ @local.modified(@file_name).class.should == Time
34
+ end
35
+
36
+ it "appends files" do
37
+ extra_content = Forgery(:lorem_ipsum).text(:paragraph)
38
+ @local.append(@file_name, extra_content).should == true
39
+ @local.get(@file_name).should == @file_content + extra_content
40
+ end
41
+
42
+ it "list files with (and without) regular expressions" do
43
+ @local.list.should include(@file_name)
44
+ @local.list(/#{@file_name}/).should include(@file_name)
45
+ @local.list(/#{@file_content}/).should == []
46
+ end
47
+
48
+ it "creates an empty file using put with empty content argument" do
49
+ file = Forgery(:basic).text
50
+
51
+ @local.put(file, nil).should == true
52
+ @local.get(file).should == ""
53
+ end
54
+
55
+ it "creates an empty file using touch" do
56
+ file = Forgery(:basic).text
57
+
58
+ @local.touch(file).should == true
59
+ @local.get(file).should == ""
60
+ end
61
+
62
+ it "copies files from one cabinet instance to another" do
63
+ new_local = Cabinet.local
64
+ new_local.directory = "/tmp/cabinet_test_2"
65
+
66
+ @local.copy_to(new_local, @file_name).should == true
67
+ new_local.get(@file_name).should == @local.get(@file_name)
68
+
69
+ new_local.delete(@file_name)
70
+ end
71
+
72
+ it "updates last_modified timestamp using touch" do
73
+ original_time = @local.modified(@file_name)
74
+ original_content = @local.get(@file_name)
75
+
76
+ sleep(1) # to force time to pass update
77
+
78
+ @local.touch(@file_name).should == true
79
+ @local.modified(@file_name).should_not == original_time
80
+ @local.get(@file_name).should == original_content
81
+ end
82
+
83
+ it "compresses files using gzip" do
84
+ gz_file_name = @file_name + '.gz'
85
+
86
+ @local.compress(gz_file_name, @file_content).should == true
87
+ Zlib::GzipReader.new(StringIO.new(@local.get(gz_file_name))).read.should == @file_content
88
+ end
89
+
90
+ it "decompresses files using gzip" do
91
+ gz_file_name = @file_name + '.gz'
92
+ @local.decompress(gz_file_name).should == @file_content
93
+ end
94
+
95
+ it "deletes files" do
96
+ @local.delete(@file_name).should == true
97
+ @local.exists?(@file_name).should == false
98
+ end
99
+
100
+ it "bulk deletes files using regular expressions" do
101
+ (1..3).each {|n| @local.put("#{@file_name}.#{n}", @file_content)}
102
+ @local.delete(/#{@file_name}/)
103
+ (1..3).inject([]) {|arr, n| arr << @local.exists?("#{@file_name}.#{n}")}.should == [false, false, false]
104
+ end
105
+
106
+ it "tests cloud connection" do
107
+ credentials = YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '..', 'cloud_credentials.yml')))
108
+ cloud = Cabinet.cloud(:rackspace, credentials)
109
+ cloud.container = 'cabinet_test'
110
+
111
+ cloud.put(@file_name, @file_content).should == true
112
+ cloud.list.should include(@file_name)
113
+ cloud.list(/#{@file_name}/).should include(@file_name)
114
+ cloud.get(@file_name).should == @file_content
115
+ cloud.delete(@file_name).should == true
116
+ cloud.list.should_not include(@file_name)
117
+ end
118
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,8 +2,4 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'cabinet')
2
2
  require 'forgery'
3
3
 
4
4
  RSpec.configure do |config|
5
- config.before(:suite) do
6
- @@file_name = 'cabinet.test'
7
- @@file_content = Forgery(:lorem_ipsum).text(:paragraphs, 10)
8
- end
9
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cabinet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sebastian von Conrad
@@ -97,11 +97,9 @@ files:
97
97
  - Rakefile
98
98
  - cabinet.gemspec
99
99
  - lib/cabinet.rb
100
- - lib/cabinet/cloud.rb
101
- - lib/cabinet/local.rb
100
+ - lib/cabinet/instance.rb
102
101
  - lib/cabinet/version.rb
103
- - spec/cabinet/cloud_spec.rb
104
- - spec/cabinet/local_spec.rb
102
+ - spec/cabinet/instance_spec.rb
105
103
  - spec/cloud_credentials.yml
106
104
  - spec/spec_helper.rb
107
105
  has_rdoc: true
@@ -139,7 +137,6 @@ signing_key:
139
137
  specification_version: 3
140
138
  summary: ""
141
139
  test_files:
142
- - spec/cabinet/cloud_spec.rb
143
- - spec/cabinet/local_spec.rb
140
+ - spec/cabinet/instance_spec.rb
144
141
  - spec/cloud_credentials.yml
145
142
  - spec/spec_helper.rb
data/lib/cabinet/cloud.rb DELETED
@@ -1,99 +0,0 @@
1
- require 'fog'
2
-
3
- module Cabinet
4
- class Cloud
5
- attr_accessor :connection, :container
6
-
7
- def initialize(config)
8
- root_dir = config.delete(:container)
9
- self.connection = Fog::Rackspace::Storage.new(config)
10
- self.container = connection.directories.get(root_dir) || connection.directories.create(:key => root_dir)
11
- end
12
-
13
- def get(name)
14
- file(name).body
15
- end
16
-
17
- def list(regexp=/.*/)
18
- container.files.reload
19
- container.files.select{|f| f.key.match(regexp)}.to_a.map(&:key)
20
- end
21
-
22
- def put(name, content)
23
- begin
24
- container.files.create(:key => name, :body => content).content_length == content.length
25
- rescue
26
- false
27
- end
28
- end
29
-
30
- def append(name, new_content)
31
- content = exists?(name) ? get(name) + new_content : new_content
32
- put(name, content) and !!reload(name)
33
- end
34
-
35
- def delete(name_or_regexp)
36
- @file = nil
37
-
38
- container.files.reload
39
-
40
- if name_or_regexp.class == Regexp
41
- container.files.select{|f| f.key.match(name_or_regexp)}.each do |file|
42
- file.destroy
43
- end
44
- else
45
- container.files.get(name_or_regexp).destroy
46
- end
47
-
48
- true
49
- end
50
-
51
- def copy_to(klass_or_sym, name)
52
- if klass_or_sym.is_a? Symbol
53
- c = case klass_or_sym
54
- when :local
55
- Local.new('/tmp')
56
- end
57
- else
58
- c = klass_or_sym
59
- end
60
-
61
- c.put(name, get(name))
62
- end
63
-
64
- def exists?(name)
65
- !!file(name)
66
- end
67
-
68
- def modified(name)
69
- file(name).last_modified + 0 if exists?(name)
70
- end
71
-
72
- def gzip(name, content)
73
- name = name.gsub(/(.+?)(\.gz)?$/, '\1.gz')
74
- local = "/tmp/#{name}"
75
-
76
- File.open(local, 'w') do |f|
77
- gz = Zlib::GzipWriter.new(f)
78
- gz.write content
79
- gz.close
80
- end
81
-
82
- put(name, File.read(local)) and File.unlink(local)
83
- end
84
-
85
- private
86
- def file(name)
87
- if @file && @file.key == name
88
- @file
89
- else
90
- reload(name)
91
- end
92
- end
93
-
94
- def reload(name)
95
- container.files.reload
96
- @file = container.files.get(name)
97
- end
98
- end
99
- end
data/lib/cabinet/local.rb DELETED
@@ -1,42 +0,0 @@
1
- module Cabinet
2
- class Local
3
- attr_accessor :dir
4
-
5
- def initialize(root_dir)
6
- self.dir = root_dir.chomp('/') + '/'
7
- end
8
-
9
- def get(file)
10
- raise ArgumentError, "The file #{file} does not exist" unless exists?(file)
11
- File.read(dir + file)
12
- end
13
-
14
- def put(file, content)
15
- File.open(dir + file, 'wb') {|f| f.write(content)} == content.length
16
- end
17
-
18
- def append(file, content)
19
- File.open(dir + file, 'ab') {|f| f.write(content)} == content.length
20
- end
21
-
22
- def delete(file_or_regexp)
23
- File.delete *Dir.glob(dir + file_or_regexp)
24
- end
25
-
26
- def exists?(file)
27
- File.exists?(dir + file)
28
- end
29
-
30
- def modified(file)
31
- File.mtime(dir + file) if exists?(file)
32
- end
33
-
34
- def gzip(file, content)
35
- File.open(dir + file, 'w') do |f|
36
- gz = Zlib::GzipWriter.new(f)
37
- gz.write content
38
- gz.close
39
- end
40
- end
41
- end
42
- end
@@ -1,84 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
-
3
- describe Cabinet::Cloud do
4
- before(:all) do
5
- credentials = YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '..', 'cloud_credentials.yml')))
6
- @cc = Cabinet::Cloud.new({:container => 'cabinet_test'}.merge(credentials))
7
- end
8
-
9
- it "should create file" do
10
- @cc.put(@@file_name, @@file_content).should == true
11
- end
12
-
13
- it "should confirm file exists" do
14
- @cc.exists?(@@file_name).should == true
15
- end
16
-
17
- it "should confirm file does not exist" do
18
- @cc.exists?(@@file_content).should == false
19
- end
20
-
21
- it "should read file" do
22
- @cc.get(@@file_name).should == @@file_content
23
- end
24
-
25
- it "should get last modified" do
26
- @cc.modified(@@file_name).class.should == Time
27
- end
28
-
29
- it "should append file" do
30
- extra_content = Forgery(:lorem_ipsum).text(:paragraph)
31
- @cc.append(@@file_name, extra_content).should == true
32
- @cc.get(@@file_name).should == @@file_content + extra_content
33
- end
34
-
35
- it "should list files" do
36
- @cc.list.should include(@@file_name)
37
- @cc.list(/#{@@file_name}/).should include(@@file_name)
38
- @cc.list(/#{@@file_content}/).should == []
39
- end
40
-
41
- it "should copy file to local filesystem using object" do
42
- cl = Cabinet::Local.new('/tmp')
43
- cl.delete(@@file_name) if cl.exists?(@@file_name)
44
-
45
- @cc.copy_to(cl, @@file_name)
46
- cl.exists?(@@file_name).should == true
47
- cl.delete(@@file_name)
48
- end
49
-
50
- it "should copy file to local filesystem using symbol" do
51
- File.unlink("/tmp/#{@@file_name}") if File.exists?("/tmp/#{@@file_name}")
52
- @cc.copy_to(:local, @@file_name)
53
- File.exists?("/tmp/#{@@file_name}").should == true
54
- File.unlink("/tmp/#{@@file_name}")
55
- end
56
-
57
- it "should not overwrite file"
58
-
59
- it "should overwrite file if :force => true"
60
-
61
- it "should gzip file" do
62
- gz_file_name = @@file_name + '.gz'
63
- File.unlink("/tmp/#{gz_file_name}") if File.exists?("/tmp/#{gz_file_name}")
64
-
65
- @cc.gzip(gz_file_name, @@file_content)
66
- @cc.copy_to(:local, gz_file_name)
67
-
68
- Zlib::GzipReader.open("/tmp/#{gz_file_name}") {|gz| gz.read}.should == @@file_content
69
-
70
- @cc.delete(gz_file_name)
71
- File.unlink("/tmp/#{gz_file_name}")
72
- end
73
-
74
- it "should delete file" do
75
- @cc.delete(@@file_name)
76
- @cc.exists?(@@file_name).should == false
77
- end
78
-
79
- it "should bulk delete files" do
80
- (1..3).each {|n| @cc.put("#{@@file_name}.#{n}", @@file_content)}
81
- @cc.delete(/#{@@file_name}/)
82
- (1..3).inject([]) {|arr, n| arr << @cc.exists?("#{@@file_name}.#{n}")}.should == [false, false, false]
83
- end
84
- end
@@ -1,57 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
-
3
- describe Cabinet::Local do
4
- before(:all) do
5
- @cl = Cabinet::Local.new('/tmp')
6
- end
7
-
8
- it "should create file" do
9
- @cl.put(@@file_name, @@file_content).should == true
10
- end
11
-
12
- it "should confirm file exists" do
13
- @cl.exists?(@@file_name).should == true
14
- end
15
-
16
- it "should confirm file does not exist" do
17
- @cl.exists?(@@file_content).should == false
18
- end
19
-
20
- it "should read file" do
21
- @cl.get(@@file_name).should == @@file_content
22
- end
23
-
24
- it "should see last modified" do
25
- @cl.modified(@@file_name).class.should == Time
26
- end
27
-
28
- it "should append file" do
29
- extra_content = Forgery(:lorem_ipsum).text(:paragraph)
30
- @cl.append(@@file_name, extra_content).should == true
31
- @cl.get(@@file_name).should == @@file_content + extra_content
32
- end
33
-
34
- it "should list files"
35
-
36
- it "should not overwrite file"
37
-
38
- it "should overwrite file if :force => true"
39
-
40
- it "should gzip file" do
41
- gz_file_name = @@file_name + '.gz'
42
- @cl.gzip(gz_file_name, @@file_content)
43
- Zlib::GzipReader.open("/tmp/#{gz_file_name}") {|gz| gz.read}.should == @@file_content
44
- @cl.delete(gz_file_name)
45
- end
46
-
47
- it "should delete file" do
48
- @cl.delete(@@file_name)
49
- @cl.exists?(@@file_name).should == false
50
- end
51
-
52
- it "should bulk delete files" do
53
- (1..3).each {|n| @cl.put("#{@@file_name}.#{n}", @@file_content)}
54
- @cl.delete("#{@@file_name}*")
55
- (1..3).inject([]) {|arr, n| arr << @cl.exists?("#{@@file_name}.#{n}")}.should == [false, false, false]
56
- end
57
- end