Commit f2088a55 authored by Praveen Arimbrathodiyil's avatar Praveen Arimbrathodiyil
Browse files

Imported Upstream version 1.22.0+gh

parent c32a87c8
* Anatol <anatol.pomozov@gmail.com>
* Chris Johnson <wchrisjohnson@gmail.com>
* Dominic Cleal <dcleal@redhat.com>
* Evan Light <evan@tripledogdare.net> * Evan Light <evan@tripledogdare.net>
* Paul Thornthwaite <paul@brightbox.co.uk>
* Paul Thornthwaite <tokengeek@gmail.com> * Paul Thornthwaite <tokengeek@gmail.com>
* Wesley Beary <geemus+github@gmail.com> * Wesley Beary <geemus+github@gmail.com>
* geemus <geemus@gmail.com> * geemus <geemus@gmail.com>
\ No newline at end of file * mountkin <moutkin@gmail.com>
\ No newline at end of file
source 'https://rubygems.org' source 'https://rubygems.org'
# Specify your gem's dependencies in fog-core.gemspec
gemspec gemspec
...@@ -4,6 +4,7 @@ gem 'nokogiri', '~>1.5.11' ...@@ -4,6 +4,7 @@ gem 'nokogiri', '~>1.5.11'
gem 'mime-types', '~>1.16' gem 'mime-types', '~>1.16'
group :development, :test do group :development, :test do
gem 'rake', '~> 10.1.0'
# This is here because gemspec doesn't support require: false # This is here because gemspec doesn't support require: false
gem 'coveralls', :require => false gem 'coveralls', :require => false
end end
......
require 'bundler/setup' require 'bundler/setup'
task :travis => ['test:travis', 'coveralls_push_workaround'] task :travis => ['test:travis', 'coveralls_push_workaround']
task :default => [:test]
require "rake/testtask"
require "tasks/test_task"
Fog::Rake::TestTask.new Rake::TestTask.new do |t|
t.libs << "lib"
t.libs << "spec"
t.pattern = "spec/**/*_spec.rb"
end
namespace :test do namespace :test do
mock = 'true' || ENV['FOG_MOCK'] mock = 'true' || ENV['FOG_MOCK']
task :travis do task :travis do
# jruby coveralls causes an OOM in travis # jruby coveralls causes an OOM in travis
ENV['COVERAGE'] = 'false' if RUBY_PLATFORM == 'java' ENV['COVERAGE'] = 'false' if RUBY_PLATFORM == 'java'
sh("export FOG_MOCK=#{mock} && bundle exec shindont") sh("export FOG_MOCK=#{mock} && rake")
end end
end end
......
1.21.1 03/18/2014 3a803405ba60ded421f4bd14677cd3c76cb7e6ab
==========================================================
remove json/xml modules and code
add travis/coveralls
update from upstream
bump/loosen excon dependency
...@@ -10,27 +10,26 @@ Gem::Specification.new do |spec| ...@@ -10,27 +10,26 @@ Gem::Specification.new do |spec|
spec.email = ["evan@tripledogdare.net", "geemus@gmail.com"] spec.email = ["evan@tripledogdare.net", "geemus@gmail.com"]
spec.summary = %q{Shared classes and tests for fog providers and services.} spec.summary = %q{Shared classes and tests for fog providers and services.}
spec.description = %q{Shared classes and tests for fog providers and services.} spec.description = %q{Shared classes and tests for fog providers and services.}
spec.homepage = "" spec.homepage = "https://github.com/fog/fog-core"
spec.license = "MIT" spec.license = "MIT"
spec.files = Dir.glob(File.join("lib", "**", "*.rb")) spec.files = `git ls-files`.split($/)
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"] spec.require_paths = ["lib"]
spec.add_dependency('builder') spec.add_dependency('builder')
spec.add_dependency('excon', '~>0.32') spec.add_dependency('excon', '~>0.33')
spec.add_dependency('formatador', '~>0.2.0') spec.add_dependency('formatador', '~>0.2')
spec.add_dependency('mime-types') spec.add_dependency('mime-types')
spec.add_dependency('net-scp', '~>1.1') spec.add_dependency('net-scp', '~>1.1')
spec.add_dependency('net-ssh', '>=2.1.3') spec.add_dependency('net-ssh', '>=2.1.3')
## List your development dependencies here. Development dependencies are
## those that are only needed during development
spec.add_development_dependency('rake') spec.add_development_dependency('rake')
spec.add_development_dependency('yard') spec.add_development_dependency('yard')
spec.add_development_dependency('thor') spec.add_development_dependency('thor')
spec.add_development_dependency('shindo', '~>0.3.4') spec.add_development_dependency('minitest')
spec.add_development_dependency('minitest-stub-const')
spec.add_development_dependency('pry') spec.add_development_dependency('pry')
spec.add_development_dependency('coveralls') spec.add_development_dependency('coveralls')
end end
...@@ -55,9 +55,14 @@ module Fog ...@@ -55,9 +55,14 @@ module Fog
else else
if self.providers.include?(provider) if self.providers.include?(provider)
require "fog/#{provider}/compute" require "fog/#{provider}/compute"
return Fog::Compute.const_get(Fog.providers[provider]).new(attributes) begin
Fog::Compute.const_get(Fog.providers[provider])
rescue
Fog::const_get(Fog.providers[provider])::Compute
end.new(attributes)
else
raise ArgumentError.new("#{provider} is not a recognized compute provider")
end end
raise ArgumentError.new("#{provider} is not a recognized compute provider")
end end
end end
......
...@@ -28,9 +28,9 @@ require 'fog/core/service' ...@@ -28,9 +28,9 @@ require 'fog/core/service'
require 'fog/core/ssh' require 'fog/core/ssh'
require 'fog/core/scp' require 'fog/core/scp'
require 'fog/core/time' require 'fog/core/time'
require 'fog/core/utils'
require 'fog/core/wait_for' require 'fog/core/wait_for'
require 'fog/core/wait_for_defaults' require 'fog/core/wait_for_defaults'
require 'fog/core/class_from_string'
require 'fog/core/uuid' require 'fog/core/uuid'
# service wrappers # service wrappers
......
module Fog
# get class by string or nil
def self.class_from_string classname, defaultpath=""
if classname and classname.is_a? String then
chain = classname.split("::")
klass = Kernel
chain.each do |klass_string|
klass = klass.const_get klass_string
end
if klass.is_a? Class then
klass
elsif defaultpath != nil then
Fog.class_from_string((defaultpath.split("::")+chain).join("::"), nil)
else
nil
end
elsif classname and classname.is_a? Class then
classname
else
nil
end
rescue NameError
defaultpath != nil ? Fog.class_from_string((defaultpath.split("::")+chain).join("::"), nil) : nil
end
end
...@@ -3,19 +3,49 @@ require 'yaml' ...@@ -3,19 +3,49 @@ require 'yaml'
module Fog module Fog
require 'fog/core/deprecation' require 'fog/core/deprecation'
# Sets the global configuration up from a Hash rather than using background loading from a file
#
# @example
# Fog.credentials = {
# :default => {
# :example_url => "https://example.com/"
# :example_username => "bob",
# :example_password => "obo"
# },
# :production => {
# :example_username => "bob",
# :example_password => "obo"
# }
# }
#
# @return [Hash] The newly assigned credentials
def self.credentials=(new_credentials)
@credentials = new_credentials
end
# Assign a new credential to use from configuration file # Assign a new credential to use from configuration file
# @param [String, Symbol] new_credential name of new credential to use #
# @ return [Symbol] name of the new credential # @param [String, Symbol] new_credential name of new credential to use
# @return [Symbol] name of the new credential
def self.credential=(new_credential) def self.credential=(new_credential)
@credentials = nil @credentials = nil
@credential = new_credential && new_credential.to_sym @credential = new_credential && new_credential.to_sym
end end
# @return [String, Symbol] The credential to use in Fog # This is the named credential from amongst the configuration file being used or +:default+
#
# @note This can be set using the +FOG_CREDENTIAL+ environment variable
#
# @return [Symbol] The credential to use in Fog
def self.credential def self.credential
@credential ||= ( ENV["FOG_CREDENTIAL"] && ENV["FOG_CREDENTIAL"].to_sym ) || :default @credential ||= ( ENV["FOG_CREDENTIAL"] && ENV["FOG_CREDENTIAL"].to_sym ) || :default
end end
# This returns the path to the configuration file being used globally to look for sets of
# credentials
#
# @note This can be set using the +FOG_RC+ environment variable or defaults to +$HOME/.fog+
#
# @return [String] The path for configuration_file # @return [String] The path for configuration_file
def self.credentials_path def self.credentials_path
@credential_path ||= begin @credential_path ||= begin
...@@ -35,9 +65,9 @@ module Fog ...@@ -35,9 +65,9 @@ module Fog
# @return [Hash] The credentials pulled from the configuration file # @return [Hash] The credentials pulled from the configuration file
# @raise [LoadError] Configuration unavailable in configuration file # @raise [LoadError] Configuration unavailable in configuration file
def self.credentials def self.credentials
@credentials ||= begin @credentials ||= begin
if credentials_path && File.exists?(credentials_path) if credentials_path && File.exists?(credentials_path)
credentials = self.symbolize_credentials(YAML.load_file(credentials_path)) credentials = Fog::Core::Utils.prepare_service_settings(YAML.load_file(credentials_path))
(credentials && credentials[credential]) || Fog::Errors.missing_credentials (credentials && credentials[credential]) || Fog::Errors.missing_credentials
else else
{} {}
...@@ -45,26 +75,15 @@ module Fog ...@@ -45,26 +75,15 @@ module Fog
end end
end end
# @return [Hash] The newly assigned credentials # @deprecated Don't use!
def self.credentials=(new_credentials) # @param [Object] key
@credentials = new_credentials # @return [true] if key == :headers
end
def self.symbolize_credential?(key) def self.symbolize_credential?(key)
![:headers].include?(key) ![:headers].include?(key)
end end
def self.symbolize_credentials(args) # @deprecated Use {Fog::Core::Utils.prepare_service_settings} instead
if args.is_a? Hash def self.symbolize_credentials(hash)
copy = Array.new Fog::Core::Utils.prepare_service_settings(hash)
args.each do |key, value|
obj = symbolize_credential?(key) ? self.symbolize_credentials(value) : value
copy.push(key.to_sym, obj)
end
Hash[*copy]
else
args
end
end end
end end
...@@ -12,12 +12,13 @@ module Fog ...@@ -12,12 +12,13 @@ module Fog
def initialize(new_attributes = {}) def initialize(new_attributes = {})
# TODO Remove compatibility with old connection option # TODO Remove compatibility with old connection option
@service = new_attributes.delete(:service) attribs = new_attributes.clone
if @service.nil? && new_attributes[:connection] @service = attribs.delete(:service)
if @service.nil? && attribs[:connection]
Fog::Logger.deprecation("Passing :connection option is deprecated, use :service instead [light_black](#{caller.first})[/]") Fog::Logger.deprecation("Passing :connection option is deprecated, use :service instead [light_black](#{caller.first})[/]")
@service = new_attributes[:connection] @service = attribs[:connection]
end end
merge_attributes(new_attributes) merge_attributes(attribs)
end end
def inspect def inspect
......
module Fog require "fog/core/utils"
module Fog
def self.services def self.services
@services ||= {} @services ||= {}
end end
class Service class Service
class Error < Fog::Errors::Error; end class Error < Fog::Errors::Error; end
class NotFound < Fog::Errors::NotFound; end class NotFound < Fog::Errors::NotFound; end
...@@ -16,7 +16,6 @@ module Fog ...@@ -16,7 +16,6 @@ module Fog
end end
module Collections module Collections
def collections def collections
service.collections service.collections
end end
...@@ -28,11 +27,9 @@ module Fog ...@@ -28,11 +27,9 @@ module Fog
def requests def requests
service.requests service.requests
end end
end end
class << self class << self
def inherited(child) def inherited(child)
child.class_eval <<-EOS, __FILE__, __LINE__ child.class_eval <<-EOS, __FILE__, __LINE__
class Error < Fog::Service::Error; end class Error < Fog::Service::Error; end
...@@ -52,27 +49,78 @@ module Fog ...@@ -52,27 +49,78 @@ module Fog
EOS EOS
end end
def new(options={}) # {Fog::Service} is (unfortunately) both a builder class and the subclass for any fog service.
options = Fog.symbolize_credentials(options) #
options = fetch_credentials(options).merge(options) # Creating a {new} instance using the builder will return either an instance of
validate_options(options) # +Fog::<Service>::<Provider>::Real+ or +Fog::<Service>::<Provider>::Mock+ based on the value
coerce_options(options) # of {Fog.mock?} when the builder is used.
#
# Each provider can require or recognize different settings (often prefixed with the providers
# name). These settings map to keys in the +~/.fog+ file.
#
# Settings can be passed as either a Hash or an object that responds to +config_service?+ with
# +true+. This object will be passed through unchanged to the +Real+ or +Mock+ service that is
# created. It is up to providers to adapt services to use these config objects.
#
# @abstract Subclass and implement real or mock code
#
# @param [Hash,#config_service?] config
# Settings or an object used to build a service instance
# @option config [Hash] :headers
# Passed to the underlying {Fog::Core::Connection} unchanged
#
# @return [Fog::Service::Provider::Real] if created while mocking is disabled
# @return [Fog::Service::Provider::Mock] if created while mocking is enabled
# @raise [ArgumentError] if a setting required by the provider was not passed in
#
# @example Minimal options (dependent on ~/.fog)
# @service = Fog::Compute::Example.new # => <#Fog::Compute::Example::Real>
#
# @example Mocked service
# Fog.mock!
# @service = Fog::Compute::Example.new # => <#Fog::Compute::Example::Mock>
#
# @example Configured using many options (options merged into ~/.fog)
# @options = {
# :example_username => "fog",
# :example_password => "fog"
# }
# @service = Fog::Compute::Example.new(@options)
#
# @example Configured using external config object (~/.fog ignored completely)
# @config = Fog::Example::Config.new(...)
# @service = Fog::Compute::Example.new(@config)
#
def new(config = {})
if config.respond_to?(:config_service?) && config.config_service?
cleaned_settings = config
else
cleaned_settings = handle_settings(config)
end
setup_requirements setup_requirements
svc = service
if Fog.mocking? if Fog.mocking?
service::Mock.send(:include, service::Collections) while svc != Fog::Service
service::Mock.new(options) service::Mock.send(:include, svc::Collections)
svc = svc.superclass
end
service::Mock.new(cleaned_settings)
else else
service::Real.send(:include, service::Collections) while svc != Fog::Service
service::Real.send(:include, svc::Collections)
svc = svc.superclass
end
service::Real.send(:include, service::NoLeakInspector) service::Real.send(:include, service::NoLeakInspector)
service::Real.new(options) service::Real.new(cleaned_settings)
end end
end end
# @deprecated
def fetch_credentials(options) def fetch_credentials(options)
# attempt to load credentials from config file # attempt to load credentials from config file
begin begin
Fog.credentials.reject {|key, value| !(recognized | requirements).include?(key)} Fog.credentials.reject { |key, value| !(recognized | requirements).include?(key) }
rescue LoadError rescue LoadError
# if there are no configured credentials, do nothing # if there are no configured credentials, do nothing
{} {}
...@@ -86,34 +134,14 @@ module Fog ...@@ -86,34 +134,14 @@ module Fog
@required ||= false @required ||= false
unless @required unless @required
for collection in collections require_models
require [@model_path, collection].join('/') require_collections_and_define
constant = collection.to_s.split('_').map {|characters| characters[0...1].upcase << characters[1..-1]}.join('') require_requests_and_mock
service::Collections.module_eval <<-EOS, __FILE__, __LINE__
def #{collection}(attributes = {})
#{service}::#{constant}.new({:service => self}.merge(attributes))
end
EOS
end
for model in models
require [@model_path, model].join('/')
end
for request in requests
require [@request_path, request].join('/')
if service::Mock.method_defined?(request)
mocked_requests << request
else
service::Mock.module_eval <<-EOS, __FILE__, __LINE__
def #{request}(*args)
Fog::Mock.not_implemented
end
EOS
end
end
@required = true @required = true
end end
end end
# @note This path is used to require model and collection files
def model_path(new_path) def model_path(new_path)
@model_path = new_path @model_path = new_path
end end
...@@ -204,6 +232,7 @@ module Fog ...@@ -204,6 +232,7 @@ module Fog
end end
end end
missing = requirements - keys missing = requirements - keys
unless missing.empty? unless missing.empty?
raise ArgumentError, "Missing required arguments: #{missing.join(', ')}" raise ArgumentError, "Missing required arguments: #{missing.join(', ')}"
end end
...@@ -216,8 +245,66 @@ module Fog ...@@ -216,8 +245,66 @@ module Fog
end end
end end
end private
# This is the original way service settings were handled. Settings from +~/.fog+ were merged
# together with the passed options, keys are turned to symbols and coerced into Boolean or
# Fixnums.
#
# If the class has declared any required settings then {ArgumentError} will be raised.
#
# Any setting that is not whitelisted will cause a warning to be output.
#
def handle_settings(settings)
combined_settings = fetch_credentials(settings).merge(settings)
prepared_settings = Fog::Core::Utils.prepare_service_settings(combined_settings)
validate_options(prepared_settings)
coerce_options(prepared_settings)
end
# This will attempt to require all model files declared by the service using fog's DSL
def require_models
models.each do |model|
require File.join(@model_path, model.to_s)
end
end
def require_collections_and_define
collections.each do |collection|
require File.join(@model_path, collection.to_s)
constant = camel_case_collection_name(collection)
service::Collections.module_eval <<-EOS, __FILE__, __LINE__
def #{collection}(attributes = {})
#{service}::#{constant}.new({ :service => self }.merge(attributes))
end
EOS
end
end
# This converts names of collections from Symbols as defined in the DSL (+:database_server+)
# into CamelCase version (+DatabaseServer+) for metaprogramming skulduggery.
#
# @param [String,Symbol] collection The name of the collection broken with underscores
# @return [String] in camel case
def camel_case_collection_name(collection)
collection.to_s.split('_').map(&:capitalize).join
end
# This will attempt to require all request files declared in the service using fog's DSL
def require_requests_and_mock
requests.each do |request|
require File.join(@request_path, request.to_s)
if service::Mock.method_defined?(request)
mocked_requests << request
else
service::Mock.module_eval <<-EOS, __FILE__, __LINE__
def #{request}(*args)
Fog::Mock.not_implemented
end
EOS
end
end
end