fog-radosgw-0.0.4/0000755000004100000410000000000012511745105013763 5ustar www-datawww-datafog-radosgw-0.0.4/Rakefile0000644000004100000410000000337212511745105015435 0ustar www-datawww-datarequire 'bundler/setup' require "bundler/gem_tasks" require 'rake/testtask' require 'date' require 'rubygems' require 'rubygems/package_task' require 'yard' require 'fog/core' require 'fog/json' ############################################################################# # # Helper functions # ############################################################################# def name @name ||= Dir['*.gemspec'].first.split('.').first end def version Fog::Radosgw::VERSION end def date Date.today.to_s end def rubyforge_project name end def gemspec_file "#{name}.gemspec" end def gem_file "#{name}-#{version}.gem" end def replace_header(head, header_name) head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"} end ############################################################################# # # Standard tasks # ############################################################################# GEM_NAME = "#{name}" task :default => :travis task :travis => ['test', 'test:travis'] Rake::TestTask.new do |t| t.pattern = File.join("spec", "**", "*_spec.rb") end namespace :test do mock = ENV['FOG_MOCK'] || 'true' task :travis do sh("export FOG_MOCK=#{mock} && bundle exec shindont") end end desc 'Run mocked tests for a specific provider' task :mock, :provider do |t, args| if args.to_a.size != 1 fail 'USAGE: rake mock[]' end provider = args[:provider] sh("export FOG_MOCK=true && bundle exec shindont tests/#{provider}") end desc 'Run live tests against a specific provider' task :live, :provider do |t, args| if args.to_a.size != 1 fail 'USAGE: rake live[]' end provider = args[:provider] sh("export FOG_MOCK=false PROVIDER=#{provider} && bundle exec shindont tests/#{provider}") end fog-radosgw-0.0.4/Gemfile0000644000004100000410000000004612511745105015256 0ustar www-datawww-datasource "https://rubygems.org" gemspec fog-radosgw-0.0.4/tests/0000755000004100000410000000000012511745105015125 5ustar www-datawww-datafog-radosgw-0.0.4/tests/helper.rb0000644000004100000410000000053712511745105016736 0ustar www-datawww-dataENV['FOG_RC'] = ENV['FOG_RC'] || File.expand_path('../.fog', __FILE__) ENV['FOG_CREDENTIAL'] = ENV['FOG_CREDENTIAL'] || 'default' require 'fog/core' require 'fog/test_helpers/formats_helper' require File.expand_path(File.join(File.dirname(__FILE__), 'helpers', 'mock_helper')) Excon.defaults.merge!(:debug_request => true, :debug_response => true) fog-radosgw-0.0.4/tests/radosgw/0000755000004100000410000000000012511745105016573 5ustar www-datawww-datafog-radosgw-0.0.4/tests/radosgw/helper.rb0000644000004100000410000000002612511745105020375 0ustar www-datawww-datarequire 'fog/radosgw' fog-radosgw-0.0.4/tests/radosgw/requests/0000755000004100000410000000000012511745105020446 5ustar www-datawww-datafog-radosgw-0.0.4/tests/radosgw/requests/provisioning/0000755000004100000410000000000012511745105023174 5ustar www-datawww-datafog-radosgw-0.0.4/tests/radosgw/requests/provisioning/provisioning_tests.rb0000644000004100000410000001140012511745105027465 0ustar www-datawww-dataShindo.tests('Radosgw::Provisioning | provisioning requests', ['radosgw']) do current_timestamp = Time.now.to_i user_format = { 'email' => String, 'display_name' => String, 'user_id' => String, 'suspended' => Integer, 'keys' => [ { 'access_key' => String, 'secret_key' => String, 'user' => String, } ], } tests('User creation') do tests('is successful').returns(String) do # Create a user. # email, name = "successful_user_creation_test_#{current_timestamp}@example.com", "Fog User 0" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] user_id.class end tests('fails if duplicate').raises(Fog::Radosgw::Provisioning::UserAlreadyExists) do 2.times do email, name = "failed_duplicate_user_creation_test_#{current_timestamp}@example.com", "Fog User 1" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] end end end tests('User delete') do tests('is successful').returns(200) do # Create a user. # email, name = "successful_user_delete_test_#{current_timestamp}@example.com", "Fog User 2" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] Fog::Radosgw[:provisioning].delete_user(user_id).status end tests('is successful').returns(404) do # Create a user. # email, name = "successful_user_delete_test_2_#{current_timestamp}@example.com", "Fog User 3" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] Fog::Radosgw[:provisioning].delete_user(user_id).status Fog::Radosgw[:provisioning].get_user(user_id).status end end tests('User disable') do tests('is successful').returns(200) do # Create a user. # email, name = "successful_user_disable_test_#{current_timestamp}@example.com", "Fog User 4" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] Fog::Radosgw[:provisioning].disable_user(user_id).status end end tests('User enable') do tests('is successful').returns(200) do # Create a user. # email, name = "successful_user_disable_enable_test_#{current_timestamp}@example.com", "Fog User 5" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] Fog::Radosgw[:provisioning].disable_user(user_id).status Fog::Radosgw[:provisioning].enable_user(user_id).status end end tests('User retrieval') do tests('is successful').formats(user_format) do # Create a user. # email, name = "user_retrieval_test_#{current_timestamp}@example.com", "Fog User 6" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] # Get user details. # Fog::Radosgw[:provisioning].get_user(user_id).body end end tests('User listing') do tests('sucessfully lists users').formats(user_format) do # Create a user. # email, name = "user_listing_test_#{current_timestamp}@example.com", "Fog User 7" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] # Ensure the list users response contains the user that we just # created. # Fog::Radosgw[:provisioning].list_users.body.select { |x| x['email'] == email }.first end tests('successfully lists users containing no disabled users').returns(nil) do # Create a user. # email, name = "user_listing_without_disabled_users_test_#{current_timestamp}@example.com", "Fog User 8" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] # Disable that user. # Fog::Radosgw[:provisioning].disable_user(user_id) # Ensure the list users response does not contain the user that we # just created and disabled. # Fog::Radosgw[:provisioning].list_users(:suspended => 0).body.select { |x| x['email'] == email }.first end tests('successfully lists users containing disabled users').formats(user_format) do # Create a user. # email, name = "user_listing_with_disabled_users_test_#{current_timestamp}@example.com", "Fog User 9" user_id = Fog::Radosgw[:provisioning].create_user(name, name, email).body['user_id'] # Disable that user. # Fog::Radosgw[:provisioning].disable_user(user_id) # Ensure the list users response contains the user that we just # created and disabled. # Fog::Radosgw[:provisioning].list_users.body.select { |x| x['email'] == email }.first end end end fog-radosgw-0.0.4/tests/radosgw/requests/usage/0000755000004100000410000000000012511745105021552 5ustar www-datawww-datafog-radosgw-0.0.4/tests/radosgw/requests/usage/usage_tests.rb0000644000004100000410000000116412511745105024427 0ustar www-datawww-dataShindo.tests('Radosgw::Usage | usage requests', ['radosgw']) do @blank_usage_format = { 'entries' => [], 'summary' => [] } tests('Statistics retrieval with no data returned') do start_time = Time.now.utc + 86400 end_time = start_time + 86400 tests('via JSON').returns(@blank_usage_format) do Fog::Radosgw[:usage].get_usage(Fog.credentials[:radosgw_access_key_id], :types => [:access, :storage], :start_time => start_time, :end_time => end_time).body end end end fog-radosgw-0.0.4/tests/helpers/0000755000004100000410000000000012511745105016567 5ustar www-datawww-datafog-radosgw-0.0.4/tests/helpers/mock_helper.rb0000644000004100000410000000060112511745105021401 0ustar www-datawww-data# Use so you can run in mock mode from the command line # # FOG_MOCK=true fog if ENV["FOG_MOCK"] == "true" Fog.mock! end # if in mocked mode, fill in some fake credentials for us if Fog.mock? Fog.credentials = { :radosgw_access_key_id => 'radosgw_access_key_id', :radosgw_secret_access_key => 'radosgw_secret_access_key', }.merge(Fog.credentials) end fog-radosgw-0.0.4/CONTRIBUTORS.md0000644000004100000410000000035712511745105016247 0ustar www-datawww-data* Jon Kåre Hellan - port of Riak CS provider to Radosgw * Christopher Meiklejohn - Riak CS provider and the [contributors to Fog](https://github.com/fog/fog/blob/master/CONTRIBUTORS.md) fog-radosgw-0.0.4/LICENSE.md0000644000004100000410000000220112511745105015362 0ustar www-datawww-dataThe MIT License (MIT) Copyright (c) 2009-2014 [CONTRIBUTORS.md](https://github.com/fog/fog-radosgw/blob/master/CONTRIBUTORS.md) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fog-radosgw-0.0.4/.travis.yml0000644000004100000410000000066212511745105016100 0ustar www-datawww-datamatrix: include: - rvm: 1.8.7 gemfile: gemfiles/Gemfile.1.9.2- - rvm: 1.9.2 gemfile: gemfiles/Gemfile.1.9.2- - rvm: 1.9.3 gemfile: gemfiles/Gemfile.1.9.3+ - rvm: 2.0.0 gemfile: gemfiles/Gemfile.1.9.3+ - rvm: 2.1.4 gemfile: gemfiles/Gemfile.1.9.3+ env: COVERAGE=true - rvm: ree gemfile: gemfiles/Gemfile.1.9.2- - rvm: jruby gemfile: gemfiles/Gemfile.1.9.3+ fog-radosgw-0.0.4/lib/0000755000004100000410000000000012511745105014531 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/0000755000004100000410000000000012511745105015304 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/radosgw.rb0000644000004100000410000000110712511745105017276 0ustar www-datawww-datarequire 'fog/core' require 'fog/json' require 'fog/xml' module Fog module Radosgw autoload :Provisioning, File.expand_path('../radosgw/provisioning', __FILE__) autoload :Usage, File.expand_path('../radosgw/usage', __FILE__) autoload :MultipartUtils, File.expand_path('../radosgw/multipart_utils', __FILE__) autoload :UserUtils, File.expand_path('../radosgw/user_utils', __FILE__) autoload :Utils, File.expand_path('../radosgw/utils', __FILE__) extend Fog::Provider service(:provisioning, 'Provisioning') service(:usage, 'Usage') end end fog-radosgw-0.0.4/lib/fog/radosgw/0000755000004100000410000000000012511745105016752 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/radosgw/utils.rb0000644000004100000410000000507012511745105020441 0ustar www-datawww-datamodule Fog module Radosgw module Utils def configure_uri_options(options = {}) @host = options[:host] || 'localhost' @persistent = options[:persistent] || true @port = options[:port] || 8080 @scheme = options[:scheme] || 'http' end def radosgw_uri "#{@scheme}://#{@host}:#{@port}" end def escape(string) string.gsub(/([^a-zA-Z0-9_.\-~]+)/) { "%" + $1.unpack("H2" * $1.bytesize).join("%").upcase } end def signature(params, expires) headers = params[:headers] || {} string_to_sign = <<-DATA #{params[:method].to_s.upcase} #{headers['Content-MD5']} #{headers['Content-Type']} #{expires} DATA amz_headers, canonical_amz_headers = {}, '' for key, value in headers if key[0..5] == 'x-amz-' amz_headers[key] = value end end amz_headers = amz_headers.sort {|x, y| x[0] <=> y[0]} for key, value in amz_headers canonical_amz_headers << "#{key}:#{value}\n" end string_to_sign << canonical_amz_headers query_string = '' if params[:query] query_args = [] for key in params[:query].keys.sort if VALID_QUERY_KEYS.include?(key) value = params[:query][key] if value query_args << "#{key}=#{value}" else query_args << key end end end if query_args.any? query_string = '?' + query_args.join('&') end end canonical_path = (params[:path] || object_to_path(params[:object_name])).to_s canonical_path = '/' + canonical_path if canonical_path[0..0] != '/' if params[:bucket_name] canonical_resource = "/#{params[:bucket_name]}#{canonical_path}" else canonical_resource = canonical_path end canonical_resource << query_string string_to_sign << canonical_resource hmac = Fog::HMAC.new('sha1', @radosgw_secret_access_key) signed_string = hmac.sign(string_to_sign) Base64.encode64(signed_string).chomp! end def signed_headers(params) expires = Fog::Time.now.to_date_header auth = signature(params,expires) awskey = @radosgw_access_key_id headers = { 'Date' => expires, 'Authorization' => "AWS #{awskey}:#{auth}" } end end end end fog-radosgw-0.0.4/lib/fog/radosgw/usage.rb0000644000004100000410000000225612511745105020410 0ustar www-datawww-datarequire 'time' module Fog module Radosgw class Usage < Fog::Service requires :radosgw_access_key_id, :radosgw_secret_access_key recognizes :host, :path, :port, :scheme, :persistent request_path 'fog/radosgw/requests/usage' request :get_usage class Mock include Utils def self.data @data ||= Hash.new do |hash, key| hash[key] = {} end end def self.reset @data = nil end def initialize(options = {}) configure_uri_options(options) end def data self.class.data[radosgw_uri] end def reset_data self.class.data.delete(radosgw_uri) end end class Real include Utils def initialize(options = {}) configure_uri_options(options) @radosgw_access_key_id = options[:radosgw_access_key_id] @radosgw_secret_access_key = options[:radosgw_secret_access_key] @connection_options = options[:connection_options] || {} @persistent = options[:persistent] || false end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/0000755000004100000410000000000012511745105020625 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/0000755000004100000410000000000012511745105023353 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/get_user.rb0000644000004100000410000000377712511745105025533 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils include MultipartUtils def get_user(user_id) path = "admin/user" user_id = escape(user_id) query = "?uid=#{user_id}&format=json" params = { :method => 'GET', :path => path, } begin response = Excon.get("#{@scheme}://#{@host}/#{path}#{query}", :headers => signed_headers(params)) if !response.body.empty? case response.headers['Content-Type'] when 'application/json' response.body = Fog::JSON.decode(response.body) end end response rescue Excon::Errors::NotFound => e raise Fog::Radosgw::Provisioning::NoSuchUser.new rescue Excon::Errors::BadRequest => e raise Fog::Radosgw::Provisioning::ServiceUnavailable.new end end end class Mock def get_user(user_id) if value = data[user_id] Excon::Response.new.tap do |response| response.status = 200 response.headers['Content-Type'] = 'application/json' response.body = { "email" => value[:email], "user_id" => value[:user_id], "display_name" => value[:display_name], "suspended" => value[:suspended], "keys" => [ { "access_key" => "XXXXXXXXXXXXXXXXXXXX", "secret_key" => value[:secret_key], "user" => value[:user_id], } ], } end else Excon::Response.new.tap do |response| response.status = 404 response.headers['Content-Type'] = 'application/json' end end end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/create_user.rb0000644000004100000410000000516012511745105026203 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils def create_user(user_id, display_name, email, options = {}) if get_user(user_id).status != 404 raise Fog::Radosgw::Provisioning::UserAlreadyExists, "User with user_id #{user_id} already exists." end path = "admin/user" user_id = escape(user_id) display_name = escape(display_name) email = escape(email) query = "?uid=#{user_id}&display-name=#{display_name}&email=#{email}&format=json" params = { :method => 'PUT', :path => path, } begin response = Excon.put("#{@scheme}://#{@host}/#{path}#{query}", :headers => signed_headers(params)) if !response.body.empty? case response.headers['Content-Type'] when 'application/json' response.body = Fog::JSON.decode(response.body) end end response rescue Excon::Errors::Conflict => e raise Fog::Radosgw::Provisioning::UserAlreadyExists.new rescue Excon::Errors::BadRequest => e raise Fog::Radosgw::Provisioning::ServiceUnavailable.new end end end class Mock def user_exists?(user_id) data.find do |key, value| value[:user_id] == user_id end end def create_user(user_id, display_name, email, options = {}) if user_exists?(user_id) raise Fog::Radosgw::Provisioning::UserAlreadyExists, "User with user_id #{user_id} already exists." end secret_key = rand(1000).to_s data[user_id] = { :email => email, :user_id => user_id, :display_name => display_name, :suspended => 0, :secret_key => secret_key, } Excon::Response.new.tap do |response| response.status = 200 response.headers['Content-Type'] = 'application/json' response.body = { "email" => email, "user_id" => user_id, "display_name" => display_name, "suspended" => 0, "keys" => [ { "access_key" => "XXXXXXXXXXXXXXXXXXXX", "secret_key" => secret_key, "user" => user_id, } ], } end end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/disable_user.rb0000644000004100000410000000067012511745105026344 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils include UserUtils include MultipartUtils def disable_user(user_id) update_radosgw_user(user_id, { :suspended => 1 }) end end class Mock include UserUtils def disable_user(user_id) update_mock_user(user_id, { :suspended => 1 }) end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/user.json0000644000004100000410000000055312511745105025227 0ustar www-datawww-data{ "keys" : [ { "access_key" : "UPET5548S0CU9112ID33", "secret_key" : "aaw1AZ7+OlEEy6FrXkGy0oP2p4BvE/Eeg0L9ucmj", "user" : "Fog User" } ], "suspended" : 0, "swift_keys" : [], "subusers" : [], "user_id" : "Fog User", "caps" : [], "display_name" : "Fog User", "email" : "", "max_buckets" : 1000 } fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/enable_user.rb0000644000004100000410000000066612511745105026174 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils include UserUtils include MultipartUtils def enable_user(user_id) update_radosgw_user(user_id, { :suspended => 0 }) end end class Mock include UserUtils def enable_user(user_id) update_mock_user(user_id, { :suspended => 0 }) end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/list_users.rb0000644000004100000410000000417212511745105026100 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils include MultipartUtils def list_user_ids() path = "admin/metadata/user" query = "?format=json" params = { :method => 'GET', :path => path, } begin response = Excon.get("#{@scheme}://#{@host}/#{path}#{query}", :headers => signed_headers(params)) if !response.body.empty? case response.headers['Content-Type'] when 'application/json' response.body = Fog::JSON.decode(response.body) end else response.body = [] end response rescue Excon::Errors::BadRequest => e raise Fog::Radosgw::Provisioning::ServiceUnavailable.new end end def list_users(options = {}) response = list_user_ids response.body = response.body.map { |user_id| get_user(user_id).body } if options[:suspended] response.body = response.body.select { |user| user[:suspended] == options[:suspended] } end response end end class Mock def list_users(options = {}) filtered_data = options[:suspended] ? data.select { |key, value| value[:suspended] == options[:suspended] } : data Excon::Response.new.tap do |response| response.status = 200 response.body = filtered_data.map do |key, value| { "email" => value[:email], "display_name" => value[:user_id], "user_id" => value[:user_id], "suspended" => value[:suspended], "keys" => [ { "access_key" => "XXXXXXXXXXXXXXXXXXXX", "secret_key" => value[:secret_key], "user" => value[:user_id], } ], } end.compact end end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/delete_user.rb0000644000004100000410000000313512511745105026202 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils def delete_user(user_id) path = "admin/user" user_id = escape(user_id) query = "?uid=#{user_id}&format=json" params = { :method => 'DELETE', :path => path, } begin response = Excon.delete("#{@scheme}://#{@host}/#{path}#{query}", :headers => signed_headers(params)) if !response.body.empty? case response.headers['Content-Type'] when 'application/json' response.body = Fog::JSON.decode(response.body) end end response rescue Excon::Errors::NotFound => e raise Fog::Radosgw::Provisioning::NoSuchUser.new rescue Excon::Errors::BadRequest => e raise Fog::Radosgw::Provisioning::ServiceUnavailable.new end end end class Mock def user_exists?(user_id) data.find do |key, value| value[:user_id] == user_id end end def delete_user(user_id) if !user_exists?(user_id) raise Fog::Radosgw::Provisioning::NoSuchUser, "No user with user_id #{user_id} exists." end data.delete(user_id) Excon::Response.new.tap do |response| response.status = 200 response.headers['Content-Type'] = 'application/json' response.body = "" end end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/provisioning/update_user.rb0000644000004100000410000000064012511745105026220 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning class Real include Utils include UserUtils include MultipartUtils def update_user(key_id, user) update_radosgw_user(key_id, user) end end class Mock include UserUtils def update_user(key_id, user) update_mock_user(key_id, user) end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/requests/usage/0000755000004100000410000000000012511745105021731 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/radosgw/requests/usage/get_usage.rb0000644000004100000410000000315712511745105024227 0ustar www-datawww-datamodule Fog module Radosgw class Usage module Utils def sanitize_and_convert_time(time) fmt = '%Y-%m-%d %H:%M:%S' escape(time.strftime(fmt)) end end class Real include Utils def get_usage(access_key_id, options = {}) path = "admin/usage" t_now = Fog::Time.now start_time = sanitize_and_convert_time(options[:start_time] || t_now - 86400) end_time = sanitize_and_convert_time(options[:end_time] || t_now) query = "?format=json&start=#{start_time}&end=#{end_time}" params = { :method => 'GET', :path => path, } begin response = Excon.get("#{@scheme}://#{@host}/#{path}#{query}", :headers => signed_headers(params)) if !response.body.empty? case response.headers['Content-Type'] when 'application/json' response.body = Fog::JSON.decode(response.body) end end response rescue Excon::Errors::BadRequest => e raise Fog::Radosgw::Provisioning::ServiceUnavailable.new end end end class Mock include Utils def get_usage(access_key, options = {}) Excon::Response.new.tap do |response| response.status = 200 response.headers['Content-Type'] = 'application/json' response.body = { 'entries' => [], 'summary' => [] } end end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/multipart_utils/0000755000004100000410000000000012511745105022213 5ustar www-datawww-datafog-radosgw-0.0.4/lib/fog/radosgw/multipart_utils/headers.rb0000644000004100000410000000156112511745105024156 0ustar www-datawww-datarequire 'net/http' module Fog module Radosgw module MultipartUtils class Headers include Net::HTTPHeader def initialize initialize_http_header({}) end # Parse a single header line into its key and value # @param [String] chunk a single header line def self.parse(chunk) line = chunk.strip # thanks Net::HTTPResponse return [nil,nil] if chunk =~ /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in m = /\A([^:]+):\s*/.match(line) [m[1], m.post_match] rescue [nil, nil] end # Parses a header line and adds it to the header collection # @param [String] chunk a single header line def parse(chunk) key, value = self.class.parse(chunk) add_field(key, value) if key && value end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/version.rb0000644000004100000410000000007412511745105020765 0ustar www-datawww-datamodule Fog module Radosgw VERSION = "0.0.4" end end fog-radosgw-0.0.4/lib/fog/radosgw/user_utils.rb0000644000004100000410000000263612511745105021504 0ustar www-datawww-datamodule Fog module Radosgw module UserUtils def update_radosgw_user(user_id, user) path = "admin/user" user_id = escape(user_id) params = { :method => 'POST', :path => path, } query = "?uid=#{user_id}&format=json&suspended=#{user[:suspended]}" begin response = Excon.post("#{@scheme}://#{@host}/#{path}#{query}", :headers => signed_headers(params)) if !response.body.empty? case response.headers['Content-Type'] when 'application/json' response.body = Fog::JSON.decode(response.body) end end response rescue Excon::Errors::NotFound => e raise Fog::Radosgw::Provisioning::NoSuchUser.new rescue Excon::Errors::BadRequest => e raise Fog::Radosgw::Provisioning::ServiceUnavailable.new end end def update_mock_user(user_id, user) if data[user_id] if suspended = user[:suspended] data[user_id][:suspended] = suspended end Excon::Response.new.tap do |response| response.status = 200 response.body = data[user_id] end else Excon::Response.new.tap do |response| response.status = 403 end end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/provisioning.rb0000644000004100000410000000514012511745105022025 0ustar www-datawww-datamodule Fog module Radosgw class Provisioning < Fog::Service class UserAlreadyExists < Fog::Radosgw::Provisioning::Error; end class NoSuchUser < Fog::Radosgw::Provisioning::Error; end class ServiceUnavailable < Fog::Radosgw::Provisioning::Error; end requires :radosgw_access_key_id, :radosgw_secret_access_key recognizes :host, :path, :port, :scheme, :persistent, :path_style request_path 'fog/radosgw/requests/provisioning' request :create_user request :delete_user request :update_user request :disable_user request :enable_user request :list_users request :get_user class Mock include Utils def self.data @data ||= Hash.new({}) end def self.reset @data = nil end def initialize(options = {}) configure_uri_options(options) end def data self.class.data[radosgw_uri] end def reset_data self.class.data.delete(radosgw_uri) end end class Real include Utils def initialize(options = {}) configure_uri_options(options) @radosgw_access_key_id = options[:radosgw_access_key_id] @radosgw_secret_access_key = options[:radosgw_secret_access_key] @connection_options = options[:connection_options] || {} @persistent = options[:persistent] || false @path_style = options[:path_style] || false @connection = Fog::XML::Connection.new(radosgw_uri, @persistent, @connection_options) end def request(params, parse_response = true, &block) begin response = @connection.request(params.merge({ :host => @host, :path => "#{@path}/#{params[:path]}", }), &block) rescue Excon::Errors::HTTPStatusError => error if match = error.message.match(/(.*?)<\/Code>(?:.*(.*?)<\/Message>)?/m) case match[1] when 'UserAlreadyExists' raise Fog::Radosgw::Provisioning.const_get(match[1]).new when 'ServiceUnavailable' raise Fog::Radosgw::Provisioning.const_get(match[1]).new else raise error end else raise error end end if !response.body.empty? && parse_response response.body = Fog::JSON.decode(response.body) end response end end end end end fog-radosgw-0.0.4/lib/fog/radosgw/multipart_utils.rb0000644000004100000410000000240712511745105022543 0ustar www-datawww-datamodule Fog module Radosgw module MultipartUtils autoload :Headers, File.expand_path('../multipart_utils/headers', __FILE__) def parse(data, boundary) contents = data.match(end_boundary_regex(boundary)).pre_match rescue "" contents.split(inner_boundary_regex(boundary)).reject(&:empty?).map do |part| parse_multipart_section(part) end.compact end def extract_boundary(header_string) $1 if header_string =~ /boundary=([A-Za-z0-9\'()+_,-.\/:=?]+)/ end private def end_boundary_regex(boundary) /\r?\n--#{Regexp.escape(boundary)}--\r?\n?/ end def inner_boundary_regex(boundary) /\r?\n--#{Regexp.escape(boundary)}\r?\n/ end def parse_multipart_section(part) headers = Headers.new if md = part.match(/\r?\n\r?\n/) body = md.post_match md.pre_match.split(/\r?\n/).each do |line| headers.parse(line) end if headers["content-type"] =~ /multipart\/mixed/ boundary = extract_boundary(headers.to_hash["content-type"].first) parse(body, boundary) else {:headers => headers.to_hash, :body => body} end end end end end end fog-radosgw-0.0.4/gemfiles/0000755000004100000410000000000012511745105015556 5ustar www-datawww-datafog-radosgw-0.0.4/gemfiles/Gemfile.1.9.2-0000644000004100000410000000021012511745105017565 0ustar www-datawww-datasource :rubygems gem 'mime-types', '< 2.0' gem 'nokogiri', '< 1.6' gem 'rest-client', '~> 1.6.8' gem 'fog-core' gemspec :path => '../'fog-radosgw-0.0.4/gemfiles/Gemfile.1.9.3+0000644000004100000410000000016712511745105017577 0ustar www-datawww-datasource :rubygems gem 'activesupport', '>= 3.0', '< 4' gem 'mime-types', '< 2.0' gem 'fog-core' gemspec :path => '../'fog-radosgw-0.0.4/metadata.yml0000644000004100000410000001031512511745105016266 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: fog-radosgw version: !ruby/object:Gem::Version version: 0.0.4 platform: ruby authors: - Jon Kåre Hellan autorequire: bindir: bin cert_chain: [] date: 2015-04-06 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: fog-json requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: fog-xml requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 0.0.1 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 0.0.1 - !ruby/object:Gem::Dependency name: fog-core requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.21.0 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.21.0 - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: yard requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: shindo requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' description: Fog backend for provisioning users on Ceph Radosgw - the Swift and S3 compatible REST API for Ceph. email: hellan@acm.org executables: [] extensions: [] extra_rdoc_files: - README.md - LICENSE.md files: - ".gitignore" - ".travis.yml" - CONTRIBUTING.md - CONTRIBUTORS.md - Gemfile - LICENSE.md - README.md - Rakefile - fog-radosgw.gemspec - gemfiles/Gemfile.1.9.2- - gemfiles/Gemfile.1.9.3+ - lib/fog/radosgw.rb - lib/fog/radosgw/multipart_utils.rb - lib/fog/radosgw/multipart_utils/headers.rb - lib/fog/radosgw/provisioning.rb - lib/fog/radosgw/requests/provisioning/create_user.rb - lib/fog/radosgw/requests/provisioning/delete_user.rb - lib/fog/radosgw/requests/provisioning/disable_user.rb - lib/fog/radosgw/requests/provisioning/enable_user.rb - lib/fog/radosgw/requests/provisioning/get_user.rb - lib/fog/radosgw/requests/provisioning/list_users.rb - lib/fog/radosgw/requests/provisioning/update_user.rb - lib/fog/radosgw/requests/provisioning/user.json - lib/fog/radosgw/requests/usage/get_usage.rb - lib/fog/radosgw/usage.rb - lib/fog/radosgw/user_utils.rb - lib/fog/radosgw/utils.rb - lib/fog/radosgw/version.rb - tests/helper.rb - tests/helpers/mock_helper.rb - tests/radosgw/helper.rb - tests/radosgw/requests/provisioning/provisioning_tests.rb - tests/radosgw/requests/usage/usage_tests.rb homepage: https://github.com/fog/fog-radosgw licenses: - MIT metadata: {} post_install_message: rdoc_options: - "--charset=UTF-8" require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.2.2 signing_key: specification_version: 4 summary: Fog backend for provisioning Ceph Radosgw. test_files: [] has_rdoc: fog-radosgw-0.0.4/.gitignore0000644000004100000410000000030112511745105015745 0ustar www-datawww-data*~ *.gem *.rbc .rbenv .rvmrc .ruby-gemset .ruby-version .bundle .DS_Store .idea .yardoc /tests/.fog bin/* !bin/fog .fog coverage doc/* docs/_site/* Gemfile.lock gemfiles/*.lock yardoc pkg tags fog-radosgw-0.0.4/CONTRIBUTING.md0000644000004100000410000000154712511745105016223 0ustar www-datawww-data## Getting Involved 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. ### Coding * Pick a task: * Offer feedback on open [pull requests](https://github.com/fog/fog-radosgw/pulls). * Review open [issues](https://github.com/fog/fog-radosgw/issues) for things to help on. * [Create an issue](https://github.com/fog/fog-radosgw/issues/new) to start a discussion on additions or features. * Fork the project, add your changes and tests to cover them in a topic branch. * Commit your changes and rebase against `fog/fog-radosgw` to ensure everything is up to date. * [Submit a pull request](https://github.com/fog/fog-radosgw/compare/) ### Non-Coding * Offer feedback on open [issues](https://github.com/fog/fog-radosgw/issues). * Organize or volunteer at events.fog-radosgw-0.0.4/README.md0000644000004100000410000000413212511745105015242 0ustar www-datawww-data# Fog::Radosgw [![Gem Version](https://badge.fury.io/rb/fog-radosgw.svg)](http://badge.fury.io/rb/fog-radosgw) [![Build Status](https://travis-ci.org/fog/fog-radosgw.svg?branch=master)](https://travis-ci.org/fog/fog-radosgw) [![Dependency Status](https://gemnasium.com/fog/fog-radosgw.svg)](https://gemnasium.com/fog/fog-radosgw) [![Coverage Status](https://img.shields.io/coveralls/fog/fog-radosgw.svg)](https://coveralls.io/r/fog/fog-radosgw) [![Code Climate](https://codeclimate.com/github/fog/fog-radosgw.png)](https://codeclimate.com/github/fog/fog-radosgw) [![Stories in Ready](https://badge.waffle.io/fog/fog-radosgw.png?label=ready&title=Ready)](https://waffle.io/fog/fog-radosgw) Fog backend for provisioning Ceph Radosgw - the Swift and S3 compatible REST API for Ceph. Currently, the gem only supports the S3 API, not Swift. Based on the Riak CS backend. ## Installation Add this line to your application's Gemfile: gem 'fog-radosgw' And then execute: $ bundle Or install it yourself as: $ gem install fog-radosgw ## Usage Example: require 'fog/radosgw' provision_client = Fog::Radosgw::Provisioning.new( host: 'objects.example.com', radosgw_access_key_id: 'CHIA1GEE0EIJ9OHSAIK6', radosgw_secret_access_key: 'IFooJ7airaebaele6baihaiw2fequuto9Foh7Sei' ) response = provision_client.create_user('fog', 'Fog User', 'fog@example.com') userkey = response.body['keys'][0]['access_key'] usersecret = response.body['keys'][0]['secret_key'] ## Tests Mock tests: bundle exec rake mock[radosgw] Live tests: bundle exec rake live[radosgw] To run live tests, you have to place credentials in `tests/.fog`, e.g.: default: host: objects.example.com radosgw_access_key_id: CHIA1GEE0EIJ9OHSAIK6 radosgw_secret_access_key: IFooJ7airaebaele6baihaiw2fequuto9Foh7Sei ## Contributing Please refer to the [CONTRIBUTING.md](https://github.com/fog/fog/blob/master/CONTRIBUTING.md) page for the main Fog project. ## License Please refer to [LICENSE.md](https://github.com/fog/fog-radosgw/blob/master/LICENSE.md). fog-radosgw-0.0.4/fog-radosgw.gemspec0000644000004100000410000000216112511745105017547 0ustar www-datawww-data# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'fog/radosgw/version' Gem::Specification.new do |s| s.name = 'fog-radosgw' s.version = Fog::Radosgw::VERSION s.authors = %q(Jon Kåre Hellan) s.email = %q(hellan@acm.org) s.summary = %q{Fog backend for provisioning Ceph Radosgw.} s.description = %q{Fog backend for provisioning users on Ceph Radosgw - the Swift and S3 compatible REST API for Ceph.} s.homepage = 'https://github.com/fog/fog-radosgw' s.license = 'MIT' s.files = `git ls-files -z`.split("\x0") s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } s.test_files = s.files.grep(%r{^(test|spec|features)/}) s.require_paths = %w(lib) s.rdoc_options = ["--charset=UTF-8"] s.extra_rdoc_files = %w[README.md LICENSE.md] s.add_dependency 'fog-json' s.add_dependency 'fog-xml', '>=0.0.1' s.add_dependency 'fog-core', '>=1.21.0' s.add_development_dependency 'rake' s.add_development_dependency 'yard' s.add_development_dependency 'shindo' end