chef-provisioning-aws 1.3.1 → 1.4.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.
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
@@ -1,7 +1,10 @@
1
1
  require 'chef/provisioning/aws_driver/aws_provider'
2
- require 'retryable'
3
2
 
4
3
  class Chef::Provider::AwsDhcpOptions < Chef::Provisioning::AWSDriver::AWSProvider
4
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
5
+
6
+ provides :aws_dhcp_options
7
+
5
8
  protected
6
9
 
7
10
  def create_aws_object
@@ -10,7 +13,7 @@ class Chef::Provider::AwsDhcpOptions < Chef::Provisioning::AWSDriver::AWSProvide
10
13
  options[:domain_name_servers] = "AmazonProvidedDNS"
11
14
  end
12
15
 
13
- converge_by "create new dhcp_options #{new_resource.name} in #{region}" do
16
+ converge_by "create DHCP options #{new_resource.name} in #{region}" do
14
17
  dhcp_options = new_resource.driver.ec2.dhcp_options.create(options)
15
18
  retry_with_backoff(AWS::EC2::Errors::InvalidDhcpOptionsID::NotFound) do
16
19
  dhcp_options.tags['Name'] = new_resource.name
@@ -35,17 +38,17 @@ class Chef::Provider::AwsDhcpOptions < Chef::Provisioning::AWSDriver::AWSProvide
35
38
  if action_handler.should_perform_actions
36
39
  dhcp_options = AWS.ec2(config: dhcp_options.config).dhcp_options.create(config.merge(desired_options))
37
40
  end
38
- action_handler.report_progress "create new dhcp_options #{dhcp_options.id} with new attributes in #{region}"
41
+ action_handler.report_progress "create DHCP options #{dhcp_options.id} with new attributes in #{region}"
39
42
 
40
43
  # attach dhcp_options to existing vpcs
41
44
  old_dhcp_options.vpcs.each do |vpc|
42
- action_handler.perform_action "attach new dhcp_options #{dhcp_options.id} to vpc #{vpc.id}" do
45
+ action_handler.perform_action "attach DHCP options #{dhcp_options.id} to vpc #{vpc.id}" do
43
46
  vpc.dhcp_options = dhcp_options
44
47
  end
45
48
  end
46
49
 
47
50
  # delete old dhcp_options
48
- action_handler.perform_action "delete old dhcp_options #{old_dhcp_options.id}" do
51
+ action_handler.perform_action "delete DHCP options #{old_dhcp_options.id}" do
49
52
  old_dhcp_options.delete
50
53
  end
51
54
 
@@ -54,7 +57,7 @@ class Chef::Provider::AwsDhcpOptions < Chef::Provisioning::AWSDriver::AWSProvide
54
57
  end
55
58
 
56
59
  def destroy_aws_object(dhcp_options)
57
- converge_by "delete dhcp_options #{new_resource.name} in #{region}" do
60
+ converge_by "delete DHCP options #{new_resource.name} in #{region}" do
58
61
  dhcp_options.delete
59
62
  end
60
63
  end
@@ -4,6 +4,10 @@ require 'date'
4
4
  require 'retryable'
5
5
 
6
6
  class Chef::Provider::AwsEbsVolume < Chef::Provisioning::AWSDriver::AWSProvider
7
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
8
+
9
+ provides :aws_ebs_volume
10
+
7
11
  class VolumeNotFoundError < RuntimeError
8
12
  def initialize(new_resource)
9
13
  super("#{new_resource} does not exist!")
@@ -34,7 +38,7 @@ class Chef::Provider::AwsEbsVolume < Chef::Provisioning::AWSDriver::AWSProvider
34
38
 
35
39
  def create_aws_object
36
40
  volume = nil
37
- converge_by "create new #{new_resource} in #{region}" do
41
+ converge_by "create #{new_resource} in #{region}" do
38
42
  volume = new_resource.driver.ec2.volumes.create(initial_options)
39
43
  retry_with_backoff(AWS::EC2::Errors::InvalidVolumeID::NotFound) do
40
44
  volume.tags['Name'] = new_resource.name
@@ -119,12 +123,12 @@ class Chef::Provider::AwsEbsVolume < Chef::Provisioning::AWSDriver::AWSProvider
119
123
  #
120
124
  # If we were told to attach the volume to a machine, do so
121
125
  #
122
- if expected_instance.is_a?(AWS::EC2::Instance)
126
+ if expected_instance.is_a?(AWS::EC2::Instance) || expected_instance.is_a?(::Aws::EC2::Instance)
123
127
  case status
124
128
  when :in_use
125
129
  # We don't want to attempt to reattach to the same instance and device
126
130
  attachment = current_attachment(volume)
127
- if attachment.instance != expected_instance || attachment.device != new_resource.device
131
+ if attachment.instance.id != expected_instance.id || attachment.device != new_resource.device
128
132
  detach(volume)
129
133
  attach(volume)
130
134
  end
@@ -4,6 +4,7 @@ require 'chef/provisioning/machine_spec'
4
4
  require 'cheffish'
5
5
 
6
6
  class Chef::Provider::AwsEipAddress < Chef::Provisioning::AWSDriver::AWSProvider
7
+ provides :aws_eip_address
7
8
 
8
9
  def action_create
9
10
  elastic_ip = super
@@ -16,10 +17,10 @@ class Chef::Provider::AwsEipAddress < Chef::Provisioning::AWSDriver::AWSProvider
16
17
  protected
17
18
 
18
19
  def create_aws_object
19
- converge_by "create new EIP address in #{region}" do
20
+ converge_by "create Elastic IP address in #{region}" do
20
21
  associate_to_vpc = new_resource.associate_to_vpc
21
22
  if associate_to_vpc.nil?
22
- if desired_instance.is_a?(AWS::EC2::Instance)
23
+ if desired_instance.is_a?(AWS::EC2::Instance) || desired_instance.is_a?(::Aws::EC2::Instance)
23
24
  associate_to_vpc = !!desired_instance.vpc_id
24
25
  Chef::Log.debug "Since associate_to_vpc is not specified and instance #{new_resource.machine} (#{desired_instance.id}) and #{associate_to_vpc ? "is" : "is not"} in a VPC, setting associate_to_vpc to #{associate_to_vpc}."
25
26
  end
@@ -39,11 +40,11 @@ class Chef::Provider::AwsEipAddress < Chef::Provisioning::AWSDriver::AWSProvider
39
40
  def destroy_aws_object(elastic_ip)
40
41
  #if it's attached to something in a vpc, disassociate first
41
42
  if elastic_ip.instance_id != nil && elastic_ip.domain == 'vpc'
42
- converge_by "dissociate Elastic IP Address #{new_resource.name} (#{elastic_ip.public_ip}) from #{elastic_ip.instance_id}" do
43
+ converge_by "dissociate Elastic IP address #{new_resource.name} (#{elastic_ip.public_ip}) from #{elastic_ip.instance_id}" do
43
44
  elastic_ip.disassociate
44
45
  end
45
46
  end
46
- converge_by "delete Elastic IP Address #{new_resource.name} (#{elastic_ip.public_ip}) in #{region}" do
47
+ converge_by "delete Elastic IP address #{new_resource.name} (#{elastic_ip.public_ip}) in #{region}" do
47
48
  elastic_ip.delete
48
49
  end
49
50
  end
@@ -65,9 +66,9 @@ class Chef::Provider::AwsEipAddress < Chef::Provisioning::AWSDriver::AWSProvider
65
66
  #
66
67
  # If we were told to associate the IP to a machine, do so
67
68
  #
68
- if desired_instance.is_a?(AWS::EC2::Instance)
69
+ if desired_instance.is_a?(AWS::EC2::Instance) || desired_instance.is_a?(::Aws::EC2::Instance)
69
70
  if desired_instance.id != elastic_ip.instance_id
70
- converge_by "associate Elastic IP Address #{new_resource.name} (#{elastic_ip.public_ip}) with #{new_resource.machine} (#{desired_instance.id})" do
71
+ converge_by "associate Elastic IP address #{new_resource.name} (#{elastic_ip.public_ip}) with #{new_resource.machine} (#{desired_instance.id})" do
71
72
  elastic_ip.associate instance: desired_instance.id
72
73
  end
73
74
  end
@@ -77,7 +78,7 @@ class Chef::Provider::AwsEipAddress < Chef::Provisioning::AWSDriver::AWSProvider
77
78
  #
78
79
  else
79
80
  if elastic_ip.associated?
80
- converge_by "disassociate Elastic IP Address #{new_resource.name} (#{elastic_ip.public_ip}) from #{elastic_ip.instance_id} in #{region}" do
81
+ converge_by "disassociate Elastic IP address #{new_resource.name} (#{elastic_ip.public_ip}) from #{elastic_ip.instance_id} in #{region}" do
81
82
  aws_object.disassociate
82
83
  end
83
84
  end
@@ -1,13 +1,18 @@
1
1
  require 'chef/provisioning/aws_driver/aws_provider'
2
+ require 'chef/provisioning/aws_driver/tagging_strategy/ec2'
2
3
 
3
4
  class Chef::Provider::AwsImage < Chef::Provisioning::AWSDriver::AWSProvider
5
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
6
+
7
+ provides :aws_image
8
+
4
9
  def destroy_aws_object(image)
5
- instance_id = image.tags['From-Instance']
6
- Chef::Log.debug("Found From-Instance tag [#{instance_id}] on #{image.id}")
10
+ instance_id = image.tags['from-instance']
11
+ Chef::Log.debug("Found from-instance tag [#{instance_id}] on #{image.id}")
7
12
  unless instance_id
8
13
  # This is an old image and doesn't have the tag added - lets try and find it from the block device mapping
9
14
  image.block_device_mappings.map do |dev, opts|
10
- snapshot = ec2.snapshots[opts[:snapshot_id]]
15
+ snapshot = new_resource.driver.ec2.snapshots[opts[:snapshot_id]]
11
16
  desc = snapshot.description
12
17
  m = /CreateImage\(([^\)]+)\)/.match(desc)
13
18
  if m
@@ -1,6 +1,11 @@
1
1
  require 'chef/provisioning/aws_driver/aws_provider'
2
+ require 'chef/provisioning/aws_driver/tagging_strategy/ec2'
2
3
 
3
4
  class Chef::Provider::AwsInstance < Chef::Provisioning::AWSDriver::AWSProvider
5
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
6
+
7
+ provides :aws_instance
8
+
4
9
  def create_aws_object(instance); end
5
10
 
6
11
  def update_aws_object(instance); end
@@ -10,12 +15,19 @@ class Chef::Provider::AwsInstance < Chef::Provisioning::AWSDriver::AWSProvider
10
15
  message += " in VPC #{instance.vpc.id}" unless instance.vpc.nil?
11
16
  message += " in #{region}"
12
17
  converge_by message do
13
- instance.delete
18
+ instance.terminate
14
19
  end
15
20
  converge_by "waited until instance #{new_resource} is :terminated" do
16
21
  # When purging, we must wait until the instance is fully terminated - thats the only way
17
22
  # to delete the network interface that I can see
18
- wait_for_status(instance, :terminated, [AWS::EC2::Errors::InvalidInstanceID::NotFound])
23
+ instance.wait_until_terminated do |w|
24
+ # TODO look at `wait_for_status` - delay and max_attempts should be configurable
25
+ w.delay = 5
26
+ w.max_attempts = 60
27
+ w.before_wait do |attempts, response|
28
+ action_handler.report_progress "waited #{(attempts-1)*5}/#{60*5}s for #{instance.id} status to terminate..."
29
+ end
30
+ end
19
31
  end
20
32
  end
21
33
  end
@@ -4,7 +4,8 @@ require 'aws-sdk-v1'
4
4
 
5
5
 
6
6
  class Chef::Provider::AwsKeyPair < Chef::Provisioning::AWSDriver::AWSProvider
7
-
7
+ provides :aws_key_pair
8
+
8
9
  action :create do
9
10
  create_key(:create)
10
11
  end
@@ -2,6 +2,8 @@ require 'chef/provisioning/aws_driver/aws_provider'
2
2
  require 'chef/resource/aws_image'
3
3
 
4
4
  class Chef::Provider::AwsLaunchConfiguration < Chef::Provisioning::AWSDriver::AWSProvider
5
+ provides :aws_launch_configuration
6
+
5
7
  protected
6
8
 
7
9
  def create_aws_object
@@ -9,7 +11,7 @@ class Chef::Provider::AwsLaunchConfiguration < Chef::Provisioning::AWSDriver::AW
9
11
  instance_type = new_resource.instance_type || new_resource.driver.default_instance_type
10
12
  options = AWSResource.lookup_options(new_resource.options || options, resource: new_resource)
11
13
 
12
- converge_by "Creating new Launch Configuration #{new_resource.name} in #{region}" do
14
+ converge_by "create launch configuration #{new_resource.name} in #{region}" do
13
15
  new_resource.driver.auto_scaling.launch_configurations.create(
14
16
  new_resource.name,
15
17
  image,
@@ -35,7 +37,7 @@ class Chef::Provider::AwsLaunchConfiguration < Chef::Provisioning::AWSDriver::AW
35
37
  end
36
38
 
37
39
  def destroy_aws_object(launch_configuration)
38
- converge_by "delete Launch Configuration #{new_resource.name} in #{region}" do
40
+ converge_by "delete launch configuration #{new_resource.name} in #{region}" do
39
41
  # TODO add a timeout here.
40
42
  # TODO is InUse really a status guaranteed to go away??
41
43
  begin
@@ -1,6 +1,24 @@
1
1
  require 'chef/provisioning/aws_driver/aws_provider'
2
2
 
3
3
  class Chef::Provider::AwsLoadBalancer < Chef::Provisioning::AWSDriver::AWSProvider
4
+
5
+ def aws_tagger
6
+ @aws_tagger ||= begin
7
+ elb_strategy = Chef::Provisioning::AWSDriver::TaggingStrategy::ELB.new(
8
+ new_resource.driver.elb_client,
9
+ new_resource.name,
10
+ new_resource.aws_tags
11
+ )
12
+ Chef::Provisioning::AWSDriver::AWSTagger.new(elb_strategy, action_handler)
13
+ end
14
+ end
15
+
16
+ def converge_tags
17
+ aws_tagger.converge_tags
18
+ end
19
+
20
+ provides :aws_load_balancer
21
+
4
22
  def destroy_aws_object(load_balancer)
5
23
  converge_by "delete load balancer #{new_resource.name} (#{load_balancer.name}) in #{region}" do
6
24
  load_balancer.delete
@@ -3,6 +3,10 @@ require 'chef/resource/aws_vpc'
3
3
  require 'retryable'
4
4
 
5
5
  class Chef::Provider::AwsNetworkAcl < Chef::Provisioning::AWSDriver::AWSProvider
6
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
7
+
8
+ provides :aws_network_acl
9
+
6
10
  def action_create
7
11
  network_acl = super
8
12
 
@@ -12,7 +16,7 @@ class Chef::Provider::AwsNetworkAcl < Chef::Provisioning::AWSDriver::AWSProvider
12
16
  protected
13
17
 
14
18
  def create_aws_object
15
- converge_by "create new Network ACL #{new_resource.name} in #{region}" do
19
+ converge_by "create network ACL #{new_resource.name} in #{region}" do
16
20
  options = {}
17
21
  options[:vpc] = new_resource.vpc if new_resource.vpc
18
22
  options = AWSResource.lookup_options(options, resource: new_resource)
@@ -87,7 +91,7 @@ class Chef::Provider::AwsNetworkAcl < Chef::Provisioning::AWSDriver::AWSProvider
87
91
  end
88
92
 
89
93
  unless replace_rules.empty? && desired_rules.empty? && current_rules.empty?
90
- action_handler.report_progress "update Network ACL #{new_resource.name} #{direction.to_s} rules"
94
+ action_handler.report_progress "update network ACL #{new_resource.name} #{direction.to_s} rules"
91
95
  replace_rules(network_acl, replace_rules)
92
96
  add_rules(network_acl, desired_rules)
93
97
  remove_rules(network_acl, current_rules)
@@ -4,11 +4,9 @@ require 'date'
4
4
  require 'retryable'
5
5
 
6
6
  class Chef::Provider::AwsNetworkInterface < Chef::Provisioning::AWSDriver::AWSProvider
7
- class NetworkInterfaceStatusTimeoutError < TimeoutError
8
- def initialize(new_resource, initial_status, expected_status)
9
- super("timed out waiting for #{new_resource} status to change from #{initial_status} to #{expected_status}!")
10
- end
11
- end
7
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
8
+
9
+ provides :aws_network_interface
12
10
 
13
11
  class NetworkInterfaceStatusTimeoutError < TimeoutError
14
12
  def initialize(new_resource, initial_status, expected_status)
@@ -43,7 +41,7 @@ class Chef::Provider::AwsNetworkInterface < Chef::Provisioning::AWSDriver::AWSPr
43
41
  end
44
42
 
45
43
  converge_by "wait for new #{new_resource} in #{region} to become available" do
46
- wait_for_eni_status(eni, :available)
44
+ wait_for_status(eni, :available)
47
45
  eni
48
46
  end
49
47
  end
@@ -122,14 +120,14 @@ class Chef::Provider::AwsNetworkInterface < Chef::Provisioning::AWSDriver::AWSPr
122
120
  #
123
121
  # If we were told to attach the network interface to a machine, do so
124
122
  #
125
- if expected_instance.is_a?(AWS::EC2::Instance)
123
+ if expected_instance.is_a?(AWS::EC2::Instance) || expected_instance.is_a?(::Aws::EC2::Instance)
126
124
  case status
127
125
  when :available
128
126
  attach(eni)
129
127
  when :in_use
130
128
  # We don't want to attempt to reattach to the same instance or device index
131
129
  attachment = current_attachment(eni)
132
- if attachment.instance != expected_instance || (options[:device_index] && attachment.device_index != new_resource.device_index)
130
+ if attachment.instance.id != expected_instance.id || (options[:device_index] && attachment.device_index != new_resource.device_index)
133
131
  detach(eni)
134
132
  attach(eni)
135
133
  end
@@ -153,38 +151,27 @@ class Chef::Provider::AwsNetworkInterface < Chef::Provisioning::AWSDriver::AWSPr
153
151
  eni
154
152
  end
155
153
 
156
- def wait_for_eni_status(eni, expected_status)
157
- initial_status = eni.status
158
- log_callback = proc {
159
- Chef::Log.info("waiting for #{new_resource} status to change to #{expected_status}...")
160
- }
161
-
162
- Retryable.retryable(:tries => 30, :sleep => 2, :on => NetworkInterfaceStatusTimeoutError, :ensure => log_callback) do
163
- raise NetworkInterfaceStatusTimeoutError.new(new_resource, initial_status, expected_status) if eni.status != expected_status
164
- end
165
- end
166
-
167
154
  def detach(eni)
168
155
  attachment = current_attachment(eni)
169
156
  instance = attachment.instance
170
157
 
171
- converge_by "detach #{new_resource} from #{instance.instance_id}" do
158
+ converge_by "detach #{new_resource} from #{instance.id}" do
172
159
  eni.detach
173
160
  end
174
161
 
175
162
  converge_by "wait for #{new_resource} to detach" do
176
- wait_for_eni_status(eni, :available)
163
+ wait_for_status(eni, :available)
177
164
  eni
178
165
  end
179
166
  end
180
167
 
181
168
  def attach(eni)
182
- converge_by "attach #{new_resource} to #{new_resource.machine} (#{expected_instance.instance_id})" do
183
- eni.attach(expected_instance, options)
169
+ converge_by "attach #{new_resource} to #{new_resource.machine} (#{expected_instance.id})" do
170
+ eni.attach(expected_instance.id, options)
184
171
  end
185
172
 
186
173
  converge_by "wait for #{new_resource} to attach" do
187
- wait_for_eni_status(eni, :in_use)
174
+ wait_for_status(eni, :in_use)
188
175
  eni
189
176
  end
190
177
  end
@@ -0,0 +1,66 @@
1
+ require 'chef/provisioning/aws_driver/aws_provider'
2
+ require 'chef/provisioning/aws_driver/tagging_strategy/rds'
3
+
4
+ class Chef::Provider::AwsRdsInstance < Chef::Provisioning::AWSDriver::AWSProvider
5
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::RDSConvergeTags
6
+
7
+ provides :aws_rds_instance
8
+
9
+ REQUIRED_OPTIONS = %i(db_instance_identifier allocated_storage engine
10
+ db_instance_class master_username master_user_password)
11
+
12
+ OTHER_OPTIONS = %i(engine_version multi_az iops publicly_accessible db_name port db_subnet_group_name)
13
+
14
+ def update_aws_object(instance)
15
+ Chef::Log.warn("aws_rds_instance does not support modifying a started instance")
16
+ # There are required optiosn (like `allocated_storage`) that the use may not
17
+ # specify on a resource to perform an update. For example, they may want to
18
+ # only specify iops to modify that attribute on an update after initial
19
+ # creation. In this case we need to load the required options from the existing
20
+ # aws_object and only override it if the user has specified a value in the
21
+ # resource. Ideally, it would be nice to mark values as required on the
22
+ # resource but right now there is not a `required_on_create`. This would
23
+ # also be different if chef-provisioning performed resource cloning, which
24
+ # it does not.
25
+ end
26
+
27
+ def create_aws_object
28
+ converge_by "create RDS instance #{new_resource.db_instance_identifier} in #{region}" do
29
+ new_resource.driver.rds.client.create_db_instance(options_hash)
30
+ end
31
+ end
32
+
33
+ def destroy_aws_object(instance)
34
+ converge_by "delete RDS instance #{new_resource.db_instance_identifier} in #{region}" do
35
+ instance.delete(skip_final_snapshot: true)
36
+ end
37
+ # Wait up to 10 minutes for the db instance to shutdown
38
+ converge_by "waited until RDS instance #{new_resource.name} was deleted" do
39
+ wait_for(
40
+ aws_object: instance,
41
+ query_method: :exists?,
42
+ expected_responses: [false],
43
+ acceptable_errors: [AWS::RDS::Errors::DBInstanceNotFound],
44
+ tries: 60,
45
+ sleep: 10
46
+ )
47
+ end
48
+ end
49
+
50
+ # Sets the additional options then overrides it with all required options from
51
+ # the resource as well as optional options
52
+ def options_hash
53
+ @options_hash ||= begin
54
+ opts = Hash[new_resource.additional_options.map{|(k,v)| [k.to_sym,v]}]
55
+ REQUIRED_OPTIONS.each do |opt|
56
+ opts[opt] = new_resource.send(opt)
57
+ end
58
+ OTHER_OPTIONS.each do |opt|
59
+ opts[opt] = new_resource.send(opt) if ! new_resource.send(opt).nil?
60
+ end
61
+ AWSResource.lookup_options(opts, resource: new_resource)
62
+ opts
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,89 @@
1
+ require 'chef/provisioning/aws_driver/aws_provider'
2
+ require 'chef/provisioning/aws_driver/tagging_strategy/rds'
3
+
4
+ class Chef::Provider::AwsRdsSubnetGroup < Chef::Provisioning::AWSDriver::AWSProvider
5
+ include Chef::Provisioning::AWSDriver::TaggingStrategy::RDSConvergeTags
6
+
7
+ provides :aws_rds_subnet_group
8
+
9
+ def create_aws_object
10
+ converge_by "create RDS subnet group #{new_resource.name} in #{region}" do
11
+ driver.create_db_subnet_group(desired_options)
12
+ end
13
+ end
14
+
15
+ def destroy_aws_object(object)
16
+ converge_by "delete RDS subnet group #{new_resource.name} in #{region}" do
17
+ driver.delete_db_subnet_group(db_subnet_group_name: new_resource.name)
18
+ end
19
+ end
20
+
21
+ def update_aws_object(object)
22
+ updates = required_updates(object)
23
+ if ! updates.empty?
24
+ converge_by updates do
25
+ driver.modify_db_subnet_group(desired_options)
26
+ end
27
+ end
28
+ end
29
+
30
+ def desired_options
31
+ @desired_options ||= begin
32
+ opts = {}
33
+ opts[:db_subnet_group_name] = new_resource.name
34
+ opts[:db_subnet_group_description] = new_resource.description
35
+ opts[:subnet_ids] = new_resource.subnets
36
+ AWSResource.lookup_options(opts, resource: new_resource)
37
+ end
38
+ end
39
+
40
+ # Given an existing object, return an array of update descriptions
41
+ # representing the updates that need to be made.
42
+ #
43
+ # If no updates are needed, an empty array is returned.
44
+ #
45
+ def required_updates(object)
46
+ ret = []
47
+ if desired_options[:db_subnet_group_description] != object[:db_subnet_group_description]
48
+ ret << " set group description to #{desired_options[:db_subnet_group_description]}"
49
+ end
50
+
51
+ if ! xor_array(desired_options[:subnet_ids], subnet_ids(object[:subnets])).empty?
52
+ ret << " set subnets to #{desired_options[:subnet_ids]}"
53
+ end
54
+
55
+ if ! (desired_options[:aws_tags].nil? || desired_options[:aws_tags].empty?)
56
+ # modify_db_subnet_group doesn't support the tags key according to
57
+ # http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/RDS/Client.html#modify_db_subnet_group-instance_method
58
+ Chef::Log.warn "Updating tags for RDS subnet groups is not supported."
59
+ end
60
+
61
+ ret.unshift("update RDS subnet group #{new_resource.name} in #{region}") unless ret.empty?
62
+ ret
63
+ end
64
+
65
+
66
+ private
67
+
68
+ def subnet_ids(subnets)
69
+ subnets.map {|i| i[:subnet_identifier] }
70
+ end
71
+
72
+ def xor_array(a, b)
73
+ (a | b) - (a & b)
74
+ end
75
+
76
+ # To be in line with the other resources. The aws_tags property
77
+ # takes a hash. But we actually need an array.
78
+ def tag_hash_to_array(tag_hash)
79
+ ret = []
80
+ tag_hash.each do |key, value|
81
+ ret << {:key => key, :value => value}
82
+ end
83
+ ret
84
+ end
85
+
86
+ def driver
87
+ new_resource.driver.rds.client
88
+ end
89
+ end