Module: Jets::Cfn::Builder::Interface

Extended by:
Memoist
Includes:
Util::Camelize
Included in:
Api::Base, Authorizer, Nested, Parent
Defined in:
lib/jets/cfn/builder/interface.rb

Instance Method Summary collapse

Methods included from Util::Camelize

#camelize

Instance Method Details

#add_description(desc) ⇒ Object



44
45
46
# File 'lib/jets/cfn/builder/interface.rb', line 44

def add_description(desc)
  @template[:Description] = desc
end

#add_output(name, options = {}) ⇒ Object



67
68
69
70
# File 'lib/jets/cfn/builder/interface.rb', line 67

def add_output(name, options={})
  @template[:Outputs] ||= {}
  @template[:Outputs][name.camelize.to_sym] = camelize(options)
end

#add_outputs(attributes) ⇒ Object



61
62
63
64
65
# File 'lib/jets/cfn/builder/interface.rb', line 61

def add_outputs(attributes)
  attributes.each do |name,value|
    add_output(name.camelize.to_sym, Value: value)
  end
end

#add_parameter(name, options = {}) ⇒ Object



54
55
56
57
58
59
# File 'lib/jets/cfn/builder/interface.rb', line 54

def add_parameter(name, options={})
  defaults = { Type: "String" }
  options = defaults.merge(options)
  @template[:Parameters] ||= {}
  @template[:Parameters][name.camelize.to_sym] = camelize(options)
end

#add_parameters(attributes) ⇒ Object



48
49
50
51
52
# File 'lib/jets/cfn/builder/interface.rb', line 48

def add_parameters(attributes)
  attributes.each do |name,value|
    add_parameter(name.camelize.to_sym, Description: value)
  end
end

#add_resource(resource) ⇒ Object

Note: Jets::Cfn::Resource::Iam classes are special treated. They are only a few resources that result in creating 2 CloudFormation resources. Cfn::Builder::Api::Methods also creates a method, permission, and possible cors resource. Though that is more of an internal Jets resource. In this case for Iam, both Iam::Policy and Iam::Role are created. This allows the user to refer to the Lambda Function name in the IAM Policy itself. We need separate resources to avoid CloudFormation erroring with a circular dependency. Using separate IAM::Policy and IAM::Role resources allows us avoid the circular dependency error.

Handling logic here also centralizes code for this special behavior. Also important to note, this does not change the user-facing interface. IE: Users still uses code like:

iam_policy("s3", "sns")

and be none-the-wiser about the special behavior.



98
99
100
101
102
103
104
105
106
# File 'lib/jets/cfn/builder/interface.rb', line 98

def add_resource(resource)
  add_template_resource(resource.logical_id, resource.type, resource.attributes)

  if resource.class.to_s.include?("Jets::Cfn::Resource::Iam")
    role = resource # for clarity: resource is a Iam::*Role class
    iam_policy = Jets::Cfn::Resource::Iam::Policy.new(role)
    add_template_resource(iam_policy.logical_id, iam_policy.type, iam_policy.attributes)
  end
end

#add_resourcesObject



72
73
74
75
76
77
78
79
80
# File 'lib/jets/cfn/builder/interface.rb', line 72

def add_resources
  @app_class.definitions.each do |definition|
    definition.associated_resources.each do |associated|
      resource = Jets::Cfn::Resource.new(associated.definition, definition.replacements)
      add_resource(resource)
      add_resource(resource.permission)
    end
  end
end

#add_template_resource(logical_id, type, options) ⇒ Object

The add_resource method can take an options Hash with both with either top level attributes or properties.

Example:

Top level options:

add_template_resource("MyId", "AWS::ApiGateway::RestApi",
  Type: "AWS::ApiGateway::RestApi",
  Properties: {
    Name: "my-api"
  },
  DependsOn: ["AnotherResource"]
)

Simple options with properties only:

add_template_resource("MyId", "AWS::CloudFormationStack",
  TemplateURL: "template_url",
  Parameters: {},
)


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/jets/cfn/builder/interface.rb', line 130

def add_template_resource(logical_id, type, options)
  options = camelize(options)

  attributes = if options.include?(:Type)
                 base = { Type: type }
                 base.merge(options) # options are top-level attributes
               else
                 {
                   Type: type,
                   Properties: options # options are properties
                 }
               end

  @template[:Resources][logical_id] = attributes
end

#buildObject



11
12
13
14
15
# File 'lib/jets/cfn/builder/interface.rb', line 11

def build
  return unless build?
  compose # must be implemented by subclass
  write
end

#build?Boolean

Do not bother building or writing the template unless there are functions defined

Returns:

  • (Boolean)


18
19
20
21
# File 'lib/jets/cfn/builder/interface.rb', line 18

def build?
  build = @app_class && !@app_class.build?
  !build
end

#templateObject



28
29
30
31
32
# File 'lib/jets/cfn/builder/interface.rb', line 28

def template
  # need the to_hash or the YAML dump has
  #  !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  @template.to_hash
end

#textObject



34
35
36
37
38
39
40
41
42
# File 'lib/jets/cfn/builder/interface.rb', line 34

def text
  # -1 means unlimited line width, it prevents the YAML.dump from wrapping
  # Otherwise the PostProcess class will not work properly.
  text = YAML.dump(template, line_width: -1)
  # post process the text so that
  # "!Ref IamRole" => !Ref IamRole
  # We strip the surrounding quotes
  PostProcess.new(text).process
end

#writeObject



23
24
25
26
# File 'lib/jets/cfn/builder/interface.rb', line 23

def write
  FileUtils.mkdir_p(File.dirname(template_path))
  IO.write(template_path, text)
end