Improve support for cross-stack references with output exports and Fn::ImportValue
Cloudformation now allows cross-stack imports using. We should add support for Export in the output function, and Fn::ImportValue.
Copying the conversation here, rather than the PR:
I can't accept this one as-is because it breaks the Export functionality as it works today. I know of at least two companies that are using that today, and I'm not comfortable asking them to make this change for stylistic reasons.
"publiczone": {
"Export": {
"Name": {
"Name": "PublicZone"
}
}
},
"Value": {
"Ref": "PublicZone"
}
},
However, I do appreciate that the current way of using exports is not the most rubyish.
The way I'd prefer to accomplish this is something like this:
def output(name, value, options = {})
self[:Outputs][name] = options.merge('Value' => value)
end
def export(name, value, options = {})
output name, value, options.merge(Export: { 'Name' => name })
end
That way, output is always a fall-back escape-hatch.
Here is my latest technique for solving this problem. This method also includes a naming convention, based on our "Environment+Application+Facet" model for deploying the same infrastructure multiple times. Solving the "Export" noise hasn't been a high priority for me because I usually use it encapsulated by a specific pattern like this, since exports are a global namespace outside of stacks.
Cfer::Core::Stack.extend_stack do
def exported_val_name(name, options={})
env = options[:environment] || parameters[:environment] # parameters[:environment] is always present
app = options[:application] || parameters[:application] # parameters[:application] is always present
facet = options[:facet] || parameters[:facet] # parameters[:facet] is always present, and defaults to "main"
{ "Fn::Join": [options[:delim] || "-", [env, app, facet, name]] }
end
def opscues_import(app, rc, options={})
val_name = exported_val_name(rc, options.merge(application: app))
{ "Fn::ImportValue": val_name }
end
def opscues_export(name, value, options = {})
export_name = exported_val_name(name, options)
output name.to_s.gsub(/[^A-Za-z0-9]+/, ''), value, Export: { Name: export_name }
end
end