Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for Fn::Split #141

Merged
merged 1 commit into from
Feb 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package com.monsanto.arch.cloudformation.model

import com.monsanto.arch.cloudformation.model.resource.Resource
import spray.json.DefaultJsonProtocol._
import spray.json._
import DefaultJsonProtocol._
import scala.language.existentials
import scala.language.implicitConversions

import scala.language.{existentials, higherKinds, implicitConversions}

/**
* Created by Ryan Richt on 2/15/15
*/

sealed abstract class AmazonFunctionCall[LogicalReturnType](val funName: String){type CFBackingType ; val arguments: CFBackingType}
object AmazonFunctionCall extends DefaultJsonProtocol {

def lazyWriter[T](format: => JsonWriter[T]) = new JsonWriter[T] {
lazy val delegate = format
def write(x: T) = delegate.write(x)
Expand All @@ -28,6 +27,7 @@ object AmazonFunctionCall extends DefaultJsonProtocol {
case ga: `Fn::GetAtt` => implicitly[JsonWriter[`Fn::GetAtt`#CFBackingType] ].write(ga.arguments)
case azs: `Fn::GetAZs` => implicitly[JsonWriter[`Fn::GetAZs`#CFBackingType] ].write(azs.arguments)
case j: `Fn::Join` => implicitly[JsonWriter[`Fn::Join`#CFBackingType] ].write(j.arguments)
case s: `Fn::Split` => implicitly[JsonWriter[`Fn::Split`#CFBackingType] ].write(s.arguments)
case fim: `Fn::FindInMap`[_] => implicit val foo = MappingRef.formatUnderscore
implicitly[JsonWriter[`Fn::FindInMap`[_]#CFBackingType]].write(fim.arguments)
case b64: `Fn::Base64` => implicitly[JsonWriter[`Fn::Base64`#CFBackingType] ].write(b64.arguments)
Expand Down Expand Up @@ -127,6 +127,12 @@ case class `Fn::GetAZs`(region: Token[String])
case class `Fn::Join`(joinChar: String, toJoin: Seq[Token[String]])
extends AmazonFunctionCall[String]("Fn::Join"){type CFBackingType = (String, Seq[Token[String]]) ; val arguments = (joinChar, toJoin)}

case class `Fn::Split`(delimiterChar: String, toSplit: Token[String])
extends AmazonFunctionCall[Seq[String]]("Fn::Split"){
override type CFBackingType = (String, Token[String])
override val arguments: (String, Token[String]) = (delimiterChar, toSplit)
}

case class `Fn::FindInMap`[R](mapName: Token[MappingRef[R]], outerKey: Token[String], innerKey: Token[String])
extends AmazonFunctionCall[R]("Fn::FindInMap"){type CFBackingType = (Token[MappingRef[_]], Token[String], Token[String]); val arguments = (mapName.asInstanceOf[Token[MappingRef[_]]], outerKey, innerKey)}

Expand Down Expand Up @@ -207,6 +213,12 @@ object Token extends DefaultJsonProtocol {
implicit def fromBoolean(s: Boolean): BooleanToken = BooleanToken(s)
implicit def fromInt(s: Int): IntToken = IntToken(s)
implicit def fromFunction[R](f: AmazonFunctionCall[R]): FunctionCallToken[R] = FunctionCallToken[R](f)

implicit def fromFunctionSeq[R](f: AmazonFunctionCall[Seq[R]]): TokenSeq[R] = Left(FunctionCallSeqToken(f))
implicit def fromSeqToken[R](s: Seq[Token[R]]): TokenSeq[R] = Right(s)
implicit def fromSeqToken[R, S](s: Seq[R])(implicit ev1: R ⇒ Token[S]): TokenSeq[S] = Right(s.map(ev1))
implicit def tokenSeqInOption[R, P](oR: Option[Seq[R]])(implicit ev1: Seq[Token[P]] ⇒ TokenSeq[P], ev2: R ⇒ Token[P]): Option[TokenSeq[P]] = oR.map(x ⇒ ev1(x.map(ev2)))

implicit def fromSome[R](oR: Some[R])(implicit ev1: R => Token[R]): Some[Token[R]] = oR.map(ev1).asInstanceOf[Some[Token[R]]]
implicit def fromOption[R](oR: Option[R])(implicit ev1: R => Token[R]): Option[Token[R]] = oR.map(ev1)

Expand All @@ -218,29 +230,43 @@ object Token extends DefaultJsonProtocol {
implicit def format[R : JsonFormat]: JsonFormat[Token[R]] = lazyFormat(new JsonFormat[Token[R]] {
def write(obj: Token[R]) = {
obj match {
case a: AnyToken[R] => a.value.toJson
case s: StringToken => s.value.toJson
case i: IntToken => i.value.toJson
case b: BooleanToken => b.value.toJson
case s: UNSAFEToken[_] => s.value.toJson
case a: AnyToken[R] => a.value.toJson
case s: StringToken => s.value.toJson
case i: IntToken => i.value.toJson
case b: BooleanToken => b.value.toJson
case s: UNSAFEToken[_] => s.value.toJson
// its OK to erase the return type of AmazonFunctionCalls b/c they are only used at compile time for checking
// not for de/serialization logic or JSON representation
case f: FunctionCallToken[_] => implicitly[JsonWriter[AmazonFunctionCall[_]]].write(f.call)
case p: PseudoParameterRef => p.toJson
case r: ResourceRef[_] => r.toJson
case f: FunctionCallToken[_] => implicitly[JsonWriter[AmazonFunctionCall[_]]].write(f.call)
case f: FunctionCallSeqToken[_] => implicitly[JsonWriter[AmazonFunctionCall[_]]].write(f.call)
case p: PseudoParameterRef => p.toJson
case r: ResourceRef[_] => r.toJson
}
}

// TODO: BLERG, for now, to make Tuple formats work
def read(json: JsValue) = ???
})

type TokenSeq[A] = Either[FunctionCallSeqToken[A], Seq[Token[A]]]

implicit def eitherFormat[R: JsonFormat]: JsonFormat[TokenSeq[R]] = lazyFormat(new JsonFormat[TokenSeq[R]] {
override def write(obj: TokenSeq[R]): JsValue = obj match {
case Left(f) ⇒ implicitly[JsonWriter[Token[Seq[R]]]].write(f)
case Right(s) ⇒ implicitly[JsonWriter[Seq[Token[R]]]].write(s)
}

override def read(json: JsValue): TokenSeq[R] = ???
})
}
case class AnyToken[R : JsonFormat](value: R) extends Token[R]
case class StringToken(value: String) extends Token[String]
case class BooleanToken(value: Boolean) extends Token[Boolean]
case class IntToken(value: Int) extends Token[Int]
case class FunctionCallToken[R](call: AmazonFunctionCall[R]) extends Token[R]

case class FunctionCallSeqToken[R](call: AmazonFunctionCall[Seq[R]]) extends Token[Seq[R]]

@deprecated("use ParameterRef or ResourceRef instead", "Feb 20 2015")
case class UNSAFEToken[R](value: String) extends Token[R]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model.{ConditionRef, ResourceRef, Token, `Fn::GetAtt`}
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json.{DefaultJsonProtocol, JsonFormat}
import DefaultJsonProtocol._

Expand Down Expand Up @@ -219,7 +220,7 @@ case class `AWS::ApiGateway::RestApi`(
CloneFrom: Option[Token[String]] = None,
Description: Option[String] = None,
FailOnWarnings: Option[Boolean] = None,
Parameters: Option[Seq[Token[String]]] = None,
Parameters: Option[TokenSeq[String]] = None,
override val Condition: Option[ConditionRef] = None
) extends Resource[`AWS::ApiGateway::RestApi`] {
override def when(newCondition: Option[ConditionRef]) = copy(Condition = newCondition)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model._
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json._

/**
Expand All @@ -9,7 +10,7 @@ import spray.json._

case class `AWS::AutoScaling::AutoScalingGroup`(
name: String,
AvailabilityZones: Seq[Token[String]],
AvailabilityZones: TokenSeq[String],
LaunchConfigurationName: Token[ResourceRef[`AWS::AutoScaling::LaunchConfiguration`]],
MinSize: StringBackedInt,
MaxSize: StringBackedInt,
Expand Down Expand Up @@ -129,7 +130,7 @@ case class AutoScalingRollingUpdate(
MaxBatchSize: Option[Token[Int]] = None,
MinInstancesInService: Option[Token[Int]] = None,
PauseTime: Option[Token[String]] = None,
SuspendProcesses: Option[Seq[Token[String]]] = None,
SuspendProcesses: Option[TokenSeq[String]] = None,
WaitOnResourceSignals: Option[Token[Boolean]] = None)

object AutoScalingRollingUpdate extends DefaultJsonProtocol {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import com.monsanto.arch.cloudformation.model._
import spray.json.JsonFormat

Expand Down Expand Up @@ -42,7 +43,7 @@ case class `AWS::CloudFormation::Stack`(name: String,
TemplateURL: Token[String],
TimeoutInMinutes: Option[StringBackedInt] = None,
Parameters: Option[Map[String, Token[String]]] = None,
NotificationARNs: Option[Seq[Token[String]]] = None,
NotificationARNs: Option[TokenSeq[String]] = None,
override val Condition: Option[ConditionRef] = None)
extends Resource[`AWS::CloudFormation::Stack`]
with HasArn {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model._
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json._

/**
Expand All @@ -19,12 +20,12 @@ case class `AWS::CloudWatch::Alarm`(
Statistic: `AWS::CloudWatch::Alarm::Statistic`,
Threshold: String, //BackedInt,
ActionsEnabled: Option[Boolean] = None,
AlarmActions: Option[Seq[Token[String]]] = None,
AlarmActions: Option[TokenSeq[String]] = None,
AlarmDescription: Option[String] = None,
AlarmName: Option[Token[String]] = None,
Dimensions: Option[Seq[`AWS::CloudWatch::Alarm::Dimension`]] = None,
InsufficientDataActions: Option[Seq[Token[String]]] = None,
OKActions: Option[Seq[Token[String]]] = None,
InsufficientDataActions: Option[TokenSeq[String]] = None,
OKActions: Option[TokenSeq[String]] = None,
Unit: Option[`AWS::CloudWatch::Alarm::Unit`] = None,
override val Condition: Option[ConditionRef] = None
) extends Resource[`AWS::CloudWatch::Alarm`]{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model.{ConditionRef, Token}
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json.{DefaultJsonProtocol, JsObject, JsValue, JsonFormat, RootJsonFormat}
import DefaultJsonProtocol._


case class Application(
AdditionalInfo: Option[Map[String, Token[String]]],
Args: Option[Seq[Token[String]]],
Args: Option[TokenSeq[String]],
Name: Option[Token[String]],
Version: Option[Token[String]]
)
Expand All @@ -16,7 +17,7 @@ object Application {
implicit val format = jsonFormat4(Application.apply)
}

case class ScriptBootstrapAction(Args: Option[Seq[Token[String]]], Path: Token[String])
case class ScriptBootstrapAction(Args: Option[TokenSeq[String]], Path: Token[String])
object ScriptBootstrapAction {
implicit val format = jsonFormat2(ScriptBootstrapAction.apply)
}
Expand Down Expand Up @@ -83,8 +84,8 @@ object PlacementType {
implicit val format = jsonFormat1(PlacementType.apply)
}

case class JobFlowInstancesConfig(AdditionalMasterSecurityGroups: Option[Seq[Token[String]]],
AdditionalSlaveSecurityGroups: Option[Seq[Token[String]]],
case class JobFlowInstancesConfig(AdditionalMasterSecurityGroups: Option[TokenSeq[String]],
AdditionalSlaveSecurityGroups: Option[TokenSeq[String]],
CoreInstanceGroup: InstanceGroupConfig,
Ec2KeyName: Option[Token[String]],
Ec2SubnetId: Option[Token[String]],
Expand Down Expand Up @@ -139,7 +140,7 @@ object `AWS::EMR::Step` {
implicit val format: RootJsonFormat[`AWS::EMR::Step`] = jsonFormat7(`AWS::EMR::Step`.apply)
}

case class HadoopJarStep(Args: Option[Seq[Token[String]]], Jar: Token[String], MainClass: Option[Token[String]], StepProperties: Option[StepProperties])
case class HadoopJarStep(Args: Option[TokenSeq[String]], Jar: Token[String], MainClass: Option[Token[String]], StepProperties: Option[StepProperties])

object HadoopJarStep {
implicit val format: RootJsonFormat[HadoopJarStep] = jsonFormat4(HadoopJarStep.apply)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model.{ConditionRef, EnumFormat, ResourceRef, StringBackedInt, Token}
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json._

/**
Expand Down Expand Up @@ -90,13 +91,13 @@ case class `AWS::ElastiCache::CacheCluster`(
NotificationTopicArn : Option[Token[String]] = None,
Port: Option[Token[Int]] = None,
PreferredAvailabilityZone : Option[Token[String]] = None,
PreferredAvailabilityZones: Option[Token[Seq[String]]] = None,
PreferredAvailabilityZones: Option[TokenSeq[String]] = None,
PreferredMaintenanceWindow: Option[Token[String]] = None,
SnapshotArns: Option[Token[Seq[String]]] = None,
SnapshotName: Option[Token[String]] = None,
SnapshotRetentionLimit: Option[Token[Int]] = None,
SnapshotWindow: Option[Token[String]] = None,
VpcSecurityGroupIds: Option[Seq[Token[String]]] = None,
VpcSecurityGroupIds: Option[TokenSeq[String]] = None,
Tags: Option[Seq[AmazonTag]] = None,
override val Condition: Option[ConditionRef] = None
) extends Resource[`AWS::ElastiCache::CacheCluster`] {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model._
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json._

/**
Expand All @@ -15,7 +16,7 @@ case class `AWS::ElasticLoadBalancing::LoadBalancer` private (
Listeners: Seq[ELBListener],
AccessLoggingPolicy: Option[ELBAccessLoggingPolicy],
AppCookieStickinessPolicy: Option[ELBAppCookieStickinessPolicy],
AvailabilityZones: Seq[Token[String]],
AvailabilityZones: TokenSeq[String],
ConnectionDrainingPolicy: Option[ELBConnectionDrainingPolicy],
ConnectionSettings: Option[ELBConnectionSettings],
CrossZone: Option[Boolean],
Expand Down Expand Up @@ -126,7 +127,7 @@ object `AWS::ElasticLoadBalancing::LoadBalancer` extends DefaultJsonProtocol {
Listeners: Seq[ELBListener],
AccessLoggingPolicy: Option[ELBAccessLoggingPolicy] = None,
AppCookieStickinessPolicy: Option[ELBAppCookieStickinessPolicy] = None,
AvailabilityZones: Seq[Token[String]] = Seq.empty,
AvailabilityZones: TokenSeq[String] = Seq.empty,
ConnectionDrainingPolicy: Option[ELBConnectionDrainingPolicy] = None,
ConnectionSettings: Option[ELBConnectionSettings] = None,
CrossZone: Option[Boolean] = None,
Expand Down Expand Up @@ -220,7 +221,7 @@ case class ELBListener(
LoadBalancerPort: String,
Protocol: ELBListenerProtocol,
InstanceProtocol: Option[ELBListenerProtocol] = Some(ELBListenerProtocol.HTTP),
PolicyNames: Seq[Token[String]] = Seq.empty,
PolicyNames: TokenSeq[String] = Seq.empty,
SSLCertificateId: Option[Token[String]] = None
)
object ELBListener extends DefaultJsonProtocol {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model._
import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import spray.json._

import scala.annotation.implicitNotFound
Expand Down Expand Up @@ -125,7 +126,7 @@ sealed trait PolicyConditionValue
case class ListPolicyConditionValue(values : Seq[String]) extends PolicyConditionValue
case class SimplePolicyConditionValue(value : String) extends PolicyConditionValue
case class TokenPolicyConditionValue(value : Token[String]) extends PolicyConditionValue
case class TokenListPolicyConditionValue(value : Seq[Token[String]]) extends PolicyConditionValue
case class TokenListPolicyConditionValue(value : TokenSeq[String]) extends PolicyConditionValue

object PolicyConditionValue extends DefaultJsonProtocol {
implicit object format extends JsonFormat[PolicyConditionValue] {
Expand Down Expand Up @@ -221,7 +222,7 @@ object PolicyPrincipal extends DefaultJsonProtocol {
def read(json: JsValue) = ???
}
}
case class DefinedPrincipal(targets: Map[String, Seq[Token[String]]]) extends PolicyPrincipal
case class DefinedPrincipal(targets: Map[String, TokenSeq[String]]) extends PolicyPrincipal
case object WildcardPrincipal extends PolicyPrincipal

case class Policy(PolicyName: String, PolicyDocument: PolicyDocument)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model._
import spray.json.{JsString, JsValue, JsonFormat, DefaultJsonProtocol}
import spray.json.{DefaultJsonProtocol, JsString, JsValue, JsonFormat}
import DefaultJsonProtocol._
import com.monsanto.arch.cloudformation.model.Token.TokenSeq

class Runtime(val runtime: String)

Expand Down Expand Up @@ -60,7 +61,7 @@ object LambdaEnvironment {
implicit val format : JsonFormat[LambdaEnvironment] = jsonFormat1(LambdaEnvironment.apply)
}

case class LambdaVpcConfig(SecurityGroupIds : Seq[Token[String]], SubnetIds : Seq[Token[String]])
case class LambdaVpcConfig(SecurityGroupIds : TokenSeq[String], SubnetIds : TokenSeq[String])

object LambdaVpcConfig {
implicit val format : JsonFormat[LambdaVpcConfig] = jsonFormat2(LambdaVpcConfig.apply)
Expand Down
Loading