diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..959dbc6
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,4 @@
+--color
+--require spec_helper
+--format d
+--order defined
diff --git a/Rakefile b/Rakefile
index a9efa1c..cb86143 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
namespace :spec do
- RSPEC_OPTS = ["--format", "nested", "--format", "html", "--out", "spec_result.html", "--colour"]
+ RSPEC_OPTS = ["--format", "documentation", "--format", "html", "--out", "spec_result.html", "--colour"]
RSpec::Core::RakeTask.new(:file) do |t|
t.rspec_opts = RSPEC_OPTS
diff --git a/cf_deployer.gemspec b/cf_deployer.gemspec
index 056d142..ab73674 100644
--- a/cf_deployer.gemspec
+++ b/cf_deployer.gemspec
@@ -8,18 +8,25 @@ Gem::Specification.new do |gem|
gem.summary = %q{Support multiple components deployment using CloudFormation templates with multiple blue green strategies.}
gem.homepage = "http://github.com/manheim/cf_deployer"
gem.license = 'MIT'
+ gem.required_ruby_version = '>= 3.2.8', '< 3.3'
- gem.add_runtime_dependency 'aws-sdk','1.44.0'
+ gem.add_runtime_dependency 'aws-sdk-autoscaling', '~> 1.86'
+ gem.add_runtime_dependency 'aws-sdk-cloudformation', '~> 1.76'
+ gem.add_runtime_dependency 'aws-sdk-core', '~> 3.170'
+ gem.add_runtime_dependency 'aws-sdk-ec2', '~> 1.365'
+ gem.add_runtime_dependency 'aws-sdk-elasticloadbalancing', '~> 1.42'
+ gem.add_runtime_dependency 'aws-sdk-route53', '~> 1.71'
+ gem.add_runtime_dependency 'diffy'
+ gem.add_runtime_dependency 'json', '~> 2.5'
gem.add_runtime_dependency 'log4r'
- gem.add_runtime_dependency 'thor'
gem.add_runtime_dependency 'rainbow'
- gem.add_runtime_dependency 'diffy'
- gem.add_development_dependency 'yard', '~> 0.8.7.6'
- gem.add_development_dependency 'pry', '~> 0.10.1'
- gem.add_development_dependency 'rspec', '2.14.1'
- gem.add_development_dependency 'rake', '~> 10.3.0'
- gem.add_development_dependency 'webmock', '~> 2.1.0'
- gem.add_development_dependency 'vcr', '~> 2.9.3'
+ gem.add_runtime_dependency 'thor'
+ gem.add_development_dependency 'pry', '~> 0.13'
+ gem.add_development_dependency 'rake', '~> 13.0'
+ gem.add_development_dependency 'rspec', '3.10'
+ gem.add_development_dependency 'vcr', '~> 6.0'
+ gem.add_development_dependency 'webmock', '~> 3.11'
+ gem.add_development_dependency 'yard', '~> 0.9'
gem.files = `git ls-files`.split($\).reject {|f| f =~ /^samples\// }
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
diff --git a/fixtures/vcr_cassettes/aws_call_count/driver/auto_scaling_group/healthy_instance_count.yml b/fixtures/vcr_cassettes/aws_call_count/driver/auto_scaling_group/healthy_instance_count.yml
index dccd0cd..4dd2765 100644
--- a/fixtures/vcr_cassettes/aws_call_count/driver/auto_scaling_group/healthy_instance_count.yml
+++ b/fixtures/vcr_cassettes/aws_call_count/driver/auto_scaling_group/healthy_instance_count.yml
@@ -45,7 +45,7 @@ http_interactions:
\ \n \n \n
\ \n 12345\n
\ \n\n"
- http_version:
+ http_version:
recorded_at: Tue, 27 Sep 2016 05:47:40 GMT
- request:
method: post
@@ -65,7 +65,7 @@ http_interactions:
\ \n \n \n
\ \n 12346\n
\ \n\n"
- http_version:
+ http_version:
recorded_at: Tue, 27 Sep 2016 05:47:40 GMT
- request:
method: post
diff --git a/lib/cf_deployer.rb b/lib/cf_deployer.rb
index 80f9580..f766032 100644
--- a/lib/cf_deployer.rb
+++ b/lib/cf_deployer.rb
@@ -2,8 +2,14 @@
require 'set'
require 'time'
require 'json'
+require 'yaml'
require 'timeout'
-require 'aws-sdk'
+require 'aws-sdk-autoscaling'
+require 'aws-sdk-ec2'
+require 'aws-sdk-core'
+require 'aws-sdk-cloudformation'
+require 'aws-sdk-elasticloadbalancing'
+require 'aws-sdk-route53'
require 'erb'
require 'fileutils'
require 'log4r'
@@ -38,7 +44,8 @@
module CfDeployer
- AWS.config(:max_retries => 20)
+ aws_config = Seahorse::Client::Configuration.new
+ aws_config.add_option(:max_retries, 20)
def self.config opts
config = self.parseconfig opts, false
@@ -50,19 +57,16 @@ def self.config opts
def self.deploy opts
config = self.parseconfig opts
- # AWS.config(:logger => Logger.new($stdout))
Application.new(config).deploy
end
def self.runhook opts
config = self.parseconfig opts
- # AWS.config(:logger => Logger.new($stdout))
Application.new(config).run_hook opts[:component].first, opts[:hook_name]
end
def self.destroy opts
config = self.parseconfig opts, false
- # AWS.config(:logger => Logger.new($stdout))
Application.new(config).destroy
end
@@ -97,7 +101,7 @@ def self.kill_inactive opts
private
def self.parseconfig options, validate_inputs = true
- AWS.config(:region => options[:region]) if options[:region]
+ Aws.config.update({region: options[:region]}) if options[:region]
options[:cli_overrides] = {:settings => options.delete(:settings), :inputs => options.delete(:inputs)}
config = ConfigLoader.new.load options
ConfigValidation.new.validate config, validate_inputs
diff --git a/lib/cf_deployer/cli.rb b/lib/cf_deployer/cli.rb
index 3568d1a..edf0606 100644
--- a/lib/cf_deployer/cli.rb
+++ b/lib/cf_deployer/cli.rb
@@ -94,7 +94,7 @@ def merged_options
def set_log_level
if options[:'log-level'] == 'aws-debug'
CfDeployer::Log.level = 'debug'
- AWS.config :logger => Logger.new($stdout)
+ Aws.config.update(:logger => Logger.new($stdout))
else
CfDeployer::Log.level = options[:'log-level']
end
diff --git a/lib/cf_deployer/config_loader.rb b/lib/cf_deployer/config_loader.rb
index 1684d71..db2faac 100644
--- a/lib/cf_deployer/config_loader.rb
+++ b/lib/cf_deployer/config_loader.rb
@@ -3,7 +3,7 @@ class ConfigLoader
def self.erb_to_json filename, config
json_file = File.join(config[:config_dir], "#{filename}.json")
- raise ApplicationError.new("#{json_file} is missing") unless File.exists?(json_file)
+ raise ApplicationError.new("#{json_file} is missing") unless File.exist?(json_file)
CfDeployer::Log.info "ERBing JSON for #{filename}"
ERB.new(File.read(json_file)).result(binding)
rescue RuntimeError,TypeError,NoMethodError => e
@@ -39,7 +39,7 @@ def load(options)
def load_yaml(text)
YAML.load text
- rescue Psych::SyntaxError => e
+ rescue ::Psych::SyntaxError => e
error_document text
raise e
rescue
diff --git a/lib/cf_deployer/config_validation.rb b/lib/cf_deployer/config_validation.rb
index afdca72..fddbc3d 100644
--- a/lib/cf_deployer/config_validation.rb
+++ b/lib/cf_deployer/config_validation.rb
@@ -79,7 +79,7 @@ def check_hook_file(component, hook_name)
file_name = component[hook_name][:file]
return unless file_name
path = File.join(component[:config_dir], file_name)
- @errors << "File '#{path}' does not exist, which is required by hook '#{hook_name}'" unless File.exists?(path)
+ @errors << "File '#{path}' does not exist, which is required by hook '#{hook_name}'" unless File.exist?(path)
end
def check_environments
diff --git a/lib/cf_deployer/driver/auto_scaling_group.rb b/lib/cf_deployer/driver/auto_scaling_group.rb
index bca8b26..9c8c2e2 100644
--- a/lib/cf_deployer/driver/auto_scaling_group.rb
+++ b/lib/cf_deployer/driver/auto_scaling_group.rb
@@ -3,7 +3,7 @@ module Driver
class AutoScalingGroup
extend Forwardable
- def_delegators :aws_group, :auto_scaling_instances, :ec2_instances, :load_balancers, :desired_capacity
+ def_delegators :aws_group, :instances, :desired_capacity, :load_balancer_names
attr_reader :group_name, :group
@@ -22,7 +22,7 @@ def warm_up desired
Log.info "warming up auto scaling group #{group_name} to #{desired}"
CfDeployer::Driver::DryRun.guard "Skipping ASG warmup" do
- aws_group.set_desired_capacity desired
+ aws_group.set_desired_capacity({desired_capacity: desired})
wait_for_desired_capacity
end
end
@@ -38,14 +38,14 @@ def cool_down
Log.info "Cooling down #{group_name}"
CfDeployer::Driver::DryRun.guard "Skipping ASG cooldown" do
aws_group.update :min_size => 0, :max_size => 0
- aws_group.set_desired_capacity 0
+ aws_group.set_desired_capacity({desired_capacity: 0})
end
end
def instance_statuses
instance_info = {}
- ec2_instances.each do |instance|
- instance_info[instance.id] = CfDeployer::Driver::Instance.new(instance).status
+ instances.each do |instance|
+ instance_info[instance.id] = CfDeployer::Driver::Instance.new(instance.id).status
end
instance_info
end
@@ -63,34 +63,25 @@ def desired_capacity_reached?
end
def healthy_instance_ids
- instances = auto_scaling_instances.select do |instance|
+ _instances = instances.select do |instance|
'HEALTHY'.casecmp(instance.health_status) == 0
end
- instances.map(&:id)
+ _instances.map(&:id)
end
def in_service_instance_ids
- elbs = load_balancers
- return [] if elbs.empty?
-
- ids = elbs.collect(&:instances)
- .collect(&:health)
- .to_a
- .collect { |elb_healths|
- elb_healths.select { |health| health[:state] == 'InService' }
- .map { |health| health[:instance].id }
- }
-
- ids.inject(:&)
+ elb_names = load_balancer_names
+
+ return [] if elb_names.empty?
+
+ elb_driver.in_service_instance_ids elb_names
end
def healthy_instance_count
- AWS.memoize do
- instances = healthy_instance_ids
- instances &= in_service_instance_ids unless load_balancers.empty?
- Log.info "Healthy instance count: #{instances.count}"
- instances.count
- end
+ instances = healthy_instance_ids
+ instances &= in_service_instance_ids unless load_balancer_names.empty?
+ Log.info "Healthy instance count: #{instances.count}"
+ instances.count
rescue => e
Log.error "Unable to determine healthy instance count due to error: #{e.message}"
-1
@@ -99,7 +90,11 @@ def healthy_instance_count
private
def aws_group
- @my_group ||= AWS::AutoScaling.new.groups[group_name]
+ @my_group ||= Aws::AutoScaling::AutoScalingGroup.new(group_name)
+ end
+
+ def elb_driver
+ @elb_driver ||= Elb.new
end
end
end
diff --git a/lib/cf_deployer/driver/cloud_formation_driver.rb b/lib/cf_deployer/driver/cloud_formation_driver.rb
index 7857d08..c46c756 100644
--- a/lib/cf_deployer/driver/cloud_formation_driver.rb
+++ b/lib/cf_deployer/driver/cloud_formation_driver.rb
@@ -7,40 +7,40 @@ def initialize stack_name
end
def stack_exists?
- aws_stack.exists?
+ !aws_stack.nil?
end
def create_stack template, opts
CfDeployer::Driver::DryRun.guard "Skipping create_stack" do
- cloud_formation.stacks.create @stack_name, template, opts
+ cloud_formation.create_stack(opts.merge(stack_name: @stack_name, template_body: template))
end
end
def update_stack template, opts
begin
CfDeployer::Driver::DryRun.guard "Skipping update_stack" do
- aws_stack.update opts.merge(:template => template)
+ cloud_formation.update_stack(opts.merge(stack_name: @stack_name, template_body: template))
end
- rescue AWS::CloudFormation::Errors::ValidationError => e
- if e.message =~ /No updates are to be performed/
- Log.info e.message
- return false
- else
- raise
- end
+ rescue Aws::CloudFormation::Errors::ValidationError => e
+ Log.info e.message
+ return false
+ rescue => e
+ puts '*' * 80
+ puts e
+ raise
end
return !CfDeployer::Driver::DryRun.enabled?
end
def stack_status
- aws_stack.status.downcase.to_sym
+ aws_stack&.stack_status&.downcase&.to_sym
end
def outputs
aws_stack.outputs.inject({}) do |memo, o|
- memo[o.key] = o.value
+ memo[o.output_key] = o.output_value
memo
end
end
@@ -50,14 +50,14 @@ def parameters
end
def query_output key
- output = aws_stack.outputs.find { |o| o.key == key }
- output && output.value
+ output = aws_stack.outputs.find { |o| o.output_key == key }
+ output && output.output_value
end
def delete_stack
if stack_exists?
CfDeployer::Driver::DryRun.guard "Skipping create_stack" do
- aws_stack.delete
+ cloud_formation.delete_stack(stack_name: @stack_name)
end
else
Log.info "Stack #{@stack_name} does not exist!"
@@ -66,7 +66,7 @@ def delete_stack
def resource_statuses
resources = {}
- aws_stack.resource_summaries.each do |rs|
+ cloud_formation.list_stack_resources(stack_name: @stack_name).stack_resource_summaries.each do |rs|
resources[rs[:resource_type]] ||= {}
resources[rs[:resource_type]][rs[:physical_resource_id]] = rs[:resource_status]
end
@@ -80,14 +80,17 @@ def template
private
def cloud_formation
- AWS::CloudFormation.new
+ Aws::CloudFormation::Client.new
end
def aws_stack
- cloud_formation.stacks[@stack_name]
+ begin
+ cloud_formation.describe_stacks({stack_name: @stack_name}).stacks.first
+ rescue Aws::CloudFormation::Errors::ValidationError => e
+ return nil
+ end
end
end
-
end
end
diff --git a/lib/cf_deployer/driver/elb_driver.rb b/lib/cf_deployer/driver/elb_driver.rb
index 971de89..c958f2a 100644
--- a/lib/cf_deployer/driver/elb_driver.rb
+++ b/lib/cf_deployer/driver/elb_driver.rb
@@ -2,16 +2,23 @@ module CfDeployer
module Driver
class Elb
def find_dns_and_zone_id elb_id
- elb = elb_driver.load_balancers[elb_id]
- { :canonical_hosted_zone_name_id => elb.canonical_hosted_zone_name_id, :dns_name => elb.dns_name }
+ elb = elb_driver.describe_load_balancers({:load_balancer_names => [elb_id]})&.load_balancer_descriptions&.first
+ { :canonical_hosted_zone_name_id => elb&.canonical_hosted_zone_name_id, :dns_name => elb&.dns_name }
+ end
+
+ def in_service_instance_ids elb_ids
+ elb_ids.collect do |elb_id|
+ elb_driver.describe_instance_health({:load_balancer_name => elb_id}).instance_states
+ .collect{|instance| instance.state == 'InService' ? instance.instance_id : nil }.compact
+ end.inject(:&)
end
private
def elb_driver
- AWS::ELB.new
+ @elb_driver ||= Aws::ElasticLoadBalancing::Client.new
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/cf_deployer/driver/instance.rb b/lib/cf_deployer/driver/instance.rb
index dac559e..1b70bca 100644
--- a/lib/cf_deployer/driver/instance.rb
+++ b/lib/cf_deployer/driver/instance.rb
@@ -14,15 +14,16 @@ def initialize instance_obj_or_id
def status
instance_info = { }
- [:status, :public_ip_address, :private_ip_address, :image_id].each do |stat|
+ [:public_ip_address, :private_ip_address, :image_id].each do |stat|
instance_info[stat] = aws_instance.send(stat)
end
+ instance_info[:status] = aws_instance.state
instance_info[:key_pair] = aws_instance.key_pair.name
instance_info
end
def aws_instance
- @instance_obj ||= AWS::EC2.new.instances[@id]
+ @instance_obj ||= Aws::EC2::Instance.new(@id)
end
end
end
diff --git a/lib/cf_deployer/driver/route53_driver.rb b/lib/cf_deployer/driver/route53_driver.rb
index 3e21d90..3846b4a 100644
--- a/lib/cf_deployer/driver/route53_driver.rb
+++ b/lib/cf_deployer/driver/route53_driver.rb
@@ -2,7 +2,7 @@ module CfDeployer
module Driver
class Route53
def initialize(aws_route53 = nil)
- @aws_route53 = aws_route53 || AWS::Route53.new
+ @aws_route53 = aws_route53 || Aws::Route53::Client.new
end
def find_alias_target(hosted_zone_name, target_host_name)
@@ -17,7 +17,7 @@ def set_alias_target(hosted_zone_name, target_host_name, elb_hosted_zone_id, elb
Log.info "set alias target --Hosted Zone: #{hosted_zone_name} --Host Name: #{target_host_name} --ELB DNS Name: #{elb_dnsname} --ELB Zone ID: #{elb_hosted_zone_id}"
hosted_zone_name = trailing_dot(hosted_zone_name)
target_host_name = trailing_dot(target_host_name)
- hosted_zone = @aws_route53.hosted_zones.find { |z| z.name == hosted_zone_name }
+ hosted_zone = @aws_route53.list_hosted_zones_by_name.hosted_zones.find { |z| z.name == hosted_zone_name }
raise ApplicationError.new('Target zone not found!') if hosted_zone.nil?
change = {
@@ -34,7 +34,7 @@ def set_alias_target(hosted_zone_name, target_host_name, elb_hosted_zone_id, elb
}
batch = {
- hosted_zone_id: hosted_zone.path,
+ hosted_zone_id: hosted_zone.id,
change_batch: {
changes: [change]
}
@@ -53,6 +53,7 @@ def delete_record_set(hosted_zone_name, target_host_name)
record_set.delete if record_set
end
end
+
private
def change_resource_record_sets_with_retry(batch)
@@ -60,7 +61,7 @@ def change_resource_record_sets_with_retry(batch)
while attempts < 20
begin
attempts = attempts + 1
- @aws_route53.client.change_resource_record_sets(batch)
+ @aws_route53.change_resource_record_sets(batch)
return
rescue Exception => e
Log.info "Failed to update alias target, trying again in 20 seconds."
@@ -72,11 +73,13 @@ def change_resource_record_sets_with_retry(batch)
end
def get_hosted_zone(zone_name)
- @aws_route53.hosted_zones.find { |z| z.name == trailing_dot(zone_name.downcase) }
+ @aws_route53.list_hosted_zones_by_name.hosted_zones.find { |z| z.name == trailing_dot(zone_name.downcase) }
end
-
+
def get_record_set(hosted_zone, target_host_name)
- hosted_zone.resource_record_sets.find { |r| r.name == trailing_dot(target_host_name.downcase) }
+ @aws_route53.list_resource_record_sets({:hosted_zone_id => hosted_zone.id})
+ .resource_record_sets
+ .find { |r| r.name == trailing_dot(target_host_name.downcase) }
end
def trailing_dot(text)
diff --git a/lib/cf_deployer/stack.rb b/lib/cf_deployer/stack.rb
index 91a752f..7c2d57e 100644
--- a/lib/cf_deployer/stack.rb
+++ b/lib/cf_deployer/stack.rb
@@ -21,7 +21,12 @@ def deploy
capabilities = @context[:capabilities] || []
notify = @context[:notify] || []
tags = @context[:tags] || {}
- params = to_str(@context[:inputs].select{|key, value| @context[:defined_parameters].keys.include?(key)})
+ params = @context[:inputs].select{|key, value| @context[:defined_parameters].keys.include?(key)}
+ .map do |key, value|
+ next nil unless @context[:defined_parameters].keys.include?(key)
+ { parameter_key: key.to_s, parameter_value: value.to_s }
+ end.compact
+
CfDeployer::Driver::DryRun.guard "Skipping deploy" do
if exists?
override_policy_json = nil
@@ -56,7 +61,12 @@ def output key
def find_output key
begin
@cf_driver.query_output(key)
- rescue AWS::CloudFormation::Errors::ValidationError => e
+ rescue Aws::CloudFormation::Errors::OperationStatusCheckFailedException => e
+ raise ResourceNotInReadyState.new("Resource stack not in ready state yet, perhaps you should provision it first?")
+ rescue => e
+ puts '*' * 80
+ puts e
+ puts '*' * 80
raise ResourceNotInReadyState.new("Resource stack not in ready state yet, perhaps you should provision it first?")
end
end
@@ -88,20 +98,18 @@ def status
end
def resource_statuses
- AWS.memoize do
- resources = @cf_driver.resource_statuses.merge( { :asg_instances => {}, :instances => {} } )
- if resources['AWS::AutoScaling::AutoScalingGroup']
- resources['AWS::AutoScaling::AutoScalingGroup'].keys.each do |asg_name|
- resources[:asg_instances][asg_name] = CfDeployer::Driver::AutoScalingGroup.new(asg_name).instance_statuses
- end
+ resources = @cf_driver.resource_statuses.merge( { :asg_instances => {}, :instances => {} } )
+ if resources['AWS::AutoScaling::AutoScalingGroup']
+ resources['AWS::AutoScaling::AutoScalingGroup'].keys.each do |asg_name|
+ resources[:asg_instances][asg_name] = CfDeployer::Driver::AutoScalingGroup.new(asg_name).instance_statuses
end
- if resources['AWS::EC2::Instance']
- resources['AWS::EC2::Instance'].keys.each do |instance_id|
- resources[:instances][instance_id] = CfDeployer::Driver::Instance.new(instance_id).status
- end
+ end
+ if resources['AWS::EC2::Instance']
+ resources['AWS::EC2::Instance'].keys.each do |instance_id|
+ resources[:instances][instance_id] = CfDeployer::Driver::Instance.new(instance_id).status
end
- resources
end
+ resources
end
def name
@@ -114,10 +122,6 @@ def template
private
- def to_str(hash)
- hash.each { |k,v| hash[k] = v.to_s }
- end
-
def update_stack(template, params, capabilities, tags, override_policy_json)
Log.info "Updating stack #{@stack_name}..."
args = {
@@ -136,7 +140,7 @@ def create_stack(template, params, capabilities, tags, notify, create_policy_jso
args = {
:disable_rollback => true,
:capabilities => capabilities,
- :notify => notify,
+ :notification_arns => notify,
:tags => reformat_tags(tags),
:parameters => params
}
@@ -148,7 +152,7 @@ def create_stack(template, params, capabilities, tags, notify, create_policy_jso
end
def stack_status
- @cf_driver.stack_status
+ @cf_driver.stack_status || :does_not_exist
end
def wait_for_stack_op_terminate
@@ -167,19 +171,19 @@ def wait_for_stack_to_delete
begin
Log.info "current status: #{stack_status}"
sleep 15
- rescue AWS::CloudFormation::Errors::ValidationError => e
- if e.message =~ /does not exist/
- break # This is what we wanted anyways
- else
- raise e
- end
+ rescue Aws::CloudFormation::Errors::StackSetNotFoundException => e
+ break # This is what we wanted anyway
+ rescue => e
+ puts '*' * 80
+ puts e
+ raise e
end
end
}
end
def reformat_tags tags_hash
- tags_hash.keys.map { |key| { 'Key' => key.to_s, 'Value' => tags_hash[key].to_s } }
+ tags_hash.keys.map { |key| { :key => key.to_s, :value => tags_hash[key].to_s } }
end
end
end
diff --git a/spec/aws_call_count_spec_helper.rb b/spec/aws_call_count_spec_helper.rb
index 73b1570..a2f5f32 100644
--- a/spec/aws_call_count_spec_helper.rb
+++ b/spec/aws_call_count_spec_helper.rb
@@ -11,8 +11,20 @@ def override_aws_environment options = {}
options[:AWS_REGION] ||= 'us-east-1'
options[:AWS_ACCESS_KEY_ID] ||= 'someId'
options[:AWS_SECRET_ACCESS_KEY] ||= 'secretKey'
-
- override_environment_variables(options) { yield }
+ options[:AWS_EC2_METADATA_DISABLED] ||= 'true'
+ options[:AWS_SDK_CONFIG_OPT_OUT] ||= '1'
+
+ override_environment_variables(options) do
+ previous_aws_config = Aws.config.dup
+ Aws.config.update(
+ region: options[:AWS_REGION],
+ credentials: Aws::Credentials.new(options[:AWS_ACCESS_KEY_ID], options[:AWS_SECRET_ACCESS_KEY])
+ )
+ yield
+ ensure
+ Aws.config.clear
+ Aws.config.update(previous_aws_config)
+ end
end
def override_environment_variables options = {}
diff --git a/spec/fakes/instance.rb b/spec/fakes/instance.rb
index 5f9fb97..d89ed24 100644
--- a/spec/fakes/instance.rb
+++ b/spec/fakes/instance.rb
@@ -1,3 +1,5 @@
+require 'ostruct'
+
module Fakes
class Instance
@@ -20,7 +22,7 @@ def initialize(options)
instance_variable_set "@#{attrib}", (options[attrib] || defaults[attrib])
end
- @key_pair = ::AWS::EC2::KeyPair.new (options[:key_pair] || defaults[:key_pair] )
+ @key_pair = OpenStruct.new(name: (options[:key_pair] || defaults[:key_pair]))
end
def inspect
@@ -29,4 +31,4 @@ def inspect
alias_method :to_s, :inspect
end
-end
\ No newline at end of file
+end
diff --git a/spec/fakes/route53_client.rb b/spec/fakes/route53_client.rb
index 797b0ee..4ddb48f 100644
--- a/spec/fakes/route53_client.rb
+++ b/spec/fakes/route53_client.rb
@@ -1,20 +1,19 @@
+require 'ostruct'
+
module Fakes
class AWSRoute53
attr_reader :fail_counter, :hosted_zones, :client
def initialize(opts = {})
- @client = AWSRoute53Client.new(opts)
@hosted_zones = opts[:hosted_zones]
- @fail_counter = 0
- end
- end
- class AWSRoute53Client
- attr_reader :fail_counter
- def initialize(opts = {})
@times_to_fail = opts[:times_to_fail]
@fail_counter = 0
end
+ def list_hosted_zones_by_name
+ OpenStruct.new(hosted_zones: hosted_zones)
+ end
+
def change_resource_record_sets(*args)
@fail_counter = @fail_counter + 1
raise 'Error' if @fail_counter <= @times_to_fail
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index bb8c348..aa47a43 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -8,7 +8,7 @@
if ENV['DEBUG']
RSPEC_LOG.level = Logger::DEBUG
- AWS.config :logger => RSPEC_LOG
+ # AWS.config :logger => RSPEC_LOG
end
def puts *args
@@ -20,3 +20,12 @@ def ignore_errors
rescue => e
RSPEC_LOG.debug "Intentionally ignoring error: #{e.message}"
end
+
+RSpec.configure do |config|
+ # These two settings work together to allow you to limit a spec run
+ # to individual examples or groups you care about by tagging them with
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+ # get run.
+ config.filter_run :focus
+ config.run_all_when_everything_filtered = true
+end
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index 7fcd716..3606d2b 100644
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -28,11 +28,11 @@
end
it "application should get all components" do
- @app.components.length.should eq(4)
- @base.should_not be_nil
- @db.should_not be_nil
- @queue.should_not be_nil
- @web.should_not be_nil
+ expect(@app.components.length).to eq(4)
+ expect(@base).not_to be_nil
+ expect(@db).not_to be_nil
+ expect(@queue).not_to be_nil
+ expect(@web).not_to be_nil
end
context "order components by dependencies" do
@@ -154,7 +154,7 @@
context "deploy all components" do
it "should deploy all components if no component specified" do
@app.deploy
- @log.should eq("base db queue web ")
+ expect(@log).to eq("base db queue web ")
end
end
@@ -162,7 +162,7 @@
it "should deploy specified components" do
@context[:targets] = ['web', 'db']
@app.deploy
- @log.should eq("db web ")
+ expect(@log).to eq("db web ")
end
end
end
@@ -179,13 +179,13 @@
it 'should get json templates for all components' do
@app.json
- @log.should eq("base db queue web ")
+ expect(@log).to eq("base db queue web ")
end
it 'should get json templates for components specified' do
@context[:targets] = ['web', 'db']
@app.json
- @log.should eq('db web ')
+ expect(@log).to eq('db web ')
end
end
end
diff --git a/spec/unit/component_spec.rb b/spec/unit/component_spec.rb
index b148983..92f3504 100644
--- a/spec/unit/component_spec.rb
+++ b/spec/unit/component_spec.rb
@@ -98,7 +98,7 @@
it "should ask strategy if component exists" do
expect(@strategy).to receive(:exists?){ true }
- @web.exists?.should eq(true)
+ expect(@web.exists?).to eq(true)
end
it "should find direct dependencies" do
@@ -106,7 +106,7 @@
base = CfDeployer::Component.new('myApp', 'uat', 'base', {})
web.dependencies << base
- web.depends_on?(base).should eq(true)
+ expect(web.depends_on?(base)).to eq(true)
end
it "should find transitive dependencies" do
@@ -117,7 +117,7 @@
haproxy.dependencies << base
web.dependencies << haproxy
- web.depends_on?(base).should eq(true)
+ expect(web.depends_on?(base)).to eq(true)
end
it "should find cyclic dependency" do
diff --git a/spec/unit/config_loader_spec.rb b/spec/unit/config_loader_spec.rb
index 69fdebf..1cb9e25 100644
--- a/spec/unit/config_loader_spec.rb
+++ b/spec/unit/config_loader_spec.rb
@@ -2,7 +2,7 @@
describe "load config settings" do
before :each do
- Dir.mkdir 'tmp' unless Dir.exists?('tmp')
+ Dir.mkdir 'tmp' unless Dir.exist?('tmp')
@config_file = File.expand_path("../../../tmp/test_config.yml", __FILE__)
@base_json = File.expand_path("../../../tmp/base.json", __FILE__)
@api_json = File.expand_path("../../../tmp/api.json", __FILE__)
@@ -146,143 +146,143 @@
it "all the keys should be symbols in config" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:base][:'deployment-strategy'].should eq('create-or-update')
- config['components'].should be_nil
+ expect(config[:components][:base][:'deployment-strategy']).to eq('create-or-update')
+ expect(config['components']).to be_nil
end
it "should copy application, environment, component to component settings" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat'})
- config[:components][:api][:settings][:application].should eq("myApp")
- config[:components][:api][:settings][:component].should eq("api")
- config[:components][:api][:settings][:environment].should eq("uat")
- config[:components][:base][:settings][:application].should eq("myApp")
- config[:components][:base][:settings][:component].should eq("base")
- config[:components][:base][:settings][:environment].should eq("uat")
+ expect(config[:components][:api][:settings][:application]).to eq("myApp")
+ expect(config[:components][:api][:settings][:component]).to eq("api")
+ expect(config[:components][:api][:settings][:environment]).to eq("uat")
+ expect(config[:components][:base][:settings][:application]).to eq("myApp")
+ expect(config[:components][:base][:settings][:component]).to eq("base")
+ expect(config[:components][:base][:settings][:environment]).to eq("uat")
end
it "should copy region to coponent settings" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat', :region => 'us-west-1'})
- config[:components][:api][:settings][:region].should eq("us-west-1")
- config[:components][:base][:settings][:region].should eq("us-west-1")
+ expect(config[:components][:api][:settings][:region]).to eq("us-west-1")
+ expect(config[:components][:base][:settings][:region]).to eq("us-west-1")
end
it "should copy application, environment, component to component inputs" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat'})
- config[:components][:api][:inputs][:application].should eq("myApp")
- config[:components][:api][:inputs][:component].should eq("api")
- config[:components][:api][:inputs][:environment].should eq("uat")
- config[:components][:base][:inputs][:application].should eq("myApp")
- config[:components][:base][:inputs][:component].should eq("base")
- config[:components][:base][:inputs][:environment].should eq("uat")
+ expect(config[:components][:api][:inputs][:application]).to eq("myApp")
+ expect(config[:components][:api][:inputs][:component]).to eq("api")
+ expect(config[:components][:api][:inputs][:environment]).to eq("uat")
+ expect(config[:components][:base][:inputs][:application]).to eq("myApp")
+ expect(config[:components][:base][:inputs][:component]).to eq("base")
+ expect(config[:components][:base][:inputs][:environment]).to eq("uat")
end
it "should copy region to coponent inputs" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat', :region => 'us-west-1'})
- config[:components][:api][:inputs][:region].should eq("us-west-1")
- config[:components][:base][:inputs][:region].should eq("us-west-1")
+ expect(config[:components][:api][:inputs][:region]).to eq("us-west-1")
+ expect(config[:components][:base][:inputs][:region]).to eq("us-west-1")
end
it "config_dir option should be copied to component context" do
config_dir = File.dirname(@config_file)
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat'})
- config[:components][:api][:config_dir].should eq(config_dir)
- config[:components][:base][:config_dir].should eq(config_dir)
- config[:components][:'front-end'][:config_dir].should eq(config_dir)
+ expect(config[:components][:api][:config_dir]).to eq(config_dir)
+ expect(config[:components][:base][:config_dir]).to eq(config_dir)
+ expect(config[:components][:'front-end'][:config_dir]).to eq(config_dir)
end
it "notify option should be merged to component context" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'dev'})
- config[:components][:base][:notify].should eq(['arn:root', 'arn:base', 'arn:dev'])
- config[:components][:api][:notify].should eq(['arn:root', 'arn:api', 'arn:dev'])
- config[:components][:'front-end'][:notify].should eq(['arn:root', 'arn:base', 'arn:dev'])
+ expect(config[:components][:base][:notify]).to eq(['arn:root', 'arn:base', 'arn:dev'])
+ expect(config[:components][:api][:notify]).to eq(['arn:root', 'arn:api', 'arn:dev'])
+ expect(config[:components][:'front-end'][:notify]).to eq(['arn:root', 'arn:base', 'arn:dev'])
end
it "notify option should be merged to environment context" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat'})
- config[:components][:base][:notify].should eq(['arn:root', 'arn:base'])
- config[:components][:api][:notify].should eq(['arn:root', 'arn:api'])
- config[:components][:'front-end'][:notify].should eq(['arn:root', 'arn:base'])
+ expect(config[:components][:base][:notify]).to eq(['arn:root', 'arn:base'])
+ expect(config[:components][:api][:notify]).to eq(['arn:root', 'arn:api'])
+ expect(config[:components][:'front-end'][:notify]).to eq(['arn:root', 'arn:base'])
end
it "tags option should be copied to component context" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat'})
- config[:components][:api][:tags].should eq({:version => 'v1.1'})
- config[:components][:base][:tags].should eq({:version => 'v1.1', :component => 'base'})
- config[:components][:'front-end'][:tags].should eq({:version => 'v1.1'})
+ expect(config[:components][:api][:tags]).to eq({:version => 'v1.1'})
+ expect(config[:components][:base][:tags]).to eq({:version => 'v1.1', :component => 'base'})
+ expect(config[:components][:'front-end'][:tags]).to eq({:version => 'v1.1'})
end
it "component's settings should be merged to common settings" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'uat'})
- config[:components][:api][:inputs][:'timeout'].should eq(90)
- config[:components][:api][:inputs][:'require-basic-auth'].should eq(true)
- config[:components][:api][:inputs][:'mail-server'].should eq('http://api.abc.com')
+ expect(config[:components][:api][:inputs][:'timeout']).to eq(90)
+ expect(config[:components][:api][:inputs][:'require-basic-auth']).to eq(true)
+ expect(config[:components][:api][:inputs][:'mail-server']).to eq('http://api.abc.com')
end
it "environment's settings should be merged to component settings" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'dev'})
- config[:components][:api][:inputs][:'timeout'].should eq(60)
- config[:components][:api][:inputs][:'require-basic-auth'].should eq(true)
- config[:components][:api][:inputs][:'mail-server'].should eq('http://dev.abc.com')
+ expect(config[:components][:api][:inputs][:'timeout']).to eq(60)
+ expect(config[:components][:api][:inputs][:'require-basic-auth']).to eq(true)
+ expect(config[:components][:api][:inputs][:'mail-server']).to eq('http://dev.abc.com')
end
it "should merge environment's components to component settings" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'production'})
- config[:components][:'front-end'][:inputs][:'cname'].should eq('prod-front-end.myserver.com')
- config[:components][:api][:inputs][:'cname'].should eq('myserver.com')
+ expect(config[:components][:'front-end'][:inputs][:'cname']).to eq('prod-front-end.myserver.com')
+ expect(config[:components][:api][:inputs][:'cname']).to eq('myserver.com')
end
it "environment variables without prefix 'cfdeploy_settings_' should not be merged to components settings" do
ENV['timeout'] = "180"
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'dev'})
- config[:components][:api][:inputs][:'timeout'].should eq(60)
+ expect(config[:components][:api][:inputs][:'timeout']).to eq(60)
end
it "should merge environment variables should be merged to components settings" do
ENV['cfdeploy_inputs_timeout'] = "180"
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'dev'})
- config[:components][:api][:inputs][:'timeout'].should eq("180")
+ expect(config[:components][:api][:inputs][:'timeout']).to eq("180")
end
it "cli settings should be merged to components settings" do
ENV['cfdeploy_settings_timeout'] = "180"
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file, :environment => 'dev',:cli_overrides => {:settings => {:timeout => 45}}})
- config[:components][:api][:settings][:'timeout'].should eq(45)
+ expect(config[:components][:api][:settings][:'timeout']).to eq(45)
end
it "should set cloudFormation parameter names into each component" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:base][:defined_parameters].should eq({})
- config[:components][:api][:defined_parameters].should eq({:'require-basic-auth' => {:Default => "true"}})
- config[:components][:'front-end'][:defined_parameters].should eq({:'require-basic-auth' => {}, :'mail-server' => {}})
+ expect(config[:components][:base][:defined_parameters]).to eq({})
+ expect(config[:components][:api][:defined_parameters]).to eq({:'require-basic-auth' => {:Default => "true"}})
+ expect(config[:components][:'front-end'][:defined_parameters]).to eq({:'require-basic-auth' => {}, :'mail-server' => {}})
end
it "should set cloudFormation output names into each component" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:base][:defined_outputs].should eq({:'vpc-id' => {}, :'AutoScalingGroupName'=>{}, :'public-subnet-id'=>{}})
- config[:components][:api][:defined_outputs].should eq({})
- config[:components][:'front-end'][:defined_outputs].should eq({:'AutoScalingGroupName'=>{}, :'elb-cname' => {}})
+ expect(config[:components][:base][:defined_outputs]).to eq({:'vpc-id' => {}, :'AutoScalingGroupName'=>{}, :'public-subnet-id'=>{}})
+ expect(config[:components][:api][:defined_outputs]).to eq({})
+ expect(config[:components][:'front-end'][:defined_outputs]).to eq({:'AutoScalingGroupName'=>{}, :'elb-cname' => {}})
end
it "should remove common settings in order not to confuse us" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:settings].should be_nil
+ expect(config[:settings]).to be_nil
end
it "should set default elb-name-output for cname-swap strategy" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:'front-end'][:settings][:'elb-name-output'].should eq('ELBName')
+ expect(config[:components][:'front-end'][:settings][:'elb-name-output']).to eq('ELBName')
end
it "should set default auto-scaling-group-name-output for cname-swap strategy" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:api][:settings][:'auto-scaling-group-name-output'].should eq([ CfDeployer::Defaults::AutoScalingGroupName ])
+ expect(config[:components][:api][:settings][:'auto-scaling-group-name-output']).to eq([ CfDeployer::Defaults::AutoScalingGroupName ])
end
it "should set auto-scaling-group-name-output to default if auto-scaling-group-name exists in output for create-or-update strategy" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:base][:settings][:'auto-scaling-group-name-output'].should eq([ CfDeployer::Defaults::AutoScalingGroupName ])
+ expect(config[:components][:base][:settings][:'auto-scaling-group-name-output']).to eq([ CfDeployer::Defaults::AutoScalingGroupName ])
end
it "should not set auto-scaling-group-name-output to default if auto-scaling-group-name does not exists in output for create-or-update strategy" do
@@ -295,17 +295,17 @@
File.open(@base_json, 'w') {|f| f.write(base_json) }
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:'base'][:settings][:'auto-scaling-group-name-output'].should be_nil
+ expect(config[:components][:'base'][:settings][:'auto-scaling-group-name-output']).to be_nil
end
it "should set auto-scaling-group-name-output to default if auto-scaling-group-name exists in output for cname-swap strategy" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:'front-end'][:settings][:'auto-scaling-group-name-output'].should eq([ CfDeployer::Defaults::AutoScalingGroupName ])
+ expect(config[:components][:'front-end'][:settings][:'auto-scaling-group-name-output']).to eq([ CfDeployer::Defaults::AutoScalingGroupName ])
end
it "should set raise-error-for-unused-inputs to default" do
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:'front-end'][:settings][:'raise-error-for-unused-inputs'].should eq(CfDeployer::Defaults::RaiseErrorForUnusedInputs)
+ expect(config[:components][:'front-end'][:settings][:'raise-error-for-unused-inputs']).to eq(CfDeployer::Defaults::RaiseErrorForUnusedInputs)
end
it "should not set auto-scaling-group-name-output to default if auto-scaling-group-name does not exists in output for cname-swap strategy" do
@@ -319,23 +319,23 @@
File.open(@front_end_json, 'w') {|f| f.write(front_end_json) }
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:'front-end'][:settings][:'auto-scaling-group-name-output'].should be_nil
+ expect(config[:components][:'front-end'][:settings][:'auto-scaling-group-name-output']).to be_nil
end
it "should ERB the config file and provide the environment in the binding" do
config = CfDeployer::ConfigLoader.new.load(:'config-file' => @config_file, :environment => 'DrWho')
- config[:components][:base][:inputs][:'foobar'].should eq('DrWho.IsGreat')
+ expect(config[:components][:base][:inputs][:'foobar']).to eq('DrWho.IsGreat')
end
it "should ERB the component JSON and make the parsed template available" do
config = CfDeployer::ConfigLoader.new.load(:'config-file' => @config_file, :environment => 'DrWho')
- CfDeployer::ConfigLoader.erb_to_json('json-with-erb', config[:components][:'json-with-erb']).should include('DrWho')
+ expect(CfDeployer::ConfigLoader.erb_to_json('json-with-erb', config[:components][:'json-with-erb'])).to include('DrWho')
end
it 'should use error_document to show the broken document when parsing broken ERB' do
config = { :config_dir => File.dirname(@config_file) }
- CfDeployer::ConfigLoader.any_instance.should_receive(:error_document)
- expect { CfDeployer::ConfigLoader.erb_to_json('broken_erb', config) }.to raise_error
+ allow_any_instance_of(CfDeployer::ConfigLoader).to receive(:error_document)
+ expect { CfDeployer::ConfigLoader.erb_to_json('broken_erb', config) }.to raise_error(TypeError)
end
it 'should use error_document to show the broken document when parsing broken json' do
@@ -347,35 +347,36 @@
:defined_parameters => {},
:defined_outputs => {}
}
- CfDeployer::ConfigLoader.any_instance.should_receive(:error_document)
- expect { loader.send(:cf_template, 'broken_json') }.to raise_error
+ allow_any_instance_of(CfDeployer::ConfigLoader).to receive(:error_document)
+
+ expect { loader.send(:cf_template, 'broken_json') }.to raise_error(RuntimeError)
end
it 'should use error_document to show the broken document when parsing broken yaml' do
- CfDeployer::ConfigLoader.any_instance.should_receive(:error_document)
- expect { CfDeployer::ConfigLoader.new.send(:load_yaml, @broken_yaml) }.to raise_error
+ allow_any_instance_of(CfDeployer::ConfigLoader).to receive(:error_document)
+ expect { CfDeployer::ConfigLoader.new.send(:load_yaml, @broken_yaml) }.to raise_error(Psych::SyntaxError)
end
it 'should set default keep-previous-stack to true' do
config = CfDeployer::ConfigLoader.new.load(:'config-file' => @config_file)
- config[:components][:api][:settings][:'keep-previous-stack'].should eq(CfDeployer::Defaults::KeepPreviousStack)
+ expect(config[:components][:api][:settings][:'keep-previous-stack']).to eq(CfDeployer::Defaults::KeepPreviousStack)
end
it 'should keep keep-previous-stack setting' do
config = CfDeployer::ConfigLoader.new.load(:'config-file' => @config_file)
- config[:components][:'front-end'][:settings][:'keep-previous-stack'].should be_false
+ expect(config[:components][:'front-end'][:settings][:'keep-previous-stack']).to be_falsey
end
context 'targets' do
it 'should use all components as targets if no targets are specified' do
config = CfDeployer::ConfigLoader.new.load(:'config-file' => @config_file)
- config[:targets].should eq(['base', 'api', 'front-end', 'very-simple', 'json-with-erb'])
+ expect(config[:targets]).to eq(['base', 'api', 'front-end', 'very-simple', 'json-with-erb'])
end
it 'should keep targets if targets are specified' do
config = CfDeployer::ConfigLoader.new.load(:'config-file' => @config_file, :component => ['api', 'web'])
- config[:targets].should eq(['api', 'web'])
+ expect(config[:targets]).to eq(['api', 'web'])
end
end
@@ -418,7 +419,7 @@
File.open(@config_file, 'w') {|f| f.write(config) }
config = CfDeployer::ConfigLoader.new.load({:'config-file' => @config_file})
- config[:components][:'api'][:defined_parameters].should eq({ db:'base::elb-cname', url:'http://abc.com'})
+ expect(config[:components][:'api'][:defined_parameters]).to eq({ db:'base::elb-cname', url:'http://abc.com'})
end
end
diff --git a/spec/unit/deployment_strategy/auto_scaling_group_swap_spec.rb b/spec/unit/deployment_strategy/auto_scaling_group_swap_spec.rb
index 4ee2533..0cffa4c 100644
--- a/spec/unit/deployment_strategy/auto_scaling_group_swap_spec.rb
+++ b/spec/unit/deployment_strategy/auto_scaling_group_swap_spec.rb
@@ -35,18 +35,18 @@
it 'no if no G and B stacks exist' do
blue_stack.die!
green_stack.die!
- CfDeployer::DeploymentStrategy.create(app, env, component, context).exists?.should be_false
+ expect(CfDeployer::DeploymentStrategy.create(app, env, component, context).exists?).to be_falsey
end
it 'yes if B stacks exist' do
blue_stack.live!
green_stack.die!
- CfDeployer::DeploymentStrategy.create(app, env, component, context).exists?.should be_true
+ expect(CfDeployer::DeploymentStrategy.create(app, env, component, context).exists?).to be_truthy
end
it 'yes if G stacks exist' do
blue_stack.die!
green_stack.live!
- CfDeployer::DeploymentStrategy.create(app, env, component, context).exists?.should be_true
+ expect(CfDeployer::DeploymentStrategy.create(app, env, component, context).exists?).to be_truthy
end
end
@@ -123,7 +123,7 @@
@log += "#{arg[:parameters][:name]} deleted."
end
CfDeployer::DeploymentStrategy.create(app, env, component, context).destroy
- @log.should eq('green deleted.blue deleted.')
+ expect(@log).to eq('green deleted.blue deleted.')
end
end
@@ -601,7 +601,7 @@
allow(green_asg_driver).to receive(:describe) {{desired: 0, min: 0, max: 0}}
allow(blue_asg_driver).to receive(:describe) {{desired: 3, min: 1, max: 5}}
asg_swap = CfDeployer::DeploymentStrategy.create(app, env, component, context)
- asg_swap.output_value("AutoScalingGroupID").should eq("blueASG")
+ expect(asg_swap.output_value("AutoScalingGroupID")).to eq("blueASG")
end
it 'should get the information where the value comes from if the active stack does not exist' do
@@ -612,7 +612,7 @@
allow(green_asg_driver).to receive(:describe) {{desired: 0, min: 0, max: 0}}
allow(blue_asg_driver).to receive(:describe) {{desired: 0, min: 0, max: 0}}
asg_swap = CfDeployer::DeploymentStrategy.create(app, env, component, context)
- asg_swap.output_value(:a_key).should eq("The value will be referenced from the output a_key of undeployed component worker")
+ expect(asg_swap.output_value(:a_key)).to eq("The value will be referenced from the output a_key of undeployed component worker")
end
end
@@ -642,7 +642,7 @@
:status => 'green deployed'
}
}
- asg_swap.status.should eq(expected_result)
+ expect(asg_swap.status).to eq(expected_result)
end
it 'should get status for both green and blue stacks including resources info' do
@@ -667,7 +667,7 @@
}
}
}
- asg_swap.status(true).should eq(expected_result)
+ expect(asg_swap.status(true)).to eq(expected_result)
end
end
@@ -686,7 +686,7 @@
allow(blue_stack).to receive(:resource_statuses) { asg_ids('foo', 'bar') }
asg_swap = CfDeployer::DeploymentStrategy.create(app, env, component, context)
- asg_swap.send(:get_active_asgs, blue_stack).should eq(['foo'])
+ expect(asg_swap.send(:get_active_asgs, blue_stack)).to eq(['foo'])
end
end
@@ -700,7 +700,7 @@
allow(green_asg_driver).to receive(:describe) { {min: 0, desired: 0, max: 0} }
asg_swap = CfDeployer::DeploymentStrategy.create(app, env, component, context)
- asg_swap.send(:stack_active?, blue_stack).should be(true)
+ expect(asg_swap.send(:stack_active?, blue_stack)).to be(true)
end
end
diff --git a/spec/unit/deployment_strategy/base_spec.rb b/spec/unit/deployment_strategy/base_spec.rb
index 8c572b7..c2e0aa4 100644
--- a/spec/unit/deployment_strategy/base_spec.rb
+++ b/spec/unit/deployment_strategy/base_spec.rb
@@ -57,12 +57,11 @@
it "should return nil if there is no active stack" do
the_stack = double()
- the_stack.should_receive(:exists?).and_return(false)
- the_stack.should_not_receive(:template)
+ expect(the_stack).to receive(:exists?).and_return(false)
+ expect(the_stack).not_to receive(:template)
strategy = CfDeployer::DeploymentStrategy.create('myApp', 'uat', 'web', @context[:components][:web])
- strategy.should_receive(:active_stack).and_return(the_stack)
- # strategy.should_not_receive(:get_parameters_outputs)
+ expect(strategy).to receive(:active_stack).and_return(the_stack)
expect( strategy.active_template ).to eq(nil)
end
@@ -71,11 +70,11 @@
the_template = double
the_stack = double
- the_stack.should_receive(:exists?).and_return(true)
- the_stack.should_receive(:template).and_return(the_template)
+ expect(the_stack).to receive(:exists?).and_return(true)
+ expect(the_stack).to receive(:template).and_return(the_template)
strategy = CfDeployer::DeploymentStrategy.create('myApp', 'uat', 'web', @context[:components][:web])
- strategy.should_receive(:active_stack).and_return(the_stack)
+ expect(strategy).to receive(:active_stack).and_return(the_stack)
expect( strategy.active_template ).to eq(the_template)
end
@@ -96,8 +95,8 @@
it "should run the specified hook" do
hook = double()
- CfDeployer::Hook.should_receive(:new).and_return(hook)
- hook.should_receive(:run)
+ expect(CfDeployer::Hook).to receive(:new).and_return(hook)
+ expect(hook).to receive(:run)
strategy = CfDeployer::DeploymentStrategy.create('myApp', 'uat', 'web', @context[:components][:web])
strategy.instance_variable_set('@params_and_outputs_resolved', true)
@@ -107,30 +106,30 @@
it "should not try to resolve parameters and outputs they're already initialized" do
strategy = CfDeployer::DeploymentStrategy.create('myApp', 'uat', 'web', @context[:components][:web])
strategy.instance_variable_set('@params_and_outputs_resolved', true)
- strategy.should_not_receive(:get_parameters_outputs)
+ expect(strategy).not_to receive(:get_parameters_outputs)
strategy.run_hook(:some_hook)
end
it "should not try to resolve parameters and outputs if there's no running stack" do
the_stack = double()
- the_stack.should_receive(:exists?).and_return(false)
- the_stack.should_receive(:name).and_return("thestack")
+ expect(the_stack).to receive(:exists?).and_return(false)
+ expect(the_stack).to receive(:name).and_return("thestack")
strategy = CfDeployer::DeploymentStrategy.create('myApp', 'uat', 'web', @context[:components][:web])
- strategy.should_receive(:active_stack).and_return(the_stack)
- strategy.should_not_receive(:get_parameters_outputs)
+ expect(strategy).to receive(:active_stack).and_return(the_stack)
+ expect(strategy).not_to receive(:get_parameters_outputs)
strategy.run_hook(:some_hook)
end
it "should not try to run a hook if there's no running stack" do
- CfDeployer::Hook.should_not_receive(:new)
+ expect(CfDeployer::Hook).not_to receive(:new)
the_stack = double()
- the_stack.should_receive(:exists?).and_return(false)
- the_stack.should_receive(:name).and_return("thestack")
+ expect(the_stack).to receive(:exists?).and_return(false)
+ expect(the_stack).to receive(:name).and_return("thestack")
strategy = CfDeployer::DeploymentStrategy.create('myApp', 'uat', 'web', @context[:components][:web])
- strategy.should_receive(:active_stack).and_return(the_stack)
+ expect(strategy).to receive(:active_stack).and_return(the_stack)
strategy.run_hook(:some_hook)
end
end
diff --git a/spec/unit/deployment_strategy/cname_swap_spec.rb b/spec/unit/deployment_strategy/cname_swap_spec.rb
index a7b8ab4..8f5a720 100644
--- a/spec/unit/deployment_strategy/cname_swap_spec.rb
+++ b/spec/unit/deployment_strategy/cname_swap_spec.rb
@@ -66,7 +66,7 @@
end
expect(dns_driver).to receive(:delete_record_set).with('foobar.com', 'test.foobar.com')
cname_swap.destroy
- @log.should eq('green deleted.blue deleted.')
+ expect(@log).to eq('green deleted.blue deleted.')
end
end
@@ -188,19 +188,19 @@
blue_stack.die!
green_stack.die!
cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
- cname_swap.exists?.should be_false
+ expect(cname_swap.exists?).to be_falsey
end
it 'yes, if green stack exists and blue stack does not' do
blue_stack.die!
cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
- cname_swap.exists?.should be_true
+ expect(cname_swap.exists?).to be_truthy
end
it 'yes, if blue stack exists and green stack does not' do
green_stack.die!
cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
- cname_swap.exists?.should be_true
+ expect(cname_swap.exists?).to be_truthy
end
end
@@ -220,7 +220,7 @@
my_context.delete :dns_driver
my_context[:settings][:'dns-driver'] = 'CfDeployer::Driver::Verisign'
cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', my_context)
- cname_swap.send(:dns_driver).class.to_s.should eq(my_context[:settings][:'dns-driver'])
+ expect(cname_swap.send(:dns_driver).class.to_s).to eq(my_context[:settings][:'dns-driver'])
end
end
@@ -283,14 +283,14 @@
it 'should get stack output if active stack exists' do
allow(dns_driver).to receive(:find_alias_target).with('foobar.com', 'test.foobar.com'){ 'BLUE-elb.aws.amazon.com' }
- cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
- cname_swap.output_value("AutoScalingGroupID").should eq("blueASG")
+ cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
+ expect(cname_swap.output_value("AutoScalingGroupID")).to eq("blueASG")
end
it 'should get the information where the value comes from if the active stack does not exist' do
allow(dns_driver).to receive(:find_alias_target).with('foobar.com', 'test.foobar.com'){ '' }
- cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
- cname_swap.output_value(:a_key).should eq("The value will be referenced from the output a_key of undeployed component web")
+ cname_swap = CfDeployer::DeploymentStrategy.create('myapp', 'dev', 'web', @context)
+ expect(cname_swap.output_value(:a_key)).to eq("The value will be referenced from the output a_key of undeployed component web")
end
end
end
diff --git a/spec/unit/deployment_strategy/create_or_update_spec.rb b/spec/unit/deployment_strategy/create_or_update_spec.rb
index f922513..da0f415 100644
--- a/spec/unit/deployment_strategy/create_or_update_spec.rb
+++ b/spec/unit/deployment_strategy/create_or_update_spec.rb
@@ -33,7 +33,7 @@
expect(@after_create_hook).to receive(:run) do |given_context|
hook_context = given_context
end
- @stack.should_receive(:exists?).and_return(false)
+ expect(@stack).to receive(:exists?).and_return(false)
expect(@stack).to receive(:deploy)
@create_or_update.deploy
expect(hook_context[:parameters]).to eq( {'vpc' => 'myvpc'} )
@@ -45,7 +45,7 @@
expect(@after_update_hook).to receive(:run) do |given_context|
hook_context = given_context
end
- @stack.should_receive(:exists?).and_return(true)
+ expect(@stack).to receive(:exists?).and_return(true)
expect(@stack).to receive(:deploy)
@create_or_update.deploy
expect(hook_context[:parameters]).to eq( {'vpc' => 'myvpc'} )
@@ -60,7 +60,7 @@
context = @context[:components][:base]
context[:settings] = {}
context[:settings][:'auto-scaling-group-name-output'] = ['AutoScalingGroupID']
- @stack.should_receive(:exists?).and_return(false)
+ expect(@stack).to receive(:exists?).and_return(false)
allow(@stack).to receive(:find_output).with('AutoScalingGroupID') { 'asg_name' }
allow(CfDeployer::Driver::AutoScalingGroup).to receive(:new).with('asg_name') { asg_driver }
allow(asg_driver).to receive(:describe) { {desired:2, min:1, max:3} }
@@ -74,19 +74,19 @@
it 'should tell if stack exists' do
expect(@stack).to receive(:exists?){true}
- @create_or_update.exists?.should eq(true)
+ expect(@create_or_update.exists?).to eq(true)
end
it 'should get stack output' do
allow(@stack).to receive(:exists?){true}
expect(@stack).to receive(:output).with(:a_key){ "output_value" }
- @create_or_update.output_value(:a_key).should eq("output_value")
+ expect(@create_or_update.output_value(:a_key)).to eq("output_value")
end
it 'should get the information where the value comes from if the stack does not exist' do
allow(@stack).to receive(:exists?){false}
expect(@stack).not_to receive(:output).with(anything)
- @create_or_update.output_value(:a_key).should eq("The value will be referenced from the output a_key of undeployed component base")
+ expect(@create_or_update.output_value(:a_key)).to eq("The value will be referenced from the output a_key of undeployed component base")
end
context '#destroy' do
@@ -119,11 +119,11 @@
allow(@stack).to receive(:exists?) { true }
end
it 'should get status from stack' do
- @create_or_update.status.should eq({ 'base-uat' => {status: 'deployed'}})
+ expect(@create_or_update.status).to eq({ 'base-uat' => {status: 'deployed'}})
end
it 'should get status from stack including resource info' do
allow(@stack).to receive(:resource_statuses) { 'resource1' }
- @create_or_update.status(true).should eq({ 'base-uat' => {status: 'deployed', resources: 'resource1'}})
+ expect(@create_or_update.status(true)).to eq({ 'base-uat' => {status: 'deployed', resources: 'resource1'}})
end
end
end
diff --git a/spec/unit/driver/auto_scaling_group_spec.rb b/spec/unit/driver/auto_scaling_group_spec.rb
index f770111..c8ccd25 100644
--- a/spec/unit/driver/auto_scaling_group_spec.rb
+++ b/spec/unit/driver/auto_scaling_group_spec.rb
@@ -2,38 +2,38 @@
describe 'Autoscaling group driver' do
let(:group) { double('group', :desired_capacity => 2, :min_size => 1, :max_size => 4)}
- let(:scaling) { double('scaling', :groups => { 'myAsg' => group}) }
let(:ec2_instance1) { double('ec2_instance1') }
let(:ec2_instance2) { double('ec2_instance2') }
let(:ec2_instance3) { double('ec2_instance3') }
let(:ec2_instance4) { double('ec2_instance4') }
- let(:instance1) { double('instance1', :health_status => 'HEALTHY', :ec2_instance => ec2_instance1)}
- let(:instance2) { double('instance2', :health_status => 'HEALTHY', :ec2_instance => ec2_instance2)}
- let(:instance3) { double('instance3', :health_status => 'HEALTHY', :ec2_instance => ec2_instance3)}
- let(:instance4) { double('instance4', :health_status => 'HEALTHY', :ec2_instance => ec2_instance4)}
+ let(:instance1) { double('instance1', :id => 'instance1', :health_status => 'HEALTHY', :ec2_instance => ec2_instance1)}
+ let(:instance2) { double('instance2', :id => 'instance2', :health_status => 'HEALTHY', :ec2_instance => ec2_instance2)}
+ let(:instance3) { double('instance3', :id => 'instance3', :health_status => 'HEALTHY', :ec2_instance => ec2_instance3)}
+ let(:instance4) { double('instance4', :id => 'instance4', :health_status => 'HEALTHY', :ec2_instance => ec2_instance4)}
let(:load_balancer) { double('load_balancer', :instances => [instance1, instance2, instance3, instance4]) }
+ let(:elb_driver) { double(Aws::ElasticLoadBalancing::Client) }
before :each do
- allow(AWS::AutoScaling).to receive(:new) { scaling }
- allow(group).to receive(:load_balancers) { [] }
- allow(group).to receive(:auto_scaling_instances) { [] }
- allow(group).to receive(:ec2_instances) { [] }
+ allow(Aws::ElasticLoadBalancing::Client).to receive(:new) { elb_driver }
+ allow(group).to receive(:load_balancer_names) { [] }
+ allow(group).to receive(:instances) { [] }
+ allow(Aws::AutoScaling::AutoScalingGroup).to receive(:new).with('myAsg') { group }
@driver = CfDeployer::Driver::AutoScalingGroup.new('myAsg', 1)
end
it 'should describe group' do
- @driver.describe.should eq({ min: 1, max: 4, desired: 2})
+ expect(@driver.describe).to eq({ min: 1, max: 4, desired: 2})
end
describe '#warm_up' do
it 'should warm up the group to the desired size' do
- expect(group).to receive(:set_desired_capacity).with(2)
+ expect(group).to receive(:set_desired_capacity).with({desired_capacity: 2})
expect(@driver).to receive(:wait_for_desired_capacity)
@driver.warm_up 2
end
it 'should wait for the warm up of the group even if desired is the same as the minimum' do
- expect(group).to receive(:set_desired_capacity).with(1)
+ expect(group).to receive(:set_desired_capacity).with({desired_capacity: 1})
expect(@driver).to receive(:wait_for_desired_capacity)
@driver.warm_up 1
end
@@ -45,7 +45,7 @@
end
it 'should warm up to maximum if desired number is greater than maximum size of group' do
- expect(group).to receive(:set_desired_capacity).with(4)
+ expect(group).to receive(:set_desired_capacity).with({desired_capacity: 4})
expect(@driver).to receive(:wait_for_desired_capacity)
@driver.warm_up 5
end
@@ -57,14 +57,14 @@
instance2 = double('instance2', :health_status => 'HEALTHY', id: 'instance2')
instance3 = double('instance3', :health_status => 'UNHEALTHY', id: 'instance3')
instance4 = double('instance4', :health_status => 'HEALTHY', id: 'instance4')
- allow(group).to receive(:auto_scaling_instances){[instance1, instance2, instance3, instance4]}
+ allow(group).to receive(:instances){[instance1, instance2, instance3, instance4]}
expect(@driver.healthy_instance_ids).to eql ['instance1', 'instance2', 'instance4']
end
it 'returns the ids of all instances that are healthy (case insensitive)' do
instance1 = double('instance1', :health_status => 'HealThy', id: 'instance1')
- allow(group).to receive(:auto_scaling_instances){[instance1]}
+ allow(group).to receive(:instances){[instance1]}
expect(@driver.healthy_instance_ids).to eql ['instance1']
end
@@ -73,69 +73,80 @@
describe '#in_service_instance_ids' do
context 'when there are no load balancers' do
it 'returns no ids' do
- allow(group).to receive(:load_balancers).and_return([])
+ allow(group).to receive(:load_balancer_names).and_return([])
expect(@driver.in_service_instance_ids).to eq []
end
end
context 'when there is only 1 elb' do
+ let(:elb1_instance_health) { double('elb1_instance_health') }
+
+ before(:each) do
+ allow(group).to receive(:load_balancer_names).and_return(['elb1'])
+ allow(elb_driver).to receive(:describe_instance_health)
+ .with(hash_including(load_balancer_name: 'elb1')) { elb1_instance_health }
+ end
+
it 'returns the ids of all instances that are in service' do
- health1 = { state: 'InService', instance: double('i1', id: 'instance1') }
- health2 = { state: 'OutOfService', instance: double('i2', id: 'instance2') }
- health3 = { state: 'InService', instance: double('i3', id: 'instance3') }
- health4 = { state: 'InService', instance: double('i4', id: 'instance4') }
+ health1 = double(:state => 'InService', instance_id: 'instance1')
+ health2 = double(:state => 'OutOfService', instance_id: 'instance2')
+ health3 = double(:state => 'InService', instance_id: 'instance3')
+ health4 = double(:state => 'InService', instance_id: 'instance4')
- instance_collection = double('instance_collection', health: [health1, health2, health3, health4])
- elb = double('elb', instances: instance_collection)
- allow(group).to receive(:load_balancers).and_return([ elb ])
+ allow(elb1_instance_health).to receive(:instance_states) { [health1, health2, health3, health4] }
+ allow(group).to receive(:load_balancer_names).and_return([ 'elb1' ])
expect(@driver.in_service_instance_ids).to eql ['instance1', 'instance3', 'instance4']
end
end
context 'when there are multiple elbs' do
+ let(:elb1_instance_health) { double('elb1_instance_health') }
+ let(:elb2_instance_health) { double('elb2_instance_health') }
+ let(:elb3_instance_health) { double('elb3_instance_health') }
+
+ before(:each) do
+ allow(group).to receive(:load_balancer_names).and_return(['elb1', 'elb2', 'elb3'])
+ allow(elb_driver).to receive(:describe_instance_health)
+ .with(hash_including(load_balancer_name: 'elb1')) { elb1_instance_health }
+ allow(elb_driver).to receive(:describe_instance_health)
+ .with(hash_including(load_balancer_name: 'elb2')) { elb2_instance_health }
+ allow(elb_driver).to receive(:describe_instance_health)
+ .with(hash_including(load_balancer_name: 'elb3')) { elb3_instance_health }
+ end
+
it 'returns only the ids of instances that are in all ELBs' do
- health1 = { state: 'InService', instance: double('i1', id: 'instance1') }
- health2 = { state: 'InService', instance: double('i2', id: 'instance2') }
- health3 = { state: 'InService', instance: double('i3', id: 'instance3') }
- health4 = { state: 'InService', instance: double('i4', id: 'instance4') }
- health5 = { state: 'InService', instance: double('i5', id: 'instance5') }
-
- instance_collection1 = double('instance_collection1', health: [health1, health2, health3])
- instance_collection2 = double('instance_collection2', health: [health2, health3, health4])
- instance_collection3 = double('instance_collection3', health: [health2, health3, health5])
- elb1 = double('elb1', instances: instance_collection1)
- elb2 = double('elb2', instances: instance_collection2)
- elb3 = double('elb3', instances: instance_collection3)
- allow(group).to receive(:load_balancers).and_return([ elb1, elb2, elb3 ])
+ health1 = double(state: 'InService', instance_id: 'instance1')
+ health2 = double(state: 'InService', instance_id: 'instance2')
+ health3 = double(state: 'InService', instance_id: 'instance3')
+ health4 = double(state: 'InService', instance_id: 'instance4')
+ health5 = double(state: 'InService', instance_id: 'instance5')
+
+ allow(elb1_instance_health).to receive(:instance_states) { [health1, health2, health3] }
+ allow(elb2_instance_health).to receive(:instance_states) { [health2, health3, health4] }
+ allow(elb3_instance_health).to receive(:instance_states) { [health2, health3, health5] }
# Only instance 2 and 3 are associated with all ELB's
expect(@driver.in_service_instance_ids).to eql ['instance2', 'instance3']
end
it 'returns only the ids instances that are InService in all ELBs' do
- health11 = { state: 'OutOfService', instance: double('i1', id: 'instance1') }
- health12 = { state: 'InService', instance: double('i2', id: 'instance2') }
- health13 = { state: 'InService', instance: double('i3', id: 'instance3') }
-
- health21 = { state: 'InService', instance: double('i1', id: 'instance1') }
- health22 = { state: 'InService', instance: double('i2', id: 'instance2') }
- health23 = { state: 'OutOfService', instance: double('i3', id: 'instance3') }
-
- health31 = { state: 'InService', instance: double('i1', id: 'instance1') }
- health32 = { state: 'InService', instance: double('i2', id: 'instance2') }
- health33 = { state: 'InService', instance: double('i3', id: 'instance3') }
+ health11 = double(state: 'OutOfService', instance_id: 'instance1')
+ health12 = double(state: 'InService', instance_id: 'instance2')
+ health13 = double(state: 'InService', instance_id: 'instance3')
- instance_collection1 = double('instance_collection1', health: [health11, health12, health13])
- instance_collection2 = double('instance_collection2', health: [health21, health22, health23])
- instance_collection3 = double('instance_collection3', health: [health31, health32, health33])
+ health21 = double(state: 'InService', instance_id: 'instance1')
+ health22 = double(state: 'InService', instance_id: 'instance2')
+ health23 = double(state: 'OutOfService', instance_id: 'instance3')
- elb1 = double('elb1', instances: instance_collection1)
- elb2 = double('elb2', instances: instance_collection2)
- elb3 = double('elb3', instances: instance_collection3)
+ health31 = double(state: 'InService', instance_id: 'instance1')
+ health32 = double(state: 'InService', instance_id: 'instance2')
+ health33 = double(state: 'InService', instance_id: 'instance3')
- allow(group).to receive(:load_balancers).and_return([ elb1, elb2, elb3 ])
+ allow(elb1_instance_health).to receive(:instance_states) { [health11, health12, health13] }
+ allow(elb2_instance_health).to receive(:instance_states) { [health21, health22, health23] }
+ allow(elb3_instance_health).to receive(:instance_states) { [health31, health32, health33] }
# Only instance 2 is InService across all ELB's
expect(@driver.in_service_instance_ids).to eql ['instance2']
@@ -158,7 +169,7 @@
it 'should return the number of instances that are both healthy, and in service' do
healthy_instance_ids = ['1', '3', '4', '5']
in_service_instance_ids = ['3', '4']
- allow(@driver).to receive(:load_balancers).and_return(double('elb', empty?: false))
+ allow(@driver).to receive(:load_balancer_names).and_return(['elb1'])
expect(@driver).to receive(:healthy_instance_ids).and_return(healthy_instance_ids)
expect(@driver).to receive(:in_service_instance_ids).and_return(in_service_instance_ids)
@@ -176,7 +187,7 @@
describe '#cool_down' do
it 'should cool down group' do
expect(group).to receive(:update).with({min_size: 0, max_size: 0})
- expect(group).to receive(:set_desired_capacity).with(0)
+ expect(group).to receive(:set_desired_capacity).with({desired_capacity: 0})
@driver.cool_down
end
end
@@ -184,7 +195,7 @@
describe '#warm_up_cooled_group' do
it 'should set min, max, and desired from a hash' do
hash = {:max => 5, :min => 2, :desired => 3}
- allow(group).to receive(:auto_scaling_instances){[instance1, instance2, instance3]}
+ allow(group).to receive(:instances){[instance1, instance2, instance3]}
expect(group).to receive(:update).with({:min_size => 2, :max_size => 5})
expect(@driver).to receive(:warm_up).with(3)
@driver.warm_up_cooled_group hash
@@ -193,15 +204,13 @@
describe '#instance_statuses' do
it 'should get the status for any EC2 instances' do
- aws_instance = double AWS::EC2::Instance
- expect(aws_instance).to receive(:id) { 'i-abcd1234' }
- allow(@driver).to receive(:ec2_instances) { [ aws_instance ] }
+ allow(@driver).to receive(:instances) { [ instance1 ] }
returned_status = { :status => :some_status }
cfd_instance = double CfDeployer::Driver::Instance
- expect(CfDeployer::Driver::Instance).to receive(:new).with(aws_instance) { cfd_instance }
+ expect(CfDeployer::Driver::Instance).to receive(:new).with(instance1.id) { cfd_instance }
expect(cfd_instance).to receive(:status) { returned_status }
- expect(@driver.instance_statuses).to eq( { 'i-abcd1234' => returned_status } )
+ expect(@driver.instance_statuses).to eq( { 'instance1' => returned_status } )
end
end
@@ -226,7 +235,7 @@
expect(group).to receive(:desired_capacity).and_return(expected_number)
expect(@driver).to receive(:healthy_instance_count).and_return(expected_number)
- expect(@driver.desired_capacity_reached?).to be_true
+ expect(@driver.desired_capacity_reached?).to be_truthy
end
it 'returns false if healthy instance count is less than desired capacity' do
@@ -235,7 +244,7 @@
expect(group).to receive(:desired_capacity).and_return(expected_number)
expect(@driver).to receive(:healthy_instance_count).and_return(expected_number - 1)
- expect(@driver.desired_capacity_reached?).to be_false
+ expect(@driver.desired_capacity_reached?).to be_falsey
end
it 'returns true if healthy instance count is more than desired capacity' do
@@ -244,7 +253,7 @@
expect(group).to receive(:desired_capacity).and_return(expected_number)
expect(@driver).to receive(:healthy_instance_count).and_return(expected_number + 1)
- expect(@driver.desired_capacity_reached?).to be_true
+ expect(@driver.desired_capacity_reached?).to be_truthy
end
end
end
diff --git a/spec/unit/driver/cloud_formation_spec.rb b/spec/unit/driver/cloud_formation_spec.rb
index dbd516a..4f594fd 100644
--- a/spec/unit/driver/cloud_formation_spec.rb
+++ b/spec/unit/driver/cloud_formation_spec.rb
@@ -2,8 +2,8 @@
describe 'CloudFormation' do
let(:outputs) { [output1, output2] }
- let(:output1) { double('output1', :key => 'key1', :value => 'value1')}
- let(:output2) { double('output2', :key => 'key2', :value => 'value2')}
+ let(:output1) { double('output1', :output_key => 'key1', :output_value => 'value1')}
+ let(:output2) { double('output2', :output_key => 'key2', :output_value => 'value2')}
let(:parameters) { double('parameters')}
let(:resource_summaries) { [
{
@@ -22,24 +22,27 @@
:resource_status => 'STATUS_2'
}
] }
- let(:stack) { double('stack', :outputs => outputs, :parameters => parameters, :resource_summaries => resource_summaries) }
+ let(:stack) { double('stack', :stack_name => 'testStack', :outputs => outputs, :parameters => parameters) }
+ let(:cloudFormationStacks) { [stack] }
let(:cloudFormation) {
double('cloudFormation',
- :stacks =>
- {'testStack' => stack
- })
+ :describe_stacks => double(:stacks => cloudFormationStacks),
+ :list_stack_resources => double(:stack_resource_summaries => resource_summaries)
+ )
}
before(:each) do
- allow(AWS::CloudFormation).to receive(:new) { cloudFormation }
+ allow(Aws::CloudFormation::Client).to receive(:new) { cloudFormation }
+ allow(cloudFormation).to receive(:create_stack)
+ allow(cloudFormation).to receive(:update_stack)
end
it 'should get outputs of stack' do
- CfDeployer::Driver::CloudFormation.new('testStack').outputs.should eq({'key1' => 'value1', 'key2' => 'value2'})
+ expect(CfDeployer::Driver::CloudFormation.new('testStack').outputs).to eq({'key1' => 'value1', 'key2' => 'value2'})
end
it 'should get parameters of stack' do
- CfDeployer::Driver::CloudFormation.new('testStack').parameters.should eq(parameters)
+ expect(CfDeployer::Driver::CloudFormation.new('testStack').parameters).to eq(parameters)
end
context 'update_stack' do
@@ -60,32 +63,31 @@
result = cloud_formation.update_stack :template, {}
end
- expect(result).to be_false
+ expect(result).to be_falsey
end
it 'returns false if no updates were performed (because no difference in template)' do
cloud_formation = CfDeployer::Driver::CloudFormation.new 'my_stack'
- expect(cloud_formation).to receive(:aws_stack).and_raise(AWS::CloudFormation::Errors::ValidationError.new('No updates are to be performed'))
+ expect(cloudFormation).to receive(:update_stack).and_raise(Aws::CloudFormation::Errors::ValidationError.new(nil, 'No updates are to be performed'))
result = nil
CfDeployer::Driver::DryRun.disable_for do
result = cloud_formation.update_stack :template, {}
end
- expect(result).to be_false
+ expect(result).to be_falsey
end
it 'returns true when updates are performed' do
cloud_formation = CfDeployer::Driver::CloudFormation.new 'my_stack'
- aws_stack = double(:update => :did_something)
- expect(cloud_formation).to receive(:aws_stack).and_return aws_stack
result = nil
CfDeployer::Driver::DryRun.disable_for do
result = cloud_formation.update_stack :template, {}
end
- expect(result).to be_true
+ expect(cloudFormation).to have_received(:update_stack)
+ expect(result).to be_truthy
end
end
@@ -102,7 +104,7 @@
}
}
- CfDeployer::Driver::CloudFormation.new('testStack').resource_statuses.should eq(expected)
+ expect(CfDeployer::Driver::CloudFormation.new('testStack').resource_statuses).to eq(expected)
end
end
end
diff --git a/spec/unit/driver/dry_run_spec.rb b/spec/unit/driver/dry_run_spec.rb
index 9c0fb93..8b48eb4 100644
--- a/spec/unit/driver/dry_run_spec.rb
+++ b/spec/unit/driver/dry_run_spec.rb
@@ -11,8 +11,8 @@
enabled_in_block = CfDeployer::Driver::DryRun.enabled?
end
- expect(enabled_in_block).to be_true
- expect(CfDeployer::Driver::DryRun.enabled?).to be_false
+ expect(enabled_in_block).to be_truthy
+ expect(CfDeployer::Driver::DryRun.enabled?).to be_falsey
end
end
@@ -27,8 +27,8 @@
end
end.to raise_error('boom')
- expect(enabled_in_block).to be_true
- expect(CfDeployer::Driver::DryRun.enabled?).to be_false
+ expect(enabled_in_block).to be_truthy
+ expect(CfDeployer::Driver::DryRun.enabled?).to be_falsey
end
end
end
@@ -42,8 +42,8 @@
enabled_in_block = CfDeployer::Driver::DryRun.enabled?
end
- expect(enabled_in_block).to be_false
- expect(CfDeployer::Driver::DryRun.enabled?).to be_true
+ expect(enabled_in_block).to be_falsey
+ expect(CfDeployer::Driver::DryRun.enabled?).to be_truthy
end
end
@@ -58,8 +58,8 @@
end
end.to raise_error('boom')
- expect(enabled_in_block).to be_false
- expect(CfDeployer::Driver::DryRun.enabled?).to be_true
+ expect(enabled_in_block).to be_falsey
+ expect(CfDeployer::Driver::DryRun.enabled?).to be_truthy
end
end
end
diff --git a/spec/unit/driver/elb_spec.rb b/spec/unit/driver/elb_spec.rb
index 3e2db14..84b7cab 100644
--- a/spec/unit/driver/elb_spec.rb
+++ b/spec/unit/driver/elb_spec.rb
@@ -2,10 +2,16 @@
describe CfDeployer::Driver::Elb do
it 'should get dns name and hosted zone id' do
- elb = double('elb', :dns_name => 'mydns', :canonical_hosted_zone_name_id => 'zone_id')
- aws = double('aws', :load_balancers => {'myelb' => elb})
+ elb = double('elasticloadbalancing', :dns_name => 'mydns', :canonical_hosted_zone_name_id => 'zone_id')
+
+ aws = double('aws')
+
elb_name = 'myelb'
- expect(AWS::ELB).to receive(:new){aws}
- CfDeployer::Driver::Elb.new.find_dns_and_zone_id(elb_name).should eq({:dns_name => 'mydns', :canonical_hosted_zone_name_id => 'zone_id'})
+ load_balancer_descriptions = double('elb', :load_balancer_descriptions => [elb])
+
+ expect(Aws::ElasticLoadBalancing::Client).to receive(:new){aws}
+ expect(aws).to receive(:describe_load_balancers).with(hash_including(load_balancer_names: [elb_name])) { load_balancer_descriptions }
+
+ expect(CfDeployer::Driver::Elb.new.find_dns_and_zone_id(elb_name)).to eq({:dns_name => 'mydns', :canonical_hosted_zone_name_id => 'zone_id'})
end
end
diff --git a/spec/unit/driver/instance_spec.rb b/spec/unit/driver/instance_spec.rb
index 5210fa4..f64b2d0 100644
--- a/spec/unit/driver/instance_spec.rb
+++ b/spec/unit/driver/instance_spec.rb
@@ -11,14 +11,9 @@
}
- aws = double AWS::EC2
- expect(AWS::EC2).to receive(:new) { aws }
-
- instance_collection = double AWS::EC2::InstanceCollection
- expect(aws).to receive(:instances) { instance_collection }
-
instance = Fakes::Instance.new expected.merge( { :id => 'i-wxyz1234' } )
- expect(instance_collection).to receive(:[]).with(instance.id) { instance }
+ allow(instance).to receive(:state) { :pending }
+ expect(Aws::EC2::Instance).to receive(:new).with('i-wxyz1234') { instance }
instance_status = CfDeployer::Driver::Instance.new('i-wxyz1234').status
diff --git a/spec/unit/driver/route53_spec.rb b/spec/unit/driver/route53_spec.rb
index 8f4fe45..4b10367 100644
--- a/spec/unit/driver/route53_spec.rb
+++ b/spec/unit/driver/route53_spec.rb
@@ -6,50 +6,59 @@
describe ".find_alias_target" do
it "should raise an error when the target zone cannot be found" do
route53 = double('route53')
- allow(AWS::Route53).to receive(:new) { route53 }
+ allow(Aws::Route53::Client).to receive(:new) { route53 }
- allow(route53).to receive(:hosted_zones) { [] }
+ allow(route53).to receive_message_chain(:list_hosted_zones_by_name, :hosted_zones) { [] }
expect { subject.find_alias_target('abc.com', 'foo') }.to raise_error('Target zone not found!')
end
it "should get empty alias target when the target host cannot be found" do
- zone = double('zone')
- allow(zone).to receive(:name) { 'target.com.' }
- allow(zone).to receive(:resource_record_sets) { [] }
+ resource_record_sets = double('resource_record_sets', :resource_record_sets => [])
+ zone = double('zone', :id => '/hostedzone/hostedzoneid', :name => 'target.com.')
route53 = double('route53')
- allow(AWS::Route53).to receive(:new) { route53 }
- allow(route53).to receive(:hosted_zones) { [zone] }
+ allow(Aws::Route53::Client).to receive(:new) { route53 }
+ allow(route53).to receive_message_chain(:list_hosted_zones_by_name, :hosted_zones) { [zone] }
+ allow(route53).to receive(:list_resource_record_sets).with(hash_including(hosted_zone_id: '/hostedzone/hostedzoneid')) { resource_record_sets }
- subject.find_alias_target('target.com', 'foo').should be_nil
+ expect(subject.find_alias_target('target.com', 'foo')).to be_nil
end
it "should get alias target" do
host = double('host', :name => 'foo.target.com.', :alias_target => { :dns_name => 'abc.com.'})
- zone = double('zone', :name => 'target.com.', :resource_record_sets => [host])
- route53 = double('route53', :hosted_zones => [zone])
- allow(AWS::Route53).to receive(:new) { route53 }
+ resource_record_sets = double('resource_record_sets', :resource_record_sets => [host])
+ zone = double('zone', :id => '/hostedzone/hostedzoneid', :name => 'target.com.')
+ route53 = double('route53')
+ allow(route53).to receive_message_chain(:list_hosted_zones_by_name, :hosted_zones) { [zone] }
+ allow(route53).to receive(:list_resource_record_sets).with(hash_including(hosted_zone_id: '/hostedzone/hostedzoneid')) { resource_record_sets }
+ allow(Aws::Route53::Client).to receive(:new) { route53 }
- subject.find_alias_target('Target.com', 'Foo.target.com').should eq('abc.com')
+ expect(subject.find_alias_target('Target.com', 'Foo.target.com')).to eq('abc.com')
end
it "should get a nil alias target when the record exists but has no alias target" do
host = double('host', :name => 'foo.target.com.', :alias_target => nil)
- zone = double('zone', :name => 'target.com.', :resource_record_sets => [host])
- route53 = double('route53', :hosted_zones => [zone])
- allow(AWS::Route53).to receive(:new) { route53 }
+ resource_record_sets = double('resource_record_sets', :resource_record_sets => [host])
+ zone = double('zone', :id => '/hostedzone/hostedzoneid', :name => 'target.com.')
+ route53 = double('route53')
+ allow(route53).to receive_message_chain(:list_hosted_zones_by_name, :hosted_zones) { [zone] }
+ allow(route53).to receive(:list_resource_record_sets).with(hash_including(hosted_zone_id: '/hostedzone/hostedzoneid')) { resource_record_sets }
+ allow(Aws::Route53::Client).to receive(:new) { route53 }
- subject.find_alias_target('target.com', 'foo.target.com').should be_nil
+ expect(subject.find_alias_target('target.com', 'foo.target.com')).to be_nil
end
it "should get alias target when zone and host name having trailing dot" do
host = double('host', :name => 'foo.target.com.', :alias_target => { :dns_name => 'abc.com.'})
- zone = double('zone', :name => 'target.com.', :resource_record_sets => [host])
- route53 = double('route53', :hosted_zones => [zone])
- allow(AWS::Route53).to receive(:new) { route53 }
+ resource_record_sets = double('resource_record_sets', :resource_record_sets => [host])
+ zone = double('zone', :id => '/hostedzone/hostedzoneid', :name => 'target.com.')
+ route53 = double('route53')
+ allow(route53).to receive_message_chain(:list_hosted_zones_by_name, :hosted_zones) { [zone] }
+ allow(route53).to receive(:list_resource_record_sets).with(hash_including(hosted_zone_id: '/hostedzone/hostedzoneid')) { resource_record_sets }
+ allow(Aws::Route53::Client).to receive(:new) { route53 }
- subject.find_alias_target('target.com.', 'foo.target.com.').should eq('abc.com')
+ expect(subject.find_alias_target('target.com.', 'foo.target.com.')).to eq('abc.com')
end
end
@@ -57,25 +66,25 @@
describe ".set_alias_target" do
it "should raise an error when the target-zone cannot be found" do
route53 = double('route53')
- allow(AWS::Route53).to receive(:new) { route53 }
+ allow(Aws::Route53::Client).to receive(:new) { route53 }
- allow(route53).to receive(:hosted_zones) { [] }
+ allow(route53).to receive_message_chain(:list_hosted_zones_by_name, :hosted_zones) { [] }
expect { subject.set_alias_target('abc.com', 'foo', 'abc', 'def') }.to raise_error('Target zone not found!')
end
it "should attempt multiple times" do
- failing_route53 = Fakes::AWSRoute53.new(times_to_fail: 5, hosted_zones: [double(name: 'abc.com.', path: '')])
+ failing_route53 = Fakes::AWSRoute53.new(times_to_fail: 5, hosted_zones: [double(id: '/hostedzone/hostedzoneid', name: 'abc.com.', path: '')])
route53_driver = CfDeployer::Driver::Route53.new(failing_route53)
allow(route53_driver).to receive(:sleep)
route53_driver.set_alias_target('abc.com', 'foo', 'abc', 'def')
- expect(failing_route53.client.fail_counter).to eq(6)
+ expect(failing_route53.fail_counter).to eq(6)
end
it "should raise an exception when failing more than 20 times" do
- failing_route53 = Fakes::AWSRoute53.new(times_to_fail: 21, hosted_zones: [double(name: 'abc.com.', path: '')])
+ failing_route53 = Fakes::AWSRoute53.new(times_to_fail: 21, hosted_zones: [double(id: '/hostedzone/hostedzoneid', name: 'abc.com.', path: '')])
route53_driver = CfDeployer::Driver::Route53.new(failing_route53)
allow(route53_driver).to receive(:sleep)
diff --git a/spec/unit/hook_spec.rb b/spec/unit/hook_spec.rb
index ef44bd2..d874497 100644
--- a/spec/unit/hook_spec.rb
+++ b/spec/unit/hook_spec.rb
@@ -3,7 +3,7 @@
describe CfDeployer::Hook do
before :all do
- Dir.mkdir 'tmp' unless Dir.exists?('tmp')
+ Dir.mkdir 'tmp' unless Dir.exist?('tmp')
@file = File.expand_path("../../../tmp/test_code.rb", __FILE__)
end
it 'should eval string as hook' do
@@ -67,8 +67,8 @@
it 'should catch SyntaxError during eval and show nicer output' do
context = { app: 'myApp' }
the_hook = CfDeployer::Hook.new('MyHook', "puts 'hello")
- the_hook.should_receive :error_document
- expect { the_hook.run(context) }.to raise_error
+ expect(the_hook).to receive(:error_document)
+ expect { the_hook.run(context) }.to raise_error(SyntaxError)
end
it 'should catch NoMethodError during eval and show nicer output' do
diff --git a/spec/unit/stack_spec.rb b/spec/unit/stack_spec.rb
index dccf3d3..57de9e6 100644
--- a/spec/unit/stack_spec.rb
+++ b/spec/unit/stack_spec.rb
@@ -26,10 +26,10 @@
expected_opt = {
:disable_rollback => true,
:capabilities => [],
- :notify => ['topic1_arn', 'topic2_arn'],
- :tags => [{'Key' => 'app', 'Value' => 'app1'},
- {'Key' => 'env', 'Value' => 'dev'}],
- :parameters => {:foo => 'bar'}
+ :notification_arns => ['topic1_arn', 'topic2_arn'],
+ :tags => [{:key => 'app', :value => 'app1'},
+ {:key => 'env', :value => 'dev'}],
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}]
}
expect(@cf_driver).to receive(:create_stack).with(template, expected_opt)
stack = CfDeployer::Stack.new('test','web', @config)
@@ -47,10 +47,10 @@
expected_opt = {
:disable_rollback => true,
:capabilities => [],
- :notify => ['topic1_arn', 'topic2_arn'],
- :tags => [{'Key' => 'app', 'Value' => 'app1'},
- {'Key' => 'env', 'Value' => 'dev'}],
- :parameters => {:foo => 'bar'},
+ :notification_arns => ['topic1_arn', 'topic2_arn'],
+ :tags => [{:key => 'app', :value => 'app1'},
+ {:key => 'env', :value => 'dev'}],
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}],
:stack_policy_body => create_policy
}
expect(@cf_driver).to receive(:create_stack).with(template, expected_opt)
@@ -65,7 +65,7 @@
allow(@cf_driver).to receive(:stack_status) { :create_complete }
expected_opt = {
:capabilities => [],
- :parameters => {:foo => 'bar'}
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}]
}
expect(@cf_driver).to receive(:update_stack).with(template, expected_opt)
stack = CfDeployer::Stack.new('test','web', @config)
@@ -79,7 +79,7 @@
allow(@cf_driver).to receive(:stack_status) { :create_complete }
expected_opt = {
:capabilities => [],
- :parameters => {:foo => 'bar'}
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}]
}
expect(@cf_driver).to receive(:update_stack).with(template, expected_opt).and_return(true)
stack = CfDeployer::Stack.new('test','web', @config)
@@ -94,7 +94,7 @@
allow(@cf_driver).to receive(:stack_status) { :create_complete }
expected_opt = {
:capabilities => [],
- :parameters => {:foo => 'bar'}
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}]
}
expect(@cf_driver).to receive(:update_stack).with(template, expected_opt).and_return(false)
stack = CfDeployer::Stack.new('test','web', @config)
@@ -109,7 +109,7 @@
allow(@cf_driver).to receive(:stack_status) { :update_rollback_complete }
expected_opt = {
:capabilities => [],
- :parameters => {:foo => 'bar'}
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}]
}
expect(@cf_driver).to receive(:update_stack).with(template, expected_opt).and_return(false)
stack = CfDeployer::Stack.new('test','web', @config)
@@ -126,7 +126,7 @@
allow(@cf_driver).to receive(:stack_status) { :create_complete }
expected_opt = {
:capabilities => [],
- :parameters => {:foo => 'bar'},
+ :parameters => [{:parameter_key => 'foo', :parameter_value => 'bar'}],
:stack_policy_during_update_body => override_policy
}
expect(@cf_driver).to receive(:update_stack).with(template, expected_opt)
@@ -168,7 +168,7 @@
context '#output' do
it 'should get output value' do
expect(@cf_driver).to receive(:query_output).with('mykey'){ 'myvalue'}
- @stack.output('mykey').should eq('myvalue')
+ expect(@stack.output('mykey')).to eq('myvalue')
end
it 'should get error if output is empty' do
@@ -180,12 +180,12 @@
context '#find_output' do
it 'should get output value' do
expect(@cf_driver).to receive(:query_output).with('mykey'){ 'myvalue'}
- @stack.find_output('mykey').should eq('myvalue')
+ expect(@stack.find_output('mykey')).to eq('myvalue')
end
it 'should return nil for non-existent value' do
expect(@cf_driver).to receive(:query_output).with('mykey'){ nil }
- @stack.find_output('mykey').should be(nil)
+ expect(@stack.find_output('mykey')).to be(nil)
end
end
@@ -218,16 +218,16 @@
it 'should be fine to get not exist error after deletion' do
allow(@stack).to receive(:exists?).and_return(true, true)
- allow(@stack).to receive(:stack_status).and_raise(AWS::CloudFormation::Errors::ValidationError.new('the stack does not exist'))
+ allow(@stack).to receive(:stack_status).and_raise(Aws::CloudFormation::Errors::StackSetNotFoundException.new(nil, 'the stack does not exist'))
expect(@cf_driver).to receive(:delete_stack)
expect {@stack.delete}.not_to raise_error
end
it 'should raise an error if a validation error is thrown not about stack does not exist' do
allow(@stack).to receive(:exists?).and_return(true, true)
- allow(@stack).to receive(:stack_status).and_raise(AWS::CloudFormation::Errors::ValidationError.new('I am an error'))
+ allow(@stack).to receive(:stack_status).and_raise(Aws::CloudFormation::Errors::InvalidOperationException.new(nil, 'I am an error'))
expect(@cf_driver).to receive(:delete_stack)
- expect {@stack.delete}.to raise_error
+ expect {@stack.delete}.to raise_error(Aws::CloudFormation::Errors::InvalidOperationException)
end
end