All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atlassian.maven.plugins.aws.it.Provisioner.kt Maven / Gradle / Ivy

package com.atlassian.maven.plugins.aws.it

import com.amazonaws.services.cloudformation.AmazonCloudFormation
import com.amazonaws.services.cloudformation.AmazonCloudFormationClientBuilder
import com.amazonaws.services.cloudformation.model.*
import com.amazonaws.services.ec2.AmazonEC2
import com.amazonaws.services.ec2.AmazonEC2ClientBuilder
import com.amazonaws.services.ec2.model.CreateKeyPairRequest
import com.amazonaws.services.ec2.model.DescribeInstancesRequest
import com.amazonaws.services.ec2.model.KeyPair
import com.amazonaws.services.ec2.model.Reservation
import com.google.gson.Gson
import org.apache.commons.io.FileUtils.readFileToString
import org.apache.commons.io.FileUtils.writeStringToFile
import org.apache.maven.plugin.logging.Log
import java.io.File
import java.util.UUID.randomUUID

class Provisioner(
        private val awsRegion: String,
        private val cloudFormationTemplate: File,
        private val buildDirectory: File,
        private val log: Log
) {

    fun provision() {
        val id = "aws-integration-test-plugin-" + randomUUID().toString()
        val keyPairName = id
        val stackName = id
        val keyPair = createEc2Client().createKeyPair(CreateKeyPairRequest(keyPairName)).keyPair
        writeKeyPairToFile(keyPairName, keyPair)
        provisionStack(keyPairName, getCloudFormationTemplate(), stackName)
        writeStackResources(stackName, keyPairName)
    }

    private fun writeStackResources(stackName: String, keyPairName: String) {
        val ec2 = createEc2Client()
        val cloudFormation = createCloudFormationClient()

        val stacks = cloudFormation.listStackResources(
                ListStackResourcesRequest()
                        .withStackName(stackName))

        val ec2InstanceIds = stacks.stackResourceSummaries
                .filter({ it.resourceType == "AWS::EC2::Instance" })
                .map({ it.physicalResourceId })

        val instances = ec2.describeInstances(DescribeInstancesRequest().withInstanceIds(ec2InstanceIds))
                .reservations
                .flatMap(Reservation::getInstances)

        val stackInfo = StackInfo(
                awsRegion,
                stackName,
                keyPairName,
                instances
        )
        writeStackJson(stackInfo)
    }

    private fun provisionStack(keyPairName: String, cloudFormationTemplateBody: String, stackName: String) {
        val cloudFormationClient = createCloudFormationClient()

        val parameters = listOf(
                Parameter().withParameterKey("KeyName").withParameterValue(keyPairName)
        )

        cloudFormationClient.createStack(
                CreateStackRequest()
                        .withTags(listOf(
                                Tag().withKey("Name").withValue("aws-integration-test-plugin"),
                                Tag().withKey("service_name").withValue("aws-integration-test-plugin"),
                                Tag().withKey("business_unit").withValue("Engineering-Server"),
                                Tag().withKey("resource_owner").withValue("mkwidzinski")
                        ))
                        .withStackName(stackName)
                        .withTemplateBody(cloudFormationTemplateBody)
                        .withParameters(parameters)
        )

        waitForStackStartup(stackName)
    }

    private fun waitForStackStartup(stackName: String) {
        val cloudFormation = createCloudFormationClient()

        while (true) {
            val result = cloudFormation.describeStacks(DescribeStacksRequest().withStackName(stackName))
            val status = result.stacks[0].stackStatus
            when (status) {
                "CREATE_IN_PROGRESS" -> {
                    log.info("Waiting for stack $stackName startup, current status: $status")
                    Thread.sleep(5000)
                }
                "CREATE_COMPLETE" -> {
                    log.info("Stack $stackName successfully created")
                    return
                }
                else -> throw RuntimeException("Stack $stackName creation failed, status: $status")
            }
        }
    }

    private fun writeStackJson(stackInfo: StackInfo) {
        val json = Gson().toJson(stackInfo)
        writeStringToFile(File(buildDirectory, "stack.json"), json)
    }

    private fun getCloudFormationTemplate(): String {
        return readFileToString(cloudFormationTemplate)
    }

    private fun writeKeyPairToFile(keyPairName: String, keyPair: KeyPair) {
        val file = File(buildDirectory, "$keyPairName.pem")
        writeStringToFile(file, keyPair.keyMaterial)

        log.info("Private key location: ${file.absolutePath}")
    }

    private fun createEc2Client(): AmazonEC2 {
        return AmazonEC2ClientBuilder.standard()
                .withRegion(awsRegion)
                .build()
    }

    private fun createCloudFormationClient(): AmazonCloudFormation {
        return AmazonCloudFormationClientBuilder.standard()
                .withRegion(awsRegion)
                .build()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy