fog-radosgw 0.0.3 → 0.0.4
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/.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
|