Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #121 from tylersouthwick/emr
Add EMR support
- Loading branch information
Showing
3 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
124 changes: 124 additions & 0 deletions
124
src/main/scala/com/monsanto/arch/cloudformation/model/resource/EMR.scala
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package com.monsanto.arch.cloudformation.model.resource | ||
|
||
import com.monsanto.arch.cloudformation.model.{ConditionRef, Token} | ||
import spray.json.{DefaultJsonProtocol, JsObject, JsValue, JsonFormat, RootJsonFormat} | ||
import DefaultJsonProtocol._ | ||
|
||
|
||
case class Application( | ||
AdditionalInfo: Option[Map[String, Token[String]]], | ||
Args: Option[Seq[Token[String]]], | ||
Name: Option[Token[String]], | ||
Version: Option[Token[String]] | ||
) | ||
|
||
object Application { | ||
implicit val format = jsonFormat4(Application.apply) | ||
} | ||
|
||
case class ScriptBootstrapAction(Args: Option[Seq[Token[String]]], Path: Token[String]) | ||
object ScriptBootstrapAction { | ||
implicit val format = jsonFormat2(ScriptBootstrapAction.apply) | ||
} | ||
|
||
case class BootstrapAction(Name: Token[String], ScriptBootstrapAction: ScriptBootstrapAction) | ||
object BootstrapAction { | ||
implicit val format = jsonFormat2(BootstrapAction.apply) | ||
} | ||
|
||
case class ClusterConfiguration(Classification: Option[Token[String]], | ||
ConfigurationProperties: Option[Map[String, Token[String]]], | ||
Configurations: Option[Seq[ClusterConfiguration]] | ||
) | ||
object ClusterConfiguration { | ||
implicit object format extends RootJsonFormat[ClusterConfiguration] { | ||
override def write(obj: ClusterConfiguration): JsValue = { | ||
val classification = obj.Classification.map(implicitly[JsonFormat[Token[String]]].write) | ||
val configurationProperties = obj.ConfigurationProperties.map(implicitly[JsonFormat[Map[String, Token[String]]]].write) | ||
lazy val seqWrite = implicitly[RootJsonFormat[Seq[ClusterConfiguration]]] | ||
val configurations = obj.Configurations.map(seqWrite.write) | ||
JsObject(Seq( | ||
"Classification" -> classification, | ||
"ConfigurationProperties" -> configurationProperties, | ||
"Configurations" -> configurations | ||
).flatMap(t => t._2.map(t._1 -> _).toSeq) | ||
.toMap) | ||
} | ||
|
||
override def read(json: JsValue): ClusterConfiguration = ??? | ||
} | ||
} | ||
|
||
case class VolumeSpecification(Iops: Option[Token[Int]], SizeInGB: Token[Int], VolumeType: Token[String]) | ||
object VolumeSpecification { | ||
implicit val format = jsonFormat3(VolumeSpecification.apply) | ||
} | ||
|
||
case class EbsBlockDeviceConfig(VolumeSpecification: VolumeSpecification, VolumesPerInstance: Option[Token[Int]]) | ||
object EbsBlockDeviceConfig { | ||
implicit val format = jsonFormat2(EbsBlockDeviceConfig.apply) | ||
} | ||
|
||
case class EbsConfiguration(EbsBlockDeviceConfigs: Option[Seq[EbsBlockDeviceConfig]], | ||
EbsOptimized: Option[Token[Boolean]]) | ||
object EbsConfiguration { | ||
implicit val format = jsonFormat2(EbsConfiguration.apply) | ||
} | ||
|
||
case class InstanceGroupConfig( | ||
BidPrice: Option[Token[String]], | ||
Configurations: Option[Seq[ClusterConfiguration]], | ||
EbsConfiguration: Option[EbsConfiguration], | ||
InstanceCount: Token[Int], | ||
InstanceType: Token[String], | ||
Market: Option[Token[String]], | ||
Name: Option[Token[String]] | ||
) | ||
object InstanceGroupConfig { | ||
implicit val format = jsonFormat7(InstanceGroupConfig.apply) | ||
} | ||
|
||
case class PlacementType(AvailabilityZone: String) | ||
object PlacementType { | ||
implicit val format = jsonFormat1(PlacementType.apply) | ||
} | ||
|
||
case class JobFlowInstancesConfig(AdditionalMasterSecurityGroups: Option[Seq[Token[String]]], | ||
AdditionalSlaveSecurityGroups: Option[Seq[Token[String]]], | ||
CoreInstanceGroup: InstanceGroupConfig, | ||
Ec2KeyName: Option[Token[String]], | ||
Ec2SubnetId: Option[Token[String]], | ||
EmrManagedMasterSecurityGroup: Option[Token[String]], | ||
EmrManagedSlaveSecurityGroup: Option[Token[String]], | ||
HadoopVersion: Option[Token[String]], | ||
MasterInstanceGroup: InstanceGroupConfig, | ||
Placement: Option[PlacementType], | ||
ServiceAccessSecurityGroup: Option[Token[String]], | ||
TerminationProtected: Option[Token[Boolean]] | ||
) | ||
object JobFlowInstancesConfig { | ||
implicit val format = jsonFormat12(JobFlowInstancesConfig.apply) | ||
} | ||
|
||
case class `AWS::EMR::Cluster`(name: String, | ||
AdditionalInfo: Option[JsValue], | ||
Applications: Option[Seq[Application]], | ||
BootstrapActions: Option[Seq[BootstrapAction]], | ||
Configurations: Option[Seq[ClusterConfiguration]], | ||
Instances: JobFlowInstancesConfig, | ||
JobFlowRole: Token[String], | ||
LogUri: Option[Token[String]], | ||
Name: Token[String], | ||
ReleaseLabel: Option[Token[String]], | ||
ServiceRole: Token[String], | ||
Tags: Option[Seq[AmazonTag]], | ||
VisibileToAllUsers: Option[Token[Boolean]], | ||
override val Condition: Option[ConditionRef] = None | ||
) extends Resource[`AWS::EMR::Cluster`] { | ||
override def when(newCondition: Option[ConditionRef]): `AWS::EMR::Cluster` = copy( | ||
Condition = newCondition | ||
) | ||
} | ||
object `AWS::EMR::Cluster` { | ||
implicit val format : JsonFormat[`AWS::EMR::Cluster`] = jsonFormat14(`AWS::EMR::Cluster`.apply) | ||
} |
54 changes: 54 additions & 0 deletions
54
src/test/scala/com/monsanto/arch/cloudformation/model/resource/EmrSpec.scala
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.monsanto.arch.cloudformation.model.resource | ||
|
||
import org.scalatest.{FunSpec, Matchers} | ||
import spray.json.{JsArray, JsObject, JsString, JsonWriter} | ||
|
||
class EmrSpec extends FunSpec with Matchers { | ||
|
||
describe("ClusterConfiguration") { | ||
it("should write non recursive") { | ||
val clusterConfiguration = ClusterConfiguration( | ||
Classification = Some("hello"), | ||
ConfigurationProperties = Some(Map("hello" -> "world")), | ||
Configurations = None | ||
) | ||
val json = implicitly[JsonWriter[ClusterConfiguration]].write(clusterConfiguration) | ||
json should equal(JsObject(Map( | ||
"Classification" -> JsString("hello"), | ||
"ConfigurationProperties" -> JsObject( | ||
"hello" -> JsString("world") | ||
) | ||
))) | ||
} | ||
|
||
it("should write and read recursive") { | ||
val clusterConfiguration = ClusterConfiguration( | ||
Classification = Some("hello"), | ||
ConfigurationProperties = Some(Map("hello" -> "world")), | ||
Configurations = Some(Seq( | ||
ClusterConfiguration( | ||
Classification = Some("hello1"), | ||
ConfigurationProperties = Some(Map("hello2" -> "world3")), | ||
Configurations = None | ||
) | ||
)) | ||
) | ||
val json = implicitly[JsonWriter[ClusterConfiguration]].write(clusterConfiguration) | ||
json should equal(JsObject(Map( | ||
"Classification" -> JsString("hello"), | ||
"ConfigurationProperties" -> JsObject( | ||
"hello" -> JsString("world") | ||
), | ||
"Configurations" -> JsArray( | ||
JsObject(Map( | ||
"Classification" -> JsString("hello1"), | ||
"ConfigurationProperties" -> JsObject( | ||
"hello2" -> JsString("world3") | ||
) | ||
)) | ||
) | ||
))) | ||
} | ||
} | ||
|
||
} |