chef-provisioning-aws 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|