Dropwizard bundle to signal the AWS AutoScalingGroup via AWS CloudFormation SignalResource API when running on an AWS EC2 instance.
Switch branches/tags
Nothing to show
Clone or download
Latest commit c1b34e0 Dec 21, 2016

README.md

cf-signal-resource-bundle

Dropwizard bundle to signal the AWS AutoScalingGroup via the AWS CloudFormation SignalResource API when running on an AWS EC2 instance.

Why does this exist

If you're deploying Dropwizard webservices on AWS using CloudFormation Templates and AutoScaling Groups with Rolling Updates then this is the bundle you've been looking for!

In short it makes your time to perform a rolling deploy as short as possible as it only depends on how fast your app can start. It's very handy when you app needs to do some work at startup sometimes (database migrations, provisioning, etc), but not others.

How to Use this bundle

CloudFormation Template

The key here is to set the Resources.<YourASG_Name>.UpdatePolicy.WaitOnResourceSignals to true. You can read up on what that means exactly here but the TL;DR is have the rolling update wait until signaled that everything worked to continue. This bundle provides that signaling!

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "AWS CloudFormation for a Dropwizard.io Webservice using instances in a AutoScalingGroup.",
  "Parameters" : {...},
  "Resources" : {
    "DropwizardWebserviceASG" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "UpdatePolicy" : {
        "AutoScalingRollingUpdate": {
          "MaxBatchSize": "2",
          "MinInstancesInService": 2,
          "PauseTime": "PT10M",
          "SuspendProcesses": [
            "HealthCheck",
            "ReplaceUnhealthy",
            "AZRebalance",
            "AlarmNotification",
            "ScheduledActions"
          ],
          "WaitOnResourceSignals": "true"
        }
      },
      "Properties" : {
        "AvailabilityZones" : [
          "us-west-2a",
          "us-west-2b"
        ],
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
        "MinSize" : 2,
        "MaxSize" : 8
      }
    },
    {...other resources}
  }
}

The credentials used by your CloudFormation client need to have the following permissions:

  • cloudformation:DescribeStackResource
    • Used to confirm that a stack update is in progress, before attempting to signal the resource state.
  • cloudformation:SignalResource

Maven Dependency

Add this to your Dropwizard Webservice pom.xml.

<dependency>
  <groupId>net.eldeen.dropwizard</groupId>
  <artifactId>cf-signal-resource-bundle</artifactId>
  <version>2.1</version>
<dependency>

Registering the Bundle

In your class that extends io.dropwizard.Application add the bundle. Use config to provide the name of the AutoScalingGroup, the Stack Name, and the AWS Region.

public class Main extends Application <AppConfig> {

  @Override
  public void initialize(Bootstrap<StipendConfig> bootstrap) {
  
    bootstrap.addBundle(new CfSignalResourceBundle());
  }
  
  // [...]

}

Your application's Dropwizard Config should look like this:

public class AppConfig extends Configuration {

    @Valid
    @NotNull
    private CfSignalResourceConfig cfSignalResource;

    @JsonProperty
    public CfSignalResourceConfig getCfSignalResource() {
      return cfSignalResourceConfig;
    }
    
    // [...]
  }

And add the actual config values to your configuration yml. The config values awsRegion and ec2InstanceId are optional. If missing they will be fetched from com.amazonaws.util.EC2MetadataUtils#getEC2InstanceRegion() and com.amazonaws.util.EC2MetadataUtils#getInstanceId() respectively.

Typical config:

cfSignalResource:
  asgResourceName: yourASG_ResourceName
  stackName: yourASG_StackName

Full config:

cfSignalResource:
  asgResourceName: yourASG_ResourceName
  stackName: yourASG_StackName
  ec2InstanceId: yourASG_spun_up_ec2InstanceId
  awsRegion: us-west-2

Skipping AWS CloudFormation SignalResource for non-AWS environments

If you have the case where you deploy the same Dropwizard Artifact in environments that are not AWS, you'll want to skip trying to signal an ASG that isn't there. Setup your config for that environment like so:

cfSignalResource:
  skip: true

All the other values are ignored when skip: true is present so they can be omitted. The CfSignalResourceBundle will not attempt to do any AWS related calls when this value is true.

Environment Variables and Config

If you have these values as environment variables you may want to have Dropwizard use those instead.

public class Main extends Application<AppConfig> {
    // [...]
    @Override
    public void initialize(Bootstrap<AppConfig> bootstrap) {
        // Enable variable substitution with environment variables
        bootstrap.setConfigurationSourceProvider(
                new SubstitutingSourceProvider(bootstrap.getConfigurationSourceProvider(),
                                                   new EnvironmentVariableSubstitutor()
                )
        );

    }

    // [...]
}

The config yaml can use the environment variable values, or provide defaults if they aren't set, following the rules of the configured EnvironmentVariableSubstitutor from above.

cfSignalResource:
  asgResourceName: ${ASG_RESOURCE_NAME}
  stackName: ${ASG_STACK_NAME:-yourASG_StackName}

License

Apache License Version 2.0