com.xebialabs.overcast.host.Ec2CloudHost.java Source code

Java tutorial

Introduction

Here is the source code for com.xebialabs.overcast.host.Ec2CloudHost.java

Source

/**
 *    Copyright 2012-2016 XebiaLabs B.V.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.xebialabs.overcast.host;

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.*;

import static com.google.common.collect.Lists.newArrayList;
import static com.xebialabs.overcast.OvercastProperties.getOvercastProperty;
import static com.xebialabs.overcast.OvercastProperties.getRequiredOvercastProperty;

class Ec2CloudHost implements CloudHost {

    public static final String AMI_AVAILABILITY_ZONE_PROPERTY_SUFFIX = ".amiAvailabilityZone";
    public static final String AMI_BOOT_SECONDS_PROPERTY_SUFFIX = ".amiBootSeconds";
    public static final String AMI_ID_PROPERTY_SUFFIX = ".amiId";
    public static final String AMI_INSTANCE_TYPE_PROPERTY_SUFFIX = ".amiInstanceType";
    public static final String AMI_KEY_NAME_PROPERTY_SUFFIX = ".amiKeyName";
    public static final String AMI_SECURITY_GROUP_PROPERTY_SUFFIX = ".amiSecurityGroup";
    public static final String AWS_ACCESS_KEY_PROPERTY = "aws.accessKey";
    public static final String AWS_ENDPOINT_DEFAULT = "https://ec2.amazonaws.com";
    public static final String AWS_ENDPOINT_PROPERTY = "aws.endpoint";
    public static final String AWS_SECRET_KEY_PROPERTY = "aws.secretKey";

    private final String hostLabel;
    private final String amiId;
    private final String awsEndpointURL;
    private final String awsAccessKey;
    private final String awsSecretKey;
    private final String amiAvailabilityZone;
    private final String amiInstanceType;
    private final String amiSecurityGroup;
    private final String amiKeyName;
    private final int amiBootSeconds;

    private AmazonEC2Client ec2;
    private String instanceId;
    private String publicDnsAddress;

    private static final Logger logger = LoggerFactory.getLogger(Ec2CloudHost.class);

    public Ec2CloudHost(String hostLabel, String amiId) {
        this.hostLabel = hostLabel;
        this.amiId = amiId;
        this.awsEndpointURL = getOvercastProperty(AWS_ENDPOINT_PROPERTY, AWS_ENDPOINT_DEFAULT);
        this.awsAccessKey = getRequiredOvercastProperty(AWS_ACCESS_KEY_PROPERTY);
        this.awsSecretKey = getRequiredOvercastProperty(AWS_SECRET_KEY_PROPERTY);
        this.amiAvailabilityZone = getOvercastProperty(hostLabel + AMI_AVAILABILITY_ZONE_PROPERTY_SUFFIX, null);
        this.amiInstanceType = getRequiredOvercastProperty(hostLabel + AMI_INSTANCE_TYPE_PROPERTY_SUFFIX);
        this.amiSecurityGroup = getRequiredOvercastProperty(hostLabel + AMI_SECURITY_GROUP_PROPERTY_SUFFIX);
        this.amiKeyName = getRequiredOvercastProperty(hostLabel + AMI_KEY_NAME_PROPERTY_SUFFIX);
        this.amiBootSeconds = Integer
                .valueOf(getRequiredOvercastProperty(hostLabel + AMI_BOOT_SECONDS_PROPERTY_SUFFIX));

        ec2 = new AmazonEC2Client(new BasicAWSCredentials(awsAccessKey, awsSecretKey));
        ec2.setEndpoint(awsEndpointURL);
    }

    @Override
    public void setup() {
        instanceId = runInstance();

        publicDnsAddress = waitUntilRunningAndGetPublicDnsName();

        setInstanceName();

        waitForAmiBoot();
    }

    @Override
    public void teardown() {
        ec2.terminateInstances(new TerminateInstancesRequest(newArrayList(instanceId)));
    }

    @Override
    public String getHostName() {
        return publicDnsAddress;
    }

    @Override
    public int getPort(int port) {
        return port;
    }

    public String getInstanceId() {
        return instanceId;
    }

    public String getPublicDnsAddress() {
        return publicDnsAddress;
    }

    public String getAmiId() {
        return amiId;
    }

    public String getHostLabel() {
        return hostLabel;
    }

    public String getAwsAccessKey() {
        return awsAccessKey;
    }

    public String getAwsSecretKey() {
        return awsSecretKey;
    }

    public String getAmiAvailabilityZone() {
        return amiAvailabilityZone;
    }

    public String getAmiInstanceType() {
        return amiInstanceType;
    }

    public String getAmiSecurityGroup() {
        return amiSecurityGroup;
    }

    public String getAmiKeyName() {
        return amiKeyName;
    }

    public int getAmiBootSeconds() {
        return amiBootSeconds;
    }

    protected String runInstance() {
        RunInstancesRequest run = new RunInstancesRequest(amiId, 1, 1);
        run.withInstanceInitiatedShutdownBehavior("terminate");
        if (amiInstanceType != null) {
            run.withInstanceType(amiInstanceType);
        }
        if (amiSecurityGroup != null) {
            run.withSecurityGroups(amiSecurityGroup);
        }
        if (amiKeyName != null) {
            run.withKeyName(amiKeyName);
        }
        if (amiAvailabilityZone != null) {
            run.withPlacement(new Placement(amiAvailabilityZone));
        }

        RunInstancesResult result = ec2.runInstances(run);

        return result.getReservation().getInstances().get(0).getInstanceId();
    }

    protected void setInstanceName() {
        ec2.createTags(new CreateTagsRequest(newArrayList(instanceId),
                newArrayList(new Tag("Name", hostLabel + " started at " + new Date()))));
    }

    public String waitUntilRunningAndGetPublicDnsName() {
        // Give Amazon some time to settle before we ask it for information
        sleep(5);

        for (;;) {
            DescribeInstancesRequest describe = new DescribeInstancesRequest()
                    .withInstanceIds(newArrayList(instanceId));
            Instance instance = ec2.describeInstances(describe).getReservations().get(0).getInstances().get(0);
            if (instance.getState().getName().equals("running")) {
                return instance.getPublicDnsName();
            }

            logger.info("Instance {} is still {}. Waiting...", instanceId, instance.getState().getName());
            sleep(1);
        }

    }

    protected void waitForAmiBoot() {
        logger.info("Waiting {} seconds for the image to finish booting", amiBootSeconds);
        sleep(amiBootSeconds);
    }

    private static void sleep(final int seconds) {
        try {
            Thread.sleep(seconds * 1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

}