openstack-swift 0.0.1 → 0.1.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.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "http://gems.locaweb.com.br"
2
2
 
3
3
  # Specify your gem's dependencies in openstack-swift.gemspec
4
4
  gemspec
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ openstack-swift (0.1.0)
5
+
6
+ GEM
7
+ remote: http://gems.locaweb.com.br/
8
+ specs:
9
+ archive-tar-minitar (0.5.2)
10
+ columnize (0.3.4)
11
+ crack (0.1.8)
12
+ diff-lcs (1.1.2)
13
+ httparty (0.7.8)
14
+ crack (= 0.1.8)
15
+ linecache19 (0.5.12)
16
+ ruby_core_source (>= 0.1.4)
17
+ rspec (2.6.0)
18
+ rspec-core (~> 2.6.0)
19
+ rspec-expectations (~> 2.6.0)
20
+ rspec-mocks (~> 2.6.0)
21
+ rspec-core (2.6.4)
22
+ rspec-expectations (2.6.0)
23
+ diff-lcs (~> 1.1.2)
24
+ rspec-mocks (2.6.0)
25
+ ruby-debug-base19 (0.11.25)
26
+ columnize (>= 0.3.1)
27
+ linecache19 (>= 0.5.11)
28
+ ruby_core_source (>= 0.1.4)
29
+ ruby-debug19 (0.11.6)
30
+ columnize (>= 0.3.1)
31
+ linecache19 (>= 0.5.11)
32
+ ruby-debug-base19 (>= 0.11.19)
33
+ ruby_core_source (0.1.5)
34
+ archive-tar-minitar (>= 0.5.2)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ httparty
41
+ openstack-swift!
42
+ rspec (~> 2.6)
43
+ ruby-debug19
@@ -0,0 +1,4 @@
1
+ :swift:
2
+ :url: "https://sw:8080/auth/v1.0"
3
+ :user: "system:root"
4
+ :pass: "testpass"
@@ -1,5 +1,41 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require "httparty"
3
+ require "net/http"
4
+ require "net/https"
5
+ require "fileutils"
6
+ require "openstack-swift/api"
7
+ require "openstack-swift/errors"
8
+ require "openstack-swift/client"
9
+ require "openstack-swift/swift_config"
10
+
1
11
  module Openstack
2
12
  module Swift
3
- # Your code goes here...
13
+ end
14
+ end
15
+
16
+ module Net
17
+ class HTTPGenericRequest
18
+ private
19
+ def send_request_with_body_stream(sock, ver, path, f)
20
+ unless content_length() or chunked?
21
+ raise ArgumentError,
22
+ "Content-Length not given and Transfer-Encoding is not `chunked'"
23
+ end
24
+ supply_default_content_type
25
+ write_header sock, ver, path
26
+ if chunked?
27
+ while s = f.read(1024)
28
+ sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
29
+ end
30
+ sock.write "0\r\n\r\n"
31
+ else
32
+ bytes_written = 0
33
+ buffer=1024
34
+ while (s = f.read(buffer)) && bytes_written < content_length()
35
+ sock.write s
36
+ bytes_written += buffer
37
+ end
38
+ end
39
+ end
4
40
  end
5
41
  end
@@ -0,0 +1,147 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module Openstack
3
+ module Swift
4
+ module Api
5
+ extend self
6
+
7
+ # Authentication method to get the url and token to conect to swift
8
+ # Returns:
9
+ # x-storage-url
10
+ # x-storage-token
11
+ # x-auth-token
12
+ def auth(proxy, user, password)
13
+ res = HTTParty.get(proxy, :headers => {"X-Auth-User" => user, "X-Auth-Key" => password})
14
+ raise AuthenticationError unless res.code == 200
15
+
16
+ [res.headers["x-storage-url"],res.headers["x-storage-token"],res.headers["x-auth-token"]]
17
+ end
18
+
19
+ # Get informations about the currect account used to connect to swift
20
+ # Returns:
21
+ # x-account-bytes-used
22
+ # x-account-object-count
23
+ # x-account-container-count
24
+ def account(url, token)
25
+ query = {:format => "json"}
26
+ HTTParty.head(url, :headers => {"X-Auth-Token"=> token}, :query => query).headers
27
+ end
28
+
29
+ # List containers
30
+ # Note that swift only returns 1000 items, so to list more than this
31
+ # you should use the marker option as the name of the last returned item (1000th item)
32
+ # to return the next sequency (1001 - 2000)
33
+ # query options: marker, prefix, limit
34
+ def containers(url, token, query = {})
35
+ query = query.merge(:format => "json")
36
+ res = HTTParty.get(url, :headers => {"X-Auth-Token"=> token}, :query => query)
37
+ res.to_a
38
+ end
39
+
40
+ # Get all objects for a given container
41
+ # Query options:
42
+ # marker
43
+ # prefix
44
+ # limit
45
+ # delimiter
46
+ def objects(url, token, container, query = {})
47
+ query = query.merge(:format => "json")
48
+ res = HTTParty.get("#{url}/#{container}", :headers => {"X-Auth-Token"=> token}, :query => query)
49
+ res.to_a
50
+ end
51
+
52
+ # Delete a container for a given name from swift
53
+ def delete_container(url, token, container)
54
+ res = HTTParty.delete("#{url}/#{container}", :headers => {"X-Auth-Token"=> token})
55
+ raise "Could not delete container '#{container}'" if res.code < 200 or res.code >= 300
56
+ true
57
+ end
58
+
59
+ # Create a container on swift from a given name
60
+ def create_container(url, token, container)
61
+ res = HTTParty.put("#{url}/#{container}", :headers => {"X-Auth-Token"=> token})
62
+ raise "Could not create container '#{container}'" if res.code < 200 or res.code >= 300
63
+ true
64
+ end
65
+
66
+ # Get the object stat given the object name and the container this object is in
67
+ def object_stat(url, token, container, object)
68
+ url = "#{url}/#{container}/#{object}"
69
+ query = {:format => "json"}
70
+ HTTParty.head(url, :headers => {"X-Auth-Token"=> token}, :query => query).headers
71
+ end
72
+
73
+ # Creates the manifest file for a splitted upload
74
+ # Given the container and file path a manifest is created to guide the downloads of this
75
+ # splitted file
76
+ def create_manifest(url, token, container, file_path)
77
+ file_name = file_path.match(/.+\/(.+?)$/)[1]
78
+ file_size = File.size(file_path)
79
+ file_mtime = File.mtime(file_path).to_f.round(2)
80
+ manifest_path = "#{container}_segments/#{file_name}/#{file_mtime}/#{file_size}/"
81
+
82
+ res = HTTParty.put("#{url}/#{container}/#{file_name}", :headers => {
83
+ "X-Auth-Token" => token,
84
+ "x-object-manifest" => manifest_path,
85
+ "Content-Type" => "application/octet-stream",
86
+ "Content-Length" => "0"
87
+ })
88
+
89
+ raise "Could not create manifest for '#{file_path}'" if res.code < 200 or res.code >= 300
90
+ true
91
+ end
92
+
93
+ # Downloads an object (file) to disk and returns the saved file path
94
+ def download_object(url, token, container, object, file_name=nil)
95
+ file_name ||= "/tmp/swift/#{container}/#{object}"
96
+
97
+ # creating directory if it doesn't exist
98
+ FileUtils.mkdir_p(file_name.match(/(.+)\/.+?$/)[1])
99
+ file = File.open(file_name, "wb")
100
+ uri = URI.parse("#{url}/#{container}/#{object}")
101
+
102
+ req = Net::HTTP::Get.new(uri.path)
103
+ req.add_field("X-Auth-Token", token)
104
+
105
+ http = Net::HTTP.new(uri.host, uri.port)
106
+ http.use_ssl = true
107
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
108
+ md5 = Digest::MD5.new
109
+
110
+ http.request(req) do |res|
111
+ res.read_body do |chunk|
112
+ file.write chunk
113
+ md5.update(chunk)
114
+ end
115
+
116
+ raise "MD5 checksum failed for #{container}/#{object}" if res["x-object-manifest"].nil? && res["etag"] != md5.hexdigest
117
+ end
118
+
119
+ file_name
120
+ ensure
121
+ file.close rescue nil
122
+ end
123
+
124
+ # Uploads a given object to a given container
125
+ def upload_object(url, token, container, file_path, options={})
126
+ options[:object_name] ||= file_path.match(/.+\/(.+?)$/)[1]
127
+ file = File.open(file_path, "rb")
128
+
129
+ file.seek(options[:position]) if options[:position]
130
+ uri = URI.parse("#{url}/#{container}/#{options[:object_name]}")
131
+
132
+ req = Net::HTTP::Put.new(uri.path)
133
+ req.add_field("X-Auth-Token", token)
134
+ req.body_stream = file
135
+ req.content_length = options[:size] || File.size(file_path)
136
+ req.content_type = "application/octet-stream"
137
+
138
+ http = Net::HTTP.new(uri.host, uri.port)
139
+ http.use_ssl = true
140
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
141
+ http.request(req)
142
+ ensure
143
+ file.close rescue nil
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,121 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module Openstack
3
+ module Swift
4
+ class Client
5
+ SWIFT_API = Openstack::Swift::Api
6
+ MAX_SIZE = 4 * 1024 ** 3
7
+
8
+ # Initialize method
9
+ # It uses the authenticate method to store the tokens for future requests
10
+ def initialize(proxy, user, password)
11
+ @proxy, @user, @password = proxy, user, password
12
+ authenticate!
13
+ end
14
+
15
+ # Authentication method
16
+ # It stores the authentication url and token for future commands
17
+ # avoiding to request a new token for each request
18
+ # It should be used to force a new token
19
+ def authenticate!
20
+ @url, _, @token = SWIFT_API.auth(@proxy, @user, @password)
21
+
22
+ if @url.blank? or @token.blank?
23
+ raise AuthenticationError
24
+ else
25
+ true
26
+ end
27
+ end
28
+
29
+ # Returns the following informations about the object:
30
+ # bytes_used: Number of bytes used by this account
31
+ # object_count: Number of objects that this account have allocated
32
+ # container_count: Number of container
33
+ def account_info
34
+ headers = SWIFT_API.account(@url, @token)
35
+ {
36
+ "bytes_used" => headers["x-account-bytes-used"],
37
+ "object_count" => headers["x-account-object-count"],
38
+ "container_count" => headers["x-account-container-count"]
39
+ }
40
+ end
41
+
42
+ # Returns the following informations about the account:
43
+ # last_modified
44
+ # md5
45
+ # content_type
46
+ # manifest
47
+ # content_length
48
+ def object_info(container, object)
49
+ headers = SWIFT_API.object_stat(@url, @token, container, object)
50
+ {
51
+ "last_modified" => headers["last-modified"],
52
+ "md5" => headers["etag"],
53
+ "content_type" => headers["content-type"],
54
+ "manifest" => headers["x-object-manifest"],
55
+ "content_length" => headers["content-length"]
56
+ }
57
+ end
58
+
59
+ # This method uploads a file from a given to a given container
60
+ def upload(container, file_path, options={})
61
+ options[:segments_size] ||= MAX_SIZE
62
+
63
+ SWIFT_API.create_container(@url, @token, container) rescue nil
64
+
65
+ file_name, file_mtime, file_size = file_info(file_path)
66
+
67
+ if file_size > options[:segments_size]
68
+ SWIFT_API.create_container(@url, @token, "#{container}_segments") rescue nil
69
+
70
+ segments_minus_one = file_size / options[:segments_size]
71
+ last_piece = file_size - segments_minus_one * options[:segments_size]
72
+ segments_minus_one.times do |segment|
73
+ upload_path_for(file_path, segment)
74
+ SWIFT_API.upload_object(
75
+ @url, @token, "#{container}_segments", file_path,
76
+ :size => options[:segments_size],
77
+ :position => options[:segments_size] * segment,
78
+ :object_name => segment_path
79
+ )
80
+ end
81
+
82
+ SWIFT_API.upload_object(
83
+ @url, @token, "#{container}_segments", file_path,
84
+ :size => last_piece,
85
+ :position => options[:segments_size] * segments_minus_one,
86
+ :object_name => upload_path_for(file_path, segments_minus_one)
87
+ )
88
+
89
+ SWIFT_API.create_manifest(@url, @token, container, file_path)
90
+ else
91
+ SWIFT_API.upload_object(@url, @token, container, file_path)
92
+ end
93
+ end
94
+
95
+ # This method downloads a object from a given container
96
+ def download(container, object)
97
+ SWIFT_API.download_object(@url, @token, container, object)
98
+ end
99
+
100
+ private
101
+
102
+ # Returns the standard swift path for a given file path and segment
103
+ def upload_path_for(file_path, segment)
104
+ "%s/%s/s/%08d" % (file_info(file_path) << segment)
105
+ end
106
+
107
+ # Get relevant informations about a file
108
+ # Returns an array with:
109
+ # file_name
110
+ # file_mtime
111
+ # file_size
112
+ def file_info(file_path)
113
+ [
114
+ file_path.match(/.+\/(.+?)$/)[1],
115
+ File.mtime(file_path).to_f.round(2),
116
+ File.size(file_path)
117
+ ]
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module Openstack::Swift
3
+ class AuthenticationError < Exception; end
4
+ end
@@ -0,0 +1,19 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module Openstack
3
+ module SwiftConfig
4
+ extend self
5
+
6
+ def [](name)
7
+ configs[name]
8
+ end
9
+
10
+ module_function
11
+ def configs
12
+ @config_file ||= load_file
13
+ end
14
+
15
+ def load_file
16
+ YAML.load_file(File.expand_path(File.dirname(__FILE__)) + "/../../config/swift.yml")[:swift]
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,6 @@
1
+ # -*- coding: UTF-8 -*-
1
2
  module Openstack
2
3
  module Swift
3
- VERSION = "0.0.1"
4
+ VERSION = "0.1.0"
4
5
  end
5
6
  end
@@ -8,14 +8,16 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["morellon", "pothix"]
10
10
  s.email = ["morellon@gmail.com", "pothix@pothix.com"]
11
- s.homepage = ""
12
- s.summary = %q{Openstack's swift client}
11
+ s.homepage = "http://github.com/morellon/openstack-swift"
13
12
  s.description = %q{Openstack's swift client}
13
+ s.summary = s.description
14
14
 
15
15
  s.rubyforge_project = "openstack-swift"
16
16
 
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.files = Dir["./**/*"].reject {|file| file =~ /\.git|pkg/}
20
18
  s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency "rspec", "~> 2.6"
21
+ s.add_development_dependency "httparty"
22
+ s.add_development_dependency "ruby-debug19"
21
23
  end
@@ -0,0 +1,47 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require "spec_helper"
3
+
4
+ describe "Openstack::Swift::Client" do
5
+ let!(:swift_dummy_file) do
6
+ file_path = "/tmp/swift-dummy"
7
+ File.open(file_path, "w") {|f| f.puts("testfile "*1000)}
8
+ file_path
9
+ end
10
+
11
+ context "when authenticating" do
12
+ it "should return authentication error if one of the parameters is incorrect" do
13
+ expect {
14
+ Openstack::Swift::Client.new("http://incorrect.com/swift", Openstack::SwiftConfig[:user], Openstack::SwiftConfig[:pass])
15
+ }.to raise_error(Openstack::Swift::AuthenticationError)
16
+ end
17
+
18
+ it "shoud not need to authenticate again" do
19
+ client = Openstack::Swift::Client.new(Openstack::SwiftConfig[:url], Openstack::SwiftConfig[:user], Openstack::SwiftConfig[:pass])
20
+ Openstack::Swift::Api.should_not_receive(:auth)
21
+ client.account_info
22
+ end
23
+ end
24
+
25
+ context "when authenticated" do
26
+ subject { Openstack::Swift::Client.new(Openstack::SwiftConfig[:url], Openstack::SwiftConfig[:user], Openstack::SwiftConfig[:pass]) }
27
+
28
+ it "should upload a splitted file and create its manifest" do
29
+ pending "WTF...Not working for a unknown reason"
30
+ subject.upload("pothix", swift_dummy_file, {:segments_size => 1024*2})
31
+ subject.object_info("pothix", "swifty-dummy")["manifest"].should_not be_nil
32
+ end
33
+
34
+ it "should download an splitted file" do
35
+ content_length = subject.object_info("morellon", "splitted_file")["content_length"].to_i
36
+ file_path = subject.download("morellon", "splitted_file")
37
+ File.size(file_path).should == content_length
38
+ end
39
+
40
+ it "should return account's details" do
41
+ account_info = subject.account_info
42
+ account_info.should have_key("bytes_used")
43
+ account_info.should have_key("object_count")
44
+ account_info.should have_key("container_count")
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,99 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require "spec_helper"
3
+
4
+ describe Openstack::Swift::Api do
5
+ context "when authenticating" do
6
+ it "should authenticate on swift" do
7
+ expect {
8
+ subject.auth(Openstack::SwiftConfig[:url], Openstack::SwiftConfig[:user], Openstack::SwiftConfig[:pass])
9
+ }.to_not raise_error Openstack::Swift::AuthenticationError
10
+ end
11
+
12
+ it "should raise error for a invalid url" do
13
+ expect {
14
+ subject.auth("http://pothix.com/swift", Openstack::SwiftConfig[:user], Openstack::SwiftConfig[:pass])
15
+ }.to raise_error Openstack::Swift::AuthenticationError
16
+ end
17
+
18
+ it "should raise error for a invalid pass" do
19
+ expect {
20
+ subject.auth(Openstack::SwiftConfig[:url], Openstack::SwiftConfig[:user], "invalidpassword")
21
+ }.to raise_error Openstack::Swift::AuthenticationError
22
+ end
23
+
24
+ it "should raise error for a invalid user" do
25
+ expect {
26
+ subject.auth(Openstack::SwiftConfig[:url], "system:weirduser", Openstack::SwiftConfig[:pass])
27
+ }.to raise_error Openstack::Swift::AuthenticationError
28
+ end
29
+
30
+ it "should return storage-url, storage-token and auth-token" do
31
+ subject.auth(Openstack::SwiftConfig[:url], Openstack::SwiftConfig[:user], Openstack::SwiftConfig[:pass]).should have(3).items
32
+ end
33
+ end
34
+
35
+ context "when authenticated" do
36
+ let!(:swift_dummy_file){ File.open("/tmp/swift-dummy", "w") {|f| f.puts("test file"*1000)} }
37
+
38
+ before do
39
+ @url, _, @token = subject.auth(
40
+ Openstack::SwiftConfig[:url],
41
+ Openstack::SwiftConfig[:user],
42
+ Openstack::SwiftConfig[:pass]
43
+ )
44
+ end
45
+
46
+ it "should return account's headers" do
47
+ account = subject.account(@url, @token)
48
+ account.should have_key("x-account-bytes-used")
49
+ account.should have_key("x-account-object-count")
50
+ account.should have_key("x-account-container-count")
51
+ end
52
+
53
+ it "should return a list of containers" do
54
+ subject.containers(@url, @token).should be_a(Array)
55
+ end
56
+
57
+ it "should return a list of objects" do
58
+ subject.objects(@url, @token, "morellon", :delimiter => "/").should be_a(Array)
59
+ end
60
+
61
+ it "should download an object" do
62
+ subject.download_object(@url, @token, "morellon", "Gemfile").should == "/tmp/swift/morellon/Gemfile"
63
+ end
64
+
65
+ it "should upload an object" do
66
+ subject.upload_object(@url, @token, "morellon", "/tmp/swift-dummy").code.should == "201"
67
+ end
68
+
69
+ it "should create a new container" do
70
+ subject.create_container(@url, @token, "pothix_container").should be_true
71
+ end
72
+
73
+ context "when excluding a container" do
74
+ before { @container = "pothix_container" }
75
+
76
+ it "should delete a existent container" do
77
+ subject.create_container(@url, @token, @container).should be_true
78
+ subject.delete_container(@url, @token, @container).should be_true
79
+ end
80
+
81
+ it "should raise an error when the container doesn't exist" do
82
+ expect {
83
+ subject.delete_container(@url, @token, @container).should be_true
84
+ subject.delete_container(@url, @token, @container).should be_true
85
+ }.to raise_error("Could not delete container '#{@container}'")
86
+ end
87
+ end
88
+
89
+ it "should get the file stat" do
90
+ subject.upload_object(@url, @token, "morellon", "/tmp/swift-dummy")
91
+ headers = subject.object_stat(@url, @token, "morellon", "swift-dummy")
92
+
93
+ headers["last-modified"].should_not be_blank
94
+ headers["etag"].should_not be_blank
95
+ headers["content-type"].should_not be_blank
96
+ headers["date"].should_not be_blank
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,13 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require "rubygems"
3
+ require "bundler/setup"
4
+
5
+ require "openstack-swift"
6
+
7
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|file| require file}
8
+
9
+ # Using a diferent YAML engine on test environment
10
+ YAML::ENGINE::yamler = "syck"
11
+
12
+ RSpec.configure do |config|
13
+ end
metadata CHANGED
@@ -1,64 +1,96 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: openstack-swift
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
4
5
  prerelease:
5
- version: 0.0.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - morellon
9
9
  - pothix
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
-
14
- date: 2011-08-10 00:00:00 -03:00
13
+ date: 2011-08-22 00:00:00.000000000 -03:00
15
14
  default_executable:
16
- dependencies: []
17
-
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ requirement: &10022160 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: '2.6'
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: *10022160
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: &10021760 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *10021760
38
+ - !ruby/object:Gem::Dependency
39
+ name: ruby-debug19
40
+ requirement: &10021280 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *10021280
18
49
  description: Openstack's swift client
19
- email:
50
+ email:
20
51
  - morellon@gmail.com
21
52
  - pothix@pothix.com
22
53
  executables: []
23
-
24
54
  extensions: []
25
-
26
55
  extra_rdoc_files: []
27
-
28
- files:
29
- - .gitignore
30
- - Gemfile
31
- - Rakefile
32
- - lib/openstack-swift.rb
33
- - lib/openstack-swift/version.rb
34
- - openstack-swift.gemspec
56
+ files:
57
+ - ./Gemfile.lock
58
+ - ./config/swift.yml
59
+ - ./Rakefile
60
+ - ./lib/openstack-swift.rb
61
+ - ./lib/openstack-swift/swift_config.rb
62
+ - ./lib/openstack-swift/errors.rb
63
+ - ./lib/openstack-swift/api.rb
64
+ - ./lib/openstack-swift/client.rb
65
+ - ./lib/openstack-swift/version.rb
66
+ - ./Gemfile
67
+ - ./openstack-swift.gemspec
68
+ - ./spec/openstack-swift/client_spec.rb
69
+ - ./spec/openstack-swift/web_api_spec.rb
70
+ - ./spec/spec_helper.rb
35
71
  has_rdoc: true
36
- homepage: ""
72
+ homepage: http://github.com/morellon/openstack-swift
37
73
  licenses: []
38
-
39
74
  post_install_message:
40
75
  rdoc_options: []
41
-
42
- require_paths:
76
+ require_paths:
43
77
  - lib
44
- required_ruby_version: !ruby/object:Gem::Requirement
78
+ required_ruby_version: !ruby/object:Gem::Requirement
45
79
  none: false
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: "0"
50
- required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
85
  none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: "0"
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
56
90
  requirements: []
57
-
58
91
  rubyforge_project: openstack-swift
59
92
  rubygems_version: 1.6.2
60
93
  signing_key:
61
94
  specification_version: 3
62
95
  summary: Openstack's swift client
63
96
  test_files: []
64
-
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- *.gem
2
- .bundle
3
- Gemfile.lock
4
- pkg/*