dynamodb get_item boto3 Parameter validation failed - python

using boto3 I am trying to get a object in a dynamodb table.
following this stack overflow post the correct syntax is
client = boto3.client('dynamodb')
response = client.get_item(TableName='Garbage_collector_table', Key={'topic':{'S':str(my_topic)}})
Not able to get_item from AWS dynamodb using python?
http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html
I have tried various iterations to get proper syntax my current is this
if event['hcpcs_codes'] != None:
# codes must be in numerical, alphabetical order
# multi codes should be seperated by a comma with no spaces
client = boto3.client('dynamodb')
payload = {
"HCPCSCodeSet": event['hcpcs_codes']
}
response = client.get_item(TableName="mce-hcpcs-associations-table-dev",
Key={'HCPCSCodeSet':{'S': payload}})
print('here comes the tacos brah')
print(response)
Im not sure what this thing wants. What is the proper syntax?
Invalid type for parameter Key.HCPCSCodeSet, value: tacoman, type: <class 'str'>, valid types: <class 'dict'>
Traceback (most recent call last):
File "/var/task/lambdafile.py", line 18, in lambda_handler
Key= payload)
File "/var/task/botocore/client.py", line 415, in _api_call
the primary key name for the dynamodb database is
Partition key
HCPCSCodeSet (String)

This code:
payload = {
"HCPCSCodeSet": event['hcpcs_codes']
}
response = client.get_item(TableName="mce-hcpcs-associations-table-dev",
Key={'HCPCSCodeSet':{'S': payload}})
Ends up trying to send the following to DynamoDB:
Key={'HCPCSCodeSet':{'S': {
"HCPCSCodeSet": event['hcpcs_codes']
}}}
Which is obviously not correct. It's unclear why you are building the payload object at all. You could just do this:
response = client.get_item(TableName="mce-hcpcs-associations-table-dev",
Key={'HCPCSCodeSet':{'S': event['hcpcs_codes']}})

Related

Parse SQS stringify json message Python

I have a SQS queue which triggers a lambda function where as a message I pass the stringify json. I am trying to get the whole message body from the Records, but throws an error,
[ERROR] KeyError: 'efsPathIn'
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 20, in lambda_handler
key = bodyDict['efsPathIn']
I'm sending this stringify json as a message in SQS queue,
{"Records": [{"body": "{\"efsPathIn\": \"163939.jpeg\",\"imageWidth\": \"492\",\"imageHeight\": \"640\",\"bucketOut\":\"output-bucket\",\"keyOut\":\"163939.webp\"}"}]}
And the code is which extracts the values,
for item in event['Records']:
body = str(item['body'])
bodyDict = json.loads(body)
key = bodyDict['efsPathIn']
bucket_out = bodyDict['bucketOut']
width = bodyDict['imageWidth']
height = bodyDict['imageHeight']
key_out = bodyDict['keyOut']
I've tried with json.dumps(item['body']) also which further loads the json, but still getting the same error.
When I test from AWS Lambda test console using the above mentioned json message, the function gets successfully executed, but I get this error while sending a message from a SQS queue.
json.dumps() is for converting a Python object into a JSON string. You have a JSON string that you are need to convert into a Python object. You should be calling json.loads() like so:
body = json.loads(item['body'])
After which you will have a Python object that you can do things like: body['efsPathIn']

AWS boto3 invoke lambda returns None payload

I'm not quite sure why this piece of code fails, please I'd be happy to hear your thoughts. I've used examples from boto3 and its works in general, but I'd get an AttributeError all of a sudden in some cases. Please explain what I am doing wrong because if a payload is None, I will get a JSON decoding error but not a None object.
Here is a simplified version of a code that causes the exception.
import boto3
import json
client = boto3.client('lambda', region_name='...')
res = client.invoke(
FunctionName='func',
InvocationType='RequestResponse',
Payload=json.dumps({'param': 123})
)
payload = json.loads(res["Payload"].read().decode('utf-8'))
for k in payload.keys():
print(f'{k} = {payload[k]}')
The error
----
[ERROR] AttributeError: 'NoneType' object has no attribute 'keys'
Traceback (most recent call last):
.....
Just replicated your issue in my environment by creating a lambda that doesn't return anything and calling it using boto3. The "null" object passes through the json loads without error but doesn't have any keys since it's not a dictionary.
def lambda_handler(event, context):
pass
I created my code just like yours and got the same error. Weirdly, I was able to get the json error by attempting to print out the streaming body with this line
print(res["Payload"].read().decode('utf-8'))
before loading it. I have no idea why this happens.
Edit: Looks like once you read from the StreamingBody object it's empty from then on. https://botocore.amazonaws.com/v1/documentation/api/latest/reference/response.html#botocore.response.StreamingBody. My recommendation is to read the data from the streaming body and check for "null" and process as normal.

JSON Post body not parsing as expected

I have a python function hosted on aws that takes an event and then does a bunch of things, but essentially the problem lies at parsing the incoming POST request.
My code looks like this:
import json
def lambda_handler(event, context):
# TODO implement
merchantid = json.dumps(event['body'])
return {
'statusCode': 200,
'body': json.dumps(merchantid)
}
To send the post request I am just using the aws API Gateway test that comes with the website, so it shouldn't be any weird encoding.
As I am passing in a JSON object, I expect the merchantid field to be storing a json object.
Instead, it returns this string:
"\"{\\n \\\"merchantEmail\\\": \\\"timcook#gmail.com\\\",\\n \\\"customerEmail\\\": \\\"billgates#gmail.com\\\",\\n \\\"merchantWallet\\\": \\\"mWallet\\\",\\n \\\"transactionTotal\\\": 1.00,\\n \\\"transactionDenomination\\\": \\\"AUD\\\",\\n \\\"customerCurrency\\\": \\\"EUR\\\",\\n \\\"merchantAccess\\\" : {\\n \\\"merchantKey\\\": \\\"key\\\",\\n \\\"merchantSecret\\\": \\\"secret\\\"\\n },\\n \\\"customerAccess\\\" : {\\n \\\"customerKey\\\": \\\"ckey\\\",\\n \\\"customerSecret\\\": \\\"csecret\\\"\\n }\\n}\""
I have never seen a string like this, and I can not seem to get this to return to JSON format.
Does anybody know how I can return this to the orignal JSON format that was submitted in the body?
I should mention that the lambda_handler works perfectly fine with the JSON using the test event, it was only once I started to try and trigger it with the API Gateway that I started having this problem.
edit:
This is the JSON object I am passing as the body of the PUT request:
{
"merchantEmail": "timcook#gmail.com",
"customerEmail": "billgates#gmail.com",
"merchantWallet": "mWallet",
"transactionTotal": 1.00,
"transactionDenomination": "AUD",
"customerCurrency": "EUR",
"merchantAccess" : {
"merchantKey": "key",
"merchantSecret": "secret"
},
"customerAccess" : {
"customerKey": "ckey",
"customerSecret": "csecret"
}
}
edit:
Before I attached the API Gateway I was handling it with
merchantid = event['merchantEmail']
but once I passed it in as the body of a PUT is would return a 502 internal server error
First of all check this what is the datatype of the event params, Is it a string, or Is it dict.
if the datatype of body key value is JSON (dict)
merchantid = event.get('body').get('merchantEmail')
if the datatype of body key value is String (str)
merchantid = json.loads(event.get('body')).get('merchantEmail')
The event argument that you get into the Lambda function is a python dict.
Assuming you know the dict structure - all you need to do is the read the value you are looking for.
Example:
data = event['my_key']

Python Boto3 Module fetching API Keys with position parameter raising an exception

I tried to fetch list of API Keys created in my aws account. There are 50 Api keys. I want to list 10 Api Keys per request. Here is the code snippet.
import boto3
client = boto3.client('apigateway')
response = client.get_api_keys(
limit=10,
position="1",
)
print response
When I run the script, It is showing an error,
Traceback (most recent call last):
File "test.py", line 7, in <module>
position="1",
File "C:\Users\Murthy\workspace\my_project\venv\lib\site-packages\botocore\client.py", line 310, in _api_call
return self._make_api_call(operation_name, kwargs)
File "C:\Users\Murthy\workspace\my_project\venv\lib\site-packages\botocore\client.py", line 599, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.errorfactory.BadRequestException: An error occurred (BadRequestException) when calling the GetApiKeys operation: Invalid position parameter
Am I doing wrong ?
Also maximum results per query is 500. How do we know total number of results to perform the pagination ?
The position variable acts as a token. It is to be used to get the next page of your request.
In the first call to retrieve the usage plans, the position should be set to null, then to get the next page, you have to assign the position the value of the position in the previous response. The position variable is more like a token.
import boto3
client = boto3.client('apigateway')
response = client.get_api_keys(
limit=10,
position=null,
)
print response
Your response would be something like this
{
"position": "vWQ3Uzc4bAY2YQ%3D%3D",
"items": [
{
"id": "fqewi1",
"name": "3rd Party",
"description": null,
"apiStages": [],
"throttle": {
"burstLimit": 2,
"rateLimit": 1.0
},
.
.
.
}
Your next request would be in this format
import boto3
client = boto3.client('apigateway')
response = client.get_api_keys(
limit=10,
position="vWQ3Uzc4bAY2YQ%3D%3D",
)
print response
This would return the next page. For the last page, the position would be null.

Instagram API fails on follow_user(user_id)

I have auth'ed with Instagram API and can retrieve media objects with no problem. The function 'follow_user(user_id) returns this:
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/instagram/bind.py", line 84, in _build_path
raise Exception('No parameter value found for path variable: %s' % name)
Exception: No parameter value found for path variable: user_id
I've tried using a string, integer, and the media.user.id property as a parameter for this function but the same error each time.
My workaround is to use a manual HTTP POST request to the API using the Requests module:
payload = { "ACCESS_TOKEN" : "Your_Instagram_Access_Token_Here",
"action" : "follow"}
r = requests.post(r'https://api.instagram.com/v1/users/'+ user_id +'/relationship?access_token=Your_Instagram_API_Token_HERe',data=payload)
print r.text
Old question - but the correct call is...
api.follow_user(user_id=the_user_id)
...where 'the_user_id' is the ID number you're trying to follow.

Categories