Skip to content

Commit

Permalink
[AWS|DynamoDB] first pass at query/scan requests
Browse files Browse the repository at this point in the history
  • Loading branch information
geemus committed Feb 5, 2012
1 parent cbd2a4e commit 2d22c8b
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 18 deletions.
4 changes: 2 additions & 2 deletions lib/fog/aws/dynamodb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class DynamoDB < Fog::Service
request :get_item
request :list_tables
request :put_item
#request :query
#request :scan
request :query
request :scan
request :update_item
request :update_table

Expand Down
44 changes: 44 additions & 0 deletions lib/fog/aws/requests/dynamodb/query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Fog
module AWS
class DynamoDB
class Real

# Query DynamoDB items
#
# ==== Parameters
# * 'table_name'<~String> - name of table to query
# * 'hash_key'<~Hash> - hash key to query
# * options<~Hash>:
# * 'AttributesToGet'<~Array> - Array of attributes to get for each item, defaults to all
# * 'ConsistentRead'<~Boolean> - Whether to wait for consistency, defaults to false
# * 'Count'<~Boolean> - If true, returns only a count of such items rather than items themselves, defaults to false
# * 'Limit'<~Integer> - limit of total items to return
# * 'RangeKeyCondition'<~Hash>: value to compare against range key
# * 'AttributeValueList'<~Hash>: one or more values to compare against
# * 'ComparisonOperator'<~String>: comparison operator to use with attribute value list, in %w{BETWEEN BEGINS_WITH EQ LE LT GE GT}
# * 'ScanIndexForward'<~Boolean>: Whether to scan from start or end of index, defaults to start
# * 'ExclusiveStartKey'<~Hash>: Key to start listing from, can be taken from LastEvaluatedKey in response
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'ConsumedCapacityUnits'<~Integer> - number of capacity units used for query
# * 'Count'<~Integer> - number of items in response
# * 'Items'<~Array> - array of items returned
# * 'LastEvaluatedKey'<~Hash> - last key scanned, can be passed to ExclusiveStartKey for pagination
def query(table_name, hash_key, options = {})
body = {
'TableName' => table_name,
'HashKeyValue' => hash_key
}.merge(options)

request(
:body => MultiJson.encode(body),
:headers => {'x-amz-target' => 'DynamoDB_20111205.Query'}
)
end

end
end
end
end
44 changes: 44 additions & 0 deletions lib/fog/aws/requests/dynamodb/scan.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Fog
module AWS
class DynamoDB
class Real

# Scan DynamoDB items
#
# ==== Parameters
# * 'table_name'<~String> - name of table to query
# * options<~Hash>:
# * 'AttributesToGet'<~Array> - Array of attributes to get for each item, defaults to all
# * 'ConsistentRead'<~Boolean> - Whether to wait for consistency, defaults to false
# * 'Count'<~Boolean> - If true, returns only a count of such items rather than items themselves, defaults to false
# * 'Limit'<~Integer> - limit of total items to return
# * 'ScanFilter'<~Hash>: value to compare against
# * attribute_name<~Hash>:
# * 'AttributeValueList'<~Hash>: one or more values to compare against
# * 'ComparisonOperator'<~String>: comparison operator to use with attribute value list, in %w{BETWEEN BEGINS_WITH EQ LE LT GE GT}
# * 'ScanIndexForward'<~Boolean>: Whether to scan from start or end of index, defaults to start
# * 'ExclusiveStartKey'<~Hash>: Key to start listing from, can be taken from LastEvaluatedKey in response
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'ConsumedCapacityUnits'<~Integer> - number of capacity units used for scan
# * 'Count'<~Integer> - number of items in response
# * 'Items'<~Array> - array of items returned
# * 'LastEvaluatedKey'<~Hash> - last key scanned, can be passed to ExclusiveStartKey for pagination
# * 'ScannedCount'<~Integer> - number of items scanned before applying filters
def scan(table_name, options = {})
body = {
'TableName' => table_name
}.merge(options)

request(
:body => MultiJson.encode(body),
:headers => {'x-amz-target' => 'DynamoDB_20111205.Scan'}
)
end

end
end
end
end
7 changes: 2 additions & 5 deletions lib/fog/aws/requests/dynamodb/update_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ def update_item(table_name, key, attribute_updates, options = {})
'TableName' => table_name
}.merge(options)

idempotent = attribute_updates.has_key?('Action')

request(
:body => MultiJson.encode(body),
:headers => {'x-amz-target' => 'DynamoDB_20111205.UpdateItem'},
:idempotent => idempotent
:body => MultiJson.encode(body),
:headers => {'x-amz-target' => 'DynamoDB_20111205.UpdateItem'}
)
end

Expand Down
23 changes: 23 additions & 0 deletions tests/aws/requests/dynamodb/item_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@
Fog::AWS[:dynamodb].get_item(@table_name, {'HashKeyElement' => {'S' => 'notakey'}}).body
end

@query_format = {
'ConsumedCapacityUnits' => Integer,
'Count' => Integer,
'Items' => [{
'key' => { 'S' => String },
'value' => { 'S' => String }
}],
'LastEvaluatedKey' => NilClass
}

tests("#query('#{@table_name}', {'S' => 'key'}").formats(@query_format) do
pending if Fog.mocking?
pending # requires a table with range key
Fog::AWS[:dynamodb].query(@table_name, {'S' => 'key'}).body
end

@scan_format = @query_format.merge('ScannedCount' => Integer)

tests("scan('#{@table_name}')").formats(@scan_format) do
pending if Fog.mocking?
Fog::AWS[:dynamodb].scan(@table_name).body
end

tests("#delete_item('#{@table_name}', {'HashKeyElement' => {'S' => 'key'}})").formats('ConsumedCapacityUnits' => Float) do
pending if Fog.mocking?
Fog::AWS[:dynamodb].delete_item(@table_name, {'HashKeyElement' => {'S' => 'key'}}).body
Expand Down
24 changes: 13 additions & 11 deletions tests/vcloud/models/compute/conn_helper.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
module Fog
module Vcloud
class Fog::Connection
def request(params, &block)
path = File.expand_path(File.join(File.dirname(__FILE__),'..','..','data',params[:path].gsub(/^\//,'').gsub('/','_+_')))
if File.exists?(path)
body = File.read(path)
else
''
if false
class Fog::Connection
def request(params, &block)
path = File.expand_path(File.join(File.dirname(__FILE__),'..','..','data',params[:path].gsub(/^\//,'').gsub('/','_+_')))
if File.exists?(path)
body = File.read(path)
else
''
end
Excon::Response.new(
:body => body,
:status => 200,
:header => '')
end
Excon::Response.new(
:body => body,
:status => 200,
:header => '')
end
end
end
Expand Down

0 comments on commit 2d22c8b

Please sign in to comment.