diff --git a/lib/fog/aws/models/rds/instance_option.rb b/lib/fog/aws/models/rds/instance_option.rb new file mode 100644 index 000000000..4db63e75d --- /dev/null +++ b/lib/fog/aws/models/rds/instance_option.rb @@ -0,0 +1,21 @@ +require 'fog/core/model' + +module Fog + module AWS + class RDS + + class InstanceOption < Fog::Model + + attribute :multi_az_capable, :aliases => 'MultiAZCapable', :type => :boolean + attribute :engine, :aliases => 'Engine' + attribute :license_model, :aliases => 'LicenseModel' + attribute :read_replica_capable, :aliases => 'ReadReplicaCapable', :type => :boolean + attribute :engine_version, :aliases => 'EngineVersion' + attribute :availability_zones, :aliases => 'AvailabilityZones', :type => :array + attribute :db_instance_class, :aliases => 'DBInstanceClass' + attribute :vpc, :aliases => 'Vpc', :type => :boolean + + end + end + end +end diff --git a/lib/fog/aws/models/rds/instance_options.rb b/lib/fog/aws/models/rds/instance_options.rb new file mode 100644 index 000000000..ededf6590 --- /dev/null +++ b/lib/fog/aws/models/rds/instance_options.rb @@ -0,0 +1,30 @@ +require 'fog/core/collection' +require 'fog/aws/models/rds/instance_option' + +module Fog + module AWS + class RDS + + class InstanceOptions < Fog::PagedCollection + attribute :filters + attribute :engine + model Fog::AWS::RDS::InstanceOption + + def initialize(attributes) + self.filters ||= {} + super + end + + # This method deliberately returns only a single page of results + def all(filters=filters) + self.filters.merge!(filters) + + result = service.describe_orderable_db_instance_options(engine, self.filters).body['DescribeOrderableDBInstanceOptionsResult'] + self.filters[:marker] = result['Marker'] + load(result['OrderableDBInstanceOptions']) + end + + end + end + end +end diff --git a/lib/fog/aws/parsers/rds/describe_orderable_db_instance_options.rb b/lib/fog/aws/parsers/rds/describe_orderable_db_instance_options.rb new file mode 100644 index 000000000..8535c9330 --- /dev/null +++ b/lib/fog/aws/parsers/rds/describe_orderable_db_instance_options.rb @@ -0,0 +1,47 @@ +module Fog + module Parsers + module AWS + module RDS + + class DescribeOrderableDBInstanceOptions < Fog::Parsers::Base + + def reset + @response = { 'DescribeOrderableDBInstanceOptionsResult' => {'OrderableDBInstanceOptions' => []}, 'ResponseMetadata' => {} } + @db_instance_option = {} + @db_instance_options = [] + end + + def start_element(name, attrs = []) + case name + when 'AvailabilityZones' then @availability_zones = [] + when 'AvailabilityZone' then @availability_zone = {} + end + super + end + + def end_element(name) + case name + when 'MultiAZCapable', 'ReadReplicaCapable', 'Vpc' then @db_instance_option[name] = to_boolean(value) + when 'Engine', 'LicenseModel', 'EngineVersion', 'DBInstanceClass' then @db_instance_option[name] = value + when 'AvailabilityZones' then @db_instance_option[name] = @availability_zones + when 'AvailabilityZone' then @availability_zones << @availability_zone unless @availability_zone.empty? + when 'Name' then @availability_zone[name] = value + when 'ProvisionedIopsCapable' then @availability_zone[name] = to_boolean(value) + when 'OrderableDBInstanceOption' + @db_instance_options << @db_instance_option + @db_instance_option = {} + when 'OrderableDBInstanceOptions' + @response['DescribeOrderableDBInstanceOptionsResult']['OrderableDBInstanceOptions'] = @db_instance_options + when 'Marker' then @response['DescribeOrderableDBInstanceOptionsResult'][name] = value + when 'RequestId' then @response['ResponseMetadata'][name] = value + end + end + + def to_boolean(v) + (v =~ /\A\s*(true|yes|1|y)\s*$/i) == 0 + end + end + end + end + end +end diff --git a/lib/fog/aws/rds.rb b/lib/fog/aws/rds.rb index 37d70dfad..4e51e214b 100644 --- a/lib/fog/aws/rds.rb +++ b/lib/fog/aws/rds.rb @@ -51,6 +51,8 @@ module Fog request :describe_db_subnet_groups # TODO: :delete_db_subnet_group, :modify_db_subnet_group + request :describe_orderable_db_instance_options + request :describe_db_log_files request :download_db_logfile_portion @@ -73,6 +75,9 @@ module Fog model :subnet_group collection :subnet_groups + model :instance_option + collection :instance_options + model :log_file collection :log_files diff --git a/lib/fog/aws/requests/rds/describe_orderable_db_instance_options.rb b/lib/fog/aws/requests/rds/describe_orderable_db_instance_options.rb new file mode 100644 index 000000000..3b0163fb1 --- /dev/null +++ b/lib/fog/aws/requests/rds/describe_orderable_db_instance_options.rb @@ -0,0 +1,76 @@ +module Fog + module AWS + class RDS + class Real + + require 'fog/aws/parsers/rds/describe_orderable_db_instance_options' + + # Describe all or specified load db instances + # http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_DescribeDBInstances.html + # ==== Parameters + # * Engine <~String> - The name of the engine to retrieve DB Instance options for. Required. + # * Options <~Hash> - Hash of options. Optional. The following keys are used: + # * :db_instance_class <~String> - Filter available offerings matching the specified DB Instance class. Optional. + # * :engine_version <~String> - Filters available offerings matching the specified engine version. Optional. + # * :license_model <~String> - Filters available offerings matching the specified license model. Optional. + # * :marker <~String> - The pagination token provided in the previous request. If this parameter is specified the response includes only records beyond the marker, up to MaxRecords. Optional. + # * :max_records <~Integer> - The maximum number of records to include in the response. If more records exist, a pagination token is included in the response. Optional. + # * :vpc <~Boolean> - Filter to show only the available VPC or non-VPC offerings. Optional. + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + def describe_orderable_db_instance_options(engine=nil, opts={}) + params = {} + params['Engine'] = engine if engine + params['DBInstanceClass'] = opts[:db_instance_class] if opts[:db_instance_class] + params['EngineVersion'] = opts[:engine_version] if opts[:engine_version] + params['LicenseModel'] = opts[:license_model] if opts[:license_model] + params['Marker'] = opts[:marker] if opts[:marker] + params['MaxRecords'] = opts[:max_records] if opts[:max_records] + params['Vpc'] = opts[:vpc] if opts[:vpc] + + request({ + 'Action' => 'DescribeOrderableDBInstanceOptions', + :parser => Fog::Parsers::AWS::RDS::DescribeOrderableDBInstanceOptions.new + }.merge(params)) + end + + end + + class Mock + + def describe_orderable_db_instance_options(engine=nil, opts={}) + instance_options = [] + response = Excon::Response.new + if engine + (opts[:db_instance_class] || %w(db.m2.xlarge db.m1.large)).each do |size| + instance_options << {'MultiAZCapable' => true, + 'Engine' => engine, + 'LicenseModel' => opts[:license_model] || 'general-public-license', + 'ReadReplicaCapable' => true, + 'EngineVersion' => opts[:engine_version] || '5.6.12', + 'AvailabilityZones' => [ + {'Name' => 'us-east-1b', 'ProvisionedIopsCapable' => true}, + {'Name' => 'us-east-1c', 'ProvisionedIopsCapable' => true}, + {'Name' => 'us-east-1d', 'ProvisionedIopsCapable' => false}, + {'Name' => 'us-east-1e', 'ProvisionedIopsCapable' => true}], + 'DBInstanceClass' => size, + 'Vpc' => opts[:vpc].nil? ? true : opts[:vpc]} + + end + else + raise Fog::AWS::RDS::NotFound.new('An engine must be specified to retrieve orderable instance options') + end + + response.status = 200 + response.body = { + 'ResponseMetadata' => { 'RequestId' => Fog::AWS::Mock.request_id }, + 'DescribeOrderableDBInstanceOptionsResult' => { 'OrderableDBInstanceOptions' => instance_options } + } + response + end + + end + end + end +end diff --git a/lib/fog/core/collection.rb b/lib/fog/core/collection.rb index 993c9a729..b6770a6ed 100644 --- a/lib/fog/core/collection.rb +++ b/lib/fog/core/collection.rb @@ -142,4 +142,22 @@ module Fog 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 diff --git a/tests/aws/models/rds/instance_option_tests.rb b/tests/aws/models/rds/instance_option_tests.rb new file mode 100644 index 000000000..15d919a1f --- /dev/null +++ b/tests/aws/models/rds/instance_option_tests.rb @@ -0,0 +1,14 @@ +Shindo.tests("AWS::RDS | db instance options", ['aws', 'rds']) do + + params = {:engine => 'mysql'} + + pending if Fog.mocking? + + tests('#options') do + tests 'contains options' do + @instance = Fog::AWS[:rds].instance_options.new(params) + returns(true) { @instance.engine == 'mysql' } + end + end + +end diff --git a/tests/aws/requests/rds/helper.rb b/tests/aws/requests/rds/helper.rb index a78f99aa3..b41dee696 100644 --- a/tests/aws/requests/rds/helper.rb +++ b/tests/aws/requests/rds/helper.rb @@ -8,6 +8,11 @@ class AWS 'ResponseMetadata' => {'RequestId' => String} } + DB_AVAILABILITY_ZONE_OPTION = { + 'Name' => String, + 'ProvisionedIopsCapable' => Fog::Boolean + } + DB_PARAMETER_GROUP = { 'DBParameterGroupFamily' => String, 'DBParameterGroupName'=> String, @@ -79,6 +84,23 @@ class AWS } } + ORDERABLE_DB_INSTANCE_OPTION = { + 'MultiAZCapable' => Fog::Boolean, + 'Engine' => String, + 'LicenseModel' => String, + 'ReadReplicaCapable' => Fog::Boolean, + 'EngineVersion' => String, + 'AvailabilityZones' => [DB_AVAILABILITY_ZONE_OPTION], + 'DBInstanceClass' => String, + 'Vpc' => Fog::Boolean + } + + DESCRIBE_ORDERABLE_DB_INSTANCE_OPTION = BASIC.merge({ + 'DescribeOrderableDBInstanceOptionsResult' =>{ + 'OrderableDBInstanceOptions' => [ORDERABLE_DB_INSTANCE_OPTION] + } + }) + MODIFY_PARAMETER_GROUP = BASIC.merge({ 'ModifyDBParameterGroupResult' => { 'DBParameterGroupName' => String diff --git a/tests/aws/requests/rds/instance_option_tests.rb b/tests/aws/requests/rds/instance_option_tests.rb new file mode 100644 index 000000000..95f780a3f --- /dev/null +++ b/tests/aws/requests/rds/instance_option_tests.rb @@ -0,0 +1,21 @@ +Shindo.tests('AWS::RDS | db instance option requests', ['aws', 'rds']) do + tests('success') do + + tests("#describe_orderable_db_instance_options('mysql)").formats(AWS::RDS::Formats::DESCRIBE_ORDERABLE_DB_INSTANCE_OPTION) do + + body = Fog::AWS[:rds].describe_orderable_db_instance_options('mysql').body + + returns(2) {body['DescribeOrderableDBInstanceOptionsResult']['OrderableDBInstanceOptions'].length} + + group = body['DescribeOrderableDBInstanceOptionsResult']['OrderableDBInstanceOptions'].first + returns( true ) { group['MultiAZCapable'] } + returns( 'mysql' ) { group['Engine'] } + returns( true ) { group['ReadReplicaCapable'] } + returns( true ) { group['AvailabilityZones'].length >= 1 } + + body + end + + end + +end