Unity to Steam – Part 6 – AWS Lambda

Table Of Contents

Introduction

Now let’s interconnect our Linux server with Unity Cloud Build.

Lambda is the layer that will be opened to the world. Thanks to it, we will create a small web service that will get the information from Unity Cloud Build and start the Steam build process.

First of all, open the Lamba console:

Function creation

Then create a new Lambda function (top right button):

Fill the form like this:

  • Choose Author from scratch
  • Runtime: Python 3.8
  • Use exiting role (the one you created in the previous step): UCB-AmazonLambdaDeployOnSteam-Role

Click on Create function

On the bottom part of the screen, you should see a code editor. There select File > New file:

Copy/paste the code from GitHub : https://github.com/polycornegames/UCB-steam/blob/main/UCB-DeployOnSteam-Handler.py

import boto3
import time
import os
import re
import socket
import json

region = os.environ['REGION_ID']
ec2instance = os.environ['INSTANCE_ID']
s3bucket = os.environ['S3_BUCKET']

def lambda_handler(event, context):
    print(event);
    if event['body'] is None:
        print(f'Nothing provided within the request')
        return False
    
    body = json.loads(event['body'])
    if body['buildTargetName'] is None:
        print(f'Missing parameters')
        return False
        
    buildTargetName = body['buildTargetName']
    branch = ""
    if buildTargetName.startswith("PROD"):
        branch = "prod"
    elif buildTargetName.startswith("BETA"):
        branch = "beta"
    elif buildTargetName.startswith("DEVELOP"):
        branch = "develop"
    else:
        print(f'Missing branch')
        return False
    
    s3_path = "UCB/steam-parameters/UCB-parameters.conf"
    stringtowrite = branch + ",0.31"
    send_string_to_s3file(s3_path, stringtowrite)
    
    result = start_instance(ec2instance)
    if result == False:
        print(f'Startup of Instance {ec2instance} failed')
        return False
    else:
        print(f'Instance {ec2instance} started')
    
    return "Done"

def start_instance(instanceid):
    returncode = False
    ec2 = boto3.resource('ec2')
    ec2client = boto3.client('ec2', region_name=region)
    objinstance = ec2.Instance(id=instanceid)
    
    print(f' Instance {instanceid} is in state {objinstance.state["Name"]}')
    if objinstance.state["Code"] != 16:
        print(f' Starting instance {instanceid}...')
        ec2client.start_instances(InstanceIds=[instanceid])
    else:
        print(f'  No need to start it again')
    
    print(f' Waiting for instance to start (step 1)...')
    objinstance.wait_until_running(
        Filters=[
            {
                'Name': 'instance-id',
                'Values': [
                    instanceid,
                ]
            },
        ]
    )
    
    objinstance.reload()
    print(f' Instance {instanceid} in status {objinstance.state["Name"]} started with DNSname {objinstance.public_dns_name}')
    
    print(f' Waiting for instance to start (step 2)...')
    retries = 10
    retry_delay = 10
    retry_count = 0
    while retry_count <= retries:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = sock.connect_ex((objinstance.public_ip_address,22))
            if result == 0:
                print(f' Instance is UP & accessible on port 22, the IP address is: {objinstance.public_ip_address}')
                break
            else:
                print(" Instance is still down retrying...")
                time.sleep(retry_delay)
            retry_count = retry_count + 1
        except ClientError as e:
            retry_count = retry_count + 1
            print(f' Error {e}')
    
    if objinstance.state["Code"] == 16:
        returncode = True
    
        
    return returncode
        
def send_string_to_s3file(s3path, stringtowrite):
    encoded_string = stringtowrite.encode("utf-8")

    s3_client = boto3.client('s3',region_name=region)
    s3_client.put_object(Bucket=s3bucket, Key=s3path, Body=encoded_string)

Then save the file with this name:

UCB-DeployOnSteam-Handler.py

Now go to the Runtime settings section at the bottom and click on Edit:

Change the Handler field for the name of the fle you saved just before:

UCB-DeployOnSteam-Handler.lambda_handler

Now click on the Deploy button to enable your changes:

Now click on the Deploy button to enable your changes:

Click on Edit then Add environment variable 3x time to add 3x environment variables:

Use the data gathered previously:
INSTANCE_ID. For this example: i-0498da462121cc54b
REGION_ID. For this example: eu-west-1
S3_bucket. For this example: empire.org

Click on Save

Still in the Configuration tab, go to the General configuration section:

Increase the time out for this function otherwise it will not have the time to start the instance (it takes dozen of seconds to be executed). Click on Edit then enter 1 minute. Click on Save.

API Gateway creation

Now let’s add a trigger. This trigger will be used as a webhook by Unity Cloud Build to execute the Lambda function.

On the top of the screen, click on Add trigger:

Select in the list API Gateway and fill the form like this:

The security could be improved by using a different security settings than Open. I will let you investigate further to enable it.

Click on Add

Tests

In order to test our Lambda configuration and the linux server configuration at the same time, let’s create some test events associated with this Lambda function.

Return to the Code tab:

Use the following parameters to create your first test event:

The body on the test event simulate a request coming from Unity Cloud Build for a Develop branch build.

Click on Create.

Select the freshly created event then click on Test:

The function is now executed:

Few minutes later, you should receive an email like this:

Meaning that the full chain of the process is now done on the AWS side !

Add Comment