Skip to content
This repository has been archived by the owner on Oct 19, 2023. It is now read-only.

Commit

Permalink
Merge pull request #170 from rapid7/task/issue-99-support-extending-t…
Browse files Browse the repository at this point in the history
…he-convection-dsl

Fix #99 - Support extending the convection resource DSL
  • Loading branch information
erran-r7 authored Aug 8, 2016
2 parents bbccace + 304c055 commit a674d31
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/convection/control/stack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def diff
# template has any changes compared to the current template (in
# CloudFormation).
def resource_changes?
ours = { 'Resources' => @template.resources.map(&:render) }
ours = { 'Resources' => @template.all_resources.map(&:render) }
thiers = { 'Resources' => @current_template['Resources'] }

ours.diff(thiers).any?
Expand Down
22 changes: 21 additions & 1 deletion lib/convection/model/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def attach_resource(name, klass)
resources[rname] = resource
end
end

def attach_resource_collection(name, klass)
define_method(name) do |rname, &block|
resource_collections[rname] = klass.new(rname, self, &block)
end
end
end
end

Expand Down Expand Up @@ -187,6 +193,7 @@ class Template
attr_reader :parameters
attr_reader :mappings
attr_reader :conditions
attr_reader :resource_collections
attr_reader :resources
attr_reader :outputs

Expand All @@ -207,6 +214,7 @@ def initialize(stack = nil, &block)
@mappings = Collection.new
@conditions = Collection.new
@resources = Collection.new
@resource_collections = Collection.new
@outputs = Collection.new
@metadata = Collection.new
end
Expand All @@ -217,6 +225,11 @@ def clone(stack_)

def execute
instance_exec(&@definition)

resource_collections.each do |_, group|
group.run_definition
group.execute
end
end

def render(stack_ = nil)
Expand All @@ -231,12 +244,18 @@ def render(stack_ = nil)
'Parameters' => parameters.map(&:render),
'Mappings' => mappings.map(&:render),
'Conditions' => conditions.map(&:render),
'Resources' => resources.map(&:render),
'Resources' => all_resources.map(&:render),
'Outputs' => outputs.map(&:render),
'Metadata' => metadata.map(&:render)
}
end

def all_resources
resource_collections.reduce(resources) do |result, (_name, resource_collection)|
result.merge(resource_collection.resources)
end
end

def diff(other, stack_ = nil)
render(stack_).diff(other).map { |diff| Diff.new(diff[0], *diff[1]) }
end
Expand Down Expand Up @@ -353,5 +372,6 @@ def validate_bytesize(rendered_stack)
require_relative 'template/resource'
require_relative 'template/resource_property'
require_relative 'template/resource_attribute'
require_relative 'template/resource_collection'
require_relative 'template/output'
require_relative 'template/metadata'
48 changes: 48 additions & 0 deletions lib/convection/model/template/resource_collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'forwardable'
require_relative './resource'
require_relative '../mixin/conditional'

module Convection
module Model
class Template
# A collection of different {Convection::Model::Template::Resource}s.
class ResourceCollection
extend Forwardable
include DSL::Helpers
include DSL::Template::Resource
include Mixin::Conditional

attr_reader :name
attr_reader :parent
attr_reader :template

def_delegator :@template, :stack

class << self
def attach_to_dsl(dsl_name)
DSL::Template::Resource.attach_resource_collection(dsl_name, self)
end
end

def initialize(name, parent, &definition)
@definition = definition
@name = name
@parent = parent
@template = parent.template
end

# @note This method is in place to be overriden by subclasses.
def execute
end

def run_definition
instance_exec(&@definition) if @definition
end

def resources
@resources ||= Convection::Model::Collection.new
end
end
end
end
end
63 changes: 63 additions & 0 deletions spec/convection/model/template/resource_collection_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'spec_helper'

class Convection::Model::Template
describe ResourceCollection do
class WebService < Convection::Model::Template::ResourceCollection
attach_to_dsl(:web_service)

attribute :use_elastic_load_balancing

def execute
web_service = self # Expose this instance to nested template methods.

ec2_instance "#{name}WebService"

elb "#{name}LoadBalancer" do
tag 'Description', "Load balancer for the #{web_service.name} web service."
end if use_elastic_load_balancing
end
end

let(:use_elb_value) { nil }
let(:template) do
outer_scope = self
Convection.template do
description 'ResourceCollection Test Template'

# A lone resource for testing merging of resources and nested resources.
ec2_instance 'LoneResource1'

web_service 'ExampleDotOrg' do
use_elastic_load_balancing outer_scope.use_elb_value
end
end
end

subject do
template_json
.fetch('Resources')
end

context 'when the use_elastic_load_balancing attribute is set' do
let(:use_elb_value) { true }

it { is_expected.to have_key('LoneResource1') }
it { is_expected.to have_key('ExampleDotOrgWebService') }
it { is_expected.to have_key('ExampleDotOrgLoadBalancer') }
end

context 'when the use_elastic_load_balancing attribute is not set' do
let(:use_elb_value) { false }

it { is_expected.to have_key('LoneResource1') }
it { is_expected.to have_key('ExampleDotOrgWebService') }
it { is_expected.to_not have_key('ExampleDotOrgLoadBalancer') }
end

private

def template_json
JSON.parse(template.to_json)
end
end
end

0 comments on commit a674d31

Please # to comment.