I am trying to invoke a Yahoo Fantasy Sports API from Lambda. Per Yahoo's oauth documentation Yahoo's OAuth function expects to load a JSON file containing all of the tokens. This has been no problem on my local machine, where I would just pass the file as an argument. But now that I am migrating to Lambda it is not so simple.
I've tried multiple variations getting the oauth file from s3 (client/resource/bytes/dumps) and passing the contents of the file into the function. Without fail I get the same error message for each approach:
s3x = boto3.client('s3')
o_bucket='mysportss3bucket'
o_path = 'oauth2.json'
resp = s3x.get_object(Bucket=o_bucket, Key = o_path)['Body'].read()
sc = OAuth2(None, None, resp)
TypeError Traceback (most recent call last)
<ipython-input-49-fd439f281ac6> in <module>
1 print(resp)
----> 2 sc = OAuth2(None, None, resp)
TypeError: __init__() takes 3 positional arguments but 4 were given
I've also attempted storing the JSON file in the Lambda function itself, both in the parent directory and in a tmp directory where I am still getting this error in both scenarios.
{
"errorMessage": "[Errno 30] Read-only file system: 'tmp/oauth2.json'",
"errorType": "OSError",
"requestId": "7f23496c-50fa-4a49-b567-fd6bb66cabbc",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 13, in lambda_handler\n sc = OAuth2(None, None, from_file=x)\n",
" File \"/opt/python/lib/python3.9/site-packages/yahoo_oauth/oauth.py\", line 234, in __init__\n super(OAuth2, self).__init__('oauth2', consumer_key, consumer_secret, **kwargs)\n",
" File \"/opt/python/lib/python3.9/site-packages/yahoo_oauth/oauth.py\", line 100, in __init__\n write_data(data, vars(self).get('from_file', 'secrets.json'))\n",
" File \"/opt/python/lib/python3.9/site-packages/yahoo_oauth/utils.py\", line 41, in write_data\n return func(data, filename)\n",
" File \"/opt/python/lib/python3.9/site-packages/yahoo_oauth/utils.py\", line 46, in json_write_data\n with open(filename, 'w') as fp:\n"
]
}
I'm pretty new to Lambda and have spent several hours troubleshooting so I would greatly appreciate anyone's help. Thank you.
CodePudding user response:
There are a few things going on here. First, /tmp
is the only writeable directory in lambda. Second, the s3
contents are of type bytes
, not str
. Third, you are either passing in from a file, or you can just grab the desired contents from your s3
object. Exploring both:
from_file
s3x = boto3.client('s3')
o_bucket='mysportss3bucket'
o_path = 'oauth2.json'
# write to the temporary file
with open('/tmp/auth.json', 'wb') as fh:
fh.write(s3x.get_object(Bucket=o_bucket, Key = o_path)['Body'].read())
# pass in that path here
sc = OAuth2(None, None, from_file='/tmp/auth.json')
json
parsing
import json
s3x = boto3.client('s3')
o_bucket='mysportss3bucket'
o_path = 'oauth2.json'
# parse into dictionary here
resp = json.loads(
s3x.get_object(Bucket=o_bucket, Key = o_path)['Body'].read().decode()
)
# pass the required fields here
sc = OAuth2(resp['consumer_key'], resp['consumer_secret'])