Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add region_alias support for multiple aliases in a single region #115

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/stack_master/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def execute_stacks_command(command, args, options)
args.each_slice(2) do |aliased_region, stack_name|
region = Utils.underscore_to_hyphen(config.unalias_region(aliased_region))
stack_name = Utils.underscore_to_hyphen(stack_name)
stack_definitions = config.filter(region, stack_name)
stack_definitions = config.filter(region, stack_name, aliased_region)
if stack_definitions.empty?
StackMaster.stdout.puts "Could not find stack definition #{stack_name} in region #{region}"
end
Expand Down
2 changes: 1 addition & 1 deletion lib/stack_master/commands/list_stacks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def initialize(config)

def perform
tp.set :max_width, self.window_size
tp @config.stacks, :region, :stack_name
tp @config.stacks, :region, :region_alias ,:raw_stack_name
end
end
end
Expand Down
37 changes: 24 additions & 13 deletions lib/stack_master/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def self.load!(config_file = 'stack_master.yml')
:region_defaults,
:region_aliases,
:template_compilers,
:prepend_region_alias_to_stack_names,

def self.search_up_and_chdir(config_file)
return config_file unless File.dirname(config_file) == "."
Expand All @@ -34,6 +35,7 @@ def initialize(config, base_dir)
@config = config
@base_dir = base_dir
@stack_defaults = config.fetch('stack_defaults', {})
@prepend_region_alias_to_stack_names = config.fetch('prepend_region_alias_to_stack_names', false)
@region_aliases = Utils.underscore_keys_to_hyphen(config.fetch('region_aliases', {}))
@region_to_aliases = @region_aliases.inject({}) do |hash, (key, value)|
hash[value] ||= []
Expand All @@ -46,10 +48,11 @@ def initialize(config, base_dir)
load_config
end

def filter(region = nil, stack_name = nil)
def filter(region = nil, stack_name = nil, region_alias = nil)
@stacks.select do |s|
(region.blank? || s.region == region || s.region == region.gsub('_', '-')) &&
(stack_name.blank? || s.stack_name == stack_name || s.stack_name == stack_name.gsub('_', '-'))
(stack_name.blank? || s.stack_name == stack_name || s.stack_name == stack_name.gsub('_', '-')) &&
(region_alias.blank? || s.region_alias == region_alias || s.region_alias == region_alias.gsub('_', '-'))
end
end

Expand Down Expand Up @@ -94,26 +97,34 @@ def load_config

def resolve_region_aliases(stacks)
stacks.inject({}) do |hash, (region, attributes)|
hash[unalias_region(region)] = attributes
hash.deeper_merge(unalias_region(region) => {region => attributes})
hash
end
end

def load_stacks(stacks)
stacks.each do |region, stacks_for_region|
region = Utils.underscore_to_hyphen(region)
stacks_for_region.each do |stack_name, attributes|
stack_name = Utils.underscore_to_hyphen(stack_name)
stack_attributes = build_stack_defaults(region).deeper_merge!(attributes).merge(
'region' => region,
'stack_name' => stack_name,
'base_dir' => @base_dir,
'additional_parameter_lookup_dirs' => @region_to_aliases[region])
@stacks << StackDefinition.new(stack_attributes)
stacks.each do |region, region_aliases|
region_aliases.each do |region_alias, stacks_for_region|
region = Utils.underscore_to_hyphen(region)
stacks_for_region.each do |stack_name, attributes|
stack_attributes = build_stack_defaults(region).deeper_merge!(attributes).merge(
'region' => region,
'region_alias' => region_alias,
'stack_name' => computed_stack_name(stack_name, region, region_alias),
'raw_stack_name' => Utils.underscore_to_hyphen(stack_name),
'base_dir' => @base_dir,
'additional_parameter_lookup_dirs' => @region_to_aliases[region])
@stacks << StackDefinition.new(stack_attributes)
end
end
end
end

def computed_stack_name(stack_name, region, region_alias)
prefix = region_alias if prepend_region_alias_to_stack_names && region != region_alias
[prefix, Utils.underscore_to_hyphen(stack_name)].compact.join('-')
end

def build_stack_defaults(region)
region_defaults = @region_defaults.fetch(region, {}).deep_dup
@stack_defaults.deep_dup.deeper_merge(region_defaults)
Expand Down
15 changes: 13 additions & 2 deletions lib/stack_master/stack_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ class StackDefinition

values do
attribute :region, String
attribute :region_alias, String
attribute :stack_name, String
attribute :raw_stack_name, String
attribute :template, String
attribute :tags, Hash
attribute :notification_arns, Array[String]
Expand All @@ -19,7 +21,12 @@ def template_file_path
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, I'm not entirely clear on the purpose of "additional_parameter_lookup_file_paths" vs as I did it below, explicitly resolving explicitly to the region_alias as I did below. I've preserved both, but I'm interested in the rationale behind additional_parameter_lookup_file_paths.

def parameter_files
[ default_parameter_file_path, region_parameter_file_path ] + additional_parameter_lookup_file_paths
[
default_parameter_file_path,
alias_parameter_file_path,
region_parameter_file_path,
additional_parameter_lookup_file_paths
].flatten.uniq
end

def stack_policy_file_path
Expand All @@ -34,6 +41,10 @@ def additional_parameter_lookup_file_paths
end
end

def alias_parameter_file_path
File.join(base_dir, 'parameters', "#{region_alias}", "#{underscored_stack_name}.yml")
end

def region_parameter_file_path
File.join(base_dir, 'parameters', "#{region}", "#{underscored_stack_name}.yml")
end
Expand All @@ -43,7 +54,7 @@ def default_parameter_file_path
end

def underscored_stack_name
stack_name.gsub('-', '_')
raw_stack_name.to_s.gsub('-', '_')
end
end
end
5 changes: 3 additions & 2 deletions spec/fixtures/stack_master.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
prepend_region_alias_to_stack_names: true
region_aliases:
production: us-east-1
staging: ap-southeast-2
Expand Down Expand Up @@ -29,12 +30,12 @@ stacks:
- test_arn_2
myapp_web:
template: myapp_web.rb
ap-southeast-2:
staging:
myapp_vpc:
template: myapp_vpc.rb
notification_arns:
- test_arn_4
myapp_web:
template: myapp_web
tags:
test_override: 2
test_override: 2
1 change: 1 addition & 0 deletions spec/stack_master/commands/apply_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
before do
allow(StackMaster::Stack).to receive(:find).with(region, stack_name).and_return(stack)
allow(StackMaster::Stack).to receive(:generate).with(stack_definition, config).and_return(proposed_stack)
allow(config).to receive(:stack_defaults).and_return({})
allow(Aws::CloudFormation::Client).to receive(:new).and_return(cf)
allow(cf).to receive(:create_stack)
allow(StackMaster::StackDiffer).to receive(:new).with(proposed_stack, stack).and_return double.as_null_object
Expand Down
2 changes: 1 addition & 1 deletion spec/stack_master/commands/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

describe "#perform" do
it "creates all the expected files" do
expect(IO).to receive(:write).with("stack_master.yml", "stacks:\n us-east-1:\n test-stack:\n template: test-stack.json\n tags:\n environment: production\n")
expect(IO).to receive(:write).with("stack_master.yml", "# prepend_region_alias_to_stack_names: true\n# region_aliases:\n# stack_defaults:\n# tags:\nstacks:\n us-east-1:\n test-stack:\n template: test-stack.json\n tags:\n environment: production\n")
expect(IO).to receive(:write).with("parameters/test_stack.yml", "# Add parameters here:\n# param1: value1\n# param2: value2\n")
expect(IO).to receive(:write).with("parameters/us-east-1/test_stack.yml", "# Add parameters here:\n# param1: value1\n# param2: value2\n")
expect(IO).to receive(:write).with("templates/test-stack.json", "{\n \"AWSTemplateFormatVersion\" : \"2010-09-09\",\n \"Description\" : \"Cloudformation stack for test-stack\",\n\n \"Parameters\" : {\n \"InstanceType\" : {\n \"Description\" : \"EC2 instance type\",\n \"Type\" : \"String\"\n }\n },\n\n \"Mappings\" : {\n },\n\n \"Resources\" : {\n },\n\n \"Outputs\" : {\n }\n}\n")
Expand Down
15 changes: 11 additions & 4 deletions spec/stack_master/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
let(:myapp_vpc_definition) {
StackMaster::StackDefinition.new(
region: 'us-east-1',
region_alias: 'us-east-1',
stack_name: 'myapp-vpc',
raw_stack_name: 'myapp-vpc',
template: 'myapp_vpc.json',
tags: { 'application' => 'my-awesome-blog', 'environment' => 'production' },
notification_arns: ['test_arn', 'test_arn_2'],
Expand Down Expand Up @@ -104,9 +106,11 @@
end

it 'deep merges stack attributes' do
expect(loaded_config.find_stack('ap-southeast-2', 'myapp-vpc')).to eq(StackMaster::StackDefinition.new(
stack_name: 'myapp-vpc',
expect(loaded_config.find_stack('ap-southeast-2', 'staging-myapp-vpc')).to eq(StackMaster::StackDefinition.new(
stack_name: 'staging-myapp-vpc',
raw_stack_name: 'myapp-vpc',
region: 'ap-southeast-2',
region_alias: 'staging',
tags: {
'application' => 'my-awesome-blog',
'environment' => 'staging',
Expand All @@ -118,9 +122,12 @@
secret_file: 'staging.yml.gpg',
additional_parameter_lookup_dirs: ['staging']
))
expect(loaded_config.find_stack('ap-southeast-2', 'myapp-web')).to eq(StackMaster::StackDefinition.new(
stack_name: 'myapp-web',

expect(loaded_config.find_stack('ap-southeast-2', 'staging-myapp-web')).to eq(StackMaster::StackDefinition.new(
stack_name: 'staging-myapp-web',
raw_stack_name: 'myapp-web',
region: 'ap-southeast-2',
region_alias: 'staging',
tags: {
'application' => 'my-awesome-blog',
'environment' => 'staging',
Expand Down
28 changes: 22 additions & 6 deletions spec/stack_master/stack_definition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@
subject(:stack_definition) do
StackMaster::StackDefinition.new(
region: region,
region_alias: region_alias,
stack_name: stack_name,
raw_stack_name: raw_stack_name,
template: template,
tags: tags,
base_dir: base_dir)
end

let(:region) { 'us-east-1' }
let(:stack_name) { 'stack_name' }
let(:region_alias) { 'us-east-1' }
let(:stack_name) { 'production_stack_name' }
let(:raw_stack_name) { 'stack_name' }
let(:template) { 'template.json' }
let(:tags) { {'environment' => 'production'} }
let(:base_dir) { '/base_dir' }

it 'has default and region specific parameter file locations' do
expect(stack_definition.parameter_files).to eq([
"/base_dir/parameters/#{stack_name}.yml",
"/base_dir/parameters/#{region}/#{stack_name}.yml"
"/base_dir/parameters/#{raw_stack_name}.yml",
"/base_dir/parameters/#{region}/#{raw_stack_name}.yml"
])
end

Expand All @@ -28,9 +32,21 @@

it 'includes a parameter lookup dir for it' do
expect(stack_definition.parameter_files).to eq([
"/base_dir/parameters/#{stack_name}.yml",
"/base_dir/parameters/#{region}/#{stack_name}.yml",
"/base_dir/parameters/production/#{stack_name}.yml"
"/base_dir/parameters/#{raw_stack_name}.yml",
"/base_dir/parameters/#{region}/#{raw_stack_name}.yml",
"/base_dir/parameters/production/#{raw_stack_name}.yml"
])
end
end

context 'if a region alias is specified' do
let(:region_alias) { 'staging' }

it 'has default, alias, and region specific parameter file locations' do
expect(stack_definition.parameter_files).to eq([
"/base_dir/parameters/#{raw_stack_name}.yml",
"/base_dir/parameters/#{region_alias}/#{raw_stack_name}.yml",
"/base_dir/parameters/#{region}/#{raw_stack_name}.yml",
])
end
end
Expand Down
4 changes: 4 additions & 0 deletions stacktemplates/stack_master.yml.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# prepend_region_alias_to_stack_names: true
# region_aliases:
# stack_defaults:
# tags:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I felt the default stack_master.yml from the init function was a little too barren, so I added some extra empty (commented out) options. Is that ok?

stacks:
<%= region %>:
<%= stack_name %>:
Expand Down