Friday, January 26, 2018

Using the AWS PHP SDK to get a current EC2 node from a group of nodes

When porting a Drupal application from on-site to cloud hosting, one of the issues was the use of drush aliases in one environment for drush commands to be run against the cloud environment.  Since EC2 nodes in an autoscaling group can be replaced at any time, the developers needed an alternative to hard-coding IPs.

Below is a snippet of a drushrc file.  Assuming the aws.phar is in the same folder as the drushrc, and the AWS CLI is properly configured with credentials (or, if this is on an EC2 instance, an IAM role is applied), this will query for nodes matching a tag "Group" and return the list.  The drush aliases are then set to reference only the first response for the query.

Multiple filters can be applied in the query, just be sure to create a second array under Filters.

<?php
require 'aws.phar';
//===================================================================
// Readme:
//===================================================================
// To populate hostnames based on current live values, look up from AWS directly.
// Requires:
// - aws.phar in same folder as this script, or full path specified in the above require
// - IAM role assigned to node that allows Get* for ec2
//
// See https://docs.aws.amazon.com/aws-sdk-php/v3/guide/getting-started/installation.html#installing-via-phar for how to get the aws.phar file
//
// In the "Set Nodes" block, always specify index [0] to ensure only one name comes back (prod farms have multiple nodes)
//===================================================================

//===================================================================
// Set up connection:
//===================================================================
$ec2 = new Aws\Ec2\Ec2Client([
     'version' => 'latest',
     'region' => 'us-east-1' 
]);

//===================================================================
// Get Nodes - retrieves all nodes matching said filters
//===================================================================
$dev_nodes = $ec2->describeInstances([
     'Filters' => [
        [
            'Name' => 'tag:Group',
            'Values' => ['myfancyappdev']
        ]
     ]
]); 

$qa_nodes = $ec2->describeInstances([
     'Filters' => [
        [
            'Name' => 'tag:Group',
            'Values' => ['myfancyappqa']
        ]
     ]
]); 

$prod_nodes = $ec2->describeInstances([
     'Filters' => [
        [
            'Name' => 'tag:Group',
            'Values' => ['myfancyappprod']
        ]
     ]
]); 

//===================================================================
// Set Nodes - assign public DNS of first node to var to use later
//===================================================================
$dev = $dev_nodes['Reservations'][0]['Instances'][0]['PublicDnsName'];
$qa = $qa_nodes['Reservations'][0]['Instances'][0]['PublicDnsName'];
$prod = $prod_nodes['Reservations'][0]['Instances'][0]['PublicDnsName'];
//===================================================================

// environment dev
$aliases['dev'] = array(
  'remote-host' => $dev,
);

// environment qa
$aliases['qa'] = array(
  'remote-host' => $qa,
);

// prod
$aliases['prod'] = array(
  'remote-host' => $prod,
);