-
Notifications
You must be signed in to change notification settings - Fork 195
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
Some feedback #90
Comments
@simplesteph i think this is legit feedback. I think the main difficulty here is that cloudformation is both data and code (intrinsics)... And goformation deals only with the data side nicely due to typing... but because a template cannot be resolved fully to types until processed by cloudformation... it's not as powerful as you'd hope. I'm using this library to manage a serverless infrastructure for a large project and we've taken the following approach:
Here's some hacks we're doing: for dealing with intrinsics that are in your MV stack.yaml var overrides = map[string]intrinsics.IntrinsicHandler{
"Fn::Base64": jsonMakingHandler,
"Fn::And": jsonMakingHandler,
"Fn::Equals": jsonMakingHandler,
"Fn::If": jsonMakingHandler,
"Fn::Not": jsonMakingHandler,
"Fn::Or": jsonMakingHandler,
"Fn::FindInMap": jsonMakingHandler,
"Fn::GetAtt": jsonMakingHandler,
"Fn::GetAZs": jsonMakingHandler,
"Fn::ImportValue": jsonMakingHandler,
"Fn::Join": jsonMakingHandler,
"Fn::Select": jsonMakingHandler,
"Fn::Split": jsonMakingHandler,
"Fn::Sub": jsonMakingHandler,
"Ref": jsonMakingHandler,
}
// HACK ALERT HACK ALERT HACK ALERT
// Intrinsic function handling do not work great with goformation due to how the
// structs are generated to be tightly coupled to the cloudformation schema
// (see https://github.com/awslabs/goformation/issues/3)
// This function creates a string out of intrinsics which will be turned
// into the json version of the intrisnic on write time of the file.
// It does so by rendering the intrinsic function as it's json version
// and preprending a token ("_decor_") to the json string.
//
// Example if you have some yaml:
// ```yaml
// Name:
// Fn::Sub:
// Some/Value/${AWS::Region}
//
// ```
// This function will generate
//
// ```yaml
// Name: _decor_{"Fn::Sub:":"Some/Value/${AWS::Region}"}
// ```
//
// Before the yaml file is written back out the `_decor_` is removed
// and the intrinsic JSON remains embedded
//
// ```yaml
// Name: {"Fn::Sub": "Some/Value/${AWS::Region}"}
// ```
func jsonMakingHandler(name string, input interface{}, template interface{}) interface{} {
var downstreamIntrinsic map[string]interface{}
var intrinsicFunc map[string]interface{}
// Check if this was processed downstream and unwind it
// So we can use it as a single json string
switch val := input.(type) {
case string:
// We know that input was processed down the stack
if strings.Contains(val, "_decor_") {
foo := strings.Replace(val, "_decor_", "", -1)
err := json.Unmarshal([]byte(foo), &downstreamIntrinsic)
if err != nil {
panic(err)
}
}
}
if downstreamIntrinsic != nil {
intrinsicFunc = map[string]interface{}{
name: downstreamIntrinsic,
}
} else {
intrinsicFunc = map[string]interface{}{
name: input,
}
}
b, err := json.Marshal(intrinsicFunc)
if err != nil {
panic(err)
}
return "_decor_" + string(b)
} For creating intrinsics while dealing with goformation: // Store md5 -> intrinsic function
var intrinsics map[string]string = map[string]string{}
// Can set a value as Intrinsify(`{"Fn::Sub":"${AWS::AccountId}"}`)
// Which will write the hash of that intrinsic as the value of some goformation struct.
func Intrinsify(value string) string {
hasher := md5.New()
hasher.Write([]byte(value))
key := hex.EncodeToString(hasher.Sum(nil))
intrinsics[key] = value
return key
}
// Find all the intrinsic hashes in the template and replace with the real value
func Resolve(template []byte) []byte {
for key, value := range intrinsics {
template = bytes.Replace(template, []byte(key), []byte(value), -1)
}
return template
} I'd love to see a better solution for cloudformation authoring in this space as well. I think goformation is a nice attempt but there's definitely room for improvement. |
This library now has support for using CloudFormation Intrinsic functions when composing CloudFormation templates - check out the examples in the README for details of how to use |
Nice addition @PaulMaddox |
I think this is a great library and here's what I love:
But I wanted to use this for one of my projects and it just fails to hit the mark....
I think it's really time you try your own product, see the pain of just doing the following:
Template with:
And it's currently impossible, but highly necessary to:
I'm sure there are also tons of other gaps, but really try to show off an "example" in your repo that just does that - pretty basic stuff. Then you'll have hit something rock solid and I can start recommending this library
I usually try to do PRs but I won't have time for this, hope the feedback helps you in some way, and I really hope to achieve the above in the future
The text was updated successfully, but these errors were encountered: