@@ -30,20 +30,21 @@ type PackageAlias struct {
3030
3131// Template represents a CloudFormation template. The Template type
3232// is minimal for now but will likely grow new features as needed by rain.
33+ //
34+ // Node is the only member that is guaranteed to exist after
35+ // parsing a template.
3336type Template struct {
34- Node * yaml.Node
35-
36- Constants map [string ]* yaml.Node
37- Packages map [string ]* PackageAlias
37+ FileName string
38+ Name string
39+ Node * yaml.Node
40+ Constants map [string ]* yaml.Node
41+ Packages map [string ]* PackageAlias
42+ ModuleMapNames map [string ][]string
43+ ModuleMaps map [string ]* ModuleConfig
44+ ModuleOutputs map [string ]* yaml.Node
45+ ModuleResolved []* yaml.Node
3846}
3947
40- // TODO - We really need a convenient Template data structure
41- // that lets us easily access elements.
42- // t.Resources["MyResource"].Properties["MyProp"]
43- //
44- // Add a Model attribute to the struct and an Init function to populate it.
45- // t.Model.Resources
46-
4748// Map returns the template as a map[string]interface{}
4849func (t Template ) Map () map [string ]interface {} {
4950 var out map [string ]interface {}
@@ -57,7 +58,7 @@ func (t Template) Map() map[string]interface{} {
5758}
5859
5960// AppendStateMap appends a "State" section to the template
60- func AppendStateMap (state Template ) * yaml.Node {
61+ func AppendStateMap (state * Template ) * yaml.Node {
6162 state .Node .Content [0 ].Content = append (state .Node .Content [0 ].Content ,
6263 & yaml.Node {Kind : yaml .ScalarNode , Value : "State" })
6364 stateMap := & yaml.Node {Kind : yaml .MappingNode , Content : make ([]* yaml.Node , 0 )}
@@ -81,6 +82,18 @@ const (
8182 Outputs Section = "Outputs"
8283 State Section = "State"
8384 Rain Section = "Rain"
85+ Modules Section = "Modules"
86+ Packages Section = "Packages"
87+ Constants Section = "Constants"
88+ )
89+
90+ type Intrinsic string
91+
92+ const (
93+ Sub Intrinsic = "Fn::Sub"
94+ GetAtt Intrinsic = "Fn::GetAtt"
95+ Ref Intrinsic = "Ref"
96+ If Intrinsic = "Fn::If"
8497)
8598
8699// GetResource returns the yaml node for a resource by logical id
@@ -148,9 +161,19 @@ func (t Template) GetSection(section Section) (*yaml.Node, error) {
148161 return s , nil
149162}
150163
164+ // HasSection returns true if the template has the section
165+ func (t Template ) HasSection (section Section ) bool {
166+ if t .Node == nil {
167+ return false
168+ }
169+ m := t .Node .Content [0 ]
170+ _ , s , _ := s11n .GetMapValue (m , string (section ))
171+ return s != nil
172+ }
173+
151174// RemoveSection removes a section node from the template
152175func (t Template ) RemoveSection (section Section ) error {
153- return node .RemoveFromMap (t .Node .Content [0 ], string (Rain ))
176+ return node .RemoveFromMap (t .Node .Content [0 ], string (section ))
154177}
155178
156179// GetTypes returns all unique type names for resources in the template
@@ -224,3 +247,38 @@ func (t Template) RemoveEmptySections() {
224247 node .RemoveFromMap (m , name )
225248 }
226249}
250+
251+ // AddMappedModule adds a reference to a module that was mapped to a CSV of keys,
252+ // which duplicates the module in the template. We store a reference here so
253+ // that we can resolve references like Content[0].Arn, which points to the first
254+ // mapped instance of a Module called Content, with an Output called Arn.
255+ func (t * Template ) AddMappedModule (copiedConfig * ModuleConfig ) {
256+ if t .ModuleMaps == nil {
257+ t .ModuleMaps = make (map [string ]* ModuleConfig )
258+ }
259+ t .ModuleMaps [copiedConfig .Name ] = copiedConfig
260+ if t .ModuleMapNames == nil {
261+ t .ModuleMapNames = make (map [string ][]string )
262+ }
263+ originalName := copiedConfig .OriginalName
264+ var mappedModules []string
265+ var ok bool
266+ if mappedModules , ok = t .ModuleMapNames [originalName ]; ! ok {
267+ mappedModules = make ([]string , 0 )
268+ }
269+ if ! slices .Contains (mappedModules , copiedConfig .Name ) {
270+ mappedModules = append (mappedModules , copiedConfig .Name )
271+ }
272+ t .ModuleMapNames [originalName ] = mappedModules
273+ }
274+
275+ func (t * Template ) AddResolvedModuleNode (n * yaml.Node ) {
276+ if t .ModuleResolved == nil {
277+ t .ModuleResolved = make ([]* yaml.Node , 0 )
278+ }
279+ t .ModuleResolved = append (t .ModuleResolved , n )
280+ }
281+
282+ func (t * Template ) ModuleAlreadyResolved (n * yaml.Node ) bool {
283+ return slices .Contains (t .ModuleResolved , n )
284+ }
0 commit comments