Skip to content

Instantly share code, notes, and snippets.

@diyan
Last active December 17, 2019 12:36
Show Gist options
  • Save diyan/3f687bbd0c085c6ea73bd468df2a8ec1 to your computer and use it in GitHub Desktop.
Save diyan/3f687bbd0c085c6ea73bd468df2a8ec1 to your computer and use it in GitHub Desktop.
ECS. AutoScaling config, Service placement, container limits in Scala
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