Skip to content

Commit

Permalink
Refactored and added the custom drop-in
Browse files Browse the repository at this point in the history
  • Loading branch information
bkrodgers committed Feb 25, 2016
1 parent a403635 commit 440862a
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,45 @@ import spray.json._
* Created by Ryan Richt on 2/28/15
*/

class `AWS::Route53::RecordSet` private (
trait Route53RecordSetBaseFields {
def name: String
def RecordName: Token[String]
def RecordType: Route53RecordType
def HostedZoneName: Option[Token[String]]
def HostedZoneId: Option[Token[String]]
def ResourceRecords: Option[Seq[Token[String]]]
def TTL: Option[Token[String]]
def AliasTarget: Option[Route53AliasTarget]
def Condition: Option[ConditionRef]
}

object Route53RecordSetBaseFields {
import DefaultJsonProtocol._
def writeField[T: JsonFormat](t: T) = {

val writer = implicitly[JsonFormat[T]]
writer match {
case _: OptionFormat[_] if t == None => None
case _ => Some(writer.write(t))
}
}

def writeCoreFields(p: Route53RecordSetBaseFields) = {
Map(
"name" -> writeField(p.name),
"Name" -> writeField(p.RecordName),
"Type" -> writeField(p.RecordType),
"HostedZoneName" -> writeField(p.HostedZoneName),
"HostedZoneId" -> writeField(p.HostedZoneId),
"ResourceRecords" -> writeField(p.ResourceRecords),
"TTL" -> writeField(p.TTL),
"AliasTarget" -> writeField(p.AliasTarget),
"Condition" -> writeField(p.Condition)
)
}
}

class `AWS::Route53::RecordSet` protected (
val name: String,
val RecordName: Token[String], // The subdomain, with a . after it.
val RecordType: Route53RecordType,
Expand All @@ -17,36 +55,17 @@ class `AWS::Route53::RecordSet` private (
val TTL: Option[Token[String]] = None,
val AliasTarget: Option[Route53AliasTarget] = None,
override val Condition: Option[ConditionRef] = None
) extends Resource[`AWS::Route53::RecordSet`]{
) extends Resource[`AWS::Route53::RecordSet`] with Route53RecordSetBaseFields{

def when(newCondition: Option[ConditionRef] = Condition) =
new `AWS::Route53::RecordSet`(name, RecordName, RecordType, HostedZoneName, HostedZoneId, ResourceRecords, TTL, AliasTarget, newCondition)
}
object `AWS::Route53::RecordSet` extends DefaultJsonProtocol {

private def writeField[T: JsonFormat](t: T) = {
val writer = implicitly[JsonFormat[T]]
writer match {
case _: OptionFormat[_] if t == None => None
case _ => Some(writer.write(t))
}
}

// Because we dont want the default case class apply method without our checks
implicit val format: JsonFormat[`AWS::Route53::RecordSet`] = new JsonFormat[`AWS::Route53::RecordSet`]{
def write(p: `AWS::Route53::RecordSet`) = {
JsObject(
Map(
"name" -> writeField(p.name),
"Name" -> writeField(p.RecordName),
"Type" -> writeField(p.RecordType),
"HostedZoneName" -> writeField(p.HostedZoneName),
"HostedZoneId" -> writeField(p.HostedZoneId),
"ResourceRecords" -> writeField(p.ResourceRecords),
"TTL" -> writeField(p.TTL),
"AliasTarget" -> writeField(p.AliasTarget),
"Condition" -> writeField(p.Condition)
).filter(_._2.isDefined).mapValues(_.get)
Route53RecordSetBaseFields.writeCoreFields(p).filter(_._2.isDefined).mapValues(_.get)
)
}

Expand Down Expand Up @@ -83,6 +102,77 @@ object `AWS::Route53::RecordSet` extends DefaultJsonProtocol {
) = new `AWS::Route53::RecordSet`(name, RecordName, Route53RecordType.A, Some(HostedZoneName), None, None, None, Some(AliasTarget), Condition)
}

class `Custom::RemoteRecordSet` private (
override val name: String,
val ServiceToken: Token[String],
val DestinationRole: Token[String],
val RecordName: Token[String], // The subdomain, with a . after it.
val RecordType: Route53RecordType,
val HostedZoneName: Option[Token[String]], // The parent domain, with a . after it. Must be route 53 managed already.
val HostedZoneId: Option[Token[String]], // the id of the hosted zone
val ResourceRecords: Option[Seq[Token[String]]] = None,
val TTL: Option[Token[String]] = None,
val AliasTarget: Option[Route53AliasTarget] = None,
override val Condition: Option[ConditionRef] = None
) extends Resource[`Custom::RemoteRecordSet`] with Route53RecordSetBaseFields{

override def when(newCondition: Option[ConditionRef] = Condition) =
new `Custom::RemoteRecordSet`(name, ServiceToken, DestinationRole, RecordName, RecordType, HostedZoneName, HostedZoneId, ResourceRecords, TTL, AliasTarget, newCondition)
}

object `Custom::RemoteRecordSet` {
import DefaultJsonProtocol._
import Route53RecordSetBaseFields.writeField
implicit val format: JsonFormat[`Custom::RemoteRecordSet`] = new JsonFormat[`Custom::RemoteRecordSet`]{
def write(p: `Custom::RemoteRecordSet`) = {
JsObject(
(Route53RecordSetBaseFields.writeCoreFields(p)
+ ("ServiceToken" -> writeField(p.ServiceToken))
+ ("DestinationRole" -> writeField(p.DestinationRole))
).filter(_._2.isDefined).mapValues(_.get)
)
}

def read(json: JsValue) = ???
}


def generalRecord(
name: String,
ServiceToken: Token[String],
DestinationRole: Token[String],
RecordName: Token[String], // The subdomain, with a . after it.
RecordType: Route53RecordType,
HostedZoneName: Token[String], // The parent domain, with a . after it. Must be route 53 managed already.
ResourceRecords: Seq[Token[String]],
TTL: Token[String],
Condition: Option[ConditionRef] = None
) = new `Custom::RemoteRecordSet`(name, ServiceToken, DestinationRole, RecordName, RecordType, Some(HostedZoneName), None, Some(ResourceRecords), Some(TTL), Condition = Condition)

def generalRecordByID(
name: String,
ServiceToken: Token[String],
DestinationRole: Token[String],
RecordName: Token[String], // The subdomain, with a . after it.
RecordType: Route53RecordType,
HostedZoneID: Token[String],
ResourceRecords: Seq[Token[String]],
TTL: Token[String],
Condition: Option[ConditionRef] = None
) = new `Custom::RemoteRecordSet`(name, ServiceToken, DestinationRole, RecordName, RecordType, None, Some(HostedZoneID), Some(ResourceRecords), Some(TTL), Condition = Condition)


def aliasRecord(
name: String,
ServiceToken: Token[String],
DestinationRole: Token[String],
RecordName: Token[String], // The subdomain, with a . after it.
HostedZoneName: Token[String], // The parent domain, with a . after it. Must be route 53 managed already.
AliasTarget: Route53AliasTarget,
Condition: Option[ConditionRef] = None
) = new `Custom::RemoteRecordSet`(name, ServiceToken, DestinationRole, RecordName, Route53RecordType.A, Some(HostedZoneName), None, None, None, Some(AliasTarget), Condition)
}

case class `AWS::Route53::HostedZone`(
name: String,
Name: Token[String],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model.{Template, `Fn::GetAtt`, ResourceRef}
import org.scalatest.{FunSpec, Matchers}
import spray.json
import spray.json._

class Route53_UT extends FunSpec with Matchers {

describe("Custom::RemoteRecordSet"){
it ("should serialize as expected") {
val record = `Custom::RemoteRecordSet`.generalRecord(
"TestRecord",
"TestServiceToken",
"TestDestinationRole",
"etcd.internal.agro.services",
Route53RecordType.CNAME,
"test",
Seq("cnn.com"),
"60")

val expectedJson = """{"AWSTemplateFormatVersion":"2010-09-09","Description":"","Resources":{"TestRecord":{"Properties":{"DestinationRole":"TestDestinationRole","Name":"etcd.internal.agro.services","ServiceToken":"TestServiceToken","HostedZoneName":"test","ResourceRecords":["cnn.com"],"TTL":"60","Type":"CNAME"},"Type":"Custom::RemoteRecordSet"}}}""".parseJson
Template.fromResource(record).toJson should be (expectedJson)
}
}
}

0 comments on commit 440862a

Please sign in to comment.