# Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. require 'aws/core/autoloader' # AWS is the root module for all of the Amazon Web Services. It is also # where you can configure you access to AWS. # # = Supported Services # # The currently supported services are: # # * {EC2} # * {ELB} # * {S3} # * {SimpleDB} # * {SimpleEmailService} # * {SNS} # * {SQS} # * {IAM} # # = AWS::Record # # In addition to the above services, bundled is an ORM based on AWS services # See {AWS::Record} for more information. # # = Configuration # # You call {AWS.config} with a hash of options to configure your # access to the Amazon Web Services. # # At a minimum you need to set your access credentials. See {AWS.config} # for additional configuration options. # # AWS.config( # :access_key_id => 'ACCESS_KEY_ID', # :secret_access_key => 'SECRET_ACCESS_KEY') # # == Rails # # If you are loading AWS inside a Rails web application, it is recomended to # place your configuration inside: # # config/initializers/aws.rb # module AWS # Current version of the AWS SDK for Ruby VERSION = "1.2.2" register_autoloads(self) do autoload :Errors, 'errors' end module Core AWS.register_autoloads(self) do autoload :ApiConfig, 'api_config' autoload :AsyncHandle, 'async_handle' autoload :AuthorizeV2, 'authorize_v2' autoload :AuthorizeV3, 'authorize_v3' autoload :AuthorizeWithSessionToken, 'authorize_with_session_token' autoload :Cacheable, 'cacheable' autoload :Client, 'client' autoload :ClientLogging, 'client_logging' autoload :Collection, 'collection' autoload :Configuration, 'configuration' autoload :ConfiguredClientMethods, 'configured_client_methods' autoload :ConfiguredGrammars, 'configured_grammars' autoload :ConfiguredOptionGrammars, 'configured_option_grammars' autoload :ConfiguredXmlGrammars, 'configured_xml_grammars' autoload :DefaultSigner, 'default_signer' autoload :IgnoreResultElement, 'ignore_result_element' autoload :IndifferentHash, 'indifferent_hash' autoload :Inflection, 'inflection' autoload :LazyErrorClasses, 'lazy_error_classes' autoload :MetaUtils, 'meta_utils' autoload :Model, 'model' autoload :Naming, 'naming' autoload :OptionGrammar, 'option_grammar' autoload :PageResult, 'page_result' autoload :Policy, 'policy' autoload :Resource, 'resource' autoload :ResourceCache, 'resource_cache' autoload :Response, 'response' autoload :ResponseCache, 'response_cache' autoload :ServiceInterface, 'service_interface' autoload :UriEscape, 'uri_escape' autoload :XmlGrammar, 'xml_grammar' end module Http AWS.register_autoloads(self) do autoload :Handler, 'handler' autoload :NetHttpHandler, 'net_http_handler' autoload :HTTPartyHandler, 'httparty_handler' # non-standard inflection autoload :Request, 'request' autoload :Response, 'response' end end end # the http party handler should still be accessible from its old namespace module Http AWS.register_autoloads(self, 'aws/core/http') do autoload :HTTPartyHandler, 'httparty_handler' end end class << self # @private @@config = nil # The global configuration for AWS. Generally you set your prefered # configuration operations once after loading the aws-sdk gem. # # AWS.config({ # :access_key_id => 'ACCESS_KEY_ID', # :secret_access_key => 'SECRET_ACCESS_KEY', # :simple_db_endpoint => 'sdb.us-west-1.amazonaws.com', # :max_retries => 2, # }) # # When using AWS classes they will always default to use configuration # values defined in {AWS.config}. # # AWS.config(:max_retries => 2) # # sqs = AWS::SQS.new # sqs.config.max_retries #=> 2 # # If you want to change a configuration value for a single instance you # pass the new configuration value to that object's initializer: # # AWS::SQS.new(:max_retries => 0) # # @note Changing the global configuration does not affect objects # that have already been constructed. # # @param [Hash] options # @option options [String] :access_key_id (nil) AWS access key id # credential. # @option options [String] :ec2_endpoint ('ec2.amazonaws.com') The # service endpoint for Amazon EC2. # @option options [Object] :http_handler (AWS::HTTPartyHandler) The # http handler that sends requests to AWS. # @option options [String] :iam_endpoint ('iam.amazonaws.com') The # service endpoint for AWS Idenity Access Management (IAM). # @option options [Object,nil] :logger (nil) A logger instance that # should receive log messages generated by service requets. # A logger needs to respond to #log and must accept a # severity (e.g. :info, :error, etc) and a string message. # @option options [Integer] :max_retries (3) The maximum number of times # service errors (500) should be retried. There is an exponential # backoff in between service request retries, so the more retries the # longer it can take to fail. # @option options [String, URI, nil] :proxy_uri (nil) The URI of the proxy # to send service requests through. You can pass a URI object or a # URI string: # # AWS.config(:proxy_uri => 'https://user:password@my.proxy:443/path?query') # # @option options [String] :s3_endpoint ('s3.amazonaws.com') The # service endpoint for Amazon S3. # # @option options [Integer] :s3_multipart_max_parts (1000) The maximum # number of parts to split a file into when uploading in parts to S3. # # @option options [Integer] :s3_multipart_threshold (16777216) When # uploading data to S3, if the number of bytes to send exceedes # +:s3_multipart_threshold+ then a multi part session is automatically # started and the data is sent up in chunks. The size of each part # is specified by +:s3_multipart_min_part_size+. Defaults to # 16777216 (16MB). # # @option options [Integer] :s3_multipart_min_part_size (5242880) The # absolute minimum size (in bytes) each S3 multipart segment should be. # Defaults to 5242880 (5MB). # # @option options [Symbol] :s3_server_side_encryption (nil) The # algorithm to use when encrypting object data on the server # side. The only valid value is +:aes256+, which specifies that # the object should be stored using the AES encryption algorithm # with 256 bit keys. Defaults to +nil+, meaning server side # encryption is not used unless specified on each individual # call to upload an object. This option controls the default # behavior for the following methods: # # * {S3::S3Object#write} # * {S3::S3Object#multipart_upload} # * {S3::S3Object#copy_from} and {S3::S3Object#copy_to} # * {S3::S3Object#presigned_post} # * {S3::Bucket#presigned_post} # # @option options [String] :secret_access_key (nil) AWS secret access # key credential. # # @option options [String,nil] :session_token (nil) AWS secret token # credential. # # @option options [String] :simple_db_endpoint ('sdb.amazonaws.com') The # service endpoint for Amazon SimpleDB. # # @option options [Boolean] :simple_db_consistent_reads (false) Determines # if all SimpleDB read requests should be done consistently. # Consistent reads are slower, but reflect all changes to SDB. # # @option options [String] :simple_email_service_endpoint ('email.us-east-1.amazonaws.com') # The service endpoint for Amazon Simple Email Service. # # @option options [Object] :signer (AWS::DefaultSigner) The request signer. Defaults to # a default request signer implementation. # # @option options [String] :ssl_ca_file The path to a CA cert bundle in # PEM format. # # If +:ssl_verify_peer+ is +true+ (the default) this bundle will be # used to validate the server certificate in each HTTPS request. # The AWS SDK for Ruby ships with a CA cert bundle, which is the # default value for this option. # # @option options [Boolean] :ssl_verify_peer (true) When +true+ # the HTTP handler validate server certificates for HTTPS requests. # # This option should only be disabled for diagnostic purposes; # leaving this option set to +false+ exposes your application to # man-in-the-middle attacks and can pose a serious security # risk. # # @option options[Boolean] :stub_requests (false) When +true+ requests # are not sent to AWS, instead empty reponses are generated and # returned to each service request. # # @option options [String] :sns_endpoint ('sns.us-east-1.amazonaws.com') The # service endpoint for Amazon SNS. # # @option options [String] :sqs_endpoint ('sqs.us-east-1.amazonaws.com') The # service endpoint for Amazon SQS. # # @option options [String] :sts_endpoint ('sts.amazonaws.com') The # service endpoint for AWS Security Token Service. # # @option options [Boolean] :use_ssl (true) When +true+, all requests # to AWS are sent using HTTPS instead vanilla HTTP. # # @option options [String] :user_agent_prefix (nil) A string prefix to # append to all requets against AWS services. This should be set # for clients and applications built ontop of the aws-sdk gem. # # @return [Core::Configuration] Returns the new configuration. def config options = {} @@config ||= Core::Configuration.new @@config = @@config.with(options) unless options.empty? @@config end # @note Memoization is currently only supported for the EC2 APIs; # other APIs are unaffected by the status of memoization. To # protect your code from future changes in memoization support, # you should not enable memoization while calling non-EC2 APIs. # # Starts memoizing service requests made in the current thread. # See {memoize} for a full discussion of the memoization feature. # This has no effect if memoization is already enabled. def start_memoizing Thread.current[:aws_memoization] ||= {} nil end # @note Memoization is currently only supported for the EC2 APIs; # other APIs are unaffected by the status of memoization. To # protect your code from future changes in memoization support, # you should not enable memoization while calling non-EC2 APIs. # # Stops memoizing service requests made in the current thread. # See {memoize} for a full discussion of the memoization feature. # This has no effect if memoization is already disabled. def stop_memoizing Thread.current[:aws_memoization] = nil end # @note Memoization is currently only supported for the EC2 APIs; # other APIs are unaffected by the status of memoization. To # protect your code from future changes in memoization support, # you should not enable memoization while calling non-EC2 APIs. # # @return [Boolean] True if memoization is enabled for the current # thread. See {memoize} for a full discussion of the # memoization feature. def memoizing? !Thread.current[:aws_memoization].nil? end # @note Memoization is currently only supported for the EC2 APIs; # other APIs are unaffected by the status of memoization. To # protect your code from future changes in memoization support, # you should not enable memoization while calling non-EC2 APIs. # # Enables memoization for the current thread, within a block. # Memoization lets you avoid making multiple requests for the same # data by reusing the responses which have already been received. # For example, consider the following code to get the most # recently launched EC2 instance: # # latest = ec2.instances.sort_by(&:launch_time).last # # The above code would make N+1 requests (where N is the number of # instances in the account); iterating the collection of instances # is one request, and +Enumerable#sort_by+ calls # {AWS::EC2::Instance#launch_time} for each instance, causing # another request per instance. We can rewrite the code as # follows to make only one request: # # latest = AWS.memoize do # ec2.instances.sort_by(&:launch_time).last # end # # Iterating the collection still causes a request, but each # subsequent call to {AWS::EC2::Instance#launch_time} uses the # results from that first request rather than making a new request # for the same data. # # While memoization is enabled, every response that is received # from the service is retained in memory. Therefore you should # use memoization only for short-lived blocks of code that make # relatively small numbers of requests. The cached responses are # used in two ways while memoization is enabled: # # 1. Before making a request, the SDK checks the cache for a # response to a request with the same signature (credentials, # service endpoint, operation name, and parameters). If such a # response is found, it is used instead of making a new # request. # # 2. Before retrieving data for an attribute of a resource # (e.g. {AWS::EC2::Instance#launch_time}), the SDK attempts to # find a cached response that contains the requested data. If # such a response is found, the cached data is returned instead # of making a new request. # # When memoization is disabled, all previously cached responses # are discarded. def memoize return yield if memoizing? begin start_memoizing yield if block_given? ensure stop_memoizing end end # @private def resource_cache if memoizing? Thread.current[:aws_memoization][:resource_cache] ||= Core::ResourceCache.new end end # @private def response_cache if memoizing? Thread.current[:aws_memoization][:response_cache] ||= Core::ResponseCache.new end end def add_service name, ruby_name, default_endpoint create_block = lambda do |config| AWS.const_get(name)::Client.new(:config => config) end needs = [:signer, :http_handler, :"#{ruby_name}_endpoint"] Core::Configuraiton.add_option :"#{ruby_name}_endpoint", default_endpoint Core::Configuraiton.add_option_with_needs( :"#{ruby_name}_client", needs, &create_block) end # Causes all requests to return empty responses without making any # requests against the live services. This does not attempt to # mock the services. # @return [nil] def stub! config(:stub_requests => true) nil end end end