chef-provisioning-aws 1.9.0 → 1.10.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 +6 -4
- data/lib/chef/provider/aws_auto_scaling_group.rb +15 -1
- data/lib/chef/provider/aws_cloudwatch_alarm.rb +84 -0
- data/lib/chef/provider/aws_ebs_volume.rb +1 -1
- data/lib/chef/provider/aws_image.rb +13 -5
- data/lib/chef/provider/aws_launch_configuration.rb +4 -4
- data/lib/chef/provider/aws_nat_gateway.rb +57 -0
- data/lib/chef/provider/aws_network_interface.rb +1 -1
- data/lib/chef/provider/aws_route_table.rb +7 -3
- data/lib/chef/provider/aws_vpc.rb +20 -0
- data/lib/chef/provisioning/aws_driver.rb +2 -0
- data/lib/chef/provisioning/aws_driver/aws_provider.rb +1 -1
- data/lib/chef/provisioning/aws_driver/driver.rb +10 -5
- data/lib/chef/provisioning/aws_driver/tagging_strategy/auto_scaling.rb +76 -0
- data/lib/chef/provisioning/aws_driver/version.rb +1 -1
- data/lib/chef/resource/aws_auto_scaling_group.rb +12 -8
- data/lib/chef/resource/aws_cloudwatch_alarm.rb +35 -0
- data/lib/chef/resource/aws_image.rb +4 -4
- data/lib/chef/resource/aws_launch_configuration.rb +1 -1
- data/lib/chef/resource/aws_nat_gateway.rb +98 -0
- data/lib/chef/resource/aws_route_table.rb +1 -0
- data/spec/aws_support.rb +1 -1
- data/spec/integration/aws_auto_scaling_group_spec.rb +118 -0
- data/spec/integration/aws_cloudwatch_alarm_spec.rb +286 -0
- data/spec/integration/aws_nat_gateway_spec.rb +52 -0
- data/spec/integration/aws_rds_instance_spec.rb +10 -10
- data/spec/integration/aws_route_table_spec.rb +22 -0
- data/spec/integration/aws_vpc_spec.rb +31 -3
- data/spec/spec_helper.rb +4 -2
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6942ab3aca17cfa681e5023c373ceca03447728
|
4
|
+
data.tar.gz: 937b97d44672eb3c4aa85e2730211b09f03d218e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a265b44bc28a8f62cc24c2d054cb4d1a9aec99b72c3a7f219f5e07498fb3e4923cdc3ffada912945df7968c5ba7f8a952de12255d764bd7da7abcda6d16467c
|
7
|
+
data.tar.gz: 7bb902bc96c98c8116f033416ad68823f93265396deb41c43ff8cdea6787e88f7bfe9207216c025d2e204d78d89e7c3db329575c145298035f1a6c3d637d055f
|
data/README.md
CHANGED
@@ -391,10 +391,12 @@ aws_subnet 'my_subnet' do
|
|
391
391
|
end
|
392
392
|
|
393
393
|
machine 'my_machine' do
|
394
|
-
machine_options
|
395
|
-
|
396
|
-
|
397
|
-
|
394
|
+
machine_options(
|
395
|
+
bootstrap_options: {
|
396
|
+
subnet_id: 'my_subnet',
|
397
|
+
security_group_ids: ['my_sg']
|
398
|
+
}
|
399
|
+
)
|
398
400
|
end
|
399
401
|
```
|
400
402
|
|
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'chef/provisioning/aws_driver/aws_provider'
|
2
2
|
require 'set'
|
3
|
+
require 'chef/provisioning/aws_driver/tagging_strategy/auto_scaling'
|
3
4
|
|
4
5
|
class Chef::Provider::AwsAutoScalingGroup < Chef::Provisioning::AWSDriver::AWSProvider
|
6
|
+
include Chef::Provisioning::AWSDriver::TaggingStrategy::AutoScalingConvergeTags
|
7
|
+
|
5
8
|
provides :aws_auto_scaling_group
|
6
9
|
|
7
10
|
protected
|
@@ -12,7 +15,18 @@ class Chef::Provider::AwsAutoScalingGroup < Chef::Provisioning::AWSDriver::AWSPr
|
|
12
15
|
options[:min_size] ||= 1
|
13
16
|
options[:max_size] ||= 1
|
14
17
|
|
15
|
-
new_resource.driver.auto_scaling.groups.create(
|
18
|
+
aws_obj = new_resource.driver.auto_scaling.groups.create(
|
19
|
+
new_resource.name, options)
|
20
|
+
|
21
|
+
new_resource.scaling_policies.each do |policy_name, policy|
|
22
|
+
aws_obj.scaling_policies.put(policy_name.to_s, policy)
|
23
|
+
end
|
24
|
+
|
25
|
+
new_resource.notification_configurations.each do |config|
|
26
|
+
aws_obj.notification_configurations.create(config)
|
27
|
+
end
|
28
|
+
|
29
|
+
aws_obj
|
16
30
|
end
|
17
31
|
end
|
18
32
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'chef/provisioning/aws_driver/aws_provider'
|
2
|
+
|
3
|
+
class Chef::Provider::AwsCloudwatchAlarm < Chef::Provisioning::AWSDriver::AWSProvider
|
4
|
+
provides :aws_cloudwatch_alarm
|
5
|
+
|
6
|
+
def create_aws_object
|
7
|
+
converge_by "creating cloudwatch alarm #{new_resource.name} in #{region}" do
|
8
|
+
new_resource.driver.cloudwatch_client.put_metric_alarm(desired_options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def update_aws_object(alarm)
|
13
|
+
if update_required?(alarm)
|
14
|
+
converge_by "updating cloudwatch alarm #{new_resource.name} in #{region}" do
|
15
|
+
new_resource.driver.cloudwatch_client.put_metric_alarm(desired_options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def destroy_aws_object(alarm)
|
21
|
+
converge_by "destroying cloudwatch alarm #{new_resource.name} in #{region}" do
|
22
|
+
alarm.delete
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def desired_options
|
27
|
+
@desired_options ||= begin
|
28
|
+
# Because an update is a PUT, we must ensure that any properties not specified
|
29
|
+
# on the resource that are already present on the object stay the same
|
30
|
+
aws_object = new_resource.aws_object
|
31
|
+
opts = {alarm_name: new_resource.name}
|
32
|
+
%i(namespace metric_name comparison_operator
|
33
|
+
evaluation_periods period statistic threshold
|
34
|
+
actions_enabled alarm_description unit).each do |opt|
|
35
|
+
if !new_resource.public_send(opt).nil?
|
36
|
+
opts[opt] = new_resource.public_send(opt)
|
37
|
+
elsif aws_object && !aws_object.public_send(opt).nil?
|
38
|
+
opts[opt] = aws_object.public_send(opt)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
if !new_resource.dimensions.nil?
|
42
|
+
opts[:dimensions] = new_resource.dimensions
|
43
|
+
elsif aws_object && !aws_object.dimensions.nil?
|
44
|
+
opts[:dimensions] = aws_object.dimensions.map! {|d| d.to_h}
|
45
|
+
end
|
46
|
+
# Normally we would just use `lookup_options` here but because these parameters
|
47
|
+
# don't necessarily sound like sns topics we manually do it
|
48
|
+
%i{insufficient_data_actions ok_actions alarm_actions}.each do |opt|
|
49
|
+
if !new_resource.public_send(opt).nil?
|
50
|
+
opts[opt] = new_resource.public_send(opt)
|
51
|
+
opts[opt].map! do |action|
|
52
|
+
if action.kind_of?(String) && !(action =~ /^arn:/)
|
53
|
+
aws_object = Chef::Resource::AwsSnsTopic.get_aws_object(action, resource: new_resource)
|
54
|
+
action = aws_object.arn if aws_object
|
55
|
+
end
|
56
|
+
action
|
57
|
+
end
|
58
|
+
elsif aws_object && !aws_object.public_send(opt).nil?
|
59
|
+
opts[opt] = aws_object.public_send(opt)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
opts
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_required?(alarm)
|
67
|
+
%i{namespace metric_name comparison_operator
|
68
|
+
evaluation_periods period statistic threshold
|
69
|
+
actions_enabled alarm_description unit}.each do |opt|
|
70
|
+
if alarm.public_send(opt) != desired_options[opt]
|
71
|
+
return true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
unless (Set.new(alarm.dimensions.map {|d| d.to_h}) ^ Set.new(desired_options[:dimensions])).empty?
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
%i(insufficient_data_actions ok_actions alarm_actions).each do |opt|
|
78
|
+
unless (Set.new(alarm.public_send(opt)) ^ Set.new(desired_options[opt])).empty?
|
79
|
+
return true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return false
|
83
|
+
end
|
84
|
+
end
|
@@ -14,7 +14,7 @@ class Chef::Provider::AwsEbsVolume < Chef::Provisioning::AWSDriver::AWSProvider
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
class VolumeStatusTimeoutError <
|
17
|
+
class VolumeStatusTimeoutError < ::Timeout::Error
|
18
18
|
def initialize(new_resource, initial_status, expected_status)
|
19
19
|
super("timed out waiting for #{new_resource} status to change from #{initial_status} to #{expected_status}!")
|
20
20
|
end
|
@@ -7,7 +7,7 @@ class Chef::Provider::AwsImage < Chef::Provisioning::AWSDriver::AWSProvider
|
|
7
7
|
provides :aws_image
|
8
8
|
|
9
9
|
def destroy_aws_object(image)
|
10
|
-
instance_id = image.tags['from-instance']
|
10
|
+
instance_id = image.tags.map {|t| [t.key, t.value] }.to_h['from-instance']
|
11
11
|
Chef::Log.debug("Found from-instance tag [#{instance_id}] on #{image.id}")
|
12
12
|
unless instance_id
|
13
13
|
# This is an old image and doesn't have the tag added - lets try and find it from the block device mapping
|
@@ -21,15 +21,23 @@ class Chef::Provider::AwsImage < Chef::Provisioning::AWSDriver::AWSProvider
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
converge_by "
|
25
|
-
image.
|
24
|
+
converge_by "deregister image #{new_resource} in #{region}" do
|
25
|
+
image.deregister
|
26
26
|
end
|
27
27
|
if instance_id
|
28
28
|
# As part of the image creation process, the source instance was automatically
|
29
29
|
# destroyed - we just need to make sure that has completed successfully
|
30
|
-
instance = new_resource.driver.
|
30
|
+
instance = new_resource.driver.ec2_resource.instance(instance_id)
|
31
31
|
converge_by "waiting until instance #{instance.id} is :terminated" do
|
32
|
-
|
32
|
+
if instance.exists?
|
33
|
+
instance.wait_until_terminated do |w|
|
34
|
+
w.delay = 5
|
35
|
+
w.max_attempts = 60
|
36
|
+
w.before_wait do |attempts, response|
|
37
|
+
action_handler.report_progress "waited #{(attempts-1)*5}/#{60*5}s for #{instance.id} status to terminate..."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
33
41
|
end
|
34
42
|
end
|
35
43
|
end
|
@@ -7,14 +7,14 @@ class Chef::Provider::AwsLaunchConfiguration < Chef::Provisioning::AWSDriver::AW
|
|
7
7
|
protected
|
8
8
|
|
9
9
|
def create_aws_object
|
10
|
-
|
10
|
+
image_id = Chef::Resource::AwsImage.get_aws_object_id(new_resource.image, resource: new_resource)
|
11
11
|
instance_type = new_resource.instance_type || new_resource.driver.default_instance_type
|
12
12
|
options = AWSResource.lookup_options(new_resource.options || options, resource: new_resource)
|
13
13
|
|
14
14
|
converge_by "create launch configuration #{new_resource.name} in #{region}" do
|
15
15
|
new_resource.driver.auto_scaling.launch_configurations.create(
|
16
16
|
new_resource.name,
|
17
|
-
|
17
|
+
image_id,
|
18
18
|
instance_type,
|
19
19
|
options
|
20
20
|
)
|
@@ -23,8 +23,8 @@ class Chef::Provider::AwsLaunchConfiguration < Chef::Provisioning::AWSDriver::AW
|
|
23
23
|
|
24
24
|
def update_aws_object(launch_configuration)
|
25
25
|
if new_resource.image
|
26
|
-
|
27
|
-
if
|
26
|
+
image_id = Chef::Resource::AwsImage.get_aws_object_id(new_resource.image, resource: new_resource)
|
27
|
+
if image_id != launch_configuration.image_id
|
28
28
|
raise "#{new_resource.to_s}.image = #{new_resource.image} (#{image.id}), but actual launch configuration has image set to #{launch_configuration.image_id}. Cannot be modified!"
|
29
29
|
end
|
30
30
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#require 'chef/provisioning/aws_driver/aws_provider'
|
2
|
+
require 'retryable'
|
3
|
+
|
4
|
+
class Chef::Provider::AwsNatGateway < Chef::Provisioning::AWSDriver::AWSProvider
|
5
|
+
|
6
|
+
provides :aws_nat_gateway
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def create_aws_object
|
11
|
+
if new_resource.subnet.nil?
|
12
|
+
raise "Nat Gateway create action for '#{new_resource.name}' requires the 'subnet' attribute."
|
13
|
+
end
|
14
|
+
subnet = Chef::Resource::AwsSubnet.get_aws_object(new_resource.subnet, resource: new_resource)
|
15
|
+
|
16
|
+
if new_resource.eip_address.nil?
|
17
|
+
# TODO Ideally it would be nice to automatically manage an eip address but
|
18
|
+
# the lack of tagging support and the limited SDK interaction with these two
|
19
|
+
# resources makes that too hard right now. So we force the user to manage their
|
20
|
+
# eip address as a seperate resource.
|
21
|
+
raise "Nat Gateway create action for '#{new_resource.name}' requires the 'eip_address' attribute."
|
22
|
+
end
|
23
|
+
eip_address = Chef::Resource::AwsEipAddress.get_aws_object(new_resource.eip_address, resource: new_resource)
|
24
|
+
|
25
|
+
converge_by "create nat gateway #{new_resource.name} in region #{region} for subnet #{subnet}" do
|
26
|
+
options = {
|
27
|
+
subnet_id: subnet.id,
|
28
|
+
allocation_id: eip_address.allocation_id
|
29
|
+
}
|
30
|
+
|
31
|
+
nat_gateway = new_resource.driver.ec2_resource.create_nat_gateway(options)
|
32
|
+
wait_for_state(nat_gateway, ['available'])
|
33
|
+
nat_gateway
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_aws_object(nat_gateway)
|
38
|
+
subnet_id = Chef::Resource::AwsSubnet.get_aws_object_id(new_resource.subnet, resource: new_resource) if new_resource.subnet
|
39
|
+
if subnet_id != nat_gateway.subnet_id
|
40
|
+
raise "Nat gateway subnet cannot be changed after being created! Desired subnet for #{new_resource.name} (#{nat_gateway.id}) was \"#{nat_gateway.subnet_id}\" and actual description is \"#{subnet_id}\""
|
41
|
+
end
|
42
|
+
|
43
|
+
if new_resource.eip_address
|
44
|
+
eip_address = Chef::Resource::AwsEipAddress.get_aws_object(new_resource.eip_address, resource: new_resource)
|
45
|
+
if eip_address.nil? or eip_address.allocation_id != nat_gateway.nat_gateway_addresses.first.allocation_id
|
46
|
+
raise "Nat gateway elastic ip address cannot be changed after being created! Desired elastic ip address for #{new_resource.name} (#{nat_gateway.id}) was \"#{nat_gateway.nat_gateway_addresses.first.allocation_id}\" and actual description is \"#{eip_address.allocation_id}\""
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def destroy_aws_object(nat_gateway)
|
52
|
+
converge_by "delete nat gateway #{new_resource.name} in region #{region} for subnet #{nat_gateway.subnet_id}" do
|
53
|
+
nat_gateway.delete
|
54
|
+
wait_for_state(nat_gateway, ['deleted'])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -8,7 +8,7 @@ class Chef::Provider::AwsNetworkInterface < Chef::Provisioning::AWSDriver::AWSPr
|
|
8
8
|
|
9
9
|
provides :aws_network_interface
|
10
10
|
|
11
|
-
class NetworkInterfaceStatusTimeoutError <
|
11
|
+
class NetworkInterfaceStatusTimeoutError < ::Timeout::Error
|
12
12
|
def initialize(new_resource, initial_status, expected_status)
|
13
13
|
super("timed out waiting for #{new_resource} status to change from #{initial_status} to #{expected_status}!")
|
14
14
|
end
|
@@ -72,7 +72,7 @@ class Chef::Provider::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSProvider
|
|
72
72
|
current_routes = {}
|
73
73
|
route_table.routes.each do |route|
|
74
74
|
# Ignore the automatic local route
|
75
|
-
route_target = route.gateway_id || route.instance_id || route.network_interface_id || route.vpc_peering_connection_id
|
75
|
+
route_target = route.gateway_id || route.nat_gateway_id || route.instance_id || route.network_interface_id || route.vpc_peering_connection_id
|
76
76
|
next if route_target == 'local'
|
77
77
|
next if ignore_route_targets.find { |target| route_target.match(/#{target}/) }
|
78
78
|
current_routes[route.destination_cidr_block] = route
|
@@ -85,7 +85,7 @@ class Chef::Provider::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSProvider
|
|
85
85
|
# If we already have a route to that CIDR block, replace it.
|
86
86
|
if current_routes[destination_cidr_block]
|
87
87
|
current_route = current_routes.delete(destination_cidr_block)
|
88
|
-
current_target = current_route.gateway_id || current_route.instance_id || current_route.network_interface_id || current_route.vpc_peering_connection_id
|
88
|
+
current_target = current_route.gateway_id || current_route.nat_gateway_id || current_route.instance_id || current_route.network_interface_id || current_route.vpc_peering_connection_id
|
89
89
|
if current_target != target
|
90
90
|
action_handler.perform_action "reroute #{destination_cidr_block} to #{route_target} (#{target}) instead of #{current_target}" do
|
91
91
|
current_route.replace(options)
|
@@ -100,7 +100,7 @@ class Chef::Provider::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSProvider
|
|
100
100
|
|
101
101
|
# Delete anything that's left (that wasn't replaced)
|
102
102
|
current_routes.values.each do |current_route|
|
103
|
-
current_target = current_route.gateway_id || current_route.instance_id || current_route.network_interface_id || current_route.vpc_peering_connection_id
|
103
|
+
current_target = current_route.gateway_id || current_route.nat_gateway_id || current_route.instance_id || current_route.network_interface_id || current_route.vpc_peering_connection_id
|
104
104
|
action_handler.perform_action "remove route sending #{current_route.destination_cidr_block} to #{current_target}" do
|
105
105
|
current_route.delete
|
106
106
|
end
|
@@ -140,6 +140,8 @@ class Chef::Provider::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSProvider
|
|
140
140
|
end
|
141
141
|
when /^igw-[A-Fa-f0-9]{8}$/, Chef::Resource::AwsInternetGateway, AWS::EC2::InternetGateway
|
142
142
|
route_target = { internet_gateway: route_target }
|
143
|
+
when /^nat-[A-Fa-f0-9]{17}$/, Chef::Resource::AwsNatGateway, Aws::EC2::NatGateway
|
144
|
+
route_target = { nat_gateway: route_target }
|
143
145
|
when /^eni-[A-Fa-f0-9]{8}$/, Chef::Resource::AwsNetworkInterface, AWS::EC2::NetworkInterface
|
144
146
|
route_target = { network_interface: route_target }
|
145
147
|
when /^pcx-[A-Fa-f0-9]{8}$/, Chef::Resource::AwsVpcPeeringConnection, ::Aws::EC2::VpcPeeringConnection
|
@@ -169,6 +171,8 @@ class Chef::Provider::AwsRouteTable < Chef::Provisioning::AWSDriver::AWSProvider
|
|
169
171
|
updated_route_target[:network_interface_id] = Chef::Resource::AwsNetworkInterface.get_aws_object_id(value, resource: new_resource)
|
170
172
|
when :internet_gateway
|
171
173
|
updated_route_target[:gateway_id] = Chef::Resource::AwsInternetGateway.get_aws_object_id(value, resource: new_resource)
|
174
|
+
when :nat_gateway
|
175
|
+
updated_route_target[:nat_gateway_id] = Chef::Resource::AwsNatGateway.get_aws_object_id(value, resource: new_resource)
|
172
176
|
when :vpc_peering_connection
|
173
177
|
updated_route_target[:vpc_peering_connection_id] = Chef::Resource::AwsVpcPeeringConnection.get_aws_object_id(value, resource: new_resource)
|
174
178
|
when :virtual_private_gateway
|
@@ -68,6 +68,26 @@ class Chef::Provider::AwsVpc < Chef::Provisioning::AWSDriver::AWSProvider
|
|
68
68
|
current_driver = self.new_resource.driver
|
69
69
|
current_chef_server = self.new_resource.chef_server
|
70
70
|
if purging
|
71
|
+
#SDK V2
|
72
|
+
nat_gateways = new_resource.driver.ec2_client.describe_nat_gateways({
|
73
|
+
:filter => [
|
74
|
+
{ name: 'vpc-id', values: [vpc.id] },
|
75
|
+
{ name: 'state', values: ['available', 'pending'] }
|
76
|
+
]
|
77
|
+
}).nat_gateways
|
78
|
+
|
79
|
+
nat_gateways.each do |nat_gw|
|
80
|
+
nat_gw_resource = new_resource.driver.ec2_resource.nat_gateway(nat_gw.nat_gateway_id)
|
81
|
+
Cheffish.inline_resource(self, action) do
|
82
|
+
aws_nat_gateway nat_gw_resource do
|
83
|
+
action :purge
|
84
|
+
driver current_driver
|
85
|
+
chef_server current_chef_server
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#SDK V1
|
71
91
|
vpc.subnets.each do |s|
|
72
92
|
Cheffish.inline_resource(self, action) do
|
73
93
|
aws_subnet s do
|
@@ -6,6 +6,7 @@ require "chef/resource/aws_cache_cluster"
|
|
6
6
|
require "chef/resource/aws_cache_replication_group"
|
7
7
|
require "chef/resource/aws_cache_subnet_group"
|
8
8
|
require "chef/resource/aws_cloudsearch_domain"
|
9
|
+
require "chef/resource/aws_cloudwatch_alarm"
|
9
10
|
require "chef/resource/aws_dhcp_options"
|
10
11
|
require "chef/resource/aws_ebs_volume"
|
11
12
|
require "chef/resource/aws_eip_address"
|
@@ -18,6 +19,7 @@ require "chef/resource/aws_internet_gateway"
|
|
18
19
|
require "chef/resource/aws_key_pair"
|
19
20
|
require "chef/resource/aws_launch_configuration"
|
20
21
|
require "chef/resource/aws_load_balancer"
|
22
|
+
require "chef/resource/aws_nat_gateway"
|
21
23
|
require "chef/resource/aws_network_acl"
|
22
24
|
require "chef/resource/aws_network_interface"
|
23
25
|
require "chef/resource/aws_rds_instance"
|
@@ -13,7 +13,7 @@ class AWSProvider < Chef::Provider::LWRPBase
|
|
13
13
|
|
14
14
|
AWSResource = Chef::Provisioning::AWSDriver::AWSResource
|
15
15
|
|
16
|
-
class StatusTimeoutError <
|
16
|
+
class StatusTimeoutError < ::Timeout::Error
|
17
17
|
def initialize(aws_object, initial_status, expected_status)
|
18
18
|
super("timed out waiting for #{aws_object.id} status to change from #{initial_status.inspect} to #{expected_status.inspect}!")
|
19
19
|
end
|
@@ -36,6 +36,8 @@ AWS_V2_SERVICES = {
|
|
36
36
|
"ElasticsearchService" => "elasticsearch",
|
37
37
|
"IAM" => "iam",
|
38
38
|
"RDS" => "rds",
|
39
|
+
"CloudWatch" => "cloudwatch",
|
40
|
+
"AutoScaling" => "auto_scaling"
|
39
41
|
}
|
40
42
|
Aws.eager_autoload!(:services => AWS_V2_SERVICES.keys)
|
41
43
|
|
@@ -536,16 +538,17 @@ module AWSDriver
|
|
536
538
|
image_options = (image_options || {}).to_h.dup
|
537
539
|
machine_options = (machine_options || {}).to_h.dup
|
538
540
|
aws_tags = image_options.delete(:aws_tags) || {}
|
539
|
-
if actual_image.nil? || !actual_image.exists? || actual_image.state == :failed
|
541
|
+
if actual_image.nil? || !actual_image.exists? || actual_image.state.to_sym == :failed
|
540
542
|
action_handler.perform_action "Create image #{image_spec.name} from machine #{machine_spec.name} with options #{image_options.inspect}" do
|
541
543
|
image_options[:name] ||= image_spec.name
|
542
544
|
image_options[:instance_id] ||= machine_spec.reference['instance_id']
|
543
545
|
image_options[:description] ||= "Image #{image_spec.name} created from machine #{machine_spec.name}"
|
544
546
|
Chef::Log.debug "AWS Image options: #{image_options.inspect}"
|
545
|
-
|
547
|
+
image_type = ec2_client.create_image(image_options.to_hash)
|
548
|
+
actual_image = ec2_resource.image(image_type.image_id)
|
546
549
|
image_spec.reference = {
|
547
550
|
'driver_version' => Chef::Provisioning::AWSDriver::VERSION,
|
548
|
-
'image_id' => actual_image.
|
551
|
+
'image_id' => actual_image.image_id,
|
549
552
|
'allocated_at' => Time.now.to_i,
|
550
553
|
'from-instance' => image_options[:instance_id]
|
551
554
|
}
|
@@ -565,7 +568,7 @@ module AWSDriver
|
|
565
568
|
aws_tags = image_options.delete(:aws_tags) || {}
|
566
569
|
aws_tags['from-instance'] = image_spec.reference['from-instance'] if image_spec.reference['from-instance']
|
567
570
|
converge_ec2_tags(actual_image, aws_tags, action_handler)
|
568
|
-
if actual_image.state != :available
|
571
|
+
if actual_image.state.to_sym != :available
|
569
572
|
action_handler.report_progress 'Waiting for image to be ready ...'
|
570
573
|
wait_until_ready_image(action_handler, image_spec, actual_image)
|
571
574
|
end
|
@@ -1242,7 +1245,7 @@ EOD
|
|
1242
1245
|
end
|
1243
1246
|
|
1244
1247
|
def wait_until_ready_image(action_handler, image_spec, image=nil)
|
1245
|
-
wait_until_image(action_handler, image_spec, image) { image.state == :available }
|
1248
|
+
wait_until_image(action_handler, image_spec, image) { |image| image.state.to_sym == :available }
|
1246
1249
|
action_handler.report_progress "Image #{image_spec.name} is now ready"
|
1247
1250
|
end
|
1248
1251
|
|
@@ -1259,6 +1262,8 @@ EOD
|
|
1259
1262
|
:matching => /did not become ready within/
|
1260
1263
|
) do |retries, exception|
|
1261
1264
|
action_handler.report_progress "been waiting #{retries*sleep_time}/#{max_wait_time} -- sleeping #{sleep_time} seconds for #{image_spec.name} (#{image.id} on #{driver_url}) to become ready ..."
|
1265
|
+
# We have to manually reload the instance each loop, otherwise data is stale
|
1266
|
+
image.reload
|
1262
1267
|
unless yield(image)
|
1263
1268
|
raise "Image #{image.id} did not become ready within #{max_wait_time} seconds"
|
1264
1269
|
end
|