1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/aws/core.rb
Paul Thornthwaite 15ef5365e5 Require json or xml in provider cores
Since `fog-json` was extracted from `fog` it means if you rely on:

    require "fog/provider/compute"

`Fog::JSON` was not defined although it was supposed to be a supported
use case.

This adds the requires for JSON or XML based APIs based on a quick scan
of each provider to declare the required part.

AWS seems to be relying on both. Which is nice.

Providers relying on native code dependencies
2014-02-19 14:58:00 +00:00

332 lines
9.7 KiB
Ruby

require 'fog/core'
require 'fog/xml'
require 'fog/json'
require 'fog/aws/credential_fetcher'
require 'fog/aws/region_methods'
require 'fog/aws/signaturev4'
module Fog
module AWS
extend Fog::Provider
service(:auto_scaling, 'AutoScaling')
service(:beanstalk, 'ElasticBeanstalk')
service(:cdn, 'CDN')
service(:compute, 'Compute')
service(:cloud_formation, 'CloudFormation')
service(:cloud_watch, 'CloudWatch')
service(:data_pipeline, 'DataPipeline')
service(:dynamodb, 'DynamoDB')
service(:dns, 'DNS')
service(:elasticache, 'Elasticache')
service(:elb, 'ELB')
service(:emr, 'EMR')
service(:glacier, 'Glacier')
service(:iam, 'IAM')
service(:rds, 'RDS')
service(:redshift, 'Redshift')
service(:ses, 'SES')
service(:simpledb, 'SimpleDB')
service(:sns, 'SNS')
service(:sqs, 'SQS')
service(:sts, 'STS')
service(:storage, 'Storage')
def self.indexed_param(key, values)
params = {}
unless key.include?('%d')
key << '.%d'
end
[*values].each_with_index do |value, index|
if value.respond_to?('keys')
k = format(key, index + 1)
value.each do | vkey, vvalue |
params["#{k}.#{vkey}"] = vvalue
end
else
params[format(key, index + 1)] = value
end
end
params
end
def self.serialize_keys(key, value, options = {})
case value
when Hash
value.each do | k, v |
options.merge!(serialize_keys("#{key}.#{k}", v))
end
return options
when Array
value.each_with_index do | it, idx |
options.merge!(serialize_keys("#{key}.member.#{(idx + 1)}", it))
end
return options
else
return {key => value}
end
end
def self.indexed_request_param(name, values)
idx = -1
Array(values).inject({}) do |params, value|
params["#{name}.#{idx += 1}"] = value
params
end
end
def self.indexed_filters(filters)
params = {}
filters.keys.each_with_index do |key, key_index|
key_index += 1
params[format('Filter.%d.Name', key_index)] = key
[*filters[key]].each_with_index do |value, value_index|
value_index += 1
params[format('Filter.%d.Value.%d', key_index, value_index)] = value
end
end
params
end
def self.escape(string)
unless @unf_loaded_or_warned
begin
require('unf/normalizer')
rescue LoadError
Fog::Logger.warning("Unable to load the 'unf' gem. Your AWS strings may not be properly encoded.")
end
@unf_loaded_or_warned = true
end
string = defined?(::UNF::Normalizer) ? ::UNF::Normalizer.normalize(string, :nfc) : string
string.gsub(/([^a-zA-Z0-9_.\-~]+)/) {
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
}
end
def self.signed_params(params, options = {})
params.merge!({
'AWSAccessKeyId' => options[:aws_access_key_id],
'SignatureMethod' => 'HmacSHA256',
'SignatureVersion' => '2',
'Timestamp' => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
'Version' => options[:version]
})
params.merge!({
'SecurityToken' => options[:aws_session_token]
}) if options[:aws_session_token]
body = ''
for key in params.keys.sort
unless (value = params[key]).nil?
body << "#{key}=#{escape(value.to_s)}&"
end
end
string_to_sign = "POST\n#{options[:host]}:#{options[:port]}\n#{options[:path]}\n" << body.chop
signed_string = options[:hmac].sign(string_to_sign)
body << "Signature=#{escape(Base64.encode64(signed_string).chomp!)}"
body
end
class Mock
def self.arn(vendor, account_id, path, region = nil)
"arn:aws:#{vendor}:#{region}:#{account_id}:#{path}"
end
def self.availability_zone(region)
"#{region}#{Fog::Mock.random_selection('abcd', 1)}"
end
def self.box_usage
sprintf("%0.10f", rand / 100).to_f
end
def self.console_output
# "[ 0.000000] Linux version 2.6.18-xenU-ec2-v1.2 (root@domU-12-31-39-07-51-82) (gcc version 4.1.2 20070626 (Red Hat 4.1.2-13)) #2 SMP Wed Aug 19 09:04:38 EDT 2009"
Base64.decode64("WyAwLjAwMDAwMF0gTGludXggdmVyc2lvbiAyLjYuMTgteGVuVS1lYzItdjEu\nMiAocm9vdEBkb21VLTEyLTMxLTM5LTA3LTUxLTgyKSAoZ2NjIHZlcnNpb24g\nNC4xLjIgMjAwNzA2MjYgKFJlZCBIYXQgNC4xLjItMTMpKSAjMiBTTVAgV2Vk\nIEF1ZyAxOSAwOTowNDozOCBFRFQgMjAwOQ==\n")
end
def self.dns_name_for(ip_address)
"ec2-#{ip_address.gsub('.','-')}.compute-1.amazonaws.com"
end
def self.private_dns_name_for(ip_address)
"ip-#{ip_address.gsub('.','-')}.ec2.internal"
end
def self.image
path = []
(rand(3) + 2).times do
path << Fog::Mock.random_letters(rand(9) + 8)
end
{
"imageOwnerId" => Fog::Mock.random_letters(rand(5) + 4),
"blockDeviceMapping" => [],
"productCodes" => [],
"kernelId" => kernel_id,
"ramdiskId" => ramdisk_id,
"imageState" => "available",
"imageId" => image_id,
"architecture" => "i386",
"isPublic" => true,
"imageLocation" => path.join('/'),
"imageType" => "machine",
"rootDeviceType" => ["ebs","instance-store"][rand(2)],
"rootDeviceName" => "/dev/sda1"
}
end
def self.image_id
"ami-#{Fog::Mock.random_hex(8)}"
end
def self.key_fingerprint
fingerprint = []
20.times do
fingerprint << Fog::Mock.random_hex(2)
end
fingerprint.join(':')
end
def self.instance_id
"i-#{Fog::Mock.random_hex(8)}"
end
def self.ip_address
Fog::Mock.random_ip
end
def self.private_ip_address
ip_address.gsub(/^\d{1,3}\./,"10.")
end
def self.kernel_id
"aki-#{Fog::Mock.random_hex(8)}"
end
def self.key_material
OpenSSL::PKey::RSA.generate(1024).to_s
end
def self.owner_id
Fog::Mock.random_numbers(12)
end
def self.ramdisk_id
"ari-#{Fog::Mock.random_hex(8)}"
end
def self.request_id
request_id = []
request_id << Fog::Mock.random_hex(8)
3.times do
request_id << Fog::Mock.random_hex(4)
end
request_id << Fog::Mock.random_hex(12)
request_id.join('-')
end
class << self
alias :reserved_instances_id :request_id
alias :reserved_instances_offering_id :request_id
alias :sqs_message_id :request_id
alias :sqs_sender_id :request_id
end
def self.reservation_id
"r-#{Fog::Mock.random_hex(8)}"
end
def self.snapshot_id
"snap-#{Fog::Mock.random_hex(8)}"
end
def self.volume_id
"vol-#{Fog::Mock.random_hex(8)}"
end
def self.security_group_id
"sg-#{Fog::Mock.random_hex(8)}"
end
def self.network_acl_id
"acl-#{Fog::Mock.random_hex(8)}"
end
def self.network_acl_association_id
"aclassoc-#{Fog::Mock.random_hex(8)}"
end
def self.network_interface_id
"eni-#{Fog::Mock.random_hex(8)}"
end
def self.internet_gateway_id
"igw-#{Fog::Mock.random_hex(8)}"
end
def self.dhcp_options_id
"dopt-#{Fog::Mock.random_hex(8)}"
end
def self.vpc_id
"vpc-#{Fog::Mock.random_hex(8)}"
end
def self.subnet_id
"subnet-#{Fog::Mock.random_hex(8)}"
end
def self.zone_id
"zone-#{Fog::Mock.random_hex(8)}"
end
def self.change_id
Fog::Mock.random_letters_and_numbers(14)
end
def self.nameservers
[
'ns-2048.awsdns-64.com',
'ns-2049.awsdns-65.net',
'ns-2050.awsdns-66.org',
'ns-2051.awsdns-67.co.uk'
]
end
def self.key_id(length=21)
#Probably close enough
Fog::Mock.random_selection('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',length)
end
def self.rds_address(db_name,region)
"#{db_name}.#{Fog::Mock.random_letters(rand(12) + 4)}.#{region}.rds.amazonaws.com"
end
end
def self.parse_security_group_options(group_name, options)
options ||= Hash.new
if group_name.is_a?(Hash)
options = group_name
elsif group_name
if options.key?('GroupName')
raise Fog::Compute::AWS::Error, 'Arguments specified both group_name and GroupName in options'
end
options = options.clone
options['GroupName'] = group_name
end
name_specified = options.key?('GroupName') && !options['GroupName'].nil?
group_id_specified = options.key?('GroupId') && !options['GroupId'].nil?
unless name_specified || group_id_specified
raise Fog::Compute::AWS::Error, 'Neither GroupName nor GroupId specified'
end
if name_specified && group_id_specified
options.delete('GroupName')
end
options
end
module Errors
def self.match_error(error)
matcher = lambda {|s| s.match(/(?:.*<Code>(.*)<\/Code>)(?:.*<Message>(.*)<\/Message>)/m)}
[error.message, error.response.body].each(&Proc.new {|s|
match = matcher.call(s)
return {:code => match[1].split('.').last, :message => match[2]} if match
})
{} # we did not match the message or response body
end
end
end
end