vbucket 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f61cddafcc0a79dc3876e6a36f6daa95e9451bf
4
- data.tar.gz: 5f2e344fb77ee76ae6c86d36aea43ee8130ce266
3
+ metadata.gz: 8596592bde62eac7f7d9c6cb19be5587c84975bc
4
+ data.tar.gz: aa5038802b098ec31ee74233b13548521a8f3e1b
5
5
  SHA512:
6
- metadata.gz: efec5fb1cef0601247e7cfef775d56d7162074fed22a00a60cd0adf74b496093a1a63ab6104142471d1c83cd3413bd824078272888504fa78d7cf105d678787d
7
- data.tar.gz: 74bea3b4df2c394bd33f6341140e374566f38953876a402220028eeaa2514d5c1397cd5b187f44605e7beab03c8ebc3e89532f2c8f6659f4f35a9f1a0e66b963
6
+ metadata.gz: f9d9da0ed244628d0ca7ec18695cf9610eba9e88be2b2c113725a9ddfab2741091b3136fcfb781061c44c8d364bafcb4b46e8b6551db6bf4cf1fafe462251a53
7
+ data.tar.gz: d74aa0ba522152dfa4865b43d091bfa69fddd0e908c8329d607e813ec9693d827bdefc9ad81298448792eaa550c1cbd0e810d09faa4a780e313197a90355b5a8
data/.gitignore CHANGED
@@ -1,14 +1,17 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.bundle
11
- *.so
12
- *.o
13
- *.a
14
- mkmf.log
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ .idea/
@@ -0,0 +1,59 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ vbucket (0.1.0)
5
+ nokogiri
6
+ rack-ssl
7
+ sinatra
8
+ sinatra-contrib
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ backports (3.6.4)
14
+ diff-lcs (1.2.5)
15
+ mini_portile (0.6.1)
16
+ multi_json (1.10.1)
17
+ nokogiri (1.6.5)
18
+ mini_portile (~> 0.6.0)
19
+ rack (1.6.0)
20
+ rack-protection (1.5.3)
21
+ rack
22
+ rack-ssl (1.4.1)
23
+ rack
24
+ rack-test (0.6.2)
25
+ rack (>= 1.0)
26
+ rake (10.3.2)
27
+ rspec (3.1.0)
28
+ rspec-core (~> 3.1.0)
29
+ rspec-expectations (~> 3.1.0)
30
+ rspec-mocks (~> 3.1.0)
31
+ rspec-core (3.1.2)
32
+ rspec-support (~> 3.1.0)
33
+ rspec-expectations (3.1.0)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.1.0)
36
+ rspec-mocks (3.1.0)
37
+ rspec-support (~> 3.1.0)
38
+ rspec-support (3.1.0)
39
+ sinatra (1.4.5)
40
+ rack (~> 1.4)
41
+ rack-protection (~> 1.4)
42
+ tilt (~> 1.3, >= 1.3.4)
43
+ sinatra-contrib (1.4.2)
44
+ backports (>= 2.0)
45
+ multi_json
46
+ rack-protection
47
+ rack-test
48
+ sinatra (~> 1.4.0)
49
+ tilt (~> 1.3)
50
+ tilt (1.4.1)
51
+
52
+ PLATFORMS
53
+ ruby
54
+
55
+ DEPENDENCIES
56
+ bundler (~> 1.3)
57
+ rake
58
+ rspec
59
+ vbucket!
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 jakerobinson
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 CHANGED
@@ -1,31 +1,71 @@
1
- # Vbucket
1
+ # vBucket
2
2
 
3
- TODO: Write a gem description
3
+ ## What is vBucket?
4
+ vBucket is an API for your files.
4
5
 
5
- ## Installation
6
+ It's goal is to provide you with http access to a directory on your linux filesystem and any metadata you want to add.
6
7
 
7
- Add this line to your application's Gemfile:
8
+ You can GET, POST, PUT and DELETE with a simple curl command:
9
+ ```
10
+ # POST a file
11
+ curl -i -F file=@funny_cat.gif http://vbucket.example.com/
12
+
13
+ # GET the file
14
+ curl http://vbucket.example.com/funny_cat.gif
8
15
 
9
- ```ruby
10
- gem 'vbucket'
16
+ # DELETE the file
17
+ curl -X DELETE http://vbucket.example.com/funny_cat.gif
18
+
19
+ #PUT a file
20
+ curl --upload-file another_cat.gif http://vbucket.example.com/another_cat.gif
11
21
  ```
12
22
 
13
- And then execute:
23
+ ## vBucket vs.
24
+ ### object storage
25
+ Object storage stores data as objects with metadata, identified by a uuid. An API is employed to access the objects.
26
+
27
+ vBucket is a REST API for a block storage filesystem. It has all the power of an object storage API without
28
+ the need for the underlying object storage hardware.
29
+
30
+ ### webdav
31
+ WebDAV(Web Distributed Authoring and Versioning) is a unique protocol with many features for reading and writing documents.
32
+
33
+ vBucket uses HTTP for all it's communication, providing maximum accessibility to any language or system. POST, PUT, GET, and DELETE are the only methods you need to know.
34
+
35
+ ### nfs
36
+ NFS(Network File System) is a distributed, open filesystem protocol that you would mount and treat like a local disk.
37
+ It is extremely valuable if you need complete control over the files and their heirarchy.
38
+
39
+ vBucket runs over HTTP, so there is no mounting or special ports to open. It works through firewalls, proxies, and NAT.
40
+
41
+ ### iscsi
42
+ iSCSI(Internet Small Computer System Interface) is an IP protocol for sending SCSI commands over the network. You can do everything from mount a disk to boot from iSCSI. It is an extremely powerful storage bus.
43
+
44
+ vBucket is very lightweight and easy to install. The only requirements to get started are Linux and Ruby.
45
+
46
+ ## Security
47
+ vBucket does not come with an encryption or authentication mechanism. If you plan on running vBucket over the Internet, its very simple to host behind Apache or Nginx. These web servers can provide basic authentication, SSL, reverse proxy.
48
+
49
+ ## Applications
50
+
51
+ ### File Server
52
+ At it's core, vBucket is designed to serve up files. If you want to host files that are accessible via REST API, you can simply run vBucket as a service and point it at a directory on your linux system. You can upload and download files over HTTP with a multitude of languages, libraries and tools.
14
53
 
15
- $ bundle
54
+ ### YUM/APT Repo
55
+ vBucket can serve as a repo for linux packages. GET requests from `yum` or `apt-get` to the API are easy for vBucket.
16
56
 
17
- Or install it yourself as:
57
+ You can also publish new packages to your repo by doing a POST or PUT. vBucket can be configured with a `post_upload` script to run repo indexing commands after an upload has completed.
18
58
 
19
- $ gem install vbucket
59
+ ### Gem Server
60
+ In addition to Linux repos, you can also serve gems from vBucket. Simply use the `post_upload` in the configuration to perform a `gem generate_index` on your vBucket directory.
20
61
 
21
- ## Usage
62
+ ### Container Repo
63
+ There is a lot of movement in this area right now and containers are all the rage. As container repos become more standardized, it should be possible to host containers much like RPMs in a yum server. Upload your container and any metadata, and rebuild the index with a `post_upload` script.
22
64
 
23
- TODO: Write usage instructions here
65
+ ### Vagrant Box Repo
66
+ Hate storing your base Vagrant boxes in Dropbox? I do. vBucket is a great way to keep them organized and accessible.
24
67
 
25
- ## Contributing
26
68
 
27
- 1. Fork it ( https://github.com/[my-github-username]/vbucket/fork )
28
- 2. Create your feature branch (`git checkout -b my-new-feature`)
29
- 3. Commit your changes (`git commit -am 'Add some feature'`)
30
- 4. Push to the branch (`git push origin my-new-feature`)
31
- 5. Create a new Pull Request
69
+ ## Features Coming Soon
70
+ * File metadata - add metadata to your files!
71
+ * File query - list files based on metadata!
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake'
3
+ require 'rspec/core/rake_task'
2
4
 
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.pattern = Dir.glob('spec/**/*_spec.rb')
7
+ t.rspec_opts = '--format documentation'
8
+ end
9
+ task :default => :spec
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/vbucket'
4
+
5
+ VBucket::Service.run!
@@ -0,0 +1,3 @@
1
+ require './lib/vbucket'
2
+
3
+ run VBucket::Service
@@ -0,0 +1,3 @@
1
+ :share: /srv/files
2
+ :log: log/vbucket.log
3
+ :post_upload_command: createrepo /srv/files
@@ -0,0 +1,5 @@
1
+ Do Not Use These Keys!!!!!!!
2
+ 32ebccd160ae5457d00630e0852062ef
3
+ 5a52f8642fc392eed1c58a7b4fdfbf7a
4
+ 74e6d2bcbb9203e868f36c3d97b54421
5
+ 527337312fc400145d75b6d0e3640253
@@ -1,5 +1,26 @@
1
- require "vbucket/version"
1
+ require 'vbucket/version'
2
+ require 'vbucket/service'
3
+ require 'vbucket/configuration'
4
+
5
+ module VBucket
6
+ class Exception < StandardError; end
7
+
8
+ class MissingConfigData < VBucket::Exception
9
+ def initialize(missing_data_)
10
+ super("The following data is missing from the config file: #{missing_data_}")
11
+ end
12
+ end
13
+
14
+ class MissingConfigFile < VBucket::Exception
15
+ def initialize(file_path_)
16
+ super("The config file is missing from path: #{file_path_}")
17
+ end
18
+ end
19
+
20
+ class CannotAccessShare < VBucket::Exception
21
+ def initialize(file_path_)
22
+ super("Directory does not exist or permissions issue: #{file_path_}")
23
+ end
24
+ end
2
25
 
3
- module Vbucket
4
- # Your code goes here...
5
26
  end
@@ -0,0 +1,32 @@
1
+ require 'yaml'
2
+ require_relative '../../lib/vbucket'
3
+
4
+ module VBucket
5
+ class Configuration
6
+ attr_reader :share, :config_path
7
+
8
+ def initialize(path_ = default_path)
9
+ @config_path = path_ || default_path
10
+ raise VBucket::MissingConfigFile, @config_path unless File.exist? @config_path
11
+ config_data = YAML.load_file(@config_path)
12
+ @share = chk_data config_data[:share]
13
+ raise VBucket::CannotAccessShare, @share unless share_exist?(@share)
14
+ end
15
+
16
+ private
17
+
18
+ def default_path
19
+ File.expand_path(File.join(File.dirname(__FILE__), '../../config/vbucket.conf'))
20
+ end
21
+
22
+ def chk_data(data_)
23
+ raise VBucket::MissingConfigData, data_ unless data_
24
+ data_
25
+ end
26
+
27
+ def share_exist?(path_)
28
+ Dir.exist? path_
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,146 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/json'
3
+ require 'sinatra/respond_with' #respond with multiple content types
4
+ require 'logger'
5
+ require 'nokogiri'
6
+ require 'fileutils'
7
+ require 'find'
8
+ require_relative 'configuration'
9
+
10
+ module VBucket
11
+ class Service < Sinatra::Base
12
+
13
+ helpers Sinatra::JSON
14
+ register Sinatra::RespondWith
15
+ configure :production, :development do
16
+ enable :logging
17
+ end
18
+
19
+ def initialize(
20
+ config = VBucket::Configuration.new,
21
+ logger = Logger.new(default_log_location)
22
+ )
23
+ super()
24
+ @logger = logger
25
+ @config = config
26
+ @logger.debug "Using Config file: #{@config.config_path}"
27
+ @logger.debug "vBucket File Root: #{@config.share}"
28
+
29
+ @share = @config.share
30
+ end
31
+
32
+ before do
33
+ log_transaction
34
+ end
35
+
36
+ # TODO: RSS support?
37
+ get '/*', provides: [:json, :html, :xml] do
38
+ halt 404 unless path_exist?
39
+ if FileTest.file?(absolute_path)
40
+ send_file absolute_path, :filename => File.basename(absolute_path), :type => 'Application/octet-stream'
41
+ else
42
+ respond_with_file_list
43
+ end
44
+ end
45
+
46
+ # get '/:file_path' do |file_path|
47
+ # halt 404 unless File.exist?(absolute_path(file_path))
48
+ #
49
+ # send_file absolute_path(file_path), :filename => File.basename(absolute_path(file_path)), :type => 'Application/octet-stream'
50
+ # end
51
+
52
+ head '/*' do
53
+ File.exist?(absolute_path) ? (status 200) : (halt 404)
54
+ response.headers['Content-Length'] = File.size(file)
55
+ end
56
+
57
+ # Upload a file
58
+ # TODO: We want to POST to specific folders for applications like gem server. (post to /gems/)
59
+ post '/' do
60
+ halt 400 unless params[:file]
61
+ (File.exist? File.join(@share, params[:file][:filename])) ? (status 200) : (status 201)
62
+ File.open(File.join(@share, params[:file][:filename]), 'wb') { |f| f.write(params[:file][:tempfile].read) }
63
+ body nil
64
+
65
+ # TODO: post_upload_directive
66
+ # TODO: Do we need to clean up the file if the transfer is unsuccessful?
67
+ # TODO: rescue IO errors
68
+ end
69
+
70
+ # Create a folder path. When specifying nested paths, any missing folders in that path will be created.
71
+ put('/folder/*') do
72
+ (Dir.exist? File.join(@share, params[:splat])) ? (halt 409) : (status 201)
73
+ FileUtils.mkdir_p File.join(@share, params[:splat])
74
+ end
75
+
76
+ # Upload a file to specific file path
77
+ put('/*') do
78
+ (File.exist? absolute_path) ? (status 200) : (status 201)
79
+ File.open(absolute_path, 'wb') { |file| file.write(request.body.read) }
80
+ body nil
81
+
82
+ # TODO: post_upload_directive
83
+ # TODO: PUT Folders or Files into folders (for Gem server use case)
84
+ # TODO: Streaming upload?
85
+ end
86
+
87
+ delete '/*' do
88
+ halt 404 unless path_exist?
89
+ File.delete(absolute_path)
90
+ status 200
91
+ end
92
+
93
+ private
94
+
95
+ def absolute_path
96
+ @absolute_path ||= File.join(@share, params[:splat])
97
+ end
98
+
99
+ def path_exist?
100
+ File.exist?(absolute_path) || File.directory?(absolute_path)
101
+ end
102
+
103
+ def default_log_location
104
+ File.expand_path(File.join(File.dirname(__FILE__), '../../log/vbucket.log'))
105
+ end
106
+
107
+ def xml_file_list(files)
108
+ builder = Nokogiri::XML::Builder.new do |xml|
109
+ xml.files {
110
+ files.each do |filename|
111
+ xml.file filename
112
+ end
113
+ }
114
+ end
115
+ builder.to_xml
116
+ end
117
+
118
+ def log_transaction
119
+ @logger.debug "#{request.ip} - #{request.request_method} #{request.path} #{request.accept}"
120
+ end
121
+
122
+ def respond_with_file_list
123
+ files = file_list absolute_path
124
+ respond_to do |accept|
125
+ accept.xml { xml_file_list files }
126
+ accept.json { json files }
127
+ accept.html { files }
128
+ end
129
+ end
130
+
131
+ def file_list(path)
132
+ all_entities = Dir.glob(File.join(path, '*'))
133
+ listing = {}
134
+ listing[:files] = all_entities.select { |entity| FileTest.file? entity }
135
+ listing[:folders] = all_entities.select { |entity| FileTest.directory? entity }
136
+
137
+ listing.each do |entity_type,list|
138
+ list.each_index do |index|
139
+ listing[entity_type][index].sub!(@share, request.url)
140
+ end
141
+ end
142
+ listing
143
+ end
144
+
145
+ end
146
+ end
@@ -1,3 +1,3 @@
1
1
  module Vbucket
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
Binary file
@@ -0,0 +1,8 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+ require_relative '../lib/vbucket/configuration'
3
+ require_relative '../lib/vbucket/service'
4
+ require 'rack/test'
5
+
6
+ RSpec.configure do |config|
7
+ config.include Rack::Test::Methods
8
+ end
@@ -0,0 +1,41 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'VBucket::Configuration' do
4
+
5
+ before(:each) do
6
+ allow(YAML).to receive(:load_file) {
7
+ {
8
+ auth_file: 'vbucket.keys',
9
+ share: '/example/vbucket/'
10
+ }
11
+ }
12
+ end
13
+
14
+ describe '#new' do
15
+ #TODO: refactor using rspec subject and contexts
16
+
17
+ it 'loads a configuration file' do
18
+ allow(Dir).to receive(:exist?).with('/example/vbucket/') { true }
19
+ test_config = VBucket::Configuration.new
20
+ expect(test_config.share).to eq('/example/vbucket/')
21
+ end
22
+
23
+ it 'raises exception if dir does not exist' do
24
+ allow(Dir).to receive(:exist?).with('/example/vbucket/') { false }
25
+ expect { VBucket::Configuration.new }.to raise_error(VBucket::CannotAccessShare)
26
+ end
27
+
28
+ it 'raises an error if required data is missing' do
29
+ allow(YAML).to receive(:load_file) { {auth_file: 'vbucket.keys'} } # Missing share
30
+
31
+ expect { VBucket::Configuration.new }.to raise_error(VBucket::MissingConfigData)
32
+ end
33
+
34
+ it 'raises an error if config file is missing' do
35
+ allow(File).to receive(:exist?) { false }
36
+
37
+ expect { VBucket::Configuration.new('') }.to raise_error(VBucket::MissingConfigFile)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,134 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'VBucket::Service' do
4
+
5
+ let(:header) { {'HTTP_AUTHORIZATION' => 'Token 527337312fc400145d75b6d0e3640253', Accept: 'application/json'} }
6
+ let(:file_list) {%w(/example/vbucket/1.txt /example/vbucket/2.txt /example/vbucket/bar /example/vbucket/baz.jpg /example/vbucket/foo /example/vbucket/qux.pdf)}
7
+ def app
8
+ VBucket::Service
9
+ end
10
+
11
+ before(:example) do
12
+ allow(Dir).to receive(:glob) { file_list }
13
+ allow(YAML).to receive(:load_file) { {share: '/example/vbucket/'} }
14
+ allow(File).to receive(:exist?).with('/Users/jrobinson/vbucket/spec/unit/vbucket/../../assets/cat.jpg') { true }
15
+ allow(File).to receive(:exist?).with('/Users/jrobinson/vbucket/config/vbucket.conf') { true }
16
+ allow(File).to receive(:exist?).with('/Users/jrobinson/vbucket/lib/vbucket/public') { false }
17
+ allow(File).to receive(:exist?).with('/example/vbucket/thisShouldBeA404') { false }
18
+ allow(File).to receive(:exist?) { true }
19
+ allow(FileTest).to receive(:file?).with('/example/vbucket/') { false }
20
+ allow(FileTest).to receive(:file?).with('/example/vbucket/cat.jpg') { true }
21
+ file_list.each { |file| allow(FileTest).to receive(:file?).with(file) { true } }
22
+ allow_any_instance_of(VBucket::Service).to receive(:send_file) { 'This is a test' }
23
+ end
24
+
25
+ describe 'run' do
26
+ context 'missing config data' do
27
+ it 'shuts down'
28
+ it 'gives a meaningful error message'
29
+ end
30
+
31
+ end
32
+
33
+ #TODO: refactor with contexts and subject
34
+ describe 'GET' do
35
+
36
+ it 'GETs /' do
37
+ allow(Dir).to receive(:exist?) { true }
38
+ get '/', nil, header
39
+ expect(last_response).to be_ok
40
+ expect(last_response.body).to eq('{"files":["http://example.org/1.txt","http://example.org/2.txt","http://example.org/bar","http://example.org/baz.jpg","http://example.org/foo","http://example.org/qux.pdf"],"folders":[]}')
41
+ end
42
+
43
+ it 'GETs /:filename' do
44
+ allow(File).to receive(:exist?) { true }
45
+ allow(Dir).to receive(:exist?) { true }
46
+
47
+ get '/1.txt', nil, header
48
+ expect(last_response).to be_ok
49
+ expect(Digest::MD5.hexdigest(last_response.body)).to eq('ce114e4501d2f4e2dcea3e17b546f339')
50
+ end
51
+
52
+ it 'responds with 404 when file does not exist' do
53
+ allow(File).to receive(:exist?) { false }
54
+ allow(Dir).to receive(:exist?) { true }
55
+
56
+ get '/thisShouldBeA404', nil, header
57
+ expect(last_response.status).to eq(404)
58
+ end
59
+
60
+ # This is covered by Rack::Protection::PathTraversal
61
+ # it 'does not allow modifying files outside of share' do
62
+ # get '/../busted.txt', nil, header
63
+ # expect(last_response.status).to eq(404)
64
+ # end
65
+ end
66
+
67
+ describe 'HEAD' do
68
+
69
+ # TODO: Mock Rack::File or move this to integration test?
70
+ it 'HEADs /:filename' do
71
+ allow(File).to receive(:exist?) { true }
72
+ allow(Dir).to receive(:exist?) { true }
73
+ head '/1.txt', nil, header
74
+ expect(last_response).to be_ok
75
+ #expect(last_response.header['Content-Length']).to eq('14')
76
+ end
77
+
78
+ it 'responds with 404 when file does not exist' do
79
+ allow(File).to receive(:exist?) { false }
80
+ allow(Dir).to receive(:exist?) { true }
81
+ head '/thisShouldBeA404', nil, header
82
+ expect(last_response.status).to eq(404)
83
+ end
84
+ end
85
+
86
+ describe 'POST' do
87
+
88
+ # # # This test is not working due to params not being passed. post using curl works fine.
89
+ # it 'POSTs file to /' do
90
+ # test_file = Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), '../../assets/cat.jpg'), 'image/jpeg', true)
91
+ # allow_any_instance_of(VBucket::Authentication).to receive(:has_permission?) { true }
92
+ # allow(File).to receive(:exist?).with(/\/example\/vbucket\/var\/folders\/.*/) { false }
93
+ # allow(File).to receive(:open)
94
+ #
95
+ # post '/', {'file' => test_file}, header
96
+ # expect(last_response.status).to eq(201)
97
+ # end
98
+
99
+ it 'responds with 400 when missing data'
100
+
101
+ end
102
+
103
+ describe 'PUT' do
104
+
105
+ it 'PUTs /:filename' do
106
+ test_file = Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), '../../assets/cat.jpg'), 'image/jpeg', true)
107
+ allow(File).to receive(:exist?).with('/example/vbucket/cat.jpg') { false }
108
+ allow(Dir).to receive(:exist?) { true }
109
+ allow(File).to receive(:open) { 4607 }
110
+
111
+ put '/cat.jpg', {'file' => test_file}, header
112
+ expect(last_response.status).to eq(201)
113
+ end
114
+ end
115
+
116
+ describe 'DELETE' do
117
+
118
+ it 'DELETEs /:filename' do
119
+ allow(File).to receive(:exist?) { true }
120
+ allow(File).to receive(:delete) { 1 }
121
+
122
+ delete '/cat.jpg', nil, header
123
+ expect(last_response.status).to eq(200)
124
+ end
125
+
126
+ it 'responds with 404 when file does not exist' do
127
+ allow(File).to receive(:exist?) { false }
128
+
129
+ delete '/foo', nil, header
130
+ expect(last_response.status).to eq(404)
131
+ end
132
+
133
+ end
134
+ end
@@ -4,19 +4,26 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'vbucket/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "vbucket"
7
+ spec.name = 'vbucket'
8
8
  spec.version = Vbucket::VERSION
9
- spec.authors = ["jakerobinson"]
10
- spec.email = ["jaker@vbucket.io"]
11
- spec.summary = %q{vBucket is a REST API for files on Linux}
12
- spec.homepage = ""
13
- spec.license = "MIT"
9
+ spec.authors = ['jakerobinson']
10
+ spec.email = ['jaker@vbucket.io']
11
+ spec.description = %q{A RESTful interface for block level storage}
12
+ spec.summary = %q{vBucket is a simple Ruby app to provide a REST API for your Linux block level storage}
13
+ spec.homepage = 'http://vbucket.io'
14
+ spec.license = 'MIT'
14
15
 
15
- spec.files = `git ls-files -z`.split("\x0")
16
+ spec.files = `git ls-files`.split($/)
16
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
19
20
 
20
- spec.add_development_dependency "bundler", "~> 1.7"
21
- spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_runtime_dependency 'sinatra'
22
+ spec.add_runtime_dependency 'sinatra-contrib'
23
+ spec.add_runtime_dependency 'rack-ssl'
24
+ spec.add_runtime_dependency 'nokogiri'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.3'
27
+ spec.add_development_dependency 'rake'
28
+ spec.add_development_dependency 'rspec'
22
29
  end
metadata CHANGED
@@ -1,58 +1,142 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vbucket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - jakerobinson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-31 00:00:00.000000000 Z
11
+ date: 2015-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra-contrib
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: rack-ssl
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
13
69
  - !ruby/object:Gem::Dependency
14
70
  name: bundler
15
71
  requirement: !ruby/object:Gem::Requirement
16
72
  requirements:
17
73
  - - ~>
18
74
  - !ruby/object:Gem::Version
19
- version: '1.7'
75
+ version: '1.3'
20
76
  type: :development
21
77
  prerelease: false
22
78
  version_requirements: !ruby/object:Gem::Requirement
23
79
  requirements:
24
80
  - - ~>
25
81
  - !ruby/object:Gem::Version
26
- version: '1.7'
82
+ version: '1.3'
27
83
  - !ruby/object:Gem::Dependency
28
84
  name: rake
29
85
  requirement: !ruby/object:Gem::Requirement
30
86
  requirements:
31
- - - ~>
87
+ - - '>='
32
88
  - !ruby/object:Gem::Version
33
- version: '10.0'
89
+ version: '0'
34
90
  type: :development
35
91
  prerelease: false
36
92
  version_requirements: !ruby/object:Gem::Requirement
37
93
  requirements:
38
- - - ~>
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
39
109
  - !ruby/object:Gem::Version
40
- version: '10.0'
41
- description:
110
+ version: '0'
111
+ description: A RESTful interface for block level storage
42
112
  email:
43
113
  - jaker@vbucket.io
44
- executables: []
114
+ executables:
115
+ - vbucket
45
116
  extensions: []
46
117
  extra_rdoc_files: []
47
118
  files:
48
119
  - .gitignore
49
120
  - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE.txt
50
123
  - README.md
51
124
  - Rakefile
125
+ - bin/vbucket
126
+ - config.ru
127
+ - config/vbucket.conf
128
+ - config/vbucket.keys
52
129
  - lib/vbucket.rb
130
+ - lib/vbucket/configuration.rb
131
+ - lib/vbucket/service.rb
53
132
  - lib/vbucket/version.rb
133
+ - log/.gitignore
134
+ - spec/assets/cat.jpg
135
+ - spec/spec_helper.rb
136
+ - spec/unit/vbucket/configuration_spec.rb
137
+ - spec/unit/vbucket/service_spec.rb
54
138
  - vbucket.gemspec
55
- homepage: ''
139
+ homepage: http://vbucket.io
56
140
  licenses:
57
141
  - MIT
58
142
  metadata: {}
@@ -75,6 +159,10 @@ rubyforge_project:
75
159
  rubygems_version: 2.2.2
76
160
  signing_key:
77
161
  specification_version: 4
78
- summary: vBucket is a REST API for files on Linux
79
- test_files: []
80
- has_rdoc:
162
+ summary: vBucket is a simple Ruby app to provide a REST API for your Linux block level
163
+ storage
164
+ test_files:
165
+ - spec/assets/cat.jpg
166
+ - spec/spec_helper.rb
167
+ - spec/unit/vbucket/configuration_spec.rb
168
+ - spec/unit/vbucket/service_spec.rb