Bayer-Group / cloudformation-template-generator

A type-safe Scala DSL for generating CloudFormation templates
BSD 3-Clause "New" or "Revised" License
211 stars 71 forks source link

Missing Support for OpsWorks #116

Open carsonfarrell opened 7 years ago

carsonfarrell commented 7 years ago

I am willing to implement this, but have a question about how to implement the CustomJson field, as it must serialize to a Json object, rather than a string containing json.

The correct output would be of the following format:

{ "field": { "subObjectField": "value" } }

Rather than

{"field" : " { \"subObjectField\" : \"value\" } "}

As far as I can see there is no other field like this currently implemented.

tjcorr commented 7 years ago

Have you double checked this requirement by manually creating a CloudFormation template and spinning it up? I'm wondering if they really are asking us to send invalid JSON? A full sample template would also nice for us to be able to test against.

carsonfarrell commented 7 years ago

I don't follow what you mean by "invalid JSON" - an example I've pulled from our existing CloudFormation template is as follows - the value of "CustomJson" must be a valid JSON object.

"CustomJson" : {
  "opsworks": {
    "data": {
      "ssf": {
        "meta": {
          "env": {"Ref" : "Environment"}
        },
        "deploy": {
          "deploy_to": "/redacted",
          "repository": "git@github.com:redacted/redacted",
          "branch": {"Ref" : "GitBranch"}
        }
      }
    }
  }
}
carsonfarrell commented 7 years ago

Sorry if I was unclear in my first comment, I should have put "CustomJson" instead of "field".

tjcorr commented 7 years ago

Ah I follow you, sorry about that. I was thinking you had to do something like "CustomJson": " {} ". Is there any harm in just doing:

case class `AWS::OpsWorks::Stack` (
                                    name: String,
                                    CustomJson: JsObject,
                                    Tags:                       Option[Seq[AmazonTag]]                                          = None,
                                    override val Condition:     Option[ConditionRef]                                            = None
) extends Resource[`AWS::OpsWorks::Stack`] {
  def when(newCondition: Option[ConditionRef] = Condition) = copy(Condition = newCondition)
}
object `AWS::OpsWorks::Stack` extends DefaultJsonProtocol {
  implicit val format: JsonFormat[`AWS::OpsWorks::Stack`] = jsonFormat4(`AWS::OpsWorks::Stack`.apply)
}
carsonfarrell commented 7 years ago

I was thinking about just putting JsObject, figured I'd bring it up for discussion first though - I think it should work, and it's explicit about what's required.

tjcorr commented 7 years ago

The only other option would be to try and fully model the inner type like we did with IAM PolicyDocument. I'm guessing that isn't feasible here though.

carsonfarrell commented 7 years ago

Yeah, it's a user defined object, so I can't see modelling it as part of the library.