fake_aws 0.0.1 → 0.0.2
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 +4 -4
- data/Gemfile +1 -1
- data/README.md +45 -5
- data/lib/fake_aws/version.rb +1 -1
- data/spec/integration/s3/get_object_spec.rb +62 -0
- data/spec/integration/s3/put_object_spec.rb +77 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/{s3 → unit/s3}/object_store_spec.rb +0 -0
- data/spec/{s3 → unit/s3}/xml_error_response_spec.rb +0 -0
- metadata +10 -8
- data/spec/s3/rack_app_spec.rb +0 -147
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed97453747d15331d9d037d50c15f413163facea
|
4
|
+
data.tar.gz: f51891713197c2413b3b5a7ad3f7d98261e47c5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6eff8dacdb4d9d42b025debebf69b7bc3c83556c767f71925be8c05c96150be68bdde518ce545ec7d0662a1d3ff83a7576644bab832fcc93e79b34bd36d877fd
|
7
|
+
data.tar.gz: 31d7f4ae800966929807971739dff4b2b50bd01ab93680a1f7859028c556ab105d584f3e4c3c0c35afe5901e71a0b081a6261c5f5c03190263d8718491c39260
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,10 +2,8 @@
|
|
2
2
|
|
3
3
|
A minimal implementation of AWS as a Rack app, for testing and development.
|
4
4
|
|
5
|
-
This is
|
5
|
+
This is designed to pair nicely with [AWSRaw](https://github.com/envato/awsraw).
|
6
6
|
|
7
|
-
So far there's only a tiny bit of S3 implemented, but it's well tested and
|
8
|
-
designed to be easy to extend. Pull requests for more features are welcome.
|
9
7
|
|
10
8
|
## Installation
|
11
9
|
|
@@ -21,9 +19,52 @@ Or install it yourself as:
|
|
21
19
|
|
22
20
|
$ gem install fake_aws
|
23
21
|
|
22
|
+
|
23
|
+
## Status
|
24
|
+
|
25
|
+
This is still in the very early stages of development.
|
26
|
+
|
27
|
+
So far there's only a tiny bit of S3 implemented, but it's well tested and
|
28
|
+
fairly easy to extend. Pull requests for more features are welcome.
|
29
|
+
|
30
|
+
The S3 implementation only supports basic PUT Object and GET Object requests.
|
31
|
+
The bucket name must be in the path, not the host. No authentication or
|
32
|
+
security is implemented. `Content-Type` and `x-amz-metadata` headers are
|
33
|
+
stored and returned. Responses may or may not be properly formatted.
|
34
|
+
|
35
|
+
|
24
36
|
## Usage
|
25
37
|
|
26
|
-
|
38
|
+
The easiest way to try this out is with [Faraday](https://github.com/lostisland/faraday):
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
connection = Faraday.new do |faraday|
|
42
|
+
faraday.adapter :rack, FakeAWS::S3::RackApp.new('root_directory')
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
The root directory you provide is used to store S3 objects and metadata.
|
47
|
+
|
48
|
+
For example, the following PUT Object request:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
connection.put do |request|
|
52
|
+
request.url("http://s3.amazonaws.com/test_bucket/test_path/test_file.txt")
|
53
|
+
request.headers["Content-Type"] = "text/plain"
|
54
|
+
request.body = "Hello, world!"
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
will create a file `root_directory/test_bucket/test_path/test_file.txt`.
|
59
|
+
|
60
|
+
(Note: `root_directory/test_bucket` must already exist! As there's no
|
61
|
+
implementation of the Create Bucket operation yet, you'll need to make the
|
62
|
+
directory for the bucket yourself before doing a PUT Object.)
|
63
|
+
|
64
|
+
It will also create
|
65
|
+
`root_directory/test_bucket/test_path/test_file.txt.metadata.json`, which holds
|
66
|
+
the metadata for the file as a JSON hash.
|
67
|
+
|
27
68
|
|
28
69
|
## Contributing
|
29
70
|
|
@@ -35,7 +76,6 @@ TODO: Write usage instructions here
|
|
35
76
|
|
36
77
|
## To Do
|
37
78
|
|
38
|
-
- Split up the rack app tests into separate files for the different operations
|
39
79
|
- Handle bucket names in the host as well as the path
|
40
80
|
- Spit out a properly formatted response on a successful PUT object operation
|
41
81
|
- Complete the missing fields in XML error responses
|
data/lib/fake_aws/version.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "S3 GET Object operation" do
|
4
|
+
include S3IntegrationSpecHelpers
|
5
|
+
|
6
|
+
let(:bucket) { "mah-bucket" }
|
7
|
+
let(:file_name) { "mah-file.txt"}
|
8
|
+
let(:file_contents) { "Hello, world!" }
|
9
|
+
|
10
|
+
def get_example_file(key)
|
11
|
+
connection.get(File.join(bucket, key))
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a file that exists" do
|
15
|
+
before do
|
16
|
+
FileUtils.mkdir(File.join(s3_path, bucket))
|
17
|
+
File.write(File.join(s3_path, bucket, file_name), file_contents)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns a 200" do
|
21
|
+
response = get_example_file(file_name)
|
22
|
+
expect(response.status).to eq(200)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns a correctly constructed response"
|
26
|
+
|
27
|
+
it "returns the contents of the file" do
|
28
|
+
response = get_example_file(file_name)
|
29
|
+
expect(response.body).to eq(file_contents)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns the right content type" do
|
33
|
+
file_metadata = {
|
34
|
+
"Content-Type" => "text/plain"
|
35
|
+
}.to_json
|
36
|
+
File.write(File.join(s3_path, bucket, "#{file_name}.metadata.json"), file_metadata)
|
37
|
+
|
38
|
+
response = get_example_file(file_name)
|
39
|
+
expect(response.headers["Content-Type"]).to eq("text/plain")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with a file that doesn't exist" do
|
44
|
+
before do
|
45
|
+
FileUtils.mkdir(File.join(s3_path, bucket))
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns a 404" do
|
49
|
+
response = get_example_file(file_name)
|
50
|
+
expect(response.status).to eq(404)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns the correct XML response"
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with a bucket that doesn't exist" do
|
57
|
+
it "returns the right sort of error" do
|
58
|
+
pending "Need to figure out what error AWS actually returns for this case"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "S3 PUT Object operation" do
|
4
|
+
include S3IntegrationSpecHelpers
|
5
|
+
|
6
|
+
let(:bucket) { "mah-bucket" }
|
7
|
+
let(:file_name) { "mah-file.txt"}
|
8
|
+
let(:file_contents) { "Hello, world!" }
|
9
|
+
|
10
|
+
def put_example_file(key)
|
11
|
+
connection.put do |request|
|
12
|
+
request.url(File.join(bucket, key))
|
13
|
+
request.headers["Content-Type"] = "text/plain"
|
14
|
+
request.headers["x-amz-meta-example"] = "example metadata"
|
15
|
+
request.body = file_contents
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_example_metadata(key)
|
20
|
+
metadata_file_path = File.join(s3_path, "/#{bucket}/#{key}.metadata.json")
|
21
|
+
JSON.parse(File.read(metadata_file_path))
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with an existing bucket" do
|
25
|
+
before do
|
26
|
+
Dir.mkdir(File.join(s3_path, bucket))
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns a 200" do
|
30
|
+
response = put_example_file(file_name)
|
31
|
+
expect(response.status).to eq(200)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns a correctly constructed response"
|
35
|
+
|
36
|
+
it "creates a file" do
|
37
|
+
put_example_file(file_name)
|
38
|
+
expect(File.read(File.join(s3_path, "/#{bucket}/#{file_name}"))).to eq(file_contents)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "stores the content-type" do
|
42
|
+
put_example_file(file_name)
|
43
|
+
|
44
|
+
metadata = read_example_metadata(file_name)
|
45
|
+
expect(metadata["Content-Type"]).to eq("text/plain")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "stores user-defined metadata" do
|
49
|
+
put_example_file(file_name)
|
50
|
+
|
51
|
+
metadata = read_example_metadata(file_name)
|
52
|
+
expect(metadata["x-amz-meta-example"]).to eq("example metadata")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "creates sub-directories for paths that contain them" do
|
56
|
+
put_example_file("foo/bar/#{file_name}")
|
57
|
+
expect(File.read(File.join(s3_path, "/#{bucket}/foo/bar/#{file_name}"))).to eq(file_contents)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "handles sub-directories that already exist" do
|
61
|
+
FileUtils.mkdir_p(File.join(s3_path, "#{bucket}/foo/bar"))
|
62
|
+
put_example_file("foo/bar/#{file_name}")
|
63
|
+
expect(File.read(File.join(s3_path, "/#{bucket}/foo/bar/#{file_name}"))).to eq(file_contents)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "without an existing bucket" do
|
68
|
+
it "returns a 404" do
|
69
|
+
response = put_example_file(file_name)
|
70
|
+
expect(response.status).to eq(404)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns the correct XML response"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -1,2 +1,20 @@
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
2
|
require 'fake_aws'
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module S3IntegrationSpecHelpers
|
6
|
+
def self.included(base)
|
7
|
+
base.let(:s3_path) { "tmp" }
|
8
|
+
|
9
|
+
base.let(:connection) do
|
10
|
+
Faraday.new do |connection|
|
11
|
+
connection.adapter :rack, FakeAWS::S3::RackApp.new(s3_path)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
base.before do
|
16
|
+
FileUtils.rm_r(s3_path) rescue Errno::ENOENT
|
17
|
+
FileUtils.mkdir(s3_path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
File without changes
|
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fake_aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pete Yandell
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -104,10 +104,11 @@ files:
|
|
104
104
|
- lib/fake_aws/s3/rack_app.rb
|
105
105
|
- lib/fake_aws/s3/xml_error_response.rb
|
106
106
|
- lib/fake_aws/version.rb
|
107
|
-
- spec/s3/
|
108
|
-
- spec/s3/
|
109
|
-
- spec/s3/xml_error_response_spec.rb
|
107
|
+
- spec/integration/s3/get_object_spec.rb
|
108
|
+
- spec/integration/s3/put_object_spec.rb
|
110
109
|
- spec/spec_helper.rb
|
110
|
+
- spec/unit/s3/object_store_spec.rb
|
111
|
+
- spec/unit/s3/xml_error_response_spec.rb
|
111
112
|
homepage: https://github.com/envato/fake_aws
|
112
113
|
licenses:
|
113
114
|
- MIT
|
@@ -134,7 +135,8 @@ specification_version: 4
|
|
134
135
|
summary: A subset of AWS (so far just a small proportion of S3) implemented as a Rack
|
135
136
|
app, useful for development and testing.
|
136
137
|
test_files:
|
137
|
-
- spec/s3/
|
138
|
-
- spec/s3/
|
139
|
-
- spec/s3/xml_error_response_spec.rb
|
138
|
+
- spec/integration/s3/get_object_spec.rb
|
139
|
+
- spec/integration/s3/put_object_spec.rb
|
140
140
|
- spec/spec_helper.rb
|
141
|
+
- spec/unit/s3/object_store_spec.rb
|
142
|
+
- spec/unit/s3/xml_error_response_spec.rb
|
data/spec/s3/rack_app_spec.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'faraday'
|
3
|
-
require 'rack/test'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
describe FakeAWS::S3::RackApp do
|
7
|
-
let(:s3_path) { "tmp" }
|
8
|
-
let(:bucket) { "mah-bucket" }
|
9
|
-
let(:file_name) { "mah-file.txt"}
|
10
|
-
let(:file_contents) { "Hello, world!" }
|
11
|
-
subject { described_class.new(s3_path) }
|
12
|
-
|
13
|
-
let(:connection) do
|
14
|
-
Faraday.new do |connection|
|
15
|
-
connection.adapter :rack, subject
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
before do
|
20
|
-
FileUtils.rm_r(s3_path) rescue Errno::ENOENT
|
21
|
-
FileUtils.mkdir(s3_path)
|
22
|
-
end
|
23
|
-
|
24
|
-
context "PUT object" do
|
25
|
-
def put_example_file(key)
|
26
|
-
connection.put do |request|
|
27
|
-
request.url(File.join(bucket, key))
|
28
|
-
request.headers["Content-Type"] = "text/plain"
|
29
|
-
request.headers["x-amz-meta-example"] = "example metadata"
|
30
|
-
request.body = file_contents
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def read_example_metadata(key)
|
35
|
-
metadata_file_path = File.join(s3_path, "/#{bucket}/#{key}.metadata.json")
|
36
|
-
JSON.parse(File.read(metadata_file_path))
|
37
|
-
end
|
38
|
-
|
39
|
-
context "with an existing bucket" do
|
40
|
-
before do
|
41
|
-
Dir.mkdir(File.join(s3_path, bucket))
|
42
|
-
end
|
43
|
-
|
44
|
-
it "returns a 200" do
|
45
|
-
response = put_example_file(file_name)
|
46
|
-
expect(response.status).to eq(200)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "returns a correctly constructed response"
|
50
|
-
|
51
|
-
it "creates a file" do
|
52
|
-
put_example_file(file_name)
|
53
|
-
expect(File.read(File.join(s3_path, "/#{bucket}/#{file_name}"))).to eq(file_contents)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "stores the content-type" do
|
57
|
-
put_example_file(file_name)
|
58
|
-
|
59
|
-
metadata = read_example_metadata(file_name)
|
60
|
-
expect(metadata["Content-Type"]).to eq("text/plain")
|
61
|
-
end
|
62
|
-
|
63
|
-
it "stores user-defined metadata" do
|
64
|
-
put_example_file(file_name)
|
65
|
-
|
66
|
-
metadata = read_example_metadata(file_name)
|
67
|
-
expect(metadata["x-amz-meta-example"]).to eq("example metadata")
|
68
|
-
end
|
69
|
-
|
70
|
-
it "creates sub-directories for paths that contain them" do
|
71
|
-
put_example_file("foo/bar/#{file_name}")
|
72
|
-
expect(File.read(File.join(s3_path, "/#{bucket}/foo/bar/#{file_name}"))).to eq(file_contents)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "handles sub-directories that already exist" do
|
76
|
-
FileUtils.mkdir_p(File.join(s3_path, "#{bucket}/foo/bar"))
|
77
|
-
put_example_file("foo/bar/#{file_name}")
|
78
|
-
expect(File.read(File.join(s3_path, "/#{bucket}/foo/bar/#{file_name}"))).to eq(file_contents)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context "without an existing bucket" do
|
83
|
-
it "returns a 404" do
|
84
|
-
response = put_example_file(file_name)
|
85
|
-
expect(response.status).to eq(404)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "returns the correct XML response"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context "GET object" do
|
93
|
-
def get_example_file(key)
|
94
|
-
connection.get(File.join(bucket, key))
|
95
|
-
end
|
96
|
-
|
97
|
-
context "with a file that exists" do
|
98
|
-
before do
|
99
|
-
FileUtils.mkdir(File.join(s3_path, bucket))
|
100
|
-
File.write(File.join(s3_path, bucket, file_name), file_contents)
|
101
|
-
end
|
102
|
-
|
103
|
-
it "returns a 200" do
|
104
|
-
response = get_example_file(file_name)
|
105
|
-
expect(response.status).to eq(200)
|
106
|
-
end
|
107
|
-
|
108
|
-
it "returns a correctly constructed response"
|
109
|
-
|
110
|
-
it "returns the contents of the file" do
|
111
|
-
response = get_example_file(file_name)
|
112
|
-
expect(response.body).to eq(file_contents)
|
113
|
-
end
|
114
|
-
|
115
|
-
it "returns the right content type" do
|
116
|
-
file_metadata = {
|
117
|
-
"Content-Type" => "text/plain"
|
118
|
-
}.to_json
|
119
|
-
File.write(File.join(s3_path, bucket, "#{file_name}.metadata.json"), file_metadata)
|
120
|
-
|
121
|
-
response = get_example_file(file_name)
|
122
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
context "with a file that doesn't exist" do
|
127
|
-
before do
|
128
|
-
FileUtils.mkdir(File.join(s3_path, bucket))
|
129
|
-
end
|
130
|
-
|
131
|
-
it "returns a 404" do
|
132
|
-
response = get_example_file(file_name)
|
133
|
-
expect(response.status).to eq(404)
|
134
|
-
end
|
135
|
-
|
136
|
-
it "returns the correct XML response"
|
137
|
-
end
|
138
|
-
|
139
|
-
context "with a bucket that doesn't exist" do
|
140
|
-
it "returns the right sort of error" do
|
141
|
-
pending "Need to figure out what error AWS actually returns for this case"
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
147
|
-
|