dragonfly-manta_data_store 0.9.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65a092b8cc5eb180248e34adb26b5d74530d4c6b
4
+ data.tar.gz: fe49ab770597a4e4f8204c97c4b481b64805d806
5
+ SHA512:
6
+ metadata.gz: 7f4faa53836bab887f4a7735569624696c01049575a46ff2363e4b15c553c8f8fb933308e3894d76bd6c7e764eef8388c21d5b44498ffc5ee8092da83c24195b
7
+ data.tar.gz: 78647412fd8213b19818ad51530d3054b29d817a45f865c2e036bec749e1af24f66253ab95778e175770e47a6a6d8b1a2d8e2a48d0b620548f55a41012321953
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
+ .s3_spec.yml
19
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gem "pry"
3
+ gem "ruby-manta", :path => "~/onyxrev/ruby-manta"
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Dan Connor
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,75 @@
1
+ # Dragonfly::MantaDataStore
2
+
3
+ Joyent Manta data store for use with the [Dragonfly](http://github.com/markevans/dragonfly) gem. Inspired by the [S3 Dragonfly gem](https://github.com/markevans/dragonfly-s3_data_store).
4
+
5
+ ## Gemfile
6
+
7
+ ```ruby
8
+ gem 'dragonfly-manta_data_store'
9
+ ```
10
+
11
+ ## Usage
12
+ Configuration (remember the require)
13
+
14
+ ```ruby
15
+ require 'dragonfly/manta_data_store'
16
+
17
+ Dragonfly.app.configure do
18
+ # ...
19
+
20
+ datastore :manta,
21
+ directory: 'my_images',
22
+ url: 'https://us-east.manta.joyent.com',
23
+ user: 'myuser,
24
+ key: 'actual ASCII ssh key (load from file or ENV)',
25
+ durability_level: 2
26
+ # ...
27
+ end
28
+ ```
29
+
30
+ ### Available configuration options
31
+
32
+ ```ruby
33
+ :directory # base directory within your public directory
34
+ :url # defaults to "https://us-east.manta.joyent.com"
35
+ :user # your joyent user
36
+ :key # SSH ASCII key
37
+ :durability_level # defaults to 2
38
+ :region # defaults to 'us-east'
39
+ :url_scheme # defaults to 'http'
40
+ :url_host # maybe useful for a CDN?
41
+ :root_path # another base directory on top of :directory (mostly to match the S3 store)
42
+ :storage_headers # headers to include for all stored objects
43
+ ```
44
+
45
+ ### Serving directly from Manta
46
+
47
+ You can get the Manta url using
48
+
49
+ ```ruby
50
+ Dragonfly.app.remote_url_for('some/uid')
51
+ ```
52
+
53
+ or
54
+
55
+ ```ruby
56
+ my_model.attachment.remote_url
57
+ ```
58
+
59
+ or with an expiring url:
60
+
61
+ ```ruby
62
+ my_model.attachment.remote_url(expires: 3.days.from_now)
63
+ ```
64
+
65
+ or with an https url:
66
+
67
+ ```ruby
68
+ my_model.attachment.remote_url(scheme: 'https') # also configurable for all urls with 'url_scheme'
69
+ ```
70
+
71
+ or with a custom host:
72
+
73
+ ```ruby
74
+ my_model.attachment.remote_url(host: 'custom.domain') # also configurable for all urls with 'url_host'
75
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dragonfly/manta_data_store/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dragonfly-manta_data_store"
8
+ spec.version = Dragonfly::MantaDataStore::VERSION
9
+ spec.authors = ["Dan Connor"]
10
+ spec.email = ["danconn@danconnor.com"]
11
+ spec.description = %q{Manta data store for Dragonfly}
12
+ spec.summary = %q{Data store for storing Dragonfly content (e.g. images) on Manta}
13
+ spec.homepage = "https://github.com/onyxrev/dragonfly-manta_data_store"
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"]
20
+
21
+ spec.add_runtime_dependency "dragonfly", "~> 1.0"
22
+ spec.add_runtime_dependency "ruby-manta", "~> 2.0"
23
+ spec.add_development_dependency "rspec", "~> 2.0"
24
+ end
@@ -0,0 +1,193 @@
1
+ require 'ruby-manta'
2
+ require 'dragonfly'
3
+
4
+ Dragonfly::App.register_datastore(:manta){ Dragonfly::MantaDataStore }
5
+
6
+ module Dragonfly
7
+ class MantaDataStore
8
+
9
+ # Exceptions
10
+ class NotConfigured < RuntimeError; end
11
+
12
+ REGIONS = {
13
+ # default (and only as of now)
14
+ 'us-east' => 'us-east.manta.joyent.com'
15
+ }
16
+
17
+ def initialize(options = {})
18
+ @directory = options[:directory]
19
+ @url = options[:url]
20
+ @user = options[:user]
21
+ @key = options[:key]
22
+ @durability_level = options[:durability_level] || 2
23
+ @region = options[:region] || REGIONS.keys.first
24
+ @url_scheme = options[:url_scheme] || 'http'
25
+ @url_host = options[:url_host]
26
+ @root_path = options[:root_path]
27
+ @storage_headers = options[:storage_headers] || {}
28
+ end
29
+
30
+ attr_accessor :directory, :url, :user, :key, :durability_level, :region, :url_scheme, :url_host, :root_path, :storage_headers
31
+
32
+ def write(content, options = {})
33
+ ensure_configured
34
+ ensure_directory
35
+ store_content(content, options)
36
+ end
37
+
38
+ def read(uid)
39
+ ensure_configured
40
+ response, headers = storage.get_object(full_path(uid))
41
+
42
+ [ response, headers_to_meta(headers) ]
43
+ rescue RubyManta::MantaClient::ResourceNotFound => e
44
+ nil
45
+ end
46
+
47
+ def destroy(uid)
48
+ storage.delete_object(full_path(uid))
49
+ rescue => e
50
+ Dragonfly.warn("#{self.class.name} destroy error: #{e}")
51
+ end
52
+
53
+ def url_for(uid, options = {})
54
+ scheme = options[:scheme] || url_scheme
55
+
56
+ if options[:expires]
57
+ url_without_scheme = storage.gen_signed_url(options[:expires], :get, full_path(uid))
58
+ else
59
+ host = options[:host] || url_host || region_host
60
+
61
+ url_without_scheme = "#{host}#{full_path(uid)}"
62
+ end
63
+
64
+ "#{scheme}://#{url_without_scheme}"
65
+ end
66
+
67
+ def storage
68
+ @storage ||= begin
69
+ RubyManta::MantaClient.new(url, user, key)
70
+ end
71
+ end
72
+
73
+ def directory_exists?
74
+ storage.list_directory(public_directory, :head => true)
75
+ true
76
+ rescue RubyManta::MantaClient::UnknownError => e
77
+ false
78
+ end
79
+
80
+ def domain
81
+ REGIONS[get_region]
82
+ end
83
+
84
+ private
85
+
86
+ def headers_to_meta(headers)
87
+ begin
88
+ JSON.parse(headers["m-dragonfly"])
89
+ rescue => e
90
+ nil
91
+ end
92
+ end
93
+
94
+ def meta_to_header(meta = {})
95
+ { :m_dragonfly => JSON.dump(meta) }
96
+ end
97
+
98
+ def store_content(content, options = {})
99
+ uid = options[:path] || generate_uid(content.name || 'file')
100
+
101
+ headers = {
102
+ :content_type => content.mime_type
103
+ }
104
+
105
+ headers.merge!(meta_to_header(content.meta))
106
+ headers.merge!(options[:headers]) if options[:headers]
107
+
108
+ path = full_path(uid)
109
+ mkdir_for_file_path(path)
110
+
111
+ content.file do |file|
112
+ storage.put_object(
113
+ path,
114
+ file.read,
115
+ full_storage_headers(headers)
116
+ )
117
+ end
118
+
119
+ uid
120
+ end
121
+
122
+ def ensure_configured
123
+ unless @configured
124
+ [:directory, :url, :user, :key].each do |attr|
125
+ raise NotConfigured, "You need to configure #{self.class.name} with #{attr}" if send(attr).nil?
126
+ end
127
+
128
+ @configured = true
129
+ end
130
+ end
131
+
132
+ def ensure_directory
133
+ unless @directory_created
134
+ mkdir(public_directory) unless directory_exists?
135
+
136
+ @directory_created = true
137
+ end
138
+ end
139
+
140
+ def public_directory
141
+ "/#{@user}/public/#{@directory}"
142
+ end
143
+
144
+ def region_host
145
+ REGIONS[get_region]
146
+ end
147
+
148
+ def get_region
149
+ raise "Invalid region #{region} - should be one of #{valid_regions.join(', ')}" unless valid_regions.include?(region)
150
+ region
151
+ end
152
+
153
+ def generate_uid(name)
154
+ # S3 was using subdirectories but Manta is ZFS and it can handle up to
155
+ # 281,474,976,710,656 files in a directory
156
+ "#{Time.now.strftime '%Y_%m_%d_%H_%M_%S'}_#{rand(1000)}_#{name.gsub(/[^\w.]+/, '_')}"
157
+ end
158
+
159
+ def full_storage_headers(options = {})
160
+ {
161
+ "durability_level" => durability_level
162
+ }.merge(storage_headers).merge(options)
163
+ end
164
+
165
+ def full_path(uid)
166
+ File.join *[public_directory, root_path, uid].compact
167
+ end
168
+
169
+ def valid_regions
170
+ REGIONS.keys
171
+ end
172
+
173
+ def mkdir_for_file_path(file_with_path)
174
+ mkdir_with_intermediates file_with_path.split("/")[0..-2].join("/")
175
+ end
176
+
177
+ def mkdir_with_intermediates(path)
178
+ path_components = path.split("/")
179
+
180
+ path_components.length.times do |index|
181
+ path_to_make = path_components[0..index].join("/")
182
+
183
+ if path_to_make.start_with?(public_directory) and not path_to_make.empty?
184
+ mkdir path_to_make
185
+ end
186
+ end
187
+ end
188
+
189
+ def mkdir(path)
190
+ storage.put_directory(path)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,5 @@
1
+ module Dragonfly
2
+ class MantaDataStore
3
+ VERSION = "0.9.0"
4
+ end
5
+ end
@@ -0,0 +1,290 @@
1
+ require 'spec_helper'
2
+ require 'ruby_manta_stub'
3
+ require 'dragonfly/spec/data_store_examples'
4
+ require 'yaml'
5
+ require 'dragonfly/manta_data_store'
6
+
7
+ describe Dragonfly::MantaDataStore do
8
+ # To run these tests, put a file ".manta_spec.yml" in the dragonfly root dir, like this:
9
+ # user: XXXXXXXXXX
10
+ # enabled: true
11
+ #
12
+ # and load your SSH key as the 'DRAGONFLY_MANTA_STORE_SSH_KEY' ENV variable
13
+ if File.exist?(file = File.expand_path('../../.manta_spec.yml', __FILE__))
14
+ config = YAML.load_file(file)
15
+ KEY = ENV['DRAGONFLY_MANTA_STORE_SSH_KEY']
16
+ enabled = config['enabled']
17
+ else
18
+ enabled = false
19
+ end
20
+
21
+ if enabled
22
+ # Make sure it's a new directory name
23
+ DIRECTORY = "dragonfly-test-#{Time.now.to_i.to_s(36)}"
24
+
25
+ before(:each) do
26
+ @data_store = Dragonfly::MantaDataStore.new(
27
+ :directory => DIRECTORY,
28
+ :user => config['user'],
29
+ :url => "https://us-east.manta.joyent.com",
30
+ :key => KEY
31
+ )
32
+ end
33
+ else
34
+ DIRECTORY = 'test-directory'
35
+
36
+ let!(:fake_client){ RubyMantaStub.new }
37
+
38
+ before(:each) do
39
+ RubyManta::MantaClient.stub(:new).and_return(fake_client)
40
+
41
+ @data_store = Dragonfly::MantaDataStore.new(
42
+ :directory => DIRECTORY,
43
+ :user => 'XXXXXXXXX',
44
+ :url => "XXXXXXXXX",
45
+ :key => 'XXXXXXXXX'
46
+ )
47
+
48
+ fake_client.user = @data_store.user
49
+ fake_client.domain = @data_store.domain
50
+ end
51
+ end
52
+
53
+ it_should_behave_like 'data_store'
54
+
55
+ let (:app) { Dragonfly.app }
56
+ let (:content) { Dragonfly::Content.new(app, "eggheads") }
57
+ let (:new_content) { Dragonfly::Content.new(app) }
58
+
59
+ describe "registering with a symbol" do
60
+ it "registers a symbol for configuring" do
61
+ app.configure do
62
+ datastore :manta
63
+ end
64
+ app.datastore.should be_a(Dragonfly::MantaDataStore)
65
+ end
66
+ end
67
+
68
+ describe "write" do
69
+ it "should use the name from the content if set" do
70
+ content.name = 'doobie.doo'
71
+ uid = @data_store.write(content)
72
+ uid.should =~ /doobie\.doo$/
73
+ new_content.update(*@data_store.read(uid))
74
+ new_content.data.should == 'eggheads'
75
+ end
76
+
77
+ it "should work ok with files with funny names" do
78
+ content.name = "A Picture with many spaces in its name (at 20:00 pm).png"
79
+ uid = @data_store.write(content)
80
+ uid.should =~ /A_Picture_with_many_spaces_in_its_name_at_20_00_pm_\.png$/
81
+ new_content.update(*@data_store.read(uid))
82
+ new_content.data.should == 'eggheads'
83
+ end
84
+
85
+ it "should allow for setting the path manually" do
86
+ uid = @data_store.write(content, :path => 'hello/there')
87
+ uid.should == 'hello/there'
88
+ new_content.update(*@data_store.read(uid))
89
+ new_content.data.should == 'eggheads'
90
+ end
91
+ end
92
+
93
+ describe "domain" do
94
+ it "should default to the us-east" do
95
+ @data_store.domain.should == 'us-east.manta.joyent.com'
96
+ end
97
+
98
+ it "should return the correct domain" do
99
+ @data_store.region = 'us-east'
100
+ @data_store.domain.should == 'us-east.manta.joyent.com'
101
+ end
102
+
103
+ it "does raise an error if an unknown region is given" do
104
+ @data_store.region = 'latvia-central'
105
+ lambda{
106
+ @data_store.domain
107
+ }.should raise_error
108
+ end
109
+ end
110
+
111
+ describe "not configuring stuff properly" do
112
+ it "should require a directory name on write" do
113
+ @data_store.directory = nil
114
+ proc{ @data_store.write(content) }.should raise_error(Dragonfly::MantaDataStore::NotConfigured)
115
+ end
116
+
117
+ it "should require a key on write" do
118
+ @data_store.key = nil
119
+ proc{ @data_store.write(content) }.should raise_error(Dragonfly::MantaDataStore::NotConfigured)
120
+ end
121
+
122
+ it "should require a url on write" do
123
+ @data_store.url = nil
124
+ proc{ @data_store.write(content) }.should raise_error(Dragonfly::MantaDataStore::NotConfigured)
125
+ end
126
+
127
+ it "should require a directory on read" do
128
+ @data_store.directory = nil
129
+ proc{ @data_store.read('asdf') }.should raise_error(Dragonfly::MantaDataStore::NotConfigured)
130
+ end
131
+
132
+ it "should require a key on read" do
133
+ @data_store.key = nil
134
+ proc{ @data_store.read('asdf') }.should raise_error(Dragonfly::MantaDataStore::NotConfigured)
135
+ end
136
+
137
+ it "should require a url on read" do
138
+ @data_store.url = nil
139
+ proc{ @data_store.read('asdf') }.should raise_error(Dragonfly::MantaDataStore::NotConfigured)
140
+ end
141
+ end
142
+
143
+ describe "root_path" do
144
+ before do
145
+ content.name = "something.png"
146
+ @data_store.root_path = "some/path"
147
+ end
148
+
149
+ it "stores files in the provided sub directory" do
150
+ @data_store.storage.should_receive(:put_object).with(/^\/#{@data_store.user}\/public\/#{DIRECTORY}\/some\/path\/.*_something\.png$/, anything, anything)
151
+ @data_store.write(content)
152
+ end
153
+
154
+ it "finds files in the provided sub directory" do
155
+ mock_response = double("response", body: "", headers: {})
156
+ uid = @data_store.write(content)
157
+ @data_store.storage.should_receive(:get_object).with(/^\/#{@data_store.user}\/public\/#{DIRECTORY}\/some\/path\/.*_something\.png$/).and_return(mock_response)
158
+ @data_store.read(uid)
159
+ end
160
+
161
+ it "does not alter the uid" do
162
+ uid = @data_store.write(content)
163
+ uid.should include("something.png")
164
+ uid.should_not include("some/path")
165
+ end
166
+
167
+ it "destroys files in the provided sub directory" do
168
+ uid = @data_store.write(content)
169
+ @data_store.storage.should_receive(:delete_object).with(/^\/#{@data_store.user}\/public\/#{DIRECTORY}\/some\/path\/.*_something\.png$/)
170
+ @data_store.destroy(uid)
171
+ end
172
+
173
+ describe "url_for" do
174
+ before do
175
+ @uid = @data_store.write(content)
176
+ end
177
+
178
+ it "returns the uid prefixed with the root_path" do
179
+ @data_store.url_for(@uid).should =~ /some\/path\/.*_something\.png/
180
+ end
181
+
182
+ it "gives an expiring url" do
183
+ expires = 1301476942
184
+ @data_store.url_for(@uid, :expires => expires).should =~ /\/some\/path\/.*_something\.png\?algorithm=rsa-sha1&expires=#{expires}&keyId=%2F#{@data_store.user}%2Fkeys%2F/
185
+ end
186
+ end
187
+
188
+ describe "autocreating the directory" do
189
+ it "should create the directory on write if it doesn't exist" do
190
+ @data_store.directory = "dragonfly-test-blah-blah-#{rand(100000000)}"
191
+ @data_store.write(content)
192
+ end
193
+
194
+ it "should not try to create the directory on read if it doesn't exist" do
195
+ @data_store.directory = "dragonfly-test-blah-blah-#{rand(100000000)}"
196
+ @data_store.send(:storage).should_not_receive(:put_directory)
197
+ @data_store.read("gungle").should be_nil
198
+ end
199
+ end
200
+ end
201
+
202
+ describe "headers" do
203
+ before(:each) do
204
+ @data_store.storage_headers = {'x-zomg' => 'biscuithead'}
205
+ end
206
+
207
+ it "should allow configuring globally" do
208
+ @data_store.storage.should_receive(:put_object).with(anything, anything,
209
+ hash_including('x-zomg' => 'biscuithead')
210
+ )
211
+ @data_store.write(content)
212
+ end
213
+
214
+ it "should allow adding per-store" do
215
+ @data_store.storage.should_receive(:put_object).with(anything, anything,
216
+ hash_including('x-zomg' => 'biscuithead', 'hello' => 'there')
217
+ )
218
+ @data_store.write(content, :headers => {'hello' => 'there'})
219
+ end
220
+
221
+ it "should let the per-store one take precedence" do
222
+ @data_store.storage.should_receive(:put_object).with(anything, anything,
223
+ hash_including('x-zomg' => 'override!')
224
+ )
225
+ @data_store.write(content, :headers => {'x-zomg' => 'override!'})
226
+ end
227
+
228
+ it "should write setting the content type" do
229
+ @data_store.storage.should_receive(:put_object) do |_, __, headers|
230
+ headers[:content_type].should == 'image/png'
231
+ end
232
+ content.name = 'egg.png'
233
+ @data_store.write(content)
234
+ end
235
+
236
+ it "allow overriding the content type" do
237
+ @data_store.storage.should_receive(:put_object) do |_, __, headers|
238
+ headers[:content_type].should == 'text/plain'
239
+ end
240
+ content.name = 'egg.png'
241
+ @data_store.write(content, :headers => {:content_type => 'text/plain'})
242
+ end
243
+ end
244
+
245
+ describe "read" do
246
+ before(:each) do
247
+ content.add_meta('bitrate' => 35, 'name' => 'danny.boy')
248
+ uid = @data_store.write(content)
249
+ stuff, meta = @data_store.read(uid)
250
+ @retrieved_content = Dragonfly::Content.new(app, stuff, meta)
251
+ end
252
+
253
+ it "should return the stored meta" do
254
+ @retrieved_content.meta['bitrate'].should == 35
255
+ @retrieved_content.meta['name'].should == 'danny.boy'
256
+ end
257
+ end
258
+
259
+ describe "urls for serving directly" do
260
+ before(:each) do
261
+ @uid = 'some/path/on/manta'
262
+ end
263
+
264
+ it "should give an expiring url" do
265
+ expires = 1301476942
266
+
267
+ @data_store.url_for(@uid, :expires => expires).should =~
268
+ %r{^http://#{@data_store.domain}/#{@data_store.user}/public/#{DIRECTORY}/some/path/on/manta\?algorithm=rsa-sha1&expires=#{expires}&keyId=%2F#{@data_store.user}%2Fkeys\.*}
269
+ end
270
+
271
+ it "should allow for using https" do
272
+ @data_store.url_for(@uid, :scheme => 'https').should =~ /^https:\/\//
273
+ end
274
+
275
+ it "should allow for always using https" do
276
+ @data_store.url_scheme = 'https'
277
+ @data_store.url_for(@uid).should =~ /^https:\/\//
278
+ end
279
+
280
+ it "should allow for customizing the host" do
281
+ @data_store.url_for(@uid, :host => 'customised.domain.com').should == "http://customised.domain.com/#{@data_store.user}/public/#{DIRECTORY}/some/path/on/manta"
282
+ end
283
+
284
+ it "should allow the url_host to be customised permanently" do
285
+ url_host = 'customised.domain.com/and/path'
286
+ @data_store.url_host = url_host
287
+ @data_store.url_for(@uid).should == "http://#{url_host}/#{@data_store.user}/public/#{DIRECTORY}/some/path/on/manta"
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,53 @@
1
+ require 'cgi'
2
+
3
+ # just close enough to make the tests pass...
4
+ class RubyMantaStub
5
+ attr_accessor :user, :domain
6
+
7
+ def initialize
8
+ @store = {}
9
+ @directories = {}
10
+ end
11
+
12
+ def put_directory(directory)
13
+ @directories[directory] ||= {}
14
+ end
15
+
16
+ def list_directory(directory, options)
17
+ raise RubyManta::MantaClient::UnknownError unless @directories[directory]
18
+
19
+ @directories[directory]
20
+ end
21
+
22
+ def put_object(path, content, headers)
23
+ @store[path] = {
24
+ :headers => headers,
25
+ :content => content
26
+ }
27
+
28
+ [ path, {} ]
29
+ end
30
+
31
+ def get_object(path)
32
+ raise RubyManta::MantaClient::ResourceNotFound unless @store[path]
33
+
34
+ headers = @store[path][:headers].dup
35
+ headers["m-dragonfly"] = headers.delete :m_dragonfly
36
+
37
+ [ @store[path][:content], headers ]
38
+ end
39
+
40
+ def delete_object(path)
41
+ @store.delete path
42
+
43
+ [ true, {} ]
44
+ end
45
+
46
+ def gen_signed_url(expiry, method, path)
47
+ fake_key = rand(36**128).to_s(36)
48
+
49
+ key_id = CGI.escape("/#{user}/keys/#{fake_key}")
50
+
51
+ "#{domain}#{path}?algorithm=rsa-sha1&expires=#{expiry}&keyId=#{key_id}"
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ RSpec.configure do |config|
2
+ config.treat_symbols_as_metadata_keys_with_true_values = true
3
+ config.run_all_when_everything_filtered = true
4
+ config.filter_run :focus
5
+ config.order = 'random'
6
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dragonfly-manta_data_store
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Dan Connor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dragonfly
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-manta
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.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: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ description: Manta data store for Dragonfly
56
+ email:
57
+ - danconn@danconnor.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - dragonfly-manta_data_store.gemspec
68
+ - lib/dragonfly/manta_data_store.rb
69
+ - lib/dragonfly/manta_data_store/version.rb
70
+ - spec/manta_data_store_spec.rb
71
+ - spec/ruby_manta_stub.rb
72
+ - spec/spec_helper.rb
73
+ homepage: https://github.com/onyxrev/dragonfly-manta_data_store
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.4.5
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Data store for storing Dragonfly content (e.g. images) on Manta
97
+ test_files:
98
+ - spec/manta_data_store_spec.rb
99
+ - spec/ruby_manta_stub.rb
100
+ - spec/spec_helper.rb