Merge pull request #2663 from fog/use_fog_core

Changes to rely on fog-core
This commit is contained in:
Evan Light 2014-02-12 11:55:48 -05:00
commit 814cdb0e51
27 changed files with 15 additions and 1845 deletions

View File

@ -5,4 +5,5 @@ group :development, :test do
gem 'coveralls', :require => false
end
gem "fog-core", :github => "fog/fog-core", :branch => "master"
gemspec

View File

@ -41,6 +41,7 @@ Gem::Specification.new do |s|
## List your runtime dependencies here. Runtime dependencies are those
## that are needed for an end user to actually USE your code.
s.add_dependency("fog-core")
s.add_dependency('builder')
s.add_dependency('excon', '~>0.31.0')
s.add_dependency('formatador', '~>0.2.0')

View File

@ -3,6 +3,19 @@
__LIB_DIR__ = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift __LIB_DIR__ unless $LOAD_PATH.include?(__LIB_DIR__)
# Use core
require 'fog/core'
# Previously treated as "core"
# data exchange specific (to be extracted and used on a per provider basis)
require 'fog/xml'
require 'fog/json'
require 'fog/core/parser'
# deprecation wrappers (XML wrapped version)
require 'fog/core/deprecated/connection'
require 'fog/core/deprecated_connection_accessors'
# any one of these can be required separately.
# they all depend on fog/core for shared functionality.
require 'fog/atmos'

View File

@ -1,23 +0,0 @@
module Fog
module CDN
def self.[](provider)
self.new(:provider => provider)
end
def self.new(attributes)
attributes = attributes.dup # prevent delete from having side effects
provider = attributes.delete(:provider).to_s.downcase.to_sym
if self.providers.include?(provider)
require "fog/#{provider}/cdn"
return Fog::CDN.const_get(Fog.providers[provider]).new(attributes)
end
raise ArgumentError.new("#{provider} is not a recognized cdn provider")
end
def self.providers
Fog.services[:cdn]
end
end
end

View File

@ -1,80 +0,0 @@
module Fog
module Compute
def self.[](provider)
self.new(:provider => provider)
end
def self.new(attributes)
attributes = attributes.dup # prevent delete from having side effects
provider = attributes.delete(:provider).to_s.downcase.to_sym
case provider
when :gogrid
require 'fog/go_grid/compute'
Fog::Compute::GoGrid.new(attributes)
when :hp
version = attributes.delete(:version)
version = version.to_s.downcase.to_sym unless version.nil?
if version == :v2
require 'fog/hp/compute_v2'
Fog::Compute::HPV2.new(attributes)
else
Fog::Logger.deprecation "HP Cloud Compute V1 service will be soon deprecated. Please use `:version => v2` attribute to use HP Cloud Compute V2 service."
require 'fog/hp/compute'
Fog::Compute::HP.new(attributes)
end
when :new_servers
require 'fog/bare_metal_cloud/compute'
Fog::Logger.deprecation "`new_servers` is deprecated. Please use `bare_metal_cloud` instead."
Fog::Compute::BareMetalCloud.new(attributes)
when :baremetalcloud
require 'fog/bare_metal_cloud/compute'
Fog::Compute::BareMetalCloud.new(attributes)
when :rackspace
version = attributes.delete(:version)
version = version.to_s.downcase.to_sym unless version.nil?
if version == :v1
Fog::Logger.deprecation "First Gen Cloud Servers are deprecated. Please use `:version => :v2` attribute to use Next Gen Cloud Servers."
require 'fog/rackspace/compute'
Fog::Compute::Rackspace.new(attributes)
else
require 'fog/rackspace/compute_v2'
Fog::Compute::RackspaceV2.new(attributes)
end
when :stormondemand
require 'fog/storm_on_demand/compute'
Fog::Compute::StormOnDemand.new(attributes)
when :vcloud
require 'fog/vcloud/compute'
Fog::Vcloud::Compute.new(attributes)
when :vclouddirector
require 'fog/vcloud_director/compute'
Fog::Compute::VcloudDirector.new(attributes)
else
if self.providers.include?(provider)
require "fog/#{provider}/compute"
return Fog::Compute.const_get(Fog.providers[provider]).new(attributes)
end
raise ArgumentError.new("#{provider} is not a recognized compute provider")
end
end
def self.providers
Fog.services[:compute]
end
def self.servers
servers = []
for provider in self.providers
begin
servers.concat(self[provider].servers)
rescue # ignore any missing credentials/etc
end
end
servers
end
end
end

View File

@ -1,104 +0,0 @@
require 'fog/core/model'
module Fog
module Compute
class Server < Fog::Model
attr_writer :username, :private_key, :private_key_path, :public_key, :public_key_path, :ssh_port, :ssh_options
def username
@username ||= 'root'
end
def private_key_path
@private_key_path ||= Fog.credentials[:private_key_path]
@private_key_path &&= File.expand_path(@private_key_path)
end
def private_key
@private_key ||= private_key_path && File.read(private_key_path)
end
def public_key_path
@public_key_path ||= Fog.credentials[:public_key_path]
@public_key_path &&= File.expand_path(@public_key_path)
end
def public_key
@public_key ||= public_key_path && File.read(public_key_path)
end
# Port used for ssh/scp interactions with server.
# @return [Integer] IP port
# @note By default this returns 22
def ssh_port
@ssh_port ||= 22
end
# Sets the proc used to determine the IP Address used for ssh/scp interactions.
# @example
# service.servers.bootstrap :name => 'bootstrap-server',
# :flavor_id => service.flavors.first.id,
# :image_id => service.images.find {|img| img.name =~ /Ubuntu/}.id,
# :public_key_path => '~/.ssh/fog_rsa.pub',
# :private_key_path => '~/.ssh/fog_rsa',
# :ssh_ip_address => Proc.new {|server| server.private_ip_address }
#
# @note By default scp/ssh will use the public_ip_address if this proc is not set.
def ssh_ip_address=(proc)
@ssh_ip_address = proc
end
# IP Address used for ssh/scp interactions with server.
# @return [String] IP Address
# @note By default this returns the public_ip_address
def ssh_ip_address
return public_ip_address unless @ssh_ip_address
return @ssh_ip_address.call(self) if @ssh_ip_address.is_a?(Proc)
@ssh_ip_address
end
def ssh_options
@ssh_options ||= {}
ssh_options = @ssh_options.merge({:port => ssh_port})
if private_key
ssh_options[:key_data] = [private_key]
ssh_options[:auth_methods] = ["publickey"]
end
ssh_options
end
def scp(local_path, remote_path, upload_options = {})
require 'net/scp'
requires :ssh_ip_address, :username
Fog::SCP.new(ssh_ip_address, username, ssh_options).upload(local_path, remote_path, upload_options)
end
alias_method :scp_upload, :scp
def scp_download(remote_path, local_path, download_options = {})
require 'net/scp'
requires :ssh_ip_address, :username
Fog::SCP.new(ssh_ip_address, username, ssh_options).download(remote_path, local_path, download_options)
end
def ssh(commands, options={}, &blk)
require 'net/ssh'
requires :ssh_ip_address, :username
options = ssh_options.merge(options)
Fog::SSH.new(ssh_ip_address, username, options).run(commands, &blk)
end
def sshable?(options={})
ready? && !ssh_ip_address.nil? && !!Timeout::timeout(8) { ssh('pwd', options) }
rescue SystemCallError, Net::SSH::AuthenticationFailed, Net::SSH::Disconnect, Timeout::Error
false
end
end
end
end

View File

@ -1,52 +0,0 @@
# external core dependencies
require 'base64'
require 'cgi'
require 'uri'
require 'excon'
require 'fileutils'
require 'formatador'
require 'openssl'
require 'time'
require 'timeout'
require 'ipaddr'
# internal core dependencies
require "fog/version"
require 'fog/core/attributes'
require 'fog/core/collection'
require 'fog/core/connection'
require 'fog/core/credentials'
require 'fog/core/current_machine'
require 'fog/core/deprecation'
require 'fog/core/errors'
require 'fog/core/hmac'
require 'fog/core/logger'
require 'fog/core/model'
require 'fog/core/mock'
require 'fog/core/provider'
require 'fog/core/service'
require 'fog/core/ssh'
require 'fog/core/scp'
require 'fog/core/time'
require 'fog/core/wait_for'
require 'fog/core/wait_for_defaults'
require 'fog/core/class_from_string'
require 'fog/core/uuid'
# data exchange specific (to be extracted and used on a per provider basis)
require 'fog/xml'
require 'fog/json'
# deprecation wrappers
require 'fog/core/deprecated/connection'
# service wrappers
require 'fog/compute'
require 'fog/identity'
require 'fog/image'
require 'fog/volume'
require 'fog/cdn'
require 'fog/dns'
require 'fog/network'
require 'fog/storage'
require 'fog/orchestration'

View File

@ -1,227 +0,0 @@
module Fog
module Attributes
module ClassMethods
def _load(marshalled)
new(Marshal.load(marshalled))
end
def aliases
@aliases ||= {}
end
def attributes
@attributes ||= []
end
def attribute(name, options = {})
class_eval <<-EOS, __FILE__, __LINE__
def #{name}
attributes[:#{name}]
end
EOS
case options[:type]
when :boolean
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = case new_#{name}
when true,'true'
true
when false,'false'
false
end
end
EOS
when :float
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = new_#{name}.to_f
end
EOS
when :integer
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = new_#{name}.to_i
end
EOS
when :string
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = new_#{name}.to_s
end
EOS
when :time
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = if new_#{name}.nil? || new_#{name} == "" || new_#{name}.is_a?(Time)
new_#{name}
else
Time.parse(new_#{name})
end
end
EOS
when :timestamp
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = Time.at(new_#{name}.to_i)
end
EOS
when :array
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = [*new_#{name}]
end
EOS
else
if squash = options[:squash]
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_data)
if new_data.is_a?(Hash)
if new_data.has_key?(:'#{squash}')
attributes[:#{name}] = new_data[:'#{squash}']
elsif new_data.has_key?("#{squash}")
attributes[:#{name}] = new_data["#{squash}"]
else
attributes[:#{name}] = [ new_data ]
end
else
attributes[:#{name}] = new_data
end
end
EOS
else
class_eval <<-EOS, __FILE__, __LINE__
def #{name}=(new_#{name})
attributes[:#{name}] = new_#{name}
end
EOS
end
end
@attributes ||= []
@attributes |= [name]
for new_alias in [*options[:aliases]]
aliases[new_alias] = name
end
end
def identity(name, options = {})
@identity = name
self.attribute(name, options)
end
def ignore_attributes(*args)
@ignored_attributes = args.collect {|attr| attr.to_s }
end
def ignored_attributes
@ignored_attributes ||= []
end
end
module InstanceMethods
def _dump(level)
Marshal.dump(attributes)
end
def attributes
@attributes ||= {}
end
def dup
copy = super
copy.dup_attributes!
copy
end
def identity
send(self.class.instance_variable_get('@identity'))
end
def identity=(new_identity)
send("#{self.class.instance_variable_get('@identity')}=", new_identity)
end
def merge_attributes(new_attributes = {})
for key, value in new_attributes
unless self.class.ignored_attributes.include?(key)
if aliased_key = self.class.aliases[key]
send("#{aliased_key}=", value)
elsif self.respond_to?("#{key}=",true)
send("#{key}=", value)
else
attributes[key] = value
end
end
end
self
end
# Returns true if a remote resource has been assigned an
# identity and we can assume it has been persisted.
#
# @return [Boolean]
def persisted?
!!identity
end
# Returns true if a remote resource has not been assigned an
# identity.
#
# This was added for a ActiveRecord like feel but has been
# outdated by ActiveModel API using {#persisted?}
#
# @deprecated Use inverted form of {#persisted?}
# @return [Boolean]
def new_record?
Fog::Logger.deprecation("#new_record? is deprecated, use !persisted? instead [light_black](#{caller.first})[/]")
!persisted?
end
# check that the attributes specified in args exist and is not nil
def requires(*args)
missing = missing_attributes(args)
if missing.length == 1
raise(ArgumentError, "#{missing.first} is required for this operation")
elsif missing.any?
raise(ArgumentError, "#{missing[0...-1].join(", ")} and #{missing[-1]} are required for this operation")
end
end
def requires_one(*args)
missing = missing_attributes(args)
if missing.length == args.length
raise(ArgumentError, "#{missing[0...-1].join(", ")} or #{missing[-1]} are required for this operation")
end
end
protected
def missing_attributes(args)
missing = []
for arg in [:service] | args
unless send("#{arg}") || attributes.has_key?(arg)
missing << arg
end
end
missing
end
def dup_attributes!
@attributes = @attributes.dup if @attributes
end
private
def remap_attributes(attributes, mapping)
for key, value in mapping
if attributes.key?(key)
attributes[value] = attributes.delete(key)
end
end
end
end
end
end

View File

@ -1,26 +0,0 @@
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

View File

@ -1,161 +0,0 @@
require "fog/core/deprecated_connection_accessors"
module Fog
class Collection < Array
extend Fog::Attributes::ClassMethods
include Fog::Attributes::InstanceMethods
include Fog::Core::DeprecatedConnectionAccessors
attr_reader :service
Array.public_instance_methods(false).each do |method|
unless [:reject, :select, :slice, :clear, :inspect].include?(method.to_sym)
class_eval <<-EOS, __FILE__, __LINE__
def #{method}(*args)
unless @loaded
lazy_load
end
super
end
EOS
end
end
%w[reject select slice].each do |method|
class_eval <<-EOS, __FILE__, __LINE__
def #{method}(*args)
unless @loaded
lazy_load
end
data = super
self.clone.clear.concat(data)
end
EOS
end
def self.model(new_model=nil)
if new_model == nil
@model
else
@model = new_model
end
end
def clear
@loaded = true
super
end
def create(attributes = {})
object = new(attributes)
object.save
object
end
def destroy(identity)
object = new(:identity => identity)
object.destroy
end
# Creates a new Fog::Collection based around the passed service
#
# @param [Hash] attributes
# @option attributes [Fog::Service] service Instance of a service
#
# @return [Fog::Collection]
#
def initialize(attributes = {})
@service = attributes.delete(:service)
@loaded = false
merge_attributes(attributes)
end
def inspect
Thread.current[:formatador] ||= Formatador.new
data = "#{Thread.current[:formatador].indentation}<#{self.class.name}\n"
Thread.current[:formatador].indent do
unless self.class.attributes.empty?
data << "#{Thread.current[:formatador].indentation}"
data << self.class.attributes.map {|attribute| "#{attribute}=#{send(attribute).inspect}"}.join(",\n#{Thread.current[:formatador].indentation}")
data << "\n"
end
data << "#{Thread.current[:formatador].indentation}["
unless self.empty?
data << "\n"
Thread.current[:formatador].indent do
data << self.map {|member| member.inspect}.join(",\n")
data << "\n"
end
data << Thread.current[:formatador].indentation
end
data << "]\n"
end
data << "#{Thread.current[:formatador].indentation}>"
data
end
def load(objects)
clear
for object in objects
self << new(object)
end
self
end
def model
self.class.instance_variable_get('@model')
end
def new(attributes = {})
unless attributes.is_a?(::Hash)
raise(ArgumentError.new("Initialization parameters must be an attributes hash, got #{attributes.class} #{attributes.inspect}"))
end
model.new(
{
:collection => self,
:service => service
}.merge(attributes)
)
end
def reload
clear
lazy_load
self
end
def table(attributes = nil)
Formatador.display_table(self.map {|instance| instance.attributes}, attributes)
end
def to_json(options = {})
Fog::JSON.encode(self.map {|member| member.attributes})
end
private
def lazy_load
self.all
end
end
# Base class for collection classes whose 'all' method returns only a single page of results and passes the
# 'Marker' option along as self.filters[:marker]
class PagedCollection < Collection
def each(filters=filters)
if block_given?
begin
page = self.all(filters)
# We need to explicitly use the base 'each' method here on the page, otherwise we get infinite recursion
base_each = Fog::Collection.instance_method(:each)
base_each.bind(page).call { |item| yield item }
end while self.filters[:marker]
end
self
end
end
end

View File

@ -1,72 +0,0 @@
module Fog
module Core
# Fog::Core::Connection is a generic class to contain a HTTP link to an API.
#
# It is intended to be subclassed by providers who can then add their own
# modifications such as authentication or response object.
#
class Connection
# Prepares the connection and sets defaults for any future requests.
#
# @param [String] url The destination URL
# @param persistent [Boolean]
# @param [Hash] params
# @option params [String] :body Default text to be sent over a socket. Only used if :body absent in Connection#request params
# @option params [Hash<Symbol, String>] :headers The default headers to supply in a request. Only used if params[:headers] is not supplied to Connection#request
# @option params [String] :host The destination host's reachable DNS name or IP, in the form of a String
# @option params [String] :path Default path; appears after 'scheme://host:port/'. Only used if params[:path] is not supplied to Connection#request
# @option params [Fixnum] :port The port on which to connect, to the destination host
# @option params [Hash] :query Default query; appended to the 'scheme://host:port/path/' in the form of '?key=value'. Will only be used if params[:query] is not supplied to Connection#request
# @option params [String] :scheme The protocol; 'https' causes OpenSSL to be used
# @option params [String] :proxy Proxy server; e.g. 'http://myproxy.com:8888'
# @option params [Fixnum] :retry_limit Set how many times we'll retry a failed request. (Default 4)
# @option params [Class] :instrumentor Responds to #instrument as in ActiveSupport::Notifications
# @option params [String] :instrumentor_name Name prefix for #instrument events. Defaults to 'excon'
#
def initialize(url, persistent=false, params={})
unless params.has_key?(:debug_response)
params[:debug_response] = true
end
params[:headers] ||= {}
params[:headers]['User-Agent'] ||= "fog/#{Fog::VERSION}"
params.merge!(:persistent => params.fetch(:persistent, persistent))
@excon = Excon.new(url, params)
end
# Makes a request using the connection using Excon
#
# @param [Hash] params
# @option params [String] :body text to be sent over a socket
# @option params [Hash<Symbol, String>] :headers The default headers to supply in a request
# @option params [String] :host The destination host's reachable DNS name or IP, in the form of a String
# @option params [String] :path appears after 'scheme://host:port/'
# @option params [Fixnum] :port The port on which to connect, to the destination host
# @option params [Hash] :query appended to the 'scheme://host:port/path/' in the form of '?key=value'
# @option params [String] :scheme The protocol; 'https' causes OpenSSL to be used
# @option params [Proc] :response_block
#
# @return [Excon::Response]
#
# @raise [Excon::Errors::StubNotFound]
# @raise [Excon::Errors::Timeout]
# @raise [Excon::Errors::SocketError]
#
def request(params, &block)
@excon.request(params, &block)
end
# Make {#request} available even when it has been overidden by a subclass
# to allow backwards compatibility.
#
alias_method :original_request, :request
protected :original_request
# Closes the connection
#
def reset
@excon.reset
end
end
end
end

View File

@ -1,70 +0,0 @@
require 'yaml'
module Fog
require 'fog/core/deprecation'
# 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
def self.credential=(new_credential)
@credentials = nil
@credential = new_credential && new_credential.to_sym
end
# @return [String, Symbol] The credential to use in Fog
def self.credential
@credential ||= ( ENV["FOG_CREDENTIAL"] && ENV["FOG_CREDENTIAL"].to_sym ) || :default
end
# @return [String] The path for configuration_file
def self.credentials_path
@credential_path ||= begin
path = ENV["FOG_RC"] || (ENV['HOME'] && File.directory?(ENV['HOME']) && '~/.fog')
File.expand_path(path) if path
rescue
nil
end
end
# @return [String] The new path for credentials file
def self.credentials_path=(new_credentials_path)
@credentials = nil
@credential_path = new_credentials_path
end
# @return [Hash] The credentials pulled from the configuration file
# @raise [LoadError] Configuration unavailable in configuration file
def self.credentials
@credentials ||= begin
if credentials_path && File.exists?(credentials_path)
credentials = self.symbolize_credentials(YAML.load_file(credentials_path))
(credentials && credentials[credential]) || Fog::Errors.missing_credentials
else
{}
end
end
end
# @return [Hash] The newly assigned credentials
def self.credentials=(new_credentials)
@credentials = new_credentials
end
def self.symbolize_credential?(key)
![:headers].include?(key)
end
def self.symbolize_credentials(args)
if args.is_a? Hash
copy = Array.new
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

View File

@ -1,34 +0,0 @@
require 'thread'
module Fog
class CurrentMachine
@@lock = Mutex.new
AMAZON_AWS_CHECK_IP = 'http://checkip.amazonaws.com'
def self.ip_address= ip_address
@@lock.synchronize do
@@ip_address = ip_address
end
end
# Get the ip address of the machine from which this command is run. It is
# recommended that you surround calls to this function with a timeout block
# to ensure optimum performance in the case where the amazonaws checkip
# service is unavailable.
#
# @example Get the current ip address
# begin
# Timeout::timeout(5) do
# puts "Your ip address is #{Fog::CurrentMachine.ip_address}"
# end
# rescue Timeout::Error
# puts "Service timeout"
# end
#
# @raise [Excon::Errors::Error] if the net/http request fails.
def self.ip_address
@@lock.synchronize do
@@ip_address ||= Excon.get(AMAZON_AWS_CHECK_IP).body.chomp
end
end
end
end

View File

@ -1,23 +0,0 @@
module Fog
module Deprecation
def deprecate(older, newer)
module_eval <<-EOS, __FILE__, __LINE__
def #{older}(*args)
Fog::Logger.deprecation("#{self} => ##{older} is deprecated, use ##{newer} instead [light_black](#{caller.first})[/]")
send(:#{newer}, *args)
end
EOS
end
def self_deprecate(older, newer)
module_eval <<-EOS, __FILE__, __LINE__
def self.#{older}(*args)
Fog::Logger.deprecation("#{self} => ##{older} is deprecated, use ##{newer} instead [light_black](#{caller.first})[/]")
send(:#{newer}, *args)
end
EOS
end
end
end

View File

@ -1,118 +0,0 @@
module Fog
module Errors
class Error < StandardError
attr_accessor :verbose
def self.slurp(error, message = nil)
new_error = new(message || error.message)
new_error.set_backtrace(error.backtrace)
new_error.verbose = error.message
new_error
end
end
class MockNotImplemented < Fog::Errors::Error; end
class NotFound < Fog::Errors::Error; end
class LoadError < LoadError; end
class TimeoutError< Fog::Errors::Error; end
class NotImplemented < Fog::Errors::Error; end
# @return [String] The error message that will be raised, if credentials cannot be found
def self.missing_credentials
missing_credentials_message = <<-YML
Missing Credentials
To run as '#{Fog.credential}', add the following to your resource config file: #{Fog.credentials_path}
An alternate file may be used by placing its path in the FOG_RC environment variable
#######################################################
# Fog Credentials File
#
# Key-value pairs should look like:
# :aws_access_key_id: 022QF06E7MXBSAMPLE
:#{Fog.credential}:
:aws_access_key_id:
:aws_secret_access_key:
:bluebox_api_key:
:bluebox_customer_id:
:brightbox_client_id:
:brightbox_secret:
:clodo_api_key:
:clodo_username:
:go_grid_api_key:
:go_grid_shared_secret:
:google_client_email:
:google_key_location:
:google_project:
:google_storage_access_key_id:
:google_storage_secret_access_key:
:hp_access_key:
:hp_secret_key:
:hp_tenant_id:
:hp_avl_zone:
:linode_api_key:
:local_root:
:bare_metal_cloud_password:
:bare_metal_cloud_username:
:public_key_path:
:private_key_path:
:openstack_api_key:
:openstack_username:
:openstack_auth_url:
:openstack_tenant:
:openstack_region:
:ovirt_username:
:ovirt_password:
:ovirt_url:
:libvirt_uri:
:rackspace_api_key:
:rackspace_username:
:rackspace_servicenet:
:rackspace_cdn_ssl:
:rage4_email:
:rage4_password:
:riakcs_access_key_id:
:riakcs_secret_access_key:
:stormondemand_username:
:stormondemand_password:
:terremark_username:
:terremark_password:
:voxel_api_key:
:voxel_api_secret:
:zerigo_email:
:zerigo_token:
:dnsimple_email:
:dnsimple_password:
:dnsmadeeasy_api_key:
:dnsmadeeasy_secret_key:
:dreamhost_api_key:
:cloudstack_host:
:cloudstack_api_key:
:cloudstack_secret_access_key:
:vsphere_server:
:vsphere_username:
:vsphere_password:
:libvirt_username:
:libvirt_password:
:libvirt_uri:
:libvirt_ip_command:
:ibm_username:
:ibm_password:
:vcloud_director_host:
:vcloud_director_username:
:vcloud_director_password:
#
# End of Fog Credentials File
#######################################################
YML
raise(Fog::Errors::LoadError.new(missing_credentials_message))
end
end
end

View File

@ -1,35 +0,0 @@
module Fog
class HMAC
def initialize(type, key)
@key = key
case type
when 'sha1'
setup_sha1
when 'sha256'
setup_sha256
end
end
def sign(data)
@signer.call(data)
end
private
def setup_sha1
@digest = OpenSSL::Digest.new('sha1')
@signer = lambda do |data|
OpenSSL::HMAC.digest(@digest, @key, data)
end
end
def setup_sha256
@digest = OpenSSL::Digest.new('sha256')
@signer = lambda do |data|
OpenSSL::HMAC.digest(@digest, @key, data)
end
end
end
end

View File

@ -1,44 +0,0 @@
module Fog
class Logger
@channels = {
:deprecation => ::STDERR,
:warning => ::STDERR
}
@channels[:debug] = ::STDERR if ENV['DEBUG']
def self.[](channel)
@channels[channel]
end
def self.[]=(channel, value)
@channels[channel] = value
end
def self.debug(message)
self.write(:debug, "[light_black][fog][DEBUG] #{message}[/]\n")
end
def self.deprecation(message)
self.write(:deprecation, "[yellow][fog][DEPRECATION] #{message}[/]\n")
end
def self.warning(message)
self.write(:warning, "[yellow][fog][WARNING] #{message}[/]\n")
end
def self.write(key, value)
if channel = @channels[key]
message = if channel.tty?
value.gsub(Formatador::PARSE_REGEX) { "\e[#{Formatador::STYLES[$1.to_sym]}m" }.gsub(Formatador::INDENT_REGEX, '')
else
value.gsub(Formatador::PARSE_REGEX, '').gsub(Formatador::INDENT_REGEX, '')
end
channel.write(message)
end
nil
end
end
end

View File

@ -1,115 +0,0 @@
module Fog
@mocking = false
def self.mock!
@mocking = true
end
def self.unmock!
@mocking = false
end
def self.mock?
@mocking
end
def self.mocking?
@mocking
end
module Mock
@delay = 1
def self.delay
@delay
end
def self.delay=(new_delay)
raise ArgumentError, "delay must be non-negative" unless new_delay >= 0
@delay = new_delay
end
def self.not_implemented(message = 'Contributions welcome!')
raise Fog::Errors::MockNotImplemented.new(message)
end
def self.random_ip(opts = {:version => :v4})
version = opts[:version]
if version == :v6
bit_length = 128
family = Socket::AF_INET6
elsif version == :v4
bit_length = 32
family = Socket::AF_INET
else
raise ArgumentError, "Unknown IP version: #{version}"
end
seed = 1 + rand((2**bit_length)-1)
IPAddr.new(seed, family).to_s
end
def self.random_base64(length)
random_selection(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
length
)
end
def self.random_hex(length)
max = ('f' * length).to_i(16)
rand(max).to_s(16).rjust(length, '0')
end
def self.random_letters(length)
random_selection(
'abcdefghijklmnopqrstuvwxyz',
length
)
end
def self.random_numbers(length)
max = ('9' * length).to_i
rand(max).to_s
end
def self.random_letters_and_numbers(length)
random_selection(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
length
)
end
def self.random_selection(characters, length)
selection = ''
length.times do
position = rand(characters.length)
selection << characters[position..position]
end
selection
end
def self.reset
mocked_services = []
Fog.constants.map do |x|
x_const = Fog.const_get(x)
x_const.respond_to?(:constants) && x_const.constants.map do |y|
y_const = x_const.const_get(y)
y_const.respond_to?(:constants) && y_const.constants.map do |z|
if z.to_sym == :Mock
mocked_services << y_const.const_get(z)
end
end
end
end
for mocked_service in mocked_services
next unless mocked_service.respond_to?(:reset)
mocked_service.reset
end
end
end
end

View File

@ -1,80 +0,0 @@
require "fog/core/deprecated_connection_accessors"
module Fog
class Model
extend Fog::Attributes::ClassMethods
include Fog::Attributes::InstanceMethods
include Fog::Core::DeprecatedConnectionAccessors
attr_accessor :collection
attr_reader :service
def initialize(new_attributes = {})
# TODO Remove compatibility with old connection option
@service = new_attributes.delete(:service)
if @service.nil? && new_attributes[:connection]
Fog::Logger.deprecation("Passing :connection option is deprecated, use :service instead [light_black](#{caller.first})[/]")
@service = new_attributes[:connection]
end
merge_attributes(new_attributes)
end
def inspect
Thread.current[:formatador] ||= Formatador.new
data = "#{Thread.current[:formatador].indentation}<#{self.class.name}"
Thread.current[:formatador].indent do
unless self.class.attributes.empty?
data << "\n#{Thread.current[:formatador].indentation}"
data << self.class.attributes.map {|attribute| "#{attribute}=#{send(attribute).inspect}"}.join(",\n#{Thread.current[:formatador].indentation}")
end
end
data << "\n#{Thread.current[:formatador].indentation}>"
data
end
def reload
requires :identity
return unless data = begin
collection.get(identity)
rescue Excon::Errors::SocketError
nil
end
new_attributes = data.attributes
merge_attributes(new_attributes)
self
end
def to_json(options = {})
Fog::JSON.encode(attributes)
end
def symbolize_keys(hash)
return nil if hash.nil?
hash.inject({}) do |options, (key, value)|
options[(key.to_sym rescue key) || key] = value
options
end
end
def wait_for(timeout=Fog.timeout, interval=1, &block)
reload_has_succeeded = false
duration = Fog.wait_for(timeout, interval) do # Note that duration = false if it times out
if reload
reload_has_succeeded = true
instance_eval(&block)
else
false
end
end
if reload_has_succeeded
return duration # false if timeout; otherwise {:duration => elapsed time }
else
raise Fog::Errors::Error.new("Reload failed, #{self.class} #{self.identity} not present.")
end
end
end
end

View File

@ -1,34 +0,0 @@
module Fog
def self.providers
@providers ||= {}
end
def self.providers=(new_providers)
@providers = new_providers
end
module Provider
def self.extended(base)
provider = base.to_s.split('::').last
Fog.providers[provider.downcase.to_sym] = provider
end
def [](service_key)
eval(@services_registry[service_key]).new
end
def service(new_service, constant_string)
Fog.services[new_service] ||= []
Fog.services[new_service] |= [self.to_s.split('::').last.downcase.to_sym]
@services_registry ||= {}
@services_registry[new_service] = [self.to_s, constant_string].join('::')
end
def services
@services_registry.keys
end
end
end

View File

@ -1,96 +0,0 @@
module Fog
module SCP
def self.new(address, username, options = {})
if Fog.mocking?
Fog::SCP::Mock.new(address, username, options)
else
Fog::SCP::Real.new(address, username, options)
end
end
class Mock
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = []
end
end
def initialize(address, username, options)
@address = address
@username = username
@options = options
end
def upload(local_path, remote_path, upload_options = {})
self.class.data[@address] << { :username => @username,
:options => @options,
:local_path => local_path,
:remote_path => remote_path,
:upload_options => upload_options }
end
def download(remote_path, local_path, download_options = {})
self.class.data[@address] << { :username => @username,
:options => @options,
:remote_path => remote_path,
:local_path => local_path,
:download_options => download_options }
end
end
class Real
def initialize(address, username, options)
require 'net/scp'
key_manager = Net::SSH::Authentication::KeyManager.new(nil, options)
unless options[:key_data] || options[:keys] || options[:password] || key_manager.agent
raise ArgumentError.new(':key_data, :keys, :password or a loaded ssh-agent is required to initialize SSH')
end
options[:timeout] = 30
if options[:key_data] || options[:keys]
options[:keys_only] = true
#Explicitly set these so net-ssh doesn't add the default keys
#as seen at https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/authentication/session.rb#L131-146
options[:keys] = [] unless options[:keys]
options[:key_data] = [] unless options[:key_data]
end
@address = address
@username = username
@options = { :paranoid => false }.merge(options)
end
def upload(local_path, remote_path, upload_options = {}, &block)
begin
Net::SCP.start(@address, @username, @options) do |scp|
scp.upload!(local_path, remote_path, upload_options) do |ch, name, sent, total|
block.call(ch, name, sent, total) if block
end
end
rescue Exception => error
raise error
end
end
def download(remote_path, local_path, download_options = {}, &block)
begin
Net::SCP.start(@address, @username, @options) do |scp|
scp.download!(remote_path, local_path, download_options) do |ch, name, sent, total|
block.call(ch, name, sent, total) if block
end
end
rescue Exception => error
raise error
end
end
end
end
end

View File

@ -1,223 +0,0 @@
module Fog
def self.services
@services ||= {}
end
class Service
class Error < Fog::Errors::Error; end
class NotFound < Fog::Errors::NotFound; end
module NoLeakInspector
def inspect
"#<#{self.class}:#{self.object_id} #{(self.instance_variables - service.secrets).map {|iv| [iv, self.instance_variable_get(iv).inspect].join('=')}.join(' ')}>"
end
end
module Collections
def collections
service.collections
end
def mocked_requests
service.mocked_requests
end
def requests
service.requests
end
end
class << self
def inherited(child)
child.class_eval <<-EOS, __FILE__, __LINE__
class Error < Fog::Service::Error; end
class NotFound < Fog::Service::NotFound; end
module Collections
include Fog::Service::Collections
def service
#{child}
end
end
def self.service
#{child}
end
EOS
end
def new(options={})
options = Fog.symbolize_credentials(options)
options = fetch_credentials(options).merge(options)
validate_options(options)
coerce_options(options)
setup_requirements
if Fog.mocking?
service::Mock.send(:include, service::Collections)
service::Mock.new(options)
else
service::Real.send(:include, service::Collections)
service::Real.send(:include, service::NoLeakInspector)
service::Real.new(options)
end
end
def fetch_credentials(options)
# attempt to load credentials from config file
begin
Fog.credentials.reject {|key, value| !(recognized | requirements).include?(key)}
rescue LoadError
# if there are no configured credentials, do nothing
{}
end
end
def setup_requirements
if superclass.respond_to?(:setup_requirements)
superclass.setup_requirements
end
@required ||= false
unless @required
for collection in collections
require [@model_path, collection].join('/')
constant = collection.to_s.split('_').map {|characters| characters[0...1].upcase << characters[1..-1]}.join('')
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
end
end
def model_path(new_path)
@model_path = new_path
end
def collection(new_collection)
collections << new_collection
end
def collections
@collections ||= []
end
def coerce_options(options)
options.each do |key, value|
value_string = value.to_s.downcase
if value.nil?
options.delete(key)
elsif value == value_string.to_i.to_s
options[key] = value.to_i
else
options[key] = case value_string
when 'false'
false
when 'true'
true
else
value
end
end
end
end
def mocked_requests
@mocked_requests ||= []
end
def model(new_model)
models << new_model
end
def models
@models ||= []
end
def request_path(new_path)
@request_path = new_path
end
def request(new_request)
requests << new_request
end
def requests
@requests ||= []
end
def secrets(*args)
if args.empty?
@secrets ||= []
else
args.inject(secrets) do |secrets, secret|
secrets << "@#{secret}".to_sym
end
end
end
def requires(*args)
requirements.concat(args)
end
def requirements
@requirements ||= []
end
def recognizes(*args)
recognized.concat(args)
end
def recognized
@recognized ||= [:connection_options]
end
def validate_options(options)
keys = []
for key, value in options
unless value.nil?
keys << key
end
end
missing = requirements - keys
unless missing.empty?
raise ArgumentError, "Missing required arguments: #{missing.join(', ')}"
end
unless recognizes.empty?
unrecognized = options.keys - requirements - recognized
unless unrecognized.empty?
Fog::Logger.warning("Unrecognized arguments: #{unrecognized.join(', ')}")
end
end
end
end
end
end

View File

@ -1,137 +0,0 @@
require 'delegate'
module Fog
module SSH
def self.new(address, username, options = {})
if Fog.mocking?
Fog::SSH::Mock.new(address, username, options)
else
Fog::SSH::Real.new(address, username, options)
end
end
class Mock
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = []
end
end
def self.reset
@data= nil
end
def initialize(address, username, options)
@address = address
@username = username
@options = options
end
def run(commands, &blk)
self.class.data[@address] << {:commands => commands, :username => @username, :options => @options}
end
end
class Real
def initialize(address, username, options)
require 'net/ssh'
key_manager = Net::SSH::Authentication::KeyManager.new(nil, options)
unless options[:key_data] || options[:keys] || options[:password] || key_manager.agent
raise ArgumentError.new(':key_data, :keys, :password or a loaded ssh-agent is required to initialize SSH')
end
options[:timeout] ||= 30
if options[:key_data] || options[:keys]
options[:keys_only] = true
#Explicitly set these so net-ssh doesn't add the default keys
#as seen at https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/authentication/session.rb#L131-146
options[:keys] = [] unless options[:keys]
options[:key_data] = [] unless options[:key_data]
end
@address = address
@username = username
@options = { :paranoid => false }.merge(options)
end
def run(commands, &blk)
commands = [*commands]
results = []
begin
Net::SSH.start(@address, @username, @options) do |ssh|
commands.each do |command|
result = Result.new(command)
ssh.open_channel do |ssh_channel|
ssh_channel.request_pty
ssh_channel.exec(command) do |channel, success|
unless success
raise "Could not execute command: #{command.inspect}"
end
channel.on_data do |ch, data|
result.stdout << data
yield [data, ''] if blk
end
channel.on_extended_data do |ch, type, data|
next unless type == 1
result.stderr << data
yield ['', data] if blk
end
channel.on_request('exit-status') do |ch, data|
result.status = data.read_long
end
channel.on_request('exit-signal') do |ch, data|
result.status = 255
end
end
end
ssh.loop
results << result
end
end
rescue Net::SSH::HostKeyMismatch => exception
exception.remember_host!
sleep 0.2
retry
end
results
end
end
class Result
attr_accessor :command, :stderr, :stdout, :status
def display_stdout
data = stdout.split("\r\n")
if data.is_a?(String)
Formatador.display_line(data)
elsif data.is_a?(Array)
Formatador.display_lines(data)
end
end
def display_stderr
Formatador.display_line(stderr.split("\r\n"))
end
def initialize(command)
@command = command
@stderr = ''
@stdout = ''
end
end
end
end

View File

@ -1,32 +0,0 @@
require 'time'
module Fog
class Time < ::Time
DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def self.now
at((::Time.now - offset).to_i)
end
def self.now=(new_now)
old_now = ::Time.now
@offset = old_now - new_now
new_now
end
def self.offset
@offset ||= 0
end
def to_date_header
self.utc.strftime("#{DAYS[self.utc.wday]}, %d #{MONTHS[self.utc.month - 1]} %Y %H:%M:%S +0000")
end
def to_iso8601_basic
self.utc.strftime('%Y%m%dT%H%M%SZ')
end
end
end

View File

@ -1,23 +0,0 @@
require 'securerandom'
module Fog
class UUID
class << self
def uuid
if supported?
SecureRandom.uuid
else
ary = SecureRandom.random_bytes(16).unpack("NnnnnN")
ary[2] = (ary[2] & 0x0fff) | 0x4000
ary[3] = (ary[3] & 0x3fff) | 0x8000
"%08x-%04x-%04x-%04x-%04x%08x" % ary
end
end
def supported?
SecureRandom.respond_to?(:uuid)
end
end
end
end

View File

@ -1,15 +0,0 @@
module Fog
def self.wait_for(timeout=Fog.timeout, interval=Fog.interval, &block)
duration = 0
start = Time.now
until yield || duration > timeout
sleep(interval.to_f)
duration = Time.now - start
end
if duration > timeout
raise Errors::TimeoutError.new("The specified wait_for timeout (#{timeout} seconds) was exceeded")
else
{ :duration => duration }
end
end
end

View File

@ -1,21 +0,0 @@
module Fog
@interval = 1
def self.interval
@interval
end
def self.interval=(interval)
raise ArgumentError, "interval must be non-negative" unless interval >= 0
@interval = interval
end
@timeout = 600
def self.timeout
@timeout
end
def self.timeout=(timeout)
raise ArgumentError, "timeout must be non-negative" unless timeout >= 0
@timeout = timeout
end
end