chef-provisioning-aws 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -69
  3. data/Rakefile +22 -2
  4. data/lib/chef/provider/aws_auto_scaling_group.rb +3 -2
  5. data/lib/chef/provider/aws_cache_cluster.rb +3 -2
  6. data/lib/chef/provider/aws_cache_replication_group.rb +5 -4
  7. data/lib/chef/provider/aws_cache_subnet_group.rb +5 -4
  8. data/lib/chef/provider/aws_cloudsearch_domain.rb +163 -0
  9. data/lib/chef/provider/aws_dhcp_options.rb +9 -6
  10. data/lib/chef/provider/aws_ebs_volume.rb +7 -3
  11. data/lib/chef/provider/aws_eip_address.rb +8 -7
  12. data/lib/chef/provider/aws_image.rb +8 -3
  13. data/lib/chef/provider/aws_instance.rb +14 -2
  14. data/lib/chef/provider/aws_key_pair.rb +2 -1
  15. data/lib/chef/provider/aws_launch_configuration.rb +4 -2
  16. data/lib/chef/provider/aws_load_balancer.rb +18 -0
  17. data/lib/chef/provider/aws_network_acl.rb +6 -2
  18. data/lib/chef/provider/aws_network_interface.rb +11 -24
  19. data/lib/chef/provider/aws_rds_instance.rb +66 -0
  20. data/lib/chef/provider/aws_rds_subnet_group.rb +89 -0
  21. data/lib/chef/provider/aws_route_table.rb +42 -23
  22. data/lib/chef/provider/aws_s3_bucket.rb +32 -8
  23. data/lib/chef/provider/aws_security_group.rb +11 -4
  24. data/lib/chef/provider/aws_server_certificate.rb +23 -0
  25. data/lib/chef/provider/aws_sns_topic.rb +4 -3
  26. data/lib/chef/provider/aws_sqs_queue.rb +3 -2
  27. data/lib/chef/provider/aws_subnet.rb +10 -7
  28. data/lib/chef/provider/aws_vpc.rb +54 -21
  29. data/lib/chef/provider/aws_vpc_peering_connection.rb +88 -0
  30. data/lib/chef/provisioning/aws_driver.rb +8 -0
  31. data/lib/chef/provisioning/aws_driver/aws_provider.rb +45 -76
  32. data/lib/chef/provisioning/aws_driver/aws_rds_resource.rb +11 -0
  33. data/lib/chef/provisioning/aws_driver/aws_resource.rb +14 -2
  34. data/lib/chef/provisioning/aws_driver/aws_resource_with_entry.rb +2 -8
  35. data/lib/chef/provisioning/aws_driver/aws_taggable.rb +18 -0
  36. data/lib/chef/provisioning/aws_driver/aws_tagger.rb +61 -0
  37. data/lib/chef/provisioning/aws_driver/credentials2.rb +51 -0
  38. data/lib/chef/provisioning/aws_driver/driver.rb +214 -162
  39. data/lib/chef/provisioning/aws_driver/tagging_strategy/ec2.rb +64 -0
  40. data/lib/chef/provisioning/aws_driver/tagging_strategy/elb.rb +39 -0
  41. data/lib/chef/provisioning/aws_driver/tagging_strategy/rds.rb +92 -0
  42. data/lib/chef/provisioning/aws_driver/tagging_strategy/s3.rb +41 -0
  43. data/lib/chef/provisioning/aws_driver/version.rb +1 -1
  44. data/lib/chef/resource/aws_cache_cluster.rb +1 -2
  45. data/lib/chef/resource/aws_cloudsearch_domain.rb +46 -0
  46. data/lib/chef/resource/aws_dhcp_options.rb +2 -0
  47. data/lib/chef/resource/aws_ebs_volume.rb +3 -1
  48. data/lib/chef/resource/aws_eip_address.rb +0 -3
  49. data/lib/chef/resource/aws_image.rb +3 -0
  50. data/lib/chef/resource/aws_instance.rb +7 -2
  51. data/lib/chef/resource/aws_internet_gateway.rb +2 -0
  52. data/lib/chef/resource/aws_load_balancer.rb +3 -0
  53. data/lib/chef/resource/aws_network_acl.rb +2 -0
  54. data/lib/chef/resource/aws_network_interface.rb +3 -1
  55. data/lib/chef/resource/aws_rds_instance.rb +42 -0
  56. data/lib/chef/resource/aws_rds_subnet_group.rb +29 -0
  57. data/lib/chef/resource/aws_route_table.rb +7 -5
  58. data/lib/chef/resource/aws_s3_bucket.rb +3 -0
  59. data/lib/chef/resource/aws_security_group.rb +2 -7
  60. data/lib/chef/resource/aws_server_certificate.rb +21 -0
  61. data/lib/chef/resource/aws_subnet.rb +2 -0
  62. data/lib/chef/resource/aws_vpc.rb +4 -1
  63. data/lib/chef/resource/aws_vpc_peering_connection.rb +73 -0
  64. data/spec/acceptance/aws_ebs_volume/nodes/ettores-mbp.lan.json +3 -0
  65. data/spec/aws_support.rb +25 -8
  66. data/spec/aws_support/aws_resource_run_wrapper.rb +5 -1
  67. data/spec/aws_support/deep_matcher/match_values_failure_messages.rb +19 -0
  68. data/spec/aws_support/matchers/create_an_aws_object.rb +1 -1
  69. data/spec/aws_support/matchers/destroy_an_aws_object.rb +1 -1
  70. data/spec/aws_support/matchers/have_aws_object_tags.rb +9 -15
  71. data/spec/aws_support/matchers/match_an_aws_object.rb +1 -1
  72. data/spec/aws_support/matchers/update_an_aws_object.rb +1 -1
  73. data/spec/integration/aws_cloudsearch_domain_spec.rb +31 -0
  74. data/spec/integration/aws_dhcp_options_spec.rb +73 -0
  75. data/spec/integration/aws_ebs_volume_spec.rb +97 -0
  76. data/spec/integration/aws_network_acl_spec.rb +51 -0
  77. data/spec/integration/aws_network_interface_spec.rb +89 -0
  78. data/spec/integration/aws_rds_instance_spec.rb +150 -0
  79. data/spec/integration/aws_rds_subnet_group_spec.rb +105 -0
  80. data/spec/integration/aws_route_table_spec.rb +94 -7
  81. data/spec/integration/aws_s3_bucket_spec.rb +88 -0
  82. data/spec/integration/aws_security_group_spec.rb +47 -0
  83. data/spec/integration/aws_server_certificate_spec.rb +24 -0
  84. data/spec/integration/aws_subnet_spec.rb +51 -2
  85. data/spec/integration/aws_vpc_peering_connection_spec.rb +99 -0
  86. data/spec/integration/aws_vpc_spec.rb +73 -0
  87. data/spec/integration/load_balancer_spec.rb +101 -0
  88. data/spec/integration/machine_image_spec.rb +61 -6
  89. data/spec/integration/machine_spec.rb +26 -0
  90. data/spec/spec_helper.rb +3 -0
  91. data/spec/unit/{aws_driver → chef/provisioning/aws_driver}/credentials_spec.rb +0 -0
  92. data/spec/unit/chef/provisioning/aws_driver/driver_spec.rb +88 -0
  93. metadata +63 -20
  94. data/spec/integration/aws_tagged_items_spec.rb +0 -166
@@ -0,0 +1,29 @@
1
+ require 'chef/provisioning/aws_driver/aws_rds_resource'
2
+ require 'chef/provisioning/aws_driver/aws_taggable'
3
+ require 'chef/resource/aws_subnet'
4
+
5
+ class Chef::Resource::AwsRdsSubnetGroup < Chef::Provisioning::AWSDriver::AWSRDSResource
6
+ include Chef::Provisioning::AWSDriver::AWSTaggable
7
+
8
+ aws_sdk_type AWS::RDS
9
+
10
+ attribute :name, kind_of: String, name_attribute: true
11
+ attribute :description, kind_of: String, required: true
12
+ attribute :subnets,
13
+ kind_of: [ String, Array, AwsSubnet, AWS::EC2::Subnet ],
14
+ required: true,
15
+ coerce: proc { |v| [v].flatten }
16
+
17
+ def aws_object
18
+ driver.rds.client
19
+ .describe_db_subnet_groups(db_subnet_group_name: name)[:db_subnet_groups].first
20
+ rescue AWS::RDS::Errors::DBSubnetGroupNotFoundFault
21
+ # triggered by describe_db_subnet_groups when the group can't
22
+ # be found
23
+ nil
24
+ end
25
+
26
+ def rds_tagging_type
27
+ "subgrp"
28
+ end
29
+ end
@@ -13,7 +13,8 @@ require 'chef/provisioning/aws_driver/aws_resource_with_entry'
13
13
  # - http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/RouteTable.html
14
14
  #
15
15
  class Chef::Resource::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
16
- aws_sdk_type AWS::EC2::RouteTable
16
+ include Chef::Provisioning::AWSDriver::AWSTaggable
17
+ aws_sdk_type ::Aws::EC2::RouteTable
17
18
 
18
19
  require 'chef/resource/aws_vpc'
19
20
 
@@ -63,7 +64,8 @@ class Chef::Resource::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSResource
63
64
  # - { internet_gateway: <AWS Internet Gateway ID or object> }
64
65
  # - { instance: <Chef machine name or resource, AWS Instance ID or object> }
65
66
  # - { network_interface: <AWS Network Interface ID or object> }
66
- # - <AWS Internet Gateway, Instance or Network Interface <ID or object)>
67
+ # - { vpc_peering_connection: <AWS VPC Peering Connection ID or object> }
68
+ # - <AWS Internet Gateway, Instance, Network Interface or a VPC Peering Connection <ID or object)>
67
69
  # - Chef machine name
68
70
  # - Chef machine resource
69
71
  #
@@ -95,11 +97,11 @@ class Chef::Resource::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSResource
95
97
 
96
98
  def aws_object
97
99
  driver, id = get_driver_and_id
98
- result = driver.ec2.route_tables[id] if id
100
+ result = driver.ec2_resource.route_table(id) if id
99
101
  begin
100
102
  # try accessing it to find out if it exists
101
- result.vpc if result
102
- rescue AWS::EC2::Errors::InvalidRouteTableID::NotFound
103
+ result.vpc_id if result
104
+ rescue ::Aws::EC2::Errors::InvalidRouteTableIDNotFound
103
105
  result = nil
104
106
  end
105
107
  result
@@ -1,12 +1,15 @@
1
1
  require 'chef/provisioning/aws_driver/aws_resource'
2
2
 
3
3
  class Chef::Resource::AwsS3Bucket < Chef::Provisioning::AWSDriver::AWSResource
4
+ include Chef::Provisioning::AWSDriver::AWSTaggable
5
+
4
6
  aws_sdk_type AWS::S3::Bucket, id: :name
5
7
 
6
8
  attribute :name, :kind_of => String, :name_attribute => true
7
9
  attribute :options, :kind_of => Hash, :default => {}
8
10
  attribute :enable_website_hosting, :kind_of => [TrueClass, FalseClass], :default => false
9
11
  attribute :website_options, :kind_of => Hash, :default => {}
12
+ attribute :recursive_delete, :kind_of => [TrueClass, FalseClass], :default => false
10
13
 
11
14
  def aws_object
12
15
  result = driver.s3.buckets[name]
@@ -3,6 +3,8 @@ require 'chef/resource/aws_vpc'
3
3
  require 'chef/provisioning/aws_driver/exceptions'
4
4
 
5
5
  class Chef::Resource::AwsSecurityGroup < Chef::Provisioning::AWSDriver::AWSResource
6
+ include Chef::Provisioning::AWSDriver::AWSTaggable
7
+
6
8
  aws_sdk_type AWS::EC2::SecurityGroup,
7
9
  id: :id,
8
10
  option_names: [:security_group, :security_group_id, :security_group_name]
@@ -11,13 +13,6 @@ class Chef::Resource::AwsSecurityGroup < Chef::Provisioning::AWSDriver::AWSResou
11
13
  attribute :vpc, kind_of: [ String, AwsVpc, AWS::EC2::VPC ]
12
14
  attribute :description, kind_of: String
13
15
 
14
- # This should be a hash of tags to apply to the AWS object
15
- # TODO this is duplicated from AWSResourceWithEntry
16
- #
17
- # @param aws_tags [Hash] Should be a hash of keys & values to add. Keys and values
18
- # can be provided as symbols or strings, but will be stored in AWS as strings.
19
- attribute :aws_tags, kind_of: Hash
20
-
21
16
  #
22
17
  # Accepts rules in the format:
23
18
  # [
@@ -0,0 +1,21 @@
1
+ require 'chef/provisioning/aws_driver/aws_resource'
2
+
3
+ class Chef::Resource::AwsServerCertificate < Chef::Provisioning::AWSDriver::AWSResource
4
+ aws_sdk_type AWS::IAM::ServerCertificate
5
+
6
+ attribute :name, kind_of: String, name_attribute: true
7
+
8
+ attribute :certificate_body, kind_of: String
9
+ attribute :private_key, kind_of: String
10
+
11
+ def aws_object
12
+ begin
13
+ cert = driver.iam.server_certificates[name]
14
+ # this will trigger a AWS::IAM::Errors::NoSuchEntity if the cert does not exist
15
+ cert.arn
16
+ cert
17
+ rescue AWS::IAM::Errors::NoSuchEntity
18
+ nil
19
+ end
20
+ end
21
+ end
@@ -14,6 +14,8 @@ require 'chef/provisioning/aws_driver/aws_resource_with_entry'
14
14
  # - http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/Subnet.html
15
15
  #
16
16
  class Chef::Resource::AwsSubnet < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
17
+ include Chef::Provisioning::AWSDriver::AWSTaggable
18
+
17
19
  aws_sdk_type AWS::EC2::Subnet
18
20
 
19
21
  require 'chef/resource/aws_vpc'
@@ -26,7 +26,10 @@ require 'chef/provisioning/aws_driver/aws_resource_with_entry'
26
26
  # - http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/VPC.html
27
27
  #
28
28
  class Chef::Resource::AwsVpc < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
29
- aws_sdk_type AWS::EC2::VPC
29
+ include Chef::Provisioning::AWSDriver::AWSTaggable
30
+ aws_sdk_type AWS::EC2::VPC,
31
+ id: :id,
32
+ option_names: [:vpc, :vpc_id, :peer_vpc_id]
30
33
 
31
34
  require 'chef/resource/aws_dhcp_options'
32
35
  require 'chef/resource/aws_route_table'
@@ -0,0 +1,73 @@
1
+ require 'chef/provisioning/aws_driver/aws_resource_with_entry'
2
+
3
+ #
4
+ # An AWS peering connection, specifying which VPC to peer.
5
+ #
6
+ # `name` is not guaranteed unique for an AWS account; therefore, Chef will
7
+ # store the vpc peering connection ID associated with this name in your Chef server in the
8
+ # data bag `data/aws_vpc_peering_connection/<name>`.
9
+ #
10
+ # API documentation for the AWS Ruby SDK for VPC Peering Connections can be found here:
11
+ #
12
+ # - http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Types/VpcPeeringConnectionVpcInfo.html
13
+ #
14
+ class Chef::Resource::AwsVpcPeeringConnection < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
15
+ aws_sdk_type ::Aws::EC2::VpcPeeringConnection
16
+ actions :accept, :create, :destroy, :purge, :nothing
17
+
18
+ require 'chef/resource/aws_vpc'
19
+
20
+ #
21
+ # The name of this peering connection.
22
+ #
23
+ attribute :name, kind_of: String, name_attribute: true
24
+
25
+ #
26
+ # The Local VPC to peer
27
+ #
28
+ # May be one of:
29
+ # - The name of an `aws_vpc` Chef resource.
30
+ # - An actual `aws_vpc` resource.
31
+ # - An AWS `VPC` object.
32
+ #
33
+ # This is required for new peering connections.
34
+ #
35
+ attribute :vpc, kind_of: [ String, AwsVpc, AWS::EC2::VPC ]
36
+
37
+ #
38
+ # The VPC to peer
39
+ #
40
+ # May be one of:
41
+ # - The name of an `aws_vpc` Chef resource.
42
+ # - An actual `aws_vpc` resource.
43
+ # - An AWS `VPC` object.
44
+ # - The id of an AWS `VPC`.
45
+ #
46
+ # This is required for new peering connections.
47
+ #
48
+ attribute :peer_vpc, kind_of: [ String, AwsVpc, AWS::EC2::VPC ]
49
+
50
+ #
51
+ # The target VPC account id to peer
52
+ #
53
+ # If not specified, will be assumed that the target VPC belongs to the current account.
54
+ #
55
+ attribute :peer_owner_id, kind_of: String
56
+
57
+ attribute :vpc_peering_connection_id, kind_of: String, aws_id_attribute: true, lazy_default: proc {
58
+ name =~ /^pcx-[a-f0-9]{8}$/ ? name : nil
59
+ }
60
+
61
+ def aws_object
62
+ driver, id = get_driver_and_id
63
+ result = driver.ec2_resource.vpc_peering_connection(id) if id
64
+
65
+ begin
66
+ # try accessing it to find out if it exists
67
+ result.requester_vpc if result
68
+ rescue ::Aws::EC2::Errors::InvalidVpcPeeringConnectionIDNotFound
69
+ result = nil
70
+ end
71
+ result
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "name": "ettores-mbp.lan"
3
+ }
data/spec/aws_support.rb CHANGED
@@ -23,7 +23,7 @@ module AWSSupport
23
23
  require 'aws'
24
24
  require 'aws_support/deep_matcher/matchable_object'
25
25
  require 'aws_support/deep_matcher/matchable_array'
26
- DeepMatcher::MatchableObject.matchable_classes << proc { |o| o.class.name =~ /^AWS::(EC2|ELB)($|::)/ }
26
+ DeepMatcher::MatchableObject.matchable_classes << proc { |o| o.class.name =~ /^(AWS|Aws)::(EC2|ELB|IAM|S3|RDS|CloudSearch)($|::)/ }
27
27
  DeepMatcher::MatchableArray.matchable_classes << AWS::Core::Data::List
28
28
 
29
29
  def purge_all
@@ -66,6 +66,12 @@ module AWSSupport
66
66
  end.converge
67
67
  end
68
68
 
69
+ aws_security_group 'test_security_group' do
70
+ vpc 'test_vpc'
71
+ inbound_rules '0.0.0.0/0' => [ 22, 80 ]
72
+ outbound_rules [ 22, 80 ] => '0.0.0.0/0'
73
+ end
74
+
69
75
  aws_subnet 'test_public_subnet' do
70
76
  vpc 'test_vpc'
71
77
  map_public_ip_on_launch true
@@ -118,8 +124,11 @@ module AWSSupport
118
124
  # Destroys it after the last example in the context runs. Objects created
119
125
  # in the order declared, and destroyed in reverse order.
120
126
  #
121
- Chef::Provisioning::AWSDriver::Resources.constants.each do |resource_class|
122
- resource_class = Chef::Provisioning::AWSDriver::Resources.const_get(resource_class)
127
+ aws_resources = Chef::Provisioning::AWSDriver::Resources.constants
128
+ aws_resources.map! {|r| Chef::Provisioning::AWSDriver::Resources.const_get(r) }
129
+
130
+ aws_resources += [Chef::Resource::Machine, Chef::Resource::MachineImage, Chef::Resource::MachineBatch, Chef::Resource::LoadBalancer]
131
+ aws_resources.each do |resource_class|
123
132
  resource_name = resource_class.resource_name
124
133
  # def aws_vpc(name, &block)
125
134
  define_method(resource_name) do |name, &block|
@@ -168,11 +177,19 @@ module AWSSupport
168
177
 
169
178
  # Destroy any objects we know got created during the test
170
179
  created_during_test.reverse_each do |resource_name, name|
171
- (recipe do
172
- public_send(resource_name, name) do
173
- action :purge
174
- end
175
- end).converge
180
+ begin
181
+ (recipe do
182
+ public_send(resource_name, name) do
183
+ action :purge
184
+ end
185
+ end).converge
186
+ rescue ::Chef::Exceptions::ValidationFailed
187
+ (recipe do
188
+ public_send(resource_name, name) do
189
+ action :destroy
190
+ end
191
+ end).converge
192
+ end
176
193
  end
177
194
  end
178
195
  end
@@ -33,7 +33,11 @@ module AWSSupport
33
33
  name = self.name
34
34
  example.recipe do
35
35
  public_send(resource_type, name) do
36
- action :purge
36
+ if allowed_actions.include?(:purge)
37
+ action :purge
38
+ else
39
+ action :destroy
40
+ end
37
41
  end
38
42
  end.converge
39
43
  end
@@ -2,6 +2,7 @@ module AWSSupport
2
2
  module DeepMatcher
3
3
  module MatchValuesFailureMessages
4
4
 
5
+ require 'set'
5
6
  require 'rspec/matchers'
6
7
  require 'rspec/matchers/composable'
7
8
  require 'aws_support/deep_matcher'
@@ -19,6 +20,8 @@ module AWSSupport
19
20
  else
20
21
  return []
21
22
  end
23
+ elsif Set === expected
24
+ return match_sets_failure_messages(expected, actual, identifier)
22
25
  elsif Hash === expected
23
26
  return match_hashes_failure_messages(expected, actual, identifier) if Hash === actual
24
27
  return match_hash_and_object_failure_messages(expected, actual, identifier) if MatchableObject === actual
@@ -35,6 +38,19 @@ module AWSSupport
35
38
  end
36
39
  end
37
40
 
41
+ def match_sets_failure_messages(expected_set, actual_setlike, identifier)
42
+ result = []
43
+ if ! actual_setlike.respond_to?(:to_set)
44
+ result << "expected #{identifier || "setlike"} to be castable to a Set, but it isn't!"
45
+ else
46
+ if ! actual_setlike.to_set == expected_set
47
+
48
+ result << "expected #{identifier || "setlike"} to #{description_of(expected_value)}"
49
+ end
50
+ end
51
+ result
52
+ end
53
+
38
54
  def match_hashes_failure_messages(expected_hash, actual_hash, identifier)
39
55
  result = []
40
56
 
@@ -62,6 +78,9 @@ module AWSSupport
62
78
  different = false
63
79
 
64
80
  expected_list = expected_list.map { |v| ExpectedValue.new(v) }
81
+ unless actual_list.class <= Array
82
+ actual_list = actual_list.to_a
83
+ end
65
84
  Diff::LCS.sdiff(expected_list, actual_list) do |change|
66
85
  case change.action
67
86
  when '='
@@ -32,7 +32,7 @@ module AWSSupport
32
32
 
33
33
  # Converge
34
34
  begin
35
- recipe.converge
35
+ recipe.converge unless recipe.converged?
36
36
  rescue
37
37
  differences += [ "error trying to create #{resource_name}[#{name}]!\n#{($!.backtrace.map { |line| "- #{line}\n" } + [ recipe.output_for_failure_message ]).join("")}" ]
38
38
  end
@@ -38,7 +38,7 @@ module AWSSupport
38
38
 
39
39
  # Converge
40
40
  begin
41
- recipe.converge
41
+ recipe.converge unless recipe.converged?
42
42
  rescue
43
43
  differences += [ "error trying to delete #{resource_name}[#{name}]!\n#{($!.backtrace.map { |line| "- #{line}\n" } + [ recipe.output_for_failure_message ]).join("")}" ]
44
44
  end
@@ -34,9 +34,9 @@ module AWSSupport
34
34
 
35
35
  # Check existence
36
36
  if @aws_object.nil?
37
- differences << "#{resource_name}[#{name}] did not exist!"
37
+ differences << "#{resource.to_s} did not exist!"
38
38
  else
39
- differences += match_hashes_failure_messages(expected_tags, aws_object_tags, "#{resource_name}[#{name}]")
39
+ differences += match_hashes_failure_messages(expected_tags, aws_object_tags(resource), resource.to_s)
40
40
  end
41
41
 
42
42
  differences
@@ -44,20 +44,14 @@ module AWSSupport
44
44
 
45
45
  private
46
46
 
47
- def aws_object_tags
48
- if @aws_object.is_a? AWS::ELB::LoadBalancer
49
- resp = @example.driver.elb.client.describe_tags load_balancer_names: [@aws_object.name]
50
- tags = {}
51
- resp.data[:tag_descriptions] && resp.data[:tag_descriptions].each do |td|
52
- td[:tags].each do |t|
53
- tags[t[:key]] = t[:value]
54
- end
55
- end
56
- tags
57
- else
58
- @aws_object.tags.to_h
59
- end
47
+ def aws_object_tags(resource)
48
+ # Okay, its annoying to have to lookup the provider for a resource and duplicate a bunch of code here.
49
+ # But I don't want to move the `converge_tags` method into the resource and until the resource & provider
50
+ # are combined, this is my best idea.
51
+ provider = resource.provider_for_action(:create)
52
+ provider.aws_tagger.current_tags
60
53
  end
54
+
61
55
  end
62
56
  end
63
57
  end
@@ -33,7 +33,7 @@ module AWSSupport
33
33
 
34
34
  # Converge
35
35
  begin
36
- recipe.converge
36
+ recipe.converge unless recipe.converged?
37
37
  rescue
38
38
  differences += [ "error trying to converge #{resource_name}[#{name}]!\n#{($!.backtrace.map { |line| "- #{line}\n" } + [ recipe.output_for_failure_message ]).join("")}" ]
39
39
  end
@@ -42,7 +42,7 @@ module AWSSupport
42
42
 
43
43
  # Converge
44
44
  begin
45
- recipe.converge
45
+ recipe.converge unless recipe.converged?
46
46
  rescue
47
47
  differences += [ "error trying to update #{resource_name}[#{name}]!\n#{($!.backtrace.map { |line| "- #{line}\n" } + [ recipe.output_for_failure_message ]).join("")}" ]
48
48
  end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chef::Resource::AwsCloudsearchDomain do
4
+ extend AWSSupport
5
+ when_the_chef_12_server "exists", organization: "foo", server_scope: :context do
6
+ with_aws "when connected to AWS" do
7
+
8
+ # Cloudsearch can take forevvvver to delete so we need to randomize our names
9
+ time = DateTime.now.strftime('%Q')
10
+
11
+ it "aws_cloudsearch_domain 'test-#{time}' creates a cloudsearch domain" do
12
+ expect_recipe {
13
+ aws_cloudsearch_domain "test-#{time}" do
14
+ multi_az false
15
+ end
16
+ }.to create_an_aws_cloudsearch_domain("test-#{time}", {}).and be_idempotent
17
+ end
18
+
19
+ it "returns nil when aws_object is called for something that does not exist" do
20
+ r = nil
21
+ converge {
22
+ r = aws_cloudsearch_domain "wont-exist" do
23
+ action :nothing
24
+ end
25
+ }
26
+ expect(r.aws_object).to eq(nil)
27
+ end
28
+
29
+ end
30
+ end
31
+ end