Class: MkStack::Template

Inherits:
Object
  • Object
show all
Defined in:
lib/mkstack/template.rb

Overview

A CloudFormation template

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format = 'json', argv = nil) ⇒ Template

Returns a new instance of Template.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/mkstack/template.rb', line 36

def initialize(format = 'json', argv = nil)
  @format = format

  @sections = {
    'AWSTemplateFormatVersion' => Section.new('AWSTemplateFormatVersion', String, nil),
    'Description' => Section.new('Description', String, 1024),

    'Conditions' => Section.new('Conditions', Hash,  nil),
    'Mappings'   => Section.new('Mappings',   Hash,  200),
    'Metadata'   => Section.new('Metadata',   Hash,  nil),
    'Outputs'    => Section.new('Outputs',    Hash,  200),
    'Parameters' => Section.new('Parameters', Hash,  200),
    'Resources'  => Section.new('Resources',  Hash,  500),
    'Transform'  => Section.new('Transform',  Array, nil),
    'Rules'      => Section.new('Rules',      Hash,  nil),
  }
  @limit = 51_200

  # Keep track of parsed files to avoid loops
  @parsed = {}

  # Save a binding so ERB can reuse it instead of creating a new one
  # every time we load a file.  This allows ERB code in one file to
  # be referenced in another.
  @binding = binding
end

Instance Attribute Details

#formatObject (readonly)

Returns the value of attribute format.



34
35
36
# File 'lib/mkstack/template.rb', line 34

def format
  @format
end

#limitObject (readonly)

Returns the value of attribute limit.



34
35
36
# File 'lib/mkstack/template.rb', line 34

def limit
  @limit
end

#sectionsObject (readonly)

Returns the value of attribute sections.



34
35
36
# File 'lib/mkstack/template.rb', line 34

def sections
  @sections
end

Instance Method Details

#[](section) ⇒ Object

Shorthand accessor for template sections



64
65
66
# File 'lib/mkstack/template.rb', line 64

def [](section)
  @sections[section]
end

#exceeds_limit?Boolean

Check if the template exceeds the AWS limit

Returns:

  • (Boolean)


74
75
76
# File 'lib/mkstack/template.rb', line 74

def exceeds_limit?
  limit && length > limit
end

#lengthObject

Return the length of the entire template



69
70
71
# File 'lib/mkstack/template.rb', line 69

def length
  to_json.to_s.length
end

#merge(file, erb) ⇒ Object

Merge contents of a file



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/mkstack/template.rb', line 81

def merge(file, erb)
  contents = load(file, erb)

  begin
    # Try JSON
    cfn = JSON.load(contents)
  rescue Exception => _e
    # Try YAML
    add_tags
    cfn = YAML.safe_load(contents, permitted_classes: [IntrinsicShort])
    @format = 'yaml'
  end

  # Check if there were any sections
  unless cfn
    $logger.debug { "no content in #{file}" }
    return
  end

  # Merge sections that are present in the file
  @sections.each do |name, section|
    section.merge(cfn[name]) if cfn[name]
  end

  # Look for Includes and merge them
  # Files are Included relative to the file with the Include directive
  cfn['Include'].each do |file|
    Dir.chdir(File.dirname(file)) { self.merge(File.basename(file), erb) }
  end if cfn['Include']
end

#ppObject

Format contents



123
124
125
126
127
128
129
130
131
132
# File 'lib/mkstack/template.rb', line 123

def pp
  case @format
  when 'json'
    to_hash.to_json
  when 'yaml'
    to_hash.to_yaml({ line_width: -1 }) # Keep Psych from splitting "long" lines
  else
    to_hash
  end
end

#validateObject



115
116
117
118
# File 'lib/mkstack/template.rb', line 115

def validate
  require 'aws-sdk-cloudformation'
  Aws::CloudFormation::Client.new.validate_template({ template_body: pp })
end