class Awscli::DynamoDB::Items

Public Class Methods

new(connection) click to toggle source
# File lib/awscli/dynamo.rb, line 79
def initialize(connection)
  @conn = connection
end

Public Instance Methods

batch_get(options) click to toggle source
# File lib/awscli/dynamo.rb, line 252
def batch_get(options)
  request_items = {}
  map = options[:requests].zip(options[:attrs_to_get])
  map.each do |request_attrs_mapping|
    #tbl1_name*,KeySet1(hash_key_type*=hash_key_value*:range_key_type=range_key_value),KeySet2,KeySetN
    table_name, *keys = request_attrs_mapping.first.split(',')
    attrs = request_attrs_mapping.last.split(':') unless request_attrs_mapping.last.nil?
    request_items[table_name] = {}
    request_items[table_name]['Keys'] = []
    keys.each do |key|
      parsed_key = {}
      hash_key, range_key = key.split(':')
      hash_key_type, hash_key_value = hash_key.split('=')
      parsed_key['HashKeyElement'] = { hash_key_type => hash_key_value }
      unless range_key.nil?
        range_key_type, range_key_value = range_key.split('=')
        parsed_key['RangeKeyElement'] = { range_key_type => range_key_value }
      end
      request_items[table_name]['Keys'] << parsed_key
    end
    request_items[table_name]['AttributesToGet'] = attrs unless attrs.nil?
  end
  puts @conn.batch_get_item(request_items).data[:body]['Responses'].to_yaml
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to get item from table. #{parse_excon_error_response($!)}"
end
batch_write(options) click to toggle source
# File lib/awscli/dynamo.rb, line 279
def batch_write(options)
  request_items = {}
  #request_items['RequestItems'] = {}
  options[:put_requests] and options[:put_requests].each do |request|
    #table_name,col_name1:col_type1:col_value1,col_name2:col_type2:col_value2 ..
    table_name, *cols = request.split(/,(?=(?:[^']|'[^']*')*$)/)
    request_items[table_name] ||= []
    put_request = {}
    put_request['PutRequest'] = {}
    put_request['PutRequest']['Item'] = {}
    cols.each do |col|
      col_name, col_type, col_value = col.split(':', 3)
      case col_type
        when 'N', 'S', 'B'
          put_request['PutRequest']['Item'][col_name] = { col_type => col_value }
        when 'NS', 'SS', 'BS'
          col_value_arry = col_value.split(';')
          abort 'Invalid attribute value format, attributes should be comma separated values' if col_value_arry.empty?
          put_request['PutRequest']['Item'][col_name] = { col_type => col_value_arry }
        else
          abort "Invalid attribute type: #{col_type}"
      end
    end
    request_items[table_name] << put_request
  end
  options[:delete_requests] and options[:delete_requests].each do |request|
    #table_name,KeySet1(hash_key_type*=hash_key_value*:range_key_type=range_key_value),KeySet2,KeySetN
    table_name, *keys = request.split(',')
    request_items[table_name] ||= []
    delete_request = {}
    delete_request['DeleteRequest'] = {}
    delete_request['DeleteRequest']['Key'] = {}
    keys.each do |key_set|
      hash_key, range_key = key_set.split(':')
      hash_key_type, hash_key_value = hash_key.split('=')
      delete_request['DeleteRequest']['Key']['HashKeyElement'] = { hash_key_type => hash_key_value }
      if range_key
        range_key_type, range_key_value = range_key.split('=')
        delete_request['DeleteRequest']['Key']['RangeKeyElement'] = { range_key_type => range_key_value }
      end
    end
    request_items[table_name] << delete_request
  end
  @conn.batch_write_item(request_items)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to batch put/delete item to/from table. #{parse_excon_error_response($!)}"
else
  puts 'Batch Put/Delete Succeeded'
end
delete(options) click to toggle source
# File lib/awscli/dynamo.rb, line 381
def delete(options)
  key = {}
  opts = {}
  #Build and validate key
  abort 'Invalid --hash-key format' unless options[:hash_key] =~ /(N|S|NS|SS|B|BS):(.*)/
  hash_key_type, hash_key_name = options[:hash_key].split(':')
  key['HashKeyElement'] = { hash_key_type => hash_key_name }
  if options[:range_key]
    abort 'Invalid --range-key format' unless options[:hash_key] =~ /(N|S|NS|SS|B|BS):(.*)/
    range_key_type, range_key_name = options[:range_key].split(':')
    key['RangeKeyElement'] = { range_key_type => range_key_name }
  end
  if options[:expected_attr] #-e
    expected_attr_name, expected_attr_type, expected_attr_value = options[:expected_attr].split(':')
    if expected_attr_name and expected_attr_type and expected_attr_value
      if options[:expected_exists] and options[:expected_exists] == 'true' #-e Id:S:001 -x true
        opts['Expected'] = { expected_attr_name => { 'Value' => { expected_attr_type => expected_attr_value }, 'Exists' => options[:expected_exists] } }
      else #-e Id:S:001
        opts['Expected'] = { expected_attr_name => { 'Value' => { expected_attr_type => expected_attr_value } } }
      end
    elsif expected_attr_name and not expected_attr_type and not expected_attr_value
      if options[:expected_exists] and options[:expected_exists] == 'false' #-e Id -x false
        opts['Expected'] = { expected_attr_name => { 'Exists' => options[:expected_exists] } }
      else
        abort 'Invalid option combination, see help for usage examples'
      end
    else
      abort 'Invalid option combination, see help for usage examples'
    end
  end
  if options[:return_values]
    abort 'Invalid return type' unless %w(ALL_NEW ALL_OLD NONE UPDATED_NEW UPDATED_OLD).include?(options[:return_values])
    opts['ReturnValues'] = options[:return_values]
  end
  @conn.delete_item(options[:table_name], key, opts)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to delete item. #{parse_excon_error_response($!)}"
else
  puts 'Item delete succeeded.'
end
get(options) click to toggle source
# File lib/awscli/dynamo.rb, line 218
def get(options)
  #get_item(table_name, key, options = {})
  opts = {}
  key = {}
  abort 'Invalid --hash-key format' unless options[:hash_key] =~ /(N|S|NS|SS|B|BS):(.*)/
  hash_key_type, hash_key_name = options[:hash_key].split(':')
  key['HashKeyElement'] = { hash_key_type => hash_key_name }
  if options[:range_key]
    abort 'Invalid --range-key format' unless options[:hash_key] =~ /(N|S|NS|SS|B|BS):(.*)/
    range_key_type, range_key_name = options[:range_key].split(':')
    key['RangeKeyElement'] = { range_key_type => range_key_name }
  end

  opts['AttributesToGet'] = options[:attrs_to_get] if options[:attrs_to_get]

  opts['ConsistentRead'] = true if options[:consistent_read]
  data = @conn.get_item(options[:table_name], key, opts)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to get item from table. #{parse_excon_error_response($!)}"
else
  #TODO: Pretty print this
  if not data.body['Item'].nil?
    puts 'Retrieved Items:'
    puts "ColumnName \t Type \t Value"
    data.body['Item'].each do |attr, pair|
      print "#{attr} \t"
      pair.map {|type,value|  print "#{type} \t #{value}"}
      puts
    end
  else
    puts 'No data retrieved'
  end
end
put(options) click to toggle source
# File lib/awscli/dynamo.rb, line 172
def put(options)
  items = {}
  opts = {}
  options[:item].each do |item|
    abort "invalid item format: #{item}" unless item =~ /(.*):(N|S|NS|SS|B|BS):(.*)/
    attr_name, attr_type, attr_value = item.split(':', 3)
    case attr_type
      when 'N', 'S', 'B'
        items[attr_name] = { attr_type => attr_value }
      when 'NS', 'SS', 'BS'
        attr_value_arry = attr_value.split(';')
        abort 'Invalid attribute value format, attributes should be comma separated values' if attr_value_arry.empty?
        items[attr_name] = { attr_type => attr_value_arry }
      else
        abort 'Invalid attribute type'
    end
  end
  if options[:expected_attr] #-a
    expected_attr_name, expected_attr_type, expected_attr_value = options[:expected_attr].split(':')
    if expected_attr_name and expected_attr_type and expected_attr_value
      if options[:expected_exists] and options[:expected_exists] == 'true' #-a Id:S:001 -e true
        opts['Expected'] = { expected_attr_name => { 'Value' => { expected_attr_type => expected_attr_value }, 'Exists' => options[:expected_exists] } }
      else #-a Id:S:001
        opts['Expected'] = { expected_attr_name => { 'Value' => { expected_attr_type => expected_attr_value } } }
      end
    elsif expected_attr_name and not expected_attr_type and not expected_attr_value
      if options[:expected_exists] and options[:expected_exists] == 'false' #-a Id -e false
        opts['Expected'] = { expected_attr_name => { 'Exists' => options[:expected_exists] } }
      else
        abort 'Invalid option combination, see help for usage examples'
      end
    else
      abort 'Invalid option combination, see help for usage examples'
    end
  end
  if options[:return_values]
    abort 'Invalid return type' unless %w(ALL_NEW ALL_OLD NONE UPDATED_NEW UPDATED_OLD).include?(options[:return_values])
    opts['ReturnValues'] = options[:return_values]
  end
  @conn.put_item(options[:table_name], items, opts)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to put item into table. #{parse_excon_error_response($!)}"
else
  puts 'Item put succeeded.'
end
query(options) click to toggle source
# File lib/awscli/dynamo.rb, line 83
def query(options)
  opts = {}
  hash_key_type, hash_key_value = options[:hash_key_value].split(',')
  hash_key = { hash_key_type => hash_key_value }
  opts['AttributesToGet'] = options[:attrs_to_get] if options[:attrs_to_get]
  opts['Limit'] = options[:limit] if options[:limit]
  opts['Count'] = options[:count] if options[:count]
  opts['ConsistentRead'] = options[:consistent_read] if options[:consistent_read]
  if options[:range_key_filter]
    operator, attr_type, attr_value = options[:range_key_filter].split(',')
    opts['RangeKeyCondition'] = {
        'AttributeValueList' => [{ attr_type => attr_value }],
        'ComparisonOperator' => operator
    }
  end
  opts['ScanIndexForward'] = options[:scan_index_forward]
  if options[:start_key]
    opts['ExclusiveStartKey'] = {}
    hash_key_type, hash_key_value = options[:start_key].split(',')
    opts['ExclusiveStartKey']['HashKeyElement'] = { hash_key_type => hash_key_value }
    if options[:start_range_key]
      range_key_type, range_key_value = options[:start_range_key].split(',')
      opts['ExclusiveStartKey']['RangeKeyElement'] = { range_key_type => range_key_value }
    end
  end
  p opts
  data = @conn.query(options[:table_name], hash_key, opts)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to perform scan on table. #{parse_excon_error_response($!)}"
else
  total_items = data.data[:body]['Count']
  items = data.data[:body]['Items']
  if not options[:count]
    puts "Retrieved #{total_items} Items"
    Formatador.display_table(items)
  else
    puts "Items Count: #{total_items}"
  end
  puts "LastEvaluatedKey: #{data.data[:body]['LastEvaluatedKey']}" if data.data[:body]['LastEvaluatedKey']
end
scan(options) click to toggle source
# File lib/awscli/dynamo.rb, line 124
def scan(options)
  opts = {}
  opts['AttributesToGet'] = options[:attrs_to_get] if options[:attrs_to_get]
  opts['Limit'] = options[:limit] if options[:limit]
  opts['ConsistentRead'] = options[:consistent_read] if options[:consistent_read]
  opts['Count'] = options[:count] if options[:count]
  if options[:scan_filter]
    #Operator(BETWEEN BEGINS_WITH EQ LE LT GE GT),Attr_Name,Attr_Type(N|S|B|NS|SS|BS),Attr_Value
    operator, attr_name, attr_type, attr_value = options[:scan_filter].split(',')
    #case operator
    #  when 'EQ', 'NE', 'LE', 'LT', 'GE', 'GT', 'CONTAINS', 'NOT_CONTAINS', 'BEGINS_WITH'
    #    #can contain only one AttributeValue element
    #  when 'BETWEEN'
    #    #contain two AttributeValue elements
    #  else
    #    #IN - can contain any number of AttributeValue elements
    #end
    opts['ScanFilter'] = {
        attr_name => {
            'AttributeValueList' => [{ attr_type => attr_value }],
            'ComparisonOperator' => operator
        }
    }
  end
  if options[:start_key]
    opts['ExclusiveStartKey'] = {}
    hash_key_type, hash_key_value = options[:start_key].split(',')
    opts['ExclusiveStartKey']['HashKeyElement'] = { hash_key_type => hash_key_value }
    if options[:start_range_key]
      range_key_type, range_key_value = options[:start_range_key].split(',')
      opts['ExclusiveStartKey']['RangeKeyElement'] = { range_key_type => range_key_value }
    end
  end
  data = @conn.scan(options[:table_name], opts)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to perform scan on table. #{parse_excon_error_response($!)}"
else
  total_items = data.data[:body]['Count']
  items = data.data[:body]['Items']
  if not options[:count]
    puts "Retrieved #{total_items} Items"
    Formatador.display_table(items)
  else
    puts "Items Count: #{total_items}"
  end
  puts "LastEvaluatedKey: #{data.data[:body]['LastEvaluatedKey']}" if data.data[:body]['LastEvaluatedKey']
end
update(options) click to toggle source
# File lib/awscli/dynamo.rb, line 329
def update(options)
  opts = {}
  key = {}
  attribute_updates = {}
  #Build and validate key
  abort 'Invalid --hash-key format' unless options[:hash_key] =~ /(N|S|NS|SS|B|BS):(.*)/
  hash_key_type, hash_key_name = options[:hash_key].split(':')
  key['HashKeyElement'] = { hash_key_type => hash_key_name }
  if options[:range_key]
    abort 'Invalid --range-key format' unless options[:hash_key] =~ /(N|S|NS|SS|B|BS):(.*)/
    range_key_type, range_key_name = options[:range_key].split(':')
    key['RangeKeyElement'] = { range_key_type => range_key_name }
  end
  #Build and validate attribute_updates
  options[:attr_updates].each do |attr_update|
    abort "invalid item format: #{attr_update}" unless attr_update =~ /(.*):(N|S|NS|SS|B|BS):(.*)/
    attr_name, attr_type, attr_value = attr_update.split(':')
    attribute_updates[attr_name] = {
        'Value' => {attr_type => attr_value},
        'Action' => options[:attr_updates_action]
    }
  end
  #Build and validate options if any
  if options[:expected_attr] #-a
    expected_attr_name, expected_attr_type, expected_attr_value = options[:expected_attr].split(':')
    if expected_attr_name and expected_attr_type and expected_attr_value
      if options[:expected_exists] and options[:expected_exists] == 'true' #-a Id:S:001 -e true
        opts['Expected'] = { expected_attr_name => { 'Value' => { expected_attr_type => expected_attr_value }, 'Exists' => options[:expected_exists] } }
      else #-a Id:S:001
        opts['Expected'] = { expected_attr_name => { 'Value' => { expected_attr_type => expected_attr_value } } }
      end
    elsif expected_attr_name and not expected_attr_type and not expected_attr_value
      if options[:expected_exists] and options[:expected_exists] == 'false' #-a Id -e false
        opts['Expected'] = { expected_attr_name => { 'Exists' => options[:expected_exists] } }
      else
        abort 'Invalid option combination, see help for usage examples'
      end
    else
      abort 'Invalid option combination, see help for usage examples'
    end
  end
  if options[:return_values]
    abort 'Invalid return type' unless %w(ALL_NEW ALL_OLD NONE UPDATED_NEW UPDATED_OLD).include?(options[:return_values])
    opts['ReturnValues'] = options[:return_values]
  end
  @conn.update_item(options[:table_name], key, attribute_updates, opts)
rescue Excon::Errors::BadRequest
  puts "[Error] Failed to update item. #{parse_excon_error_response($!)}"
else
  puts 'Item update succeeded.'
end

Private Instance Methods

parse_excon_error_response(response) click to toggle source
# File lib/awscli/dynamo.rb, line 424
def parse_excon_error_response(response)
  response.response.data[:body].match(/message.*|Message.*/)[0].gsub(/[^A-Za-z0-9: ]/, '')
end