Last active
December 17, 2019 12:36
-
-
Save diyan/3f687bbd0c085c6ea73bd468df2a8ec1 to your computer and use it in GitHub Desktop.
ECS. AutoScaling config, Service placement, container limits in Scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sample | |
import java.util.concurrent.TimeUnit | |
import com.fasterxml.jackson.dataformat.csv.CsvSchema.ColumnType | |
import com.fasterxml.jackson.dataformat.csv.{CsvMapper, CsvSchema} | |
import com.fasterxml.jackson.module.scala.DefaultScalaModule | |
import software.amazon.awssdk.services.ecs.EcsClient | |
import software.amazon.awssdk.services.ecs.model.{DescribeClustersRequest, DescribeServicesRequest, DescribeTaskDefinitionRequest, ListServicesRequest} | |
import scala.collection.JavaConverters._ | |
/* | |
ISSUE 1 | |
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". | |
SLF4J: Defaulting to no-operation (NOP) logger implementation | |
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. | |
*/ | |
object EcsAutoScalingReport extends App { | |
val startTime = System.nanoTime | |
val ecs = EcsClient.create | |
val containerConfigs = ecs.describeClusters( | |
DescribeClustersRequest.builder | |
.clusters(ecs.listClustersPaginator.clusterArns.asScala.asJavaCollection) | |
.build) | |
.clusters.asScala.par.flatMap { ecsCluster => | |
ecs.listServicesPaginator( | |
ListServicesRequest.builder | |
.cluster(ecsCluster.clusterArn) | |
.build) | |
.serviceArns.asScala.grouped(10).toParArray.flatMap { ecsServiceArns => | |
ecs.describeServices( | |
DescribeServicesRequest.builder | |
.cluster(ecsCluster.clusterArn) | |
.services(ecsServiceArns.asJavaCollection) | |
.build) | |
.services.asScala.map { ecsService => | |
val ecsTask = ecs.describeTaskDefinition( | |
DescribeTaskDefinitionRequest.builder | |
.taskDefinition(ecsService.taskDefinition) | |
.build) | |
.taskDefinition | |
val placementStrategy1 = ecsService.placementStrategy.asScala.headOption | |
val placementStrategy2 = ecsService.placementStrategy.asScala.lift(1) | |
val container = ecsTask.containerDefinitions.asScala.head | |
val ulimits = container.ulimits.asScala | |
val ulimit1 = ulimits.headOption | |
val ulimit2 = ulimits.lift(1) | |
val ulimit3 = ulimits.lift(2) | |
ContainerConfig( | |
awsAccountName = "TODO", | |
clusterName = ecsCluster.clusterName, | |
serviceName = ecsService.serviceName, | |
placementStrategy1Type = placementStrategy1.map(x => x.`type`.toString), | |
placementStrategy1Field = placementStrategy1.map(x => x.field), | |
placementStrategy2Type = placementStrategy2.map(x => x.`type`.toString), | |
placementStrategy2Field = placementStrategy2.map(x => x.field), | |
taskDefinitionFamily = ecsTask.family, | |
containerDefinitionName = container.name, | |
containerDefinitionMemoryMb = container.memory, | |
containerDefinitionMemoryReservationMb = container.memoryReservation, | |
containerDefinitionUlimit1Name = ulimit1.map(x => x.name.toString), | |
containerDefinitionUlimit1SoftLimit = ulimit1.map(x => x.softLimit), | |
containerDefinitionUlimit1HardLimit = ulimit1.map(x => x.hardLimit), | |
containerDefinitionUlimit2Name = ulimit2.map(x => x.name.toString), | |
containerDefinitionUlimit2SoftLimit = ulimit2.map(x => x.softLimit), | |
containerDefinitionUlimit2HardLimit = ulimit2.map(x => x.hardLimit), | |
containerDefinitionUlimit3Name = ulimit3.map(x => x.name.toString), | |
containerDefinitionUlimit3SoftLimit = ulimit3.map(x => x.softLimit), | |
containerDefinitionUlimit3HardLimit = ulimit3.map(x => x.hardLimit), | |
) | |
} | |
} | |
} | |
val tsvColumnNames = classOf[ContainerConfig].getDeclaredFields.toSeq.map(x => x.getName) | |
val tsvSchema = CsvSchema.builder | |
.addColumns(tsvColumnNames.asJava, ColumnType.STRING) | |
.build | |
.withHeader | |
.withColumnSeparator('\t') | |
.withoutQuoteChar | |
new CsvMapper() | |
.registerModule(DefaultScalaModule) | |
.writer(tsvSchema) | |
.writeValues(System.out) | |
.write(containerConfigs.toVector) | |
// WORKS toList, toStream, toVector | |
// FAIL toSeq, toParArray | |
// FAIL ParIterable[ContainerConfig] as is | |
val timeTakenSec = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime - startTime) | |
println(s"DONE in $timeTakenSec secs") | |
} | |
case class ContainerConfig( | |
awsAccountName: String, | |
clusterName: String, | |
serviceName: String, | |
placementStrategy1Type: Option[String], | |
placementStrategy1Field: Option[String], | |
placementStrategy2Type: Option[String], | |
placementStrategy2Field: Option[String], | |
taskDefinitionFamily: String, | |
containerDefinitionName: String, | |
containerDefinitionMemoryMb: Integer, | |
containerDefinitionMemoryReservationMb: Integer, | |
containerDefinitionUlimit1Name: Option[String], | |
containerDefinitionUlimit1SoftLimit: Option[Integer], | |
containerDefinitionUlimit1HardLimit: Option[Integer], | |
containerDefinitionUlimit2Name: Option[String], | |
containerDefinitionUlimit2SoftLimit: Option[Integer], | |
containerDefinitionUlimit2HardLimit: Option[Integer], | |
containerDefinitionUlimit3Name: Option[String], | |
containerDefinitionUlimit3SoftLimit: Option[Integer], | |
containerDefinitionUlimit3HardLimit: Option[Integer] | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment