Search code examples
python-3.xamazon-web-servicesboto3unzipamazon-gamelift

How do I update an AWS Gamelift script with boto3 in python?


I am running into a problem trying to update an AWS Gamelift script with a python command that zips a directory and uploads it with all its contents as a newer version to AWS Gamelift.

from zipfile import ZipFile
import os
from os.path import basename
import boto3
import sys, getopt

def main(argv):
    versInput = sys.argv[1]
    #initializes client for updating script in aws gamelift
    client = boto3.client('gamelift')

    #Where is the directory relative to the script directory. In this case, one folder dir lower and the contents of the RealtimeServer dir
    dirName = '../RealtimeServer'

    # create a ZipFile object
    with ZipFile('RealtimeServer.zip', 'w') as zipObj:
        # Iterate over all the files in directory
        for folderName, subfolders, filenames in os.walk(dirName):
            rootlen = len(dirName) + 1
            for filename in filenames:
                #create complete filepath of file in directory
                filePath = os.path.join(folderName, filename)
                # Add file to zip
                zipObj.write(filePath, filePath[rootlen:])

    response = client.update_script(
        ScriptId=SCRIPT_ID_GOES_HERE,
        Version=sys.argv[1],
        ZipFile=b'--zip-file \"fileb://RealtimeServer.zip\"'
    )

if __name__ == "__main__":
   main(sys.argv[1])

I plan on using it by giving it a new version number everytime I make changes with:

python updateScript.py "0.1.1"

This is meant to help speed up development. However, I am doing something wrong with the ZipFile parameter of client.update_script()

For context, I can use the AWS CLI directly from the commandline and update a script without a problem by using:

aws gamelift update-script --script-id SCRIPT_STRING_ID_HERE --script-version "0.4.5" --zip-file fileb://RealtimeServer.zip

However, I am not sure what is going on because it fails to unzip the file when I try it:

botocore.errorfactory.InvalidRequestException: An error occurred (InvalidRequestException) when calling the UpdateScript operation: Failed to unzip the zipped file.

UPDATE:

After reading more documentation about the ZipFile parameter:

https://docs.aws.amazon.com/gamelift/latest/apireference/API_UpdateScript.html

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/gamelift.html#GameLift.Client.update_script

I tried sending a base64 encoded version of the zip file. However, that didn't work. I put the following code before the client_update part of the script and used b64EncodedZip as the ZipFile parameter.

with open("RealtimeServer.zip", "rb") as f:
        bytes = f.read()
        b64EncodedZip = base64.b64encode(bytes)

Solution

  • I was able to get it to work by having some help from a maintainer of boto3 over at https://github.com/boto/boto3/issues/2646 (Thanks @swetashre)

    Here is the code and it will only work up to 5mb and requires use of an s3 bucket if you want to upload a zip file any larger than that.

    from zipfile import ZipFile
    import os
    from os.path import basename
    import boto3
    import sys, getopt
    
    def main(argv):
        versInput = sys.argv[1]
        #initializes client for updating script in aws gamelift
        client = boto3.client('gamelift')
    
        #Where is the directory relative to the script directory. In this case, one folder dir lower and the contents of the RealtimeServer dir
        dirName = '../RealtimeServer'
    
        # create a ZipFile object
        with ZipFile('RealtimeServer.zip', 'w') as zipObj:
            # Iterate over all the files in directory
            for folderName, subfolders, filenames in os.walk(dirName):
                rootlen = len(dirName) + 1
                for filename in filenames:
                    #create complete filepath of file in directory
                    filePath = os.path.join(folderName, filename)
                    # Add file to zip
                    zipObj.write(filePath, filePath[rootlen:])
    
        with open('RealtimeServer.zip','rb') as f:
            contents = f.read()
    
        response = client.update_script(
            ScriptId="SCRIPT_ID_GOES_HERE",
            Version=sys.argv[1],
            ZipFile=contents
        )
    
    if __name__ == "__main__":
       main(sys.argv[1])