fog-radosgw 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +17 -0
- data/CONTRIBUTING.md +18 -0
- data/Rakefile +1 -1
- data/gemfiles/Gemfile.1.9.2- +8 -0
- data/gemfiles/Gemfile.1.9.3+ +7 -0
- data/lib/fog/radosgw.rb +18 -2
- data/lib/fog/radosgw/multipart_utils.rb +44 -0
- data/lib/fog/radosgw/multipart_utils/headers.rb +32 -0
- data/lib/fog/radosgw/provisioning.rb +0 -4
- data/lib/fog/radosgw/usage.rb +0 -1
- data/lib/fog/radosgw/user_utils.rb +47 -0
- data/lib/fog/radosgw/utils.rb +89 -0
- data/lib/fog/radosgw/version.rb +1 -1
- metadata +27 -20
- data/lib/fog/radosgw/core.rb +0 -207
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b619efd888c9797d8ebc88e36beb34dba79068f8
|
4
|
+
data.tar.gz: 933ef7e27304aaadab19434e2bcbdd9fe8114c4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3b4eee7b957bb3cf84cd2e563ec0eee04c36b120c7e9593195e7b74290d787d9c0cb8b68840aba1f0720ae5319a713c4951ddb6a5d25d715a82c94bd574c21f
|
7
|
+
data.tar.gz: 0cf767e88a221857d18f863a7860dc89de40ee828a13a43c152d3afa798237597904994280773d4b38ea5f3c3ea72e91c0c81d75023553c94e33f39b97a5bb54
|
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
matrix:
|
2
|
+
include:
|
3
|
+
- rvm: 1.8.7
|
4
|
+
gemfile: gemfiles/Gemfile.1.9.2-
|
5
|
+
- rvm: 1.9.2
|
6
|
+
gemfile: gemfiles/Gemfile.1.9.2-
|
7
|
+
- rvm: 1.9.3
|
8
|
+
gemfile: gemfiles/Gemfile.1.9.3+
|
9
|
+
- rvm: 2.0.0
|
10
|
+
gemfile: gemfiles/Gemfile.1.9.3+
|
11
|
+
- rvm: 2.1.4
|
12
|
+
gemfile: gemfiles/Gemfile.1.9.3+
|
13
|
+
env: COVERAGE=true
|
14
|
+
- rvm: ree
|
15
|
+
gemfile: gemfiles/Gemfile.1.9.2-
|
16
|
+
- rvm: jruby
|
17
|
+
gemfile: gemfiles/Gemfile.1.9.3+
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
## Getting Involved
|
2
|
+
|
3
|
+
New contributors are always welcome, when it doubt please ask questions. We strive to be an open and welcoming community. Please be nice to one another.
|
4
|
+
|
5
|
+
### Coding
|
6
|
+
|
7
|
+
* Pick a task:
|
8
|
+
* Offer feedback on open [pull requests](https://github.com/fog/fog-radosgw/pulls).
|
9
|
+
* Review open [issues](https://github.com/fog/fog-radosgw/issues) for things to help on.
|
10
|
+
* [Create an issue](https://github.com/fog/fog-radosgw/issues/new) to start a discussion on additions or features.
|
11
|
+
* Fork the project, add your changes and tests to cover them in a topic branch.
|
12
|
+
* Commit your changes and rebase against `fog/fog-radosgw` to ensure everything is up to date.
|
13
|
+
* [Submit a pull request](https://github.com/fog/fog-radosgw/compare/)
|
14
|
+
|
15
|
+
### Non-Coding
|
16
|
+
|
17
|
+
* Offer feedback on open [issues](https://github.com/fog/fog-radosgw/issues).
|
18
|
+
* Organize or volunteer at events.
|
data/Rakefile
CHANGED
data/lib/fog/radosgw.rb
CHANGED
@@ -1,2 +1,18 @@
|
|
1
|
-
require 'fog/
|
2
|
-
require 'fog/
|
1
|
+
require 'fog/core'
|
2
|
+
require 'fog/json'
|
3
|
+
require 'fog/xml'
|
4
|
+
|
5
|
+
module Fog
|
6
|
+
module Radosgw
|
7
|
+
autoload :Provisioning, File.expand_path('../radosgw/provisioning', __FILE__)
|
8
|
+
autoload :Usage, File.expand_path('../radosgw/usage', __FILE__)
|
9
|
+
autoload :MultipartUtils, File.expand_path('../radosgw/multipart_utils', __FILE__)
|
10
|
+
autoload :UserUtils, File.expand_path('../radosgw/user_utils', __FILE__)
|
11
|
+
autoload :Utils, File.expand_path('../radosgw/utils', __FILE__)
|
12
|
+
|
13
|
+
extend Fog::Provider
|
14
|
+
|
15
|
+
service(:provisioning, 'Provisioning')
|
16
|
+
service(:usage, 'Usage')
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Fog
|
2
|
+
module Radosgw
|
3
|
+
module MultipartUtils
|
4
|
+
autoload :Headers, File.expand_path('../multipart_utils/headers', __FILE__)
|
5
|
+
|
6
|
+
def parse(data, boundary)
|
7
|
+
contents = data.match(end_boundary_regex(boundary)).pre_match rescue ""
|
8
|
+
contents.split(inner_boundary_regex(boundary)).reject(&:empty?).map do |part|
|
9
|
+
parse_multipart_section(part)
|
10
|
+
end.compact
|
11
|
+
end
|
12
|
+
|
13
|
+
def extract_boundary(header_string)
|
14
|
+
$1 if header_string =~ /boundary=([A-Za-z0-9\'()+_,-.\/:=?]+)/
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def end_boundary_regex(boundary)
|
19
|
+
/\r?\n--#{Regexp.escape(boundary)}--\r?\n?/
|
20
|
+
end
|
21
|
+
|
22
|
+
def inner_boundary_regex(boundary)
|
23
|
+
/\r?\n--#{Regexp.escape(boundary)}\r?\n/
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_multipart_section(part)
|
27
|
+
headers = Headers.new
|
28
|
+
if md = part.match(/\r?\n\r?\n/)
|
29
|
+
body = md.post_match
|
30
|
+
md.pre_match.split(/\r?\n/).each do |line|
|
31
|
+
headers.parse(line)
|
32
|
+
end
|
33
|
+
|
34
|
+
if headers["content-type"] =~ /multipart\/mixed/
|
35
|
+
boundary = extract_boundary(headers.to_hash["content-type"].first)
|
36
|
+
parse(body, boundary)
|
37
|
+
else
|
38
|
+
{:headers => headers.to_hash, :body => body}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
module Radosgw
|
5
|
+
module MultipartUtils
|
6
|
+
class Headers
|
7
|
+
include Net::HTTPHeader
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
initialize_http_header({})
|
11
|
+
end
|
12
|
+
|
13
|
+
# Parse a single header line into its key and value
|
14
|
+
# @param [String] chunk a single header line
|
15
|
+
def self.parse(chunk)
|
16
|
+
line = chunk.strip
|
17
|
+
# thanks Net::HTTPResponse
|
18
|
+
return [nil,nil] if chunk =~ /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in
|
19
|
+
m = /\A([^:]+):\s*/.match(line)
|
20
|
+
[m[1], m.post_match] rescue [nil, nil]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Parses a header line and adds it to the header collection
|
24
|
+
# @param [String] chunk a single header line
|
25
|
+
def parse(chunk)
|
26
|
+
key, value = self.class.parse(chunk)
|
27
|
+
add_field(key, value) if key && value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/fog/radosgw/usage.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Fog
|
2
|
+
module Radosgw
|
3
|
+
module UserUtils
|
4
|
+
def update_radosgw_user(user_id, user)
|
5
|
+
path = "admin/user"
|
6
|
+
user_id = escape(user_id)
|
7
|
+
params = {
|
8
|
+
:method => 'POST',
|
9
|
+
:path => path,
|
10
|
+
}
|
11
|
+
query = "?uid=#{user_id}&format=json&suspended=#{user[:suspended]}"
|
12
|
+
begin
|
13
|
+
response = Excon.post("#{@scheme}://#{@host}/#{path}#{query}",
|
14
|
+
:headers => signed_headers(params))
|
15
|
+
if !response.body.empty?
|
16
|
+
case response.headers['Content-Type']
|
17
|
+
when 'application/json'
|
18
|
+
response.body = Fog::JSON.decode(response.body)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
response
|
22
|
+
rescue Excon::Errors::NotFound => e
|
23
|
+
raise Fog::Radosgw::Provisioning::NoSuchUser.new
|
24
|
+
rescue Excon::Errors::BadRequest => e
|
25
|
+
raise Fog::Radosgw::Provisioning::ServiceUnavailable.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_mock_user(user_id, user)
|
30
|
+
if data[user_id]
|
31
|
+
if suspended = user[:suspended]
|
32
|
+
data[user_id][:suspended] = suspended
|
33
|
+
end
|
34
|
+
|
35
|
+
Excon::Response.new.tap do |response|
|
36
|
+
response.status = 200
|
37
|
+
response.body = data[user_id]
|
38
|
+
end
|
39
|
+
else
|
40
|
+
Excon::Response.new.tap do |response|
|
41
|
+
response.status = 403
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Fog
|
2
|
+
module Radosgw
|
3
|
+
module Utils
|
4
|
+
def configure_uri_options(options = {})
|
5
|
+
@host = options[:host] || 'localhost'
|
6
|
+
@persistent = options[:persistent] || true
|
7
|
+
@port = options[:port] || 8080
|
8
|
+
@scheme = options[:scheme] || 'http'
|
9
|
+
end
|
10
|
+
|
11
|
+
def radosgw_uri
|
12
|
+
"#{@scheme}://#{@host}:#{@port}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def escape(string)
|
16
|
+
string.gsub(/([^a-zA-Z0-9_.\-~]+)/) {
|
17
|
+
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def signature(params, expires)
|
22
|
+
headers = params[:headers] || {}
|
23
|
+
|
24
|
+
string_to_sign =
|
25
|
+
<<-DATA
|
26
|
+
#{params[:method].to_s.upcase}
|
27
|
+
#{headers['Content-MD5']}
|
28
|
+
#{headers['Content-Type']}
|
29
|
+
#{expires}
|
30
|
+
DATA
|
31
|
+
|
32
|
+
amz_headers, canonical_amz_headers = {}, ''
|
33
|
+
for key, value in headers
|
34
|
+
if key[0..5] == 'x-amz-'
|
35
|
+
amz_headers[key] = value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
amz_headers = amz_headers.sort {|x, y| x[0] <=> y[0]}
|
39
|
+
for key, value in amz_headers
|
40
|
+
canonical_amz_headers << "#{key}:#{value}\n"
|
41
|
+
end
|
42
|
+
string_to_sign << canonical_amz_headers
|
43
|
+
|
44
|
+
|
45
|
+
query_string = ''
|
46
|
+
if params[:query]
|
47
|
+
query_args = []
|
48
|
+
for key in params[:query].keys.sort
|
49
|
+
if VALID_QUERY_KEYS.include?(key)
|
50
|
+
value = params[:query][key]
|
51
|
+
if value
|
52
|
+
query_args << "#{key}=#{value}"
|
53
|
+
else
|
54
|
+
query_args << key
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
if query_args.any?
|
59
|
+
query_string = '?' + query_args.join('&')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
canonical_path = (params[:path] || object_to_path(params[:object_name])).to_s
|
64
|
+
canonical_path = '/' + canonical_path if canonical_path[0..0] != '/'
|
65
|
+
if params[:bucket_name]
|
66
|
+
canonical_resource = "/#{params[:bucket_name]}#{canonical_path}"
|
67
|
+
else
|
68
|
+
canonical_resource = canonical_path
|
69
|
+
end
|
70
|
+
canonical_resource << query_string
|
71
|
+
string_to_sign << canonical_resource
|
72
|
+
|
73
|
+
hmac = Fog::HMAC.new('sha1', @radosgw_secret_access_key)
|
74
|
+
signed_string = hmac.sign(string_to_sign)
|
75
|
+
Base64.encode64(signed_string).chomp!
|
76
|
+
end
|
77
|
+
|
78
|
+
def signed_headers(params)
|
79
|
+
expires = Fog::Time.now.to_date_header
|
80
|
+
auth = signature(params,expires)
|
81
|
+
awskey = @radosgw_access_key_id
|
82
|
+
headers = {
|
83
|
+
'Date' => expires,
|
84
|
+
'Authorization' => "AWS #{awskey}:#{auth}"
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/fog/radosgw/version.rb
CHANGED
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fog-radosgw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Kåre Hellan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fog-json
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: fog-xml
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.0.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.0.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: fog-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 1.21.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.21.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: shindo
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: Fog backend for provisioning users on Ceph Radosgw - the Swift and S3
|
@@ -103,15 +103,20 @@ extra_rdoc_files:
|
|
103
103
|
- README.md
|
104
104
|
- LICENSE.md
|
105
105
|
files:
|
106
|
-
- .gitignore
|
106
|
+
- ".gitignore"
|
107
|
+
- ".travis.yml"
|
108
|
+
- CONTRIBUTING.md
|
107
109
|
- CONTRIBUTORS.md
|
108
110
|
- Gemfile
|
109
111
|
- LICENSE.md
|
110
112
|
- README.md
|
111
113
|
- Rakefile
|
112
114
|
- fog-radosgw.gemspec
|
115
|
+
- gemfiles/Gemfile.1.9.2-
|
116
|
+
- gemfiles/Gemfile.1.9.3+
|
113
117
|
- lib/fog/radosgw.rb
|
114
|
-
- lib/fog/radosgw/
|
118
|
+
- lib/fog/radosgw/multipart_utils.rb
|
119
|
+
- lib/fog/radosgw/multipart_utils/headers.rb
|
115
120
|
- lib/fog/radosgw/provisioning.rb
|
116
121
|
- lib/fog/radosgw/requests/provisioning/create_user.rb
|
117
122
|
- lib/fog/radosgw/requests/provisioning/delete_user.rb
|
@@ -123,6 +128,8 @@ files:
|
|
123
128
|
- lib/fog/radosgw/requests/provisioning/user.json
|
124
129
|
- lib/fog/radosgw/requests/usage/get_usage.rb
|
125
130
|
- lib/fog/radosgw/usage.rb
|
131
|
+
- lib/fog/radosgw/user_utils.rb
|
132
|
+
- lib/fog/radosgw/utils.rb
|
126
133
|
- lib/fog/radosgw/version.rb
|
127
134
|
- tests/helper.rb
|
128
135
|
- tests/helpers/mock_helper.rb
|
@@ -135,22 +142,22 @@ licenses:
|
|
135
142
|
metadata: {}
|
136
143
|
post_install_message:
|
137
144
|
rdoc_options:
|
138
|
-
- --charset=UTF-8
|
145
|
+
- "--charset=UTF-8"
|
139
146
|
require_paths:
|
140
147
|
- lib
|
141
148
|
required_ruby_version: !ruby/object:Gem::Requirement
|
142
149
|
requirements:
|
143
|
-
- -
|
150
|
+
- - ">="
|
144
151
|
- !ruby/object:Gem::Version
|
145
152
|
version: '0'
|
146
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
154
|
requirements:
|
148
|
-
- -
|
155
|
+
- - ">="
|
149
156
|
- !ruby/object:Gem::Version
|
150
157
|
version: '0'
|
151
158
|
requirements: []
|
152
159
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.
|
160
|
+
rubygems_version: 2.2.2
|
154
161
|
signing_key:
|
155
162
|
specification_version: 4
|
156
163
|
summary: Fog backend for provisioning Ceph Radosgw.
|
data/lib/fog/radosgw/core.rb
DELETED
@@ -1,207 +0,0 @@
|
|
1
|
-
require 'fog/core'
|
2
|
-
|
3
|
-
module Fog
|
4
|
-
module Radosgw
|
5
|
-
module MultipartUtils
|
6
|
-
require 'net/http'
|
7
|
-
|
8
|
-
class Headers
|
9
|
-
include Net::HTTPHeader
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
initialize_http_header({})
|
13
|
-
end
|
14
|
-
|
15
|
-
# Parse a single header line into its key and value
|
16
|
-
# @param [String] chunk a single header line
|
17
|
-
def self.parse(chunk)
|
18
|
-
line = chunk.strip
|
19
|
-
# thanks Net::HTTPResponse
|
20
|
-
return [nil,nil] if chunk =~ /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in
|
21
|
-
m = /\A([^:]+):\s*/.match(line)
|
22
|
-
[m[1], m.post_match] rescue [nil, nil]
|
23
|
-
end
|
24
|
-
|
25
|
-
# Parses a header line and adds it to the header collection
|
26
|
-
# @param [String] chunk a single header line
|
27
|
-
def parse(chunk)
|
28
|
-
key, value = self.class.parse(chunk)
|
29
|
-
add_field(key, value) if key && value
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def parse(data, boundary)
|
34
|
-
contents = data.match(end_boundary_regex(boundary)).pre_match rescue ""
|
35
|
-
contents.split(inner_boundary_regex(boundary)).reject(&:empty?).map do |part|
|
36
|
-
parse_multipart_section(part)
|
37
|
-
end.compact
|
38
|
-
end
|
39
|
-
|
40
|
-
def extract_boundary(header_string)
|
41
|
-
$1 if header_string =~ /boundary=([A-Za-z0-9\'()+_,-.\/:=?]+)/
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
def end_boundary_regex(boundary)
|
46
|
-
/\r?\n--#{Regexp.escape(boundary)}--\r?\n?/
|
47
|
-
end
|
48
|
-
|
49
|
-
def inner_boundary_regex(boundary)
|
50
|
-
/\r?\n--#{Regexp.escape(boundary)}\r?\n/
|
51
|
-
end
|
52
|
-
|
53
|
-
def parse_multipart_section(part)
|
54
|
-
headers = Headers.new
|
55
|
-
if md = part.match(/\r?\n\r?\n/)
|
56
|
-
body = md.post_match
|
57
|
-
md.pre_match.split(/\r?\n/).each do |line|
|
58
|
-
headers.parse(line)
|
59
|
-
end
|
60
|
-
|
61
|
-
if headers["content-type"] =~ /multipart\/mixed/
|
62
|
-
boundary = extract_boundary(headers.to_hash["content-type"].first)
|
63
|
-
parse(body, boundary)
|
64
|
-
else
|
65
|
-
{:headers => headers.to_hash, :body => body}
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
module UserUtils
|
72
|
-
|
73
|
-
def update_radosgw_user(user_id, user)
|
74
|
-
path = "admin/user"
|
75
|
-
user_id = escape(user_id)
|
76
|
-
params = {
|
77
|
-
:method => 'POST',
|
78
|
-
:path => path,
|
79
|
-
}
|
80
|
-
query = "?uid=#{user_id}&format=json&suspended=#{user[:suspended]}"
|
81
|
-
begin
|
82
|
-
response = Excon.post("#{@scheme}://#{@host}/#{path}#{query}",
|
83
|
-
:headers => signed_headers(params))
|
84
|
-
if !response.body.empty?
|
85
|
-
case response.headers['Content-Type']
|
86
|
-
when 'application/json'
|
87
|
-
response.body = Fog::JSON.decode(response.body)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
response
|
91
|
-
rescue Excon::Errors::NotFound => e
|
92
|
-
raise Fog::Radosgw::Provisioning::NoSuchUser.new
|
93
|
-
rescue Excon::Errors::BadRequest => e
|
94
|
-
raise Fog::Radosgw::Provisioning::ServiceUnavailable.new
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def update_mock_user(user_id, user)
|
99
|
-
if data[user_id]
|
100
|
-
if suspended = user[:suspended]
|
101
|
-
data[user_id][:suspended] = suspended
|
102
|
-
end
|
103
|
-
|
104
|
-
Excon::Response.new.tap do |response|
|
105
|
-
response.status = 200
|
106
|
-
response.body = data[user_id]
|
107
|
-
end
|
108
|
-
else
|
109
|
-
Excon::Response.new.tap do |response|
|
110
|
-
response.status = 403
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
module Utils
|
117
|
-
def configure_uri_options(options = {})
|
118
|
-
@host = options[:host] || 'localhost'
|
119
|
-
@persistent = options[:persistent] || true
|
120
|
-
@port = options[:port] || 8080
|
121
|
-
@scheme = options[:scheme] || 'http'
|
122
|
-
end
|
123
|
-
|
124
|
-
def radosgw_uri
|
125
|
-
"#{@scheme}://#{@host}:#{@port}"
|
126
|
-
end
|
127
|
-
|
128
|
-
def escape(string)
|
129
|
-
string.gsub(/([^a-zA-Z0-9_.\-~]+)/) {
|
130
|
-
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
131
|
-
}
|
132
|
-
end
|
133
|
-
|
134
|
-
def signature(params, expires)
|
135
|
-
headers = params[:headers] || {}
|
136
|
-
|
137
|
-
string_to_sign =
|
138
|
-
<<-DATA
|
139
|
-
#{params[:method].to_s.upcase}
|
140
|
-
#{headers['Content-MD5']}
|
141
|
-
#{headers['Content-Type']}
|
142
|
-
#{expires}
|
143
|
-
DATA
|
144
|
-
|
145
|
-
amz_headers, canonical_amz_headers = {}, ''
|
146
|
-
for key, value in headers
|
147
|
-
if key[0..5] == 'x-amz-'
|
148
|
-
amz_headers[key] = value
|
149
|
-
end
|
150
|
-
end
|
151
|
-
amz_headers = amz_headers.sort {|x, y| x[0] <=> y[0]}
|
152
|
-
for key, value in amz_headers
|
153
|
-
canonical_amz_headers << "#{key}:#{value}\n"
|
154
|
-
end
|
155
|
-
string_to_sign << canonical_amz_headers
|
156
|
-
|
157
|
-
|
158
|
-
query_string = ''
|
159
|
-
if params[:query]
|
160
|
-
query_args = []
|
161
|
-
for key in params[:query].keys.sort
|
162
|
-
if VALID_QUERY_KEYS.include?(key)
|
163
|
-
value = params[:query][key]
|
164
|
-
if value
|
165
|
-
query_args << "#{key}=#{value}"
|
166
|
-
else
|
167
|
-
query_args << key
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
if query_args.any?
|
172
|
-
query_string = '?' + query_args.join('&')
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
canonical_path = (params[:path] || object_to_path(params[:object_name])).to_s
|
177
|
-
canonical_path = '/' + canonical_path if canonical_path[0..0] != '/'
|
178
|
-
if params[:bucket_name]
|
179
|
-
canonical_resource = "/#{params[:bucket_name]}#{canonical_path}"
|
180
|
-
else
|
181
|
-
canonical_resource = canonical_path
|
182
|
-
end
|
183
|
-
canonical_resource << query_string
|
184
|
-
string_to_sign << canonical_resource
|
185
|
-
|
186
|
-
hmac = Fog::HMAC.new('sha1', @radosgw_secret_access_key)
|
187
|
-
signed_string = hmac.sign(string_to_sign)
|
188
|
-
Base64.encode64(signed_string).chomp!
|
189
|
-
end
|
190
|
-
|
191
|
-
def signed_headers(params)
|
192
|
-
expires = Fog::Time.now.to_date_header
|
193
|
-
auth = signature(params,expires)
|
194
|
-
awskey = @radosgw_access_key_id
|
195
|
-
headers = {
|
196
|
-
'Date' => expires,
|
197
|
-
'Authorization' => "AWS #{awskey}:#{auth}"
|
198
|
-
}
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
extend Fog::Provider
|
203
|
-
|
204
|
-
service(:provisioning, 'Provisioning')
|
205
|
-
service(:usage, 'Usage')
|
206
|
-
end
|
207
|
-
end
|