com.kinesisboard.amazonaws.utils.CloudFormationUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.kinesisboard.amazonaws.utils.CloudFormationUtils.java

Source

/*
 * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Amazon Software License (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/asl/
 *
 * or in the "license" file accompanying this file. This file 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.kinesisboard.amazonaws.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.cloudformation.AmazonCloudFormation;
import com.amazonaws.services.cloudformation.model.CreateStackRequest;
import com.amazonaws.services.cloudformation.model.DescribeStacksRequest;
import com.amazonaws.services.cloudformation.model.Parameter;
import com.amazonaws.services.cloudformation.model.StackStatus;
import com.amazonaws.services.kinesis.connectors.KinesisConnectorConfiguration;

public class CloudFormationUtils {
    private static Log LOG = LogFactory.getLog(CloudFormationUtils.class);

    public static void createStackIfNotExists(AmazonCloudFormation client, KinesisConnectorConfiguration config) {
        String stackName = config.ELASTICSEARCH_CLOUDFORMATION_STACK_NAME;

        if (stackExists(client, stackName)) {
            StackStatus status = stackStatus(client, stackName);
            switch (status) {
            case CREATE_COMPLETE:
            case UPDATE_COMPLETE:
                LOG.info("Stack " + stackName + " already exists.");
                return;
            case CREATE_IN_PROGRESS:
            case UPDATE_IN_PROGRESS:
            case UPDATE_COMPLETE_CLEANUP_IN_PROGRESS:
                LOG.info("Stack " + stackName + " exists with status: " + status + ". Waiting for completion.");
                break;
            default:
                throw new IllegalStateException(
                        "Stack " + stackName + " exists but has an invalid status: " + status);
            }
        } else {
            CreateStackRequest createStackRequest = new CreateStackRequest();
            createStackRequest.setStackName(stackName);

            String templateBody = null;
            try {
                templateBody = loadTemplate(config.ELASTICSEARCH_CLOUDFORMATION_TEMPLATE_URL);
            } catch (IOException ioe) {
                LOG.error("Error reading template", ioe);
                throw new RuntimeException(
                        "Could not load template at location: " + config.ELASTICSEARCH_CLOUDFORMATION_TEMPLATE_URL);
            }
            createStackRequest.setTemplateBody(templateBody);

            List<Parameter> parameters = new ArrayList<Parameter>();
            parameters.add(new Parameter().withParameterKey("KeyName")
                    .withParameterValue(config.ELASTICSEARCH_CLOUDFORMATION_KEY_PAIR_NAME));
            parameters.add(new Parameter().withParameterKey("InstanceType")
                    .withParameterValue(config.ELASTICSEARCH_CLOUDFORMATION_CLUSTER_INSTANCE_TYPE));
            parameters.add(new Parameter().withParameterKey("SSHLocation")
                    .withParameterValue(config.ELASTICSEARCH_CLOUDFORMATION_SSH_LOCATION));
            parameters.add(new Parameter().withParameterKey("ClusterSize")
                    .withParameterValue(config.ELASTICSEARCH_CLOUDFORMATION_CLUSTER_SIZE));
            parameters.add(new Parameter().withParameterKey("ElasticsearchVersion")
                    .withParameterValue(config.ELASTICSEARCH_VERSION_NUMBER));
            createStackRequest.setParameters(parameters);

            List<String> capabilities = new ArrayList<String>();
            capabilities.add("CAPABILITY_IAM");
            createStackRequest.setCapabilities(capabilities);

            client.createStack(createStackRequest);
            LOG.info("Stack " + stackName + " is creating");
        }

        // now wait for good status
        while (true) {
            try {
                Thread.sleep(1000 * 10);
            } catch (Exception e) {
            }
            StackStatus status = stackStatus(client, stackName);
            switch (status) {
            case CREATE_COMPLETE:
            case UPDATE_COMPLETE:
                return;
            case CREATE_IN_PROGRESS:
            case UPDATE_IN_PROGRESS:
            case UPDATE_COMPLETE_CLEANUP_IN_PROGRESS:
                break;
            default:
                throw new IllegalStateException("Stack " + stackName + " failed to create with status: " + status);
            }
        }
    }

    private static String loadTemplate(String templateUrl) throws IOException {
        try (InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(templateUrl)) {
            if (input == null) {
                throw new IOException("Could not find template at location: " + templateUrl);
            }
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(input))) {
                StringBuilder stringBuilder = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line).append("\n");
                }
                return stringBuilder.toString();
            }
        }
    }

    private static boolean stackExists(AmazonCloudFormation client, String stackName) {
        DescribeStacksRequest describeStacksRequest = new DescribeStacksRequest();
        describeStacksRequest.setStackName(stackName);
        try {
            client.describeStacks(describeStacksRequest);
            return true;
        } catch (AmazonServiceException e) {
            return false;
        }
    }

    private static StackStatus stackStatus(AmazonCloudFormation client, String stackName) {
        DescribeStacksRequest describeStacksRequest = new DescribeStacksRequest();
        describeStacksRequest.setStackName(stackName);
        // describeStacks (with stack name specified) will return list of size 1 if found
        // and throw AmazonServiceException if no stack with that name exists
        try {
            return StackStatus
                    .fromValue(client.describeStacks(describeStacksRequest).getStacks().get(0).getStackStatus());
        } catch (AmazonServiceException ase) {
            return null;
        }
    }
}