I have some simple Python code running as a REST service I use to automate the creation of Google calendar entries. The auth part of the code looks like this:
store = file.Storage('token.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets('credentials.json', SCOPES) creds = tools.run_flow(flow, store) calendar_service = build('calendar', 'v3', credentials=creds)
I’m attempting to move this to an AWS Lambda function. The same code running as a Lambda function results in the following error.
[ERROR] OSError: [Errno 30] Read-only file system: 'token.json' Traceback (most recent call last): File "/function/app-google-calendar.py", line 54, in handler insert_result = calendar_service.events().insert(calendarId=MENU_CALENDAR_ID, body=new_event).execute() File "/function/googleapiclient/_helpers.py", line 131, in positional_wrapper return wrapped(*args, **kwargs) File "/function/googleapiclient/http.py", line 922, in execute resp, content = _retry_request( File "/function/googleapiclient/http.py", line 190, in _retry_request resp, content = http.request(uri, method, *args, **kwargs) File "/function/oauth2client/transport.py", line 186, in new_request credentials._refresh(orig_request_method) File "/function/oauth2client/client.py", line 761, in _refresh self._do_refresh_request(http) File "/function/oauth2client/client.py", line 802, in _do_refresh_request self.store.locked_put(self) File "/function/oauth2client/file.py", line 85, in locked_put f = open(self._filename, 'w')
The root cause appears to be pretty clear. To wit, Lambda file system is read only. I however have been unable to find documentation or an example for how to do this oauth dance without requiring file system write access.
In the course of debugging this I ended up with some other strange errors, and in investigating those discovered that my root cause was a mismatch in architectures between my Mac and Lambda. I added
--platform=linux/amd64 to my
docker build command.
This still didn’t my original file system R/W issue with the JSON token file.
/tmp is writable, but it looks like it is wiped clean at image startup, so putting the credential files there when building your image doesn’t work. I ended up adding the following to
def handler(event, context): # Note moving token.json and credentials.json from same directory as python code to /tmp # because python code directory is not R/W and the Oauth dance to auth to google requires # the token file to be rewritten. Do this only if in lambda environment. We need to do this here and # not when the image is built, because /tmp seems to be wiped when the function image is starting if len(event) > 0: # We know we're in the lambda environment copyfile('/function/token.json', '/tmp/token.json') store = file.Storage('/tmp/token.json') else: # running locally store = file.Storage('token.json')