Module: AutoStacker24::Preprocessor

Defined in:
lib/autostacker24/template_preprocessor.rb

Constant Summary collapse

SUPPORTED_TYPES =
Set[%w(AWS::AutoScaling::AutoScalingGroup AWS::CloudTrail::Trail AWS::EC2::CustomerGateway AWS::EC2::DHCPOptions AWS::EC2::Instance AWS::EC2::InternetGateway AWS::EC2::NetworkAcl AWS::EC2::NetworkInterface AWS::EC2::RouteTable AWS::EC2::SecurityGroup AWS::EC2::Subnet AWS::EC2::Volume AWS::EC2::VPC AWS::EC2::VPCPeeringConnection AWS::EC2::VPNConnection AWS::EC2::VPNGateway AWS::ElasticBeanstalk::Environment AWS::ElasticLoadBalancing::LoadBalancer AWS::RDS::DBCluster AWS::RDS::DBClusterParameterGroup AWS::RDS::DBInstance AWS::RDS::DBParameterGroup AWS::RDS::DBSecurityGroup AWS::RDS::DBSubnetGroup AWS::RDS::OptionGroup AWS::S3::Bucket)]

Class Method Summary collapse

Class Method Details

.adjust_tags_for_asg(tags) ⇒ Object



46
47
48
# File 'lib/autostacker24/template_preprocessor.rb', line 46

def self.adjust_tags_for_asg(tags)
  tags.map {|element| element.merge('PropagateAtLaunch' => 'true') }
end

.preprocess(template, tags = nil) ⇒ Object



9
10
11
12
13
14
15
16
# File 'lib/autostacker24/template_preprocessor.rb', line 9

def self.preprocess(template, tags = nil)
  if template =~ /^\s*\/{2}\s*/i
    template = template.gsub(/(\s*\/\/.*$)|(".*")/) {|m| m[0] == '"' ? m : ''} # replace comments
    template = preprocess_json(JSON(template))
    template = preprocess_tags(template, tags).to_json
  end
  template
end

.preprocess_json(json) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/autostacker24/template_preprocessor.rb', line 50

def self.preprocess_json(json)
  if json.is_a?(Hash)
    json.inject({}) do |m, (k, v)|
      if k == 'UserData' && v.is_a?(String)
        m.merge(k => preprocess_user_data(v))
      else
        m.merge(k => preprocess_json(v))
      end
    end
  elsif json.is_a?(Array)
    json.map{|v| preprocess_json(v)}
  elsif json.is_a?(String)
    preprocess_string(json)
  else
    json
  end
end

.preprocess_string(s) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/autostacker24/template_preprocessor.rb', line 74

def self.preprocess_string(s)
  parts = tokenize(s).map do |token|
    case token
      when '@@' then '@'
      when /^@/ then {'Ref' => token[1..-1]}
      else token
    end
  end

  # merge neighboured strings
  parts = parts.reduce([])do |m, p|
    if m.last.is_a?(String) && p.is_a?(String)
      m[-1] += p
    else
      m << p
    end
    m
  end

  if parts.length == 1
    parts.first
  else # we need a join construct
    {'Fn::Join' => ['', parts]}
  end
end

.preprocess_tags(template, tags = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/autostacker24/template_preprocessor.rb', line 20

def self.preprocess_tags(template, tags = nil)

  unless tags.nil?

    tags_for_asg = adjust_tags_for_asg(tags)

    template['Resources'].each {|(key, value)|

      tags_to_apply = tags
      if value['Type'] == 'AWS::AutoScaling::AutoScalingGroup'
        tags_to_apply = tags_for_asg
      end

      if SUPPORTED_TYPES.include? value['Type']
        if value['Properties']['Tags'].nil?
          value['Properties']['Tags'] = tags_to_apply
        else
          value['Properties']['Tags'] = (tags_to_apply + value['Properties']['Tags']).uniq { |s| s.first }
        end
      end
    }
  end

  template
end

.preprocess_user_data(s) ⇒ Object



68
69
70
71
72
# File 'lib/autostacker24/template_preprocessor.rb', line 68

def self.preprocess_user_data(s)
  m = /^@file:\/\/(.*)/.match(s)
  s = File.read(m[1]) if m
  {'Fn::Base64' => s}
end

.tokenize(s) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/autostacker24/template_preprocessor.rb', line 100

def self.tokenize(s)
  pattern = /@@|@((\w+(::)?\w+)+)/
  tokens = []
  loop do
    m = pattern.match(s)
    if m
      tokens << m.pre_match unless m.pre_match.empty?
      tokens << m.to_s
      s = m.post_match
    else
      tokens << s unless s.empty? && !tokens.empty?
      break
    end
  end
  tokens
end