Commit 4ab1bf46 authored by Andreas Muttscheller's avatar Andreas Muttscheller

Add tasks to start, list and stop mockserver ECS tasks

parent fc943a12
......@@ -8,7 +8,7 @@ ThisBuild / scalacOptions := Seq(
ThisBuild / javacOptions ++= Seq("-encoding", "UTF-8")
ThisBuild / javaOptions ++= Seq("-Dfile.encoding=UTF-8")
addCommandAlias("cloudItTest", "; it:awsCleanup; it:test; it:awsCleanup")
addCommandAlias("cloudItTest", "; it:awsCleanup; it:startECSMockServer; it:test; it:stopECSMockServer it:awsCleanup")
lazy val root = (project in file("."))
.configs(IntegrationTest)
......@@ -25,7 +25,7 @@ lazy val root = (project in file("."))
fork in IntegrationTest := true,
testOptions in IntegrationTest += Tests.Argument("-oDF"),
envVars in IntegrationTest := Map(
envVars in IntegrationTest ++= Map(
"SERVERLESS_SERVICE" -> (awsServiceName in IntegrationTest).value,
"SERVERLESS_STAGE" -> (awsStage in IntegrationTest).value,
"SLACK_API_URL" -> "http://localhost:1080/slack/",
......
import java.util.function.Consumer
import com.amazonaws.services.dynamodbv2.document.{DynamoDB, Table}
import com.amazonaws.services.dynamodbv2.model._
import com.amazonaws.services.dynamodbv2.model.{BillingMode, CreateTableRequest, GlobalSecondaryIndex, GlobalSecondaryIndexDescription}
import com.amazonaws.services.dynamodbv2.{AmazonDynamoDB, AmazonDynamoDBClientBuilder}
import com.amazonaws.services.ec2.AmazonEC2ClientBuilder
import com.amazonaws.services.ec2.model.DescribeNetworkInterfacesRequest
import com.amazonaws.services.ecs.AmazonECSClientBuilder
import com.amazonaws.services.ecs.model._
import com.amazonaws.services.elasticsearch.AWSElasticsearchClientBuilder
import com.amazonaws.services.elasticsearch.model.DescribeElasticsearchDomainRequest
import com.sksamuel.elastic4s.aws.Aws4ElasticClient
......@@ -10,6 +14,7 @@ import com.sksamuel.elastic4s.http.ElasticDsl._
import com.sksamuel.elastic4s.http.ElasticProperties
import sbt._
import scala.collection.JavaConverters._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
......@@ -24,6 +29,9 @@ object AwsUtils extends AutoPlugin {
val awsServiceName = taskKey[String]("Service name of the application")
val awsStage = taskKey[String]("Stage of the application")
val awsCleanup = taskKey[Unit]("Cleanup AWS resources like DynamoDB or ElasticSearch")
val startECSMockServer = taskKey[Unit]("Start MockServer on ECS")
val listECSMockServer = taskKey[Unit]("List MockServer on ECS")
val stopECSMockServer = taskKey[Unit]("Stop MockServer on ECS")
}
import autoImport._
......@@ -32,7 +40,7 @@ object AwsUtils extends AutoPlugin {
Future {
val ddbClient: AmazonDynamoDB = AmazonDynamoDBClientBuilder.standard.build
val ddb: DynamoDB = new DynamoDB(ddbClient)
val fullTableName = s"$serviceName-$stage-$tableName"
println(s"Clearing table $fullTableName")
......@@ -93,6 +101,98 @@ object AwsUtils extends AutoPlugin {
}
}
def getIpForNetworkInterfaceId(networkInterfaceId: String): String = {
val client = AmazonEC2ClientBuilder.standard.build
val request = new DescribeNetworkInterfacesRequest()
.withNetworkInterfaceIds(networkInterfaceId)
val describeNetworkInterfaceResponse = client.describeNetworkInterfaces(request)
describeNetworkInterfaceResponse.getNetworkInterfaces.get(0).getAssociation.getPublicIp
}
def getRunningMockServerTasks(): List[com.amazonaws.services.ecs.model.Task] = {
val client = AmazonECSClientBuilder.standard.build
val res = client.listTasks(new ListTasksRequest().withCluster("mockserver-cluster"))
if (res.getTaskArns.isEmpty) {
List.empty
} else {
val tasks = client.describeTasks(new DescribeTasksRequest()
.withCluster("mockserver-cluster")
.withTasks(res.getTaskArns)
)
tasks.getTasks.asScala
.filter(_.getStartedBy == "sbt")
.filter(_.getLastStatus == "RUNNING")
.toList
}
}
def startMockServer(): String = {
val client = AmazonECSClientBuilder.standard.build
val request = new RunTaskRequest()
.withCluster("mockserver-cluster")
.withTaskDefinition("mockserver-definition:1")
.withCount(1)
.withLaunchType(LaunchType.FARGATE)
.withStartedBy("sbt")
.withTags(new Tag().withKey("SBT").withValue("IntegrationTest"))
.withNetworkConfiguration(new NetworkConfiguration().withAwsvpcConfiguration(
new AwsVpcConfiguration()
.withSecurityGroups("sg-0d4a0c0e5d2c09e41")
.withSubnets("subnet-06c53f215b9f4c65c")
.withAssignPublicIp(AssignPublicIp.ENABLED)
))
val runTaskResponse = client.runTask(request)
var break = false
var publicIp = ""
print("Wait for running")
while (!break) {
val tasks = client.describeTasks(new DescribeTasksRequest()
.withCluster("mockserver-cluster")
.withTasks(runTaskResponse.getTasks.get(0).getTaskArn)
)
val task = tasks.getTasks.get(0)
task.getLastStatus match {
case "RUNNING" =>
val attachmentsDetails = task.getAttachments.get(0).getDetails.asScala
val networkInterfaceId = attachmentsDetails.find(kvp => kvp.getName == "networkInterfaceId").get
publicIp = getIpForNetworkInterfaceId(networkInterfaceId.getValue)
break = true
println(s"Done. Public IP: $publicIp")
println(s"Started task ${task.getTaskArn}")
case "PENDING" | "PROVISIONING" =>
Thread.sleep(3000)
print(".")
case other =>
println()
println(s"Server could not be started, status = $other")
break = true
}
}
publicIp
}
def stopMockServers(tasks: List[com.amazonaws.services.ecs.model.Task]): Unit = {
val client = AmazonECSClientBuilder.standard.build
tasks.foreach { t =>
client.stopTask(new StopTaskRequest()
.withCluster("mockserver-cluster")
.withTask(t.getTaskArn)
)
println(s"Stopped task ${t.getTaskArn}")
}
}
override lazy val projectSettings = Seq(
awsServiceName in IntegrationTest := "delay-info",
awsStage in IntegrationTest := "sbt-it",
......@@ -116,7 +216,28 @@ object AwsUtils extends AutoPlugin {
}
Await.ready(elasticFuture, Duration.Inf)
}
},
startECSMockServer in IntegrationTest := {
val runningTasks = getRunningMockServerTasks()
if (runningTasks.nonEmpty) {
val attachmentsDetails = runningTasks.head.getAttachments.get(0).getDetails.asScala
val networkInterfaceId = attachmentsDetails.find(kvp => kvp.getName == "networkInterfaceId").get
val publicIp = getIpForNetworkInterfaceId(networkInterfaceId.getValue)
println(s"Mockserver ${runningTasks.head.getTaskArn} already running on ip $publicIp")
} else {
startMockServer()
}
},
listECSMockServer in IntegrationTest := {
getRunningMockServerTasks() foreach println
},
stopECSMockServer in IntegrationTest := {
val runningTasks = getRunningMockServerTasks()
stopMockServers(runningTasks)
},
)
}
\ No newline at end of file
......@@ -2,6 +2,8 @@ libraryDependencies ++= Seq(
// AWS
"com.amazonaws" % "aws-java-sdk-dynamodb" % "1.11.488",
"com.amazonaws" % "aws-java-sdk-elasticsearch" % "1.11.488",
"com.amazonaws" % "aws-java-sdk-ecs" % "1.11.488",
"com.amazonaws" % "aws-java-sdk-ec2" % "1.11.488",
// ElasticSearch
"com.sksamuel.elastic4s" % "elastic4s-core_2.12" % "6.3.8",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment