chef-provisioning-aws 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -8
- data/lib/chef/provider/aws_cache_cluster.rb +75 -0
- data/lib/chef/provider/aws_cache_replication_group.rb +49 -0
- data/lib/chef/provider/aws_cache_subnet_group.rb +60 -0
- data/lib/chef/provider/aws_instance.rb +4 -1
- data/lib/chef/provider/aws_key_pair.rb +1 -1
- data/lib/chef/provider/aws_network_acl.rb +131 -0
- data/lib/chef/provider/aws_security_group.rb +1 -1
- data/lib/chef/provider/aws_subnet.rb +14 -0
- data/lib/chef/provider/aws_vpc.rb +1 -0
- data/lib/chef/provisioning/aws_driver.rb +4 -0
- data/lib/chef/provisioning/aws_driver/aws_provider.rb +25 -0
- data/lib/chef/provisioning/aws_driver/aws_resource.rb +7 -2
- data/lib/chef/provisioning/aws_driver/driver.rb +59 -24
- data/lib/chef/provisioning/aws_driver/version.rb +1 -1
- data/lib/chef/resource/aws_cache_cluster.rb +37 -0
- data/lib/chef/resource/aws_cache_replication_group.rb +37 -0
- data/lib/chef/resource/aws_cache_subnet_group.rb +28 -0
- data/lib/chef/resource/aws_network_acl.rb +61 -0
- data/lib/chef/resource/aws_subnet.rb +9 -0
- data/spec/aws_support.rb +4 -1
- data/spec/aws_support/matchers/match_an_aws_object.rb +58 -0
- data/spec/integration/aws_cache_subnet_group_spec.rb +32 -0
- data/spec/integration/aws_key_pair_spec.rb +2 -2
- data/spec/integration/aws_network_acl_spec.rb +107 -0
- data/spec/integration/aws_security_group_spec.rb +16 -0
- data/spec/integration/aws_subnet_spec.rb +8 -11
- data/spec/integration/aws_tagged_items_spec.rb +1 -1
- data/spec/integration/aws_vpc_spec.rb +16 -0
- metadata +27 -2
@@ -42,6 +42,7 @@ class Chef::Provider::AwsVpc < Chef::Provisioning::AWSDriver::AWSProvider
|
|
42
42
|
|
43
43
|
converge_by "create new VPC #{new_resource.name} in #{region}" do
|
44
44
|
vpc = new_resource.driver.ec2.vpcs.create(new_resource.cidr_block, options)
|
45
|
+
wait_for_state(vpc, [:available])
|
45
46
|
vpc.tags['Name'] = new_resource.name
|
46
47
|
vpc
|
47
48
|
end
|
@@ -2,6 +2,9 @@ require 'chef/provisioning'
|
|
2
2
|
require 'chef/provisioning/aws_driver/driver'
|
3
3
|
|
4
4
|
require "chef/resource/aws_auto_scaling_group"
|
5
|
+
require "chef/resource/aws_cache_cluster"
|
6
|
+
require "chef/resource/aws_cache_replication_group"
|
7
|
+
require "chef/resource/aws_cache_subnet_group"
|
5
8
|
require "chef/resource/aws_dhcp_options"
|
6
9
|
require "chef/resource/aws_ebs_volume"
|
7
10
|
require "chef/resource/aws_eip_address"
|
@@ -10,6 +13,7 @@ require "chef/resource/aws_instance"
|
|
10
13
|
require "chef/resource/aws_internet_gateway"
|
11
14
|
require "chef/resource/aws_launch_configuration"
|
12
15
|
require "chef/resource/aws_load_balancer"
|
16
|
+
require "chef/resource/aws_network_acl"
|
13
17
|
require "chef/resource/aws_network_interface"
|
14
18
|
require "chef/resource/aws_route_table"
|
15
19
|
require "chef/resource/aws_s3_bucket"
|
@@ -288,5 +288,30 @@ class AWSProvider < Chef::Provider::LWRPBase
|
|
288
288
|
end
|
289
289
|
end
|
290
290
|
|
291
|
+
# Wait until aws_object obtains one of expected_state
|
292
|
+
#
|
293
|
+
# @param aws_object Aws SDK Object to check state on
|
294
|
+
# @param expected_state [Symbol,Array<Symbol>] Final state(s) to look for
|
295
|
+
# @param acceptable_errors [Exception,Array<Exception>] Acceptable errors that are caught and squelched
|
296
|
+
# @param tries [Integer] Number of times to check state
|
297
|
+
# @param sleep [Integer] Time to wait between checking states
|
298
|
+
#
|
299
|
+
def wait_for_state(aws_object, expected_states, acceptable_errors = [], tries=60, sleep=5)
|
300
|
+
acceptable_errors = [acceptable_errors].flatten
|
301
|
+
expected_states = [expected_states].flatten
|
302
|
+
current_state = aws_object.state
|
303
|
+
|
304
|
+
Retryable.retryable(:tries => tries, :sleep => sleep, :on => StatusTimeoutError) do |retries, exception|
|
305
|
+
action_handler.report_progress "waited #{retries*sleep}/#{tries*sleep}s for #{aws_object.id} state to change to #{expected_states.inspect}..."
|
306
|
+
begin
|
307
|
+
current_state = aws_object.state
|
308
|
+
unless expected_states.include?(current_state)
|
309
|
+
raise StatusTimeoutError.new(aws_object, current_state, expected_states)
|
310
|
+
end
|
311
|
+
rescue *acceptable_errors
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
291
316
|
end
|
292
317
|
end
|
@@ -25,8 +25,13 @@ class AWSResource < Chef::Provisioning::AWSDriver::SuperLWRP
|
|
25
25
|
super
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
|
-
|
28
|
+
|
29
|
+
# In Chef < 12.4 we need to define this method. In > 12.4 this method is
|
30
|
+
# already defined for us so we don't need to overwrite it.
|
31
|
+
unless defined?(:action=)
|
32
|
+
def action=(value)
|
33
|
+
action(value)
|
34
|
+
end
|
30
35
|
end
|
31
36
|
|
32
37
|
#
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'chef/mixin/shell_out'
|
2
|
+
require 'chef/mixin/deep_merge'
|
2
3
|
require 'chef/provisioning/driver'
|
3
4
|
require 'chef/provisioning/convergence_strategy/install_cached'
|
4
5
|
require 'chef/provisioning/convergence_strategy/install_sh'
|
@@ -21,7 +22,7 @@ require 'chef/provisioning/aws_driver/credentials'
|
|
21
22
|
require 'yaml'
|
22
23
|
require 'aws-sdk-v1'
|
23
24
|
require 'retryable'
|
24
|
-
|
25
|
+
require 'ubuntu_ami'
|
25
26
|
|
26
27
|
# loads the entire aws-sdk
|
27
28
|
AWS.eager_autoload!
|
@@ -33,6 +34,7 @@ module AWSDriver
|
|
33
34
|
class Driver < Chef::Provisioning::Driver
|
34
35
|
|
35
36
|
include Chef::Mixin::ShellOut
|
37
|
+
include Chef::Mixin::DeepMerge
|
36
38
|
|
37
39
|
attr_reader :aws_config
|
38
40
|
|
@@ -69,6 +71,9 @@ module AWSDriver
|
|
69
71
|
# Load balancer methods
|
70
72
|
def allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
|
71
73
|
lb_options = AWSResource.lookup_options(lb_options || {}, managed_entry_store: lb_spec.managed_entry_store, driver: self)
|
74
|
+
# We delete the attributes here because they are not valid in the create call
|
75
|
+
# and must be applied afterward
|
76
|
+
lb_attributes = lb_options.delete(:attributes)
|
72
77
|
|
73
78
|
old_elb = nil
|
74
79
|
actual_elb = load_balancer_for(lb_spec)
|
@@ -304,6 +309,21 @@ module AWSDriver
|
|
304
309
|
}
|
305
310
|
converge_tags(actual_elb, lb_options[:aws_tags], action_handler, read_tags_block, set_tags_block, delete_tags_block)
|
306
311
|
|
312
|
+
# Update load balancer attributes
|
313
|
+
if lb_attributes
|
314
|
+
current = elb.client.describe_load_balancer_attributes(load_balancer_name: actual_elb.name)[:load_balancer_attributes]
|
315
|
+
# Need to do a deep copy w/ Marshal load/dump to avoid overwriting current
|
316
|
+
desired = deep_merge!(lb_attributes, Marshal.load(Marshal.dump(current)))
|
317
|
+
if current != desired
|
318
|
+
perform_action.call(" updating attributes to #{desired.inspect}") do
|
319
|
+
elb.client.modify_load_balancer_attributes(
|
320
|
+
load_balancer_name: actual_elb.name,
|
321
|
+
load_balancer_attributes: desired.to_hash
|
322
|
+
)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
307
327
|
# Update instance list, but only if there are machines specified
|
308
328
|
if machine_specs
|
309
329
|
actual_instance_ids = actual_elb.instances.map { |i| i.instance_id }
|
@@ -522,6 +542,10 @@ EOD
|
|
522
542
|
@elb ||= AWS::ELB.new(config: aws_config)
|
523
543
|
end
|
524
544
|
|
545
|
+
def elasticache
|
546
|
+
@elasticache ||= AWS::ElastiCache::Client.new(config: aws_config)
|
547
|
+
end
|
548
|
+
|
525
549
|
def iam
|
526
550
|
@iam ||= AWS::IAM.new(config: aws_config)
|
527
551
|
end
|
@@ -675,31 +699,42 @@ EOD
|
|
675
699
|
end
|
676
700
|
end
|
677
701
|
|
678
|
-
def
|
679
|
-
|
702
|
+
def default_ami_arch
|
703
|
+
'amd64'
|
704
|
+
end
|
680
705
|
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
'ami-b9471c89'
|
700
|
-
else
|
701
|
-
raise 'Unsupported region!'
|
706
|
+
def default_ami_release
|
707
|
+
'vivid'
|
708
|
+
end
|
709
|
+
|
710
|
+
def default_ami_root_store
|
711
|
+
'ebs'
|
712
|
+
end
|
713
|
+
|
714
|
+
def default_ami_virtualization_type
|
715
|
+
'hvm'
|
716
|
+
end
|
717
|
+
|
718
|
+
def default_ami_for_criteria(region, arch, release, root_store, virtualization_type)
|
719
|
+
ami = Ubuntu.release(release).amis.find do |ami|
|
720
|
+
ami.arch == arch &&
|
721
|
+
ami.root_store == root_store &&
|
722
|
+
ami.region == region &&
|
723
|
+
ami.virtualization_type == virtualization_type
|
702
724
|
end
|
725
|
+
|
726
|
+
ami.name || fail("Default AMI not found")
|
727
|
+
end
|
728
|
+
|
729
|
+
def default_ami_for_region(region, criteria = {})
|
730
|
+
Chef::Log.debug("Choosing default AMI for region '#{region}'")
|
731
|
+
|
732
|
+
arch = criteria['arch'] || default_ami_arch
|
733
|
+
release = criteria['release'] || default_ami_release
|
734
|
+
root_store = criteria['root_store'] || default_ami_root_store
|
735
|
+
virtualization_type = criteria['virtualization_type'] || default_ami_virtualization_type
|
736
|
+
|
737
|
+
default_ami_for_criteria(region, arch, release, root_store, virtualization_type)
|
703
738
|
end
|
704
739
|
|
705
740
|
def create_winrm_transport(machine_spec, machine_options, instance)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'chef/provisioning/aws_driver/aws_resource'
|
2
|
+
require 'chef/resource/aws_security_group'
|
3
|
+
|
4
|
+
class Chef::Resource::AwsCacheCluster < Chef::Provisioning::AWSDriver::AWSResource
|
5
|
+
# Note: There isn't actually an SDK class for Elasticache.
|
6
|
+
aws_sdk_type AWS::ElastiCache
|
7
|
+
|
8
|
+
# See http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/ElastiCache/Client/V20140930.html#create_cache_cluster-instance_method
|
9
|
+
# for information on possible values for each attribute. Values are passed
|
10
|
+
# straight through to AWS, with the exception of security_groups, which
|
11
|
+
# may contain a reference to a Chef aws_security_group resource.
|
12
|
+
attribute :cluster_name, kind_of: String, name_attribute: true
|
13
|
+
attribute :az_mode, kind_of: String
|
14
|
+
attribute :preferred_availability_zone, kind_of: String
|
15
|
+
attribute :preferred_availability_zones,
|
16
|
+
kind_of: [ String, Array ],
|
17
|
+
coerce: proc { |v| [v].flatten }
|
18
|
+
attribute :number_nodes, kind_of: Integer, default: 1
|
19
|
+
attribute :node_type, kind_of: String, required: true
|
20
|
+
attribute :engine, kind_of: String, required: true
|
21
|
+
attribute :engine_version, kind_of: String, required: true
|
22
|
+
attribute :subnet_group_name, kind_of: String
|
23
|
+
attribute :security_groups,
|
24
|
+
kind_of: [ String, Array, AwsSecurityGroup, AWS::EC2::SecurityGroup ],
|
25
|
+
required: true,
|
26
|
+
coerce: proc { |v| [v].flatten }
|
27
|
+
|
28
|
+
def aws_object
|
29
|
+
begin
|
30
|
+
driver.elasticache
|
31
|
+
.describe_cache_clusters(cache_cluster_id: cluster_name)
|
32
|
+
.data[:cache_clusters].first
|
33
|
+
rescue AWS::ElastiCache::Errors::CacheClusterNotFound
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'chef/provisioning/aws_driver/aws_resource'
|
2
|
+
require 'chef/resource/aws_security_group'
|
3
|
+
|
4
|
+
class Chef::Resource::AwsCacheReplicationGroup < Chef::Provisioning::AWSDriver::AWSResource
|
5
|
+
# Note: There isn't actually an SDK class for Elasticache.
|
6
|
+
aws_sdk_type AWS::ElastiCache
|
7
|
+
|
8
|
+
# See http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/ElastiCache/Client/V20140930.html#create_replication_group-instance_method
|
9
|
+
# for information on possible values for each attribute. Values are passed
|
10
|
+
# straight through to AWS, with the exception of security_groups, which
|
11
|
+
# may contain a reference to a Chef aws_security_group resource.
|
12
|
+
attribute :group_name, kind_of: String, name_attribute: true
|
13
|
+
attribute :description, kind_of: String, required: true
|
14
|
+
attribute :automatic_failover, kind_of: [TrueClass, FalseClass], default: false
|
15
|
+
attribute :number_cache_clusters, kind_of: Integer, default: 2
|
16
|
+
attribute :node_type, kind_of: String, required: true
|
17
|
+
attribute :engine, kind_of: String, required: true
|
18
|
+
attribute :engine_version, kind_of: String, required: true
|
19
|
+
attribute :subnet_group_name, kind_of: String
|
20
|
+
attribute :security_groups,
|
21
|
+
kind_of: [ String, Array, AwsSecurityGroup, AWS::EC2::SecurityGroup ],
|
22
|
+
required: true,
|
23
|
+
coerce: proc { |v| [v].flatten }
|
24
|
+
attribute :preferred_availability_zones,
|
25
|
+
kind_of: [ String, Array ],
|
26
|
+
coerce: proc { |v| [v].flatten }
|
27
|
+
|
28
|
+
def aws_object
|
29
|
+
begin
|
30
|
+
driver.elasticache
|
31
|
+
.describe_replication_groups(replication_group_id: group_name)
|
32
|
+
.data[:replication_groups].first
|
33
|
+
rescue AWS::ElastiCache::Errors::ReplicationGroupNotFoundFault
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'chef/provisioning/aws_driver/aws_resource'
|
2
|
+
require 'chef/resource/aws_subnet'
|
3
|
+
|
4
|
+
class Chef::Resource::AwsCacheSubnetGroup < Chef::Provisioning::AWSDriver::AWSResource
|
5
|
+
# Note: There isn't actually an SDK class for Elasticache.
|
6
|
+
aws_sdk_type AWS::ElastiCache, id: :group_name
|
7
|
+
|
8
|
+
# See http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/ElastiCache/Client/V20140930.html#create_cache_subnet_group-instance_method
|
9
|
+
# for information on possible values for each attribute. Values are passed
|
10
|
+
# straight through to AWS, with the exception of subnets, which
|
11
|
+
# may contain a reference to a Chef aws_subnet resource.
|
12
|
+
attribute :group_name, kind_of: String, name_attribute: true
|
13
|
+
attribute :description, kind_of: String, required: true
|
14
|
+
attribute :subnets,
|
15
|
+
kind_of: [ String, Array, AwsSubnet, AWS::EC2::Subnet ],
|
16
|
+
required: true,
|
17
|
+
coerce: proc { |v| [v].flatten }
|
18
|
+
|
19
|
+
def aws_object
|
20
|
+
begin
|
21
|
+
driver.elasticache
|
22
|
+
.describe_cache_subnet_groups(cache_subnet_group_name: group_name)
|
23
|
+
.data[:cache_subnet_groups].first
|
24
|
+
rescue AWS::ElastiCache::Errors::CacheSubnetGroupNotFoundFault
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'chef/provisioning/aws_driver/aws_resource_with_entry'
|
2
|
+
require 'chef/resource/aws_vpc'
|
3
|
+
require 'chef/resource/aws_subnet'
|
4
|
+
|
5
|
+
class Chef::Resource::AwsNetworkAcl < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
|
6
|
+
aws_sdk_type AWS::EC2::NetworkACL
|
7
|
+
|
8
|
+
#
|
9
|
+
# The name of this network acl.
|
10
|
+
#
|
11
|
+
attribute :name, kind_of: String, name_attribute: true
|
12
|
+
|
13
|
+
#
|
14
|
+
# The VPC of this network acl.
|
15
|
+
#
|
16
|
+
# May be one of:
|
17
|
+
# - The name of an `aws_vpc` Chef resource.
|
18
|
+
# - An actual `aws_vpc` resource.
|
19
|
+
# - An AWS `VPC` object.
|
20
|
+
#
|
21
|
+
attribute :vpc, kind_of: [ String, AwsVpc, AWS::EC2::VPC ]
|
22
|
+
|
23
|
+
#
|
24
|
+
# Accepts rules in the format:
|
25
|
+
# [
|
26
|
+
# { rule_number: 100, action: <:deny|:allow>, protocol: -1, cidr_block: '0.0.0.0/0', port_range: 80..80 }
|
27
|
+
# ]
|
28
|
+
#
|
29
|
+
# `cidr_block` will be a source if it is an inbound rule, or a destination if it is an outbound rule
|
30
|
+
#
|
31
|
+
# If `inbound_rules` or `outbound_rules` is `nil`, respective current rules will not be changed.
|
32
|
+
# However, if either is set to `[]` all respective current rules will be removed.
|
33
|
+
#
|
34
|
+
attribute :inbound_rules,
|
35
|
+
kind_of: [ Array, Hash ],
|
36
|
+
coerce: proc { |v| [v].flatten }
|
37
|
+
|
38
|
+
attribute :outbound_rules,
|
39
|
+
kind_of: [ Array, Hash ],
|
40
|
+
coerce: proc { |v| [v].flatten }
|
41
|
+
|
42
|
+
attribute :network_acl_id,
|
43
|
+
kind_of: String,
|
44
|
+
aws_id_attribute: true,
|
45
|
+
lazy_default: proc {
|
46
|
+
name =~ /^acl-[a-f0-9]{8}$/ ? name : nil
|
47
|
+
}
|
48
|
+
|
49
|
+
def aws_object
|
50
|
+
driver, id = get_driver_and_id
|
51
|
+
result = driver.ec2.network_acls[id] if id
|
52
|
+
begin
|
53
|
+
# network_acls don't have an `exists?` method so have to query an attribute
|
54
|
+
result.vpc_id
|
55
|
+
result
|
56
|
+
rescue AWS::EC2::Errors::InvalidNetworkAclID::NotFound
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -17,6 +17,7 @@ class Chef::Resource::AwsSubnet < Chef::Provisioning::AWSDriver::AWSResourceWith
|
|
17
17
|
aws_sdk_type AWS::EC2::Subnet
|
18
18
|
|
19
19
|
require 'chef/resource/aws_vpc'
|
20
|
+
require 'chef/resource/aws_network_acl'
|
20
21
|
require 'chef/resource/aws_route_table'
|
21
22
|
|
22
23
|
#
|
@@ -75,6 +76,14 @@ class Chef::Resource::AwsSubnet < Chef::Provisioning::AWSDriver::AWSResourceWith
|
|
75
76
|
#
|
76
77
|
attribute :route_table#, kind_of: [ String, AwsRouteTable, AWS::EC2::RouteTable ], equal_to: [ :default_to_main ]
|
77
78
|
|
79
|
+
#
|
80
|
+
# The Network ACL to associate with this subnet. Subnets may only
|
81
|
+
# be associated with a single Network ACL.
|
82
|
+
#
|
83
|
+
# TODO: See if it's possible to disassociate a Network ACL.
|
84
|
+
#
|
85
|
+
attribute :network_acl, kind_of: [ String, AwsNetworkAcl, AWS::EC2::NetworkACL ]
|
86
|
+
|
78
87
|
attribute :subnet_id, kind_of: String, aws_id_attribute: true, lazy_default: proc {
|
79
88
|
name =~ /^subnet-[a-f0-9]{8}$/ ? name : nil
|
80
89
|
}
|
data/spec/aws_support.rb
CHANGED
@@ -14,6 +14,7 @@ module AWSSupport
|
|
14
14
|
require 'aws_support/matchers/update_an_aws_object'
|
15
15
|
require 'aws_support/matchers/destroy_an_aws_object'
|
16
16
|
require 'aws_support/matchers/have_aws_object_tags'
|
17
|
+
require 'aws_support/matchers/match_an_aws_object'
|
17
18
|
require 'aws_support/delayed_stream'
|
18
19
|
require 'chef/provisioning/aws_driver/resources'
|
19
20
|
require 'aws_support/aws_resource_run_wrapper'
|
@@ -196,7 +197,9 @@ module AWSSupport
|
|
196
197
|
define_method("destroy_an_#{resource_name}") do |name, expected_values={}|
|
197
198
|
AWSSupport::Matchers::DestroyAnAWSObject.new(self, resource_class, name)
|
198
199
|
end
|
199
|
-
|
200
|
+
define_method("match_an_#{resource_name}") do |name, expected_values={}|
|
201
|
+
AWSSupport::Matchers::MatchAnAWSObject.new(self, resource_class, name, expected_values)
|
202
|
+
end
|
200
203
|
end
|
201
204
|
|
202
205
|
def chef_config
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rspec/matchers'
|
2
|
+
require 'chef/provisioning'
|
3
|
+
require 'aws_support/deep_matcher'
|
4
|
+
|
5
|
+
module AWSSupport
|
6
|
+
module Matchers
|
7
|
+
|
8
|
+
# This matcher doesn't try to validate that an example was created/updated/destroyed
|
9
|
+
# it just checks that the object exists and posses the attributes you specify
|
10
|
+
# It also doesn't clean up any aws objects so only use if the resource is defined outside
|
11
|
+
# of an example block
|
12
|
+
class MatchAnAWSObject
|
13
|
+
include RSpec::Matchers::Composable
|
14
|
+
include AWSSupport::DeepMatcher
|
15
|
+
|
16
|
+
def initialize(example, resource_class, name, expected_values)
|
17
|
+
@example = example
|
18
|
+
@resource_class = resource_class
|
19
|
+
@name = name
|
20
|
+
@expected_values = expected_values
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :example
|
24
|
+
attr_reader :resource_class
|
25
|
+
attr_reader :name
|
26
|
+
attr_reader :expected_values
|
27
|
+
def resource_name
|
28
|
+
@resource_class.resource_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def match_failure_messages(recipe)
|
32
|
+
differences = []
|
33
|
+
|
34
|
+
# Converge
|
35
|
+
begin
|
36
|
+
recipe.converge
|
37
|
+
rescue
|
38
|
+
differences += [ "error trying to converge #{resource_name}[#{name}]!\n#{($!.backtrace.map { |line| "- #{line}\n" } + [ recipe.output_for_failure_message ]).join("")}" ]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Check for object existence and properties
|
42
|
+
resource = resource_class.new(name, nil)
|
43
|
+
resource.driver example.driver
|
44
|
+
resource.managed_entry_store Chef::Provisioning.chef_managed_entry_store
|
45
|
+
aws_object = resource.aws_object
|
46
|
+
|
47
|
+
# Check existence
|
48
|
+
if aws_object.nil?
|
49
|
+
differences << "#{resource_name}[#{name}] AWS object did not exist!"
|
50
|
+
else
|
51
|
+
differences += match_values_failure_messages(expected_values, aws_object, "#{resource_name}[#{name}]")
|
52
|
+
end
|
53
|
+
|
54
|
+
differences
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|