chef-provisioning-aws 0.4.0 → 0.5.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/Rakefile +2 -0
- data/lib/chef/provider/aws_auto_scaling_group.rb +30 -41
- data/lib/chef/provider/aws_dhcp_options.rb +70 -0
- data/lib/chef/provider/aws_ebs_volume.rb +182 -34
- data/lib/chef/provider/aws_eip_address.rb +63 -60
- data/lib/chef/provider/aws_key_pair.rb +18 -27
- data/lib/chef/provider/aws_launch_configuration.rb +50 -0
- data/lib/chef/provider/aws_route_table.rb +122 -0
- data/lib/chef/provider/aws_s3_bucket.rb +42 -49
- data/lib/chef/provider/aws_security_group.rb +252 -59
- data/lib/chef/provider/aws_sns_topic.rb +10 -26
- data/lib/chef/provider/aws_sqs_queue.rb +16 -38
- data/lib/chef/provider/aws_subnet.rb +85 -32
- data/lib/chef/provider/aws_vpc.rb +163 -23
- data/lib/chef/provisioning/aws_driver.rb +18 -1
- data/lib/chef/provisioning/aws_driver/aws_provider.rb +206 -0
- data/lib/chef/provisioning/aws_driver/aws_resource.rb +186 -0
- data/lib/chef/provisioning/aws_driver/aws_resource_with_entry.rb +114 -0
- data/lib/chef/provisioning/aws_driver/driver.rb +317 -255
- data/lib/chef/provisioning/aws_driver/resources.rb +8 -5
- data/lib/chef/provisioning/aws_driver/super_lwrp.rb +45 -0
- data/lib/chef/provisioning/aws_driver/version.rb +1 -1
- data/lib/chef/resource/aws_auto_scaling_group.rb +15 -13
- data/lib/chef/resource/aws_dhcp_options.rb +57 -0
- data/lib/chef/resource/aws_ebs_volume.rb +20 -22
- data/lib/chef/resource/aws_eip_address.rb +50 -25
- data/lib/chef/resource/aws_image.rb +20 -0
- data/lib/chef/resource/aws_instance.rb +20 -0
- data/lib/chef/resource/aws_internet_gateway.rb +16 -0
- data/lib/chef/resource/aws_key_pair.rb +6 -10
- data/lib/chef/resource/aws_launch_configuration.rb +15 -0
- data/lib/chef/resource/aws_load_balancer.rb +16 -0
- data/lib/chef/resource/aws_network_interface.rb +16 -0
- data/lib/chef/resource/aws_route_table.rb +76 -0
- data/lib/chef/resource/aws_s3_bucket.rb +8 -18
- data/lib/chef/resource/aws_security_group.rb +49 -19
- data/lib/chef/resource/aws_sns_topic.rb +14 -15
- data/lib/chef/resource/aws_sqs_queue.rb +16 -14
- data/lib/chef/resource/aws_subnet.rb +87 -17
- data/lib/chef/resource/aws_vpc.rb +137 -15
- data/spec/integration/aws_security_group_spec.rb +55 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/support/aws_support.rb +211 -0
- metadata +33 -10
- data/lib/chef/provider/aws_launch_config.rb +0 -43
- data/lib/chef/provider/aws_provider.rb +0 -22
- data/lib/chef/provisioning/aws_driver/aws_profile.rb +0 -73
- data/lib/chef/resource/aws_launch_config.rb +0 -14
- data/lib/chef/resource/aws_resource.rb +0 -10
- data/spec/chef_zero_rspec_helper.rb +0 -8
- data/spec/unit/provider/aws_subnet_spec.rb +0 -67
- data/spec/unit/resource/aws_subnet_spec.rb +0 -23
@@ -1,3 +1,20 @@
|
|
1
1
|
require 'chef/provisioning'
|
2
2
|
require 'chef/provisioning/aws_driver/driver'
|
3
|
-
|
3
|
+
|
4
|
+
require "chef/resource/aws_auto_scaling_group"
|
5
|
+
require "chef/resource/aws_dhcp_options"
|
6
|
+
require "chef/resource/aws_ebs_volume"
|
7
|
+
require "chef/resource/aws_eip_address"
|
8
|
+
require "chef/resource/aws_image"
|
9
|
+
require "chef/resource/aws_instance"
|
10
|
+
require "chef/resource/aws_internet_gateway"
|
11
|
+
require "chef/resource/aws_launch_configuration"
|
12
|
+
require "chef/resource/aws_load_balancer"
|
13
|
+
require "chef/resource/aws_network_interface"
|
14
|
+
require "chef/resource/aws_route_table"
|
15
|
+
require "chef/resource/aws_s3_bucket"
|
16
|
+
require "chef/resource/aws_security_group"
|
17
|
+
require "chef/resource/aws_sns_topic"
|
18
|
+
require "chef/resource/aws_sqs_queue"
|
19
|
+
require "chef/resource/aws_subnet"
|
20
|
+
require "chef/resource/aws_vpc"
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'chef/provider/lwrp_base'
|
2
|
+
require 'chef/provisioning/aws_driver/aws_resource'
|
3
|
+
require 'chef/provisioning/aws_driver/aws_resource_with_entry'
|
4
|
+
require 'chef/provisioning/chef_managed_entry_store'
|
5
|
+
require 'chef/provisioning/chef_provider_action_handler'
|
6
|
+
|
7
|
+
module Chef::Provisioning::AWSDriver
|
8
|
+
class AWSProvider < Chef::Provider::LWRPBase
|
9
|
+
use_inline_resources
|
10
|
+
|
11
|
+
AWSResource = Chef::Provisioning::AWSDriver::AWSResource
|
12
|
+
|
13
|
+
def action_handler
|
14
|
+
@action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
# All these need to implement whyrun
|
18
|
+
def whyrun_supported?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def region
|
23
|
+
new_resource.driver.aws_config.region
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Return the damned value from the block, not whatever weirdness converge_by
|
28
|
+
# normally returns.
|
29
|
+
#
|
30
|
+
def converge_by(*args, &block)
|
31
|
+
result = nil
|
32
|
+
super(*args) do
|
33
|
+
result = block.call
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
action :create do
|
39
|
+
#
|
40
|
+
# If the user specified an ID, get the object for it, and fail if it does not exist.
|
41
|
+
#
|
42
|
+
desired_driver = new_resource.driver
|
43
|
+
desired_id = new_resource.public_send(new_resource.class.aws_id_attribute) if new_resource.class.aws_id_attribute
|
44
|
+
if desired_id
|
45
|
+
aws_object = new_resource.class.get_aws_object(desired_id, resource: new_resource)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# If Chef has already associated the object with an AWS ID, check if it's
|
50
|
+
# the same as the desired AWS ID.
|
51
|
+
#
|
52
|
+
if new_resource.is_a?(AWSResourceWithEntry)
|
53
|
+
entry_driver, entry_id, entry = new_resource.get_id_from_managed_entry
|
54
|
+
if entry_id
|
55
|
+
if desired_id
|
56
|
+
|
57
|
+
#
|
58
|
+
# We have both a desired ID and an entry ID. Find out whether they
|
59
|
+
# match and warn if they don't (because we're going to reassociate and
|
60
|
+
# update the *desired* AWS thing.).
|
61
|
+
#
|
62
|
+
if desired_driver.driver_url == entry_driver.driver_url && desired_id == entry_id
|
63
|
+
Chef::Log.debug "#{new_resource.to_s} is already associated with #{entry_id} in #{entry_driver.driver_url}"
|
64
|
+
else
|
65
|
+
Chef::Log.warn "#{new_resource.to_s} is currently associated with #{entry_id} in #{entry_driver.driver_url}, but the desired ID is #{desired_id} in #{new_resource.driver.driver_url}! Will associate with new desired ID #{desired_id}."
|
66
|
+
end
|
67
|
+
|
68
|
+
else
|
69
|
+
|
70
|
+
#
|
71
|
+
# If we don't have desired (common case), we'll update the existing
|
72
|
+
# resource or create a new one if it's been deleted.
|
73
|
+
#
|
74
|
+
aws_object = new_resource.class.get_aws_object(entry_id, driver: entry_driver, resource: new_resource, required: false)
|
75
|
+
if aws_object
|
76
|
+
Chef::Log.debug "#{new_resource.to_s} is currently associated with #{entry_id} in #{entry_driver.driver_url}."
|
77
|
+
else
|
78
|
+
Chef::Log.warn "#{new_resource.to_s} is currently associated with #{entry_id} in #{entry_driver.driver_url}, but it does not exist! We will create a new one to replace it."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
else
|
83
|
+
|
84
|
+
#
|
85
|
+
# If we don't currently have an AWS ID associated with this resource, we
|
86
|
+
# will either associate the desired one, or create a new one.
|
87
|
+
#
|
88
|
+
if desired_id
|
89
|
+
Chef::Log.debug "#{new_resource.to_s} is not yet associated with anything. Associating with desired object #{desired_id} in #{desired_driver.driver_url}."
|
90
|
+
else
|
91
|
+
Chef::Log.debug "#{new_resource.to_s} is not yet associated with anything. Creating a new one in #{desired_driver.driver_url} ..."
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
else
|
96
|
+
|
97
|
+
#
|
98
|
+
# If it does not support storing IDs in Chef at all, just grab the existing
|
99
|
+
# object and we'll update (or not) based on that.
|
100
|
+
#
|
101
|
+
aws_object ||= new_resource.aws_object
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Actually update or create the AWS object
|
107
|
+
#
|
108
|
+
if aws_object
|
109
|
+
action, new_obj = update_aws_object(aws_object)
|
110
|
+
if action == :replaced_aws_object
|
111
|
+
aws_object = new_obj
|
112
|
+
end
|
113
|
+
else
|
114
|
+
aws_object = create_aws_object
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Associate the managed entry with the AWS object
|
119
|
+
#
|
120
|
+
if new_resource.is_a?(AWSResourceWithEntry)
|
121
|
+
new_resource.save_managed_entry(aws_object, action_handler, existing_entry: entry)
|
122
|
+
end
|
123
|
+
|
124
|
+
aws_object
|
125
|
+
end
|
126
|
+
|
127
|
+
action :destroy do
|
128
|
+
desired_driver = new_resource.driver
|
129
|
+
desired_id = new_resource.public_send(new_resource.class.aws_id_attribute) if new_resource.class.aws_id_attribute
|
130
|
+
|
131
|
+
#
|
132
|
+
# If the user specified an ID, delete THAT; do NOT delete the associated object.
|
133
|
+
#
|
134
|
+
if desired_id
|
135
|
+
aws_object = new_resource.class.get_aws_object(desired_id, resource: new_resource, required: false)
|
136
|
+
if aws_object
|
137
|
+
Chef::Log.debug "#{new_resource.to_s} provided #{new_resource.class.aws_id_attribute} #{desired_id} in #{desired_driver.driver_url}. Will delete."
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Managed entries are looked up by ID.
|
143
|
+
#
|
144
|
+
if new_resource.is_a?(AWSResourceWithEntry)
|
145
|
+
entry_driver, entry_id, entry = new_resource.get_id_from_managed_entry
|
146
|
+
if entry_id
|
147
|
+
if desired_id && (desired_id != entry_id || desired_driver.driver_url != entry_driver.driver_url)
|
148
|
+
if new_resource.class.get_aws_object(entry_id, driver: entry_driver, resource: new_resource, required: false)
|
149
|
+
# If the desired ID / driver differs from the entry, don't delete. We
|
150
|
+
# certainly can't delete the AWS object itself, and we don't *want* to
|
151
|
+
# delete the association, because the expectation is that after doing a
|
152
|
+
# delete, you should be able to create a new thing.
|
153
|
+
raise "#{new_resource.to_s} provided #{new_resource.class.aws_id_attribute} #{desired_id} in #{desired_driver.driver_url}, but is currently associated with #{entry_id} in #{entry_driver.driver_url}. Cannot delete the entry or the association until this inconsistency is resolved."
|
154
|
+
else
|
155
|
+
Chef::Log.debug "#{new_resource.to_s} provided #{new_resource.class.aws_id_attribute} #{desired_id} in #{desired_driver.driver_url}, but is currently associated with #{entry_id} in #{entry_driver.driver_url}, which does not exist. Will delete #{desired_id} and disassociate from #{entry_id}."
|
156
|
+
end
|
157
|
+
else
|
158
|
+
|
159
|
+
# Normal case: entry exists, and is the same as desired (or no desired)
|
160
|
+
aws_object = new_resource.class.get_aws_object(entry_id, driver: entry_driver, resource: new_resource, required: false)
|
161
|
+
if aws_object
|
162
|
+
Chef::Log.debug "#{new_resource.to_s} is associated with #{entry_id} in #{entry_driver.driver_url}. Will delete."
|
163
|
+
else
|
164
|
+
Chef::Log.debug "#{new_resource.to_s} is associated with #{entry_id} in #{entry_driver.driver_url}, but it does not exist. Will disassociate the entry but not delete."
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# Non-managed entries all have their own way of looking it up
|
171
|
+
#
|
172
|
+
else
|
173
|
+
aws_object ||= new_resource.aws_object
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Call the delete method
|
178
|
+
#
|
179
|
+
if aws_object
|
180
|
+
destroy_aws_object(aws_object)
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# Associate the managed entry with the AWS object
|
185
|
+
#
|
186
|
+
if new_resource.is_a?(AWSResourceWithEntry) && entry
|
187
|
+
new_resource.delete_managed_entry(action_handler)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
protected
|
192
|
+
|
193
|
+
def create_aws_object
|
194
|
+
raise NotImplementedError, :create_aws_object
|
195
|
+
end
|
196
|
+
|
197
|
+
def update_aws_object(obj)
|
198
|
+
raise NotImplementedError, :update_aws_object
|
199
|
+
end
|
200
|
+
|
201
|
+
def destroy_aws_object(obj)
|
202
|
+
raise NotImplementedError, :destroy_aws_object
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'aws'
|
2
|
+
require 'chef/provisioning/aws_driver/super_lwrp'
|
3
|
+
require 'chef/provisioning/chef_managed_entry_store'
|
4
|
+
|
5
|
+
# Common AWS resource - contains metadata that all AWS resources will need
|
6
|
+
module Chef::Provisioning::AWSDriver
|
7
|
+
class AWSResource < Chef::Provisioning::AWSDriver::SuperLWRP
|
8
|
+
actions :create, :destroy, :nothing
|
9
|
+
default_action :create
|
10
|
+
|
11
|
+
def initialize(name, run_context=nil)
|
12
|
+
name = name.public_send(self.class.aws_sdk_class_id) if name.is_a?(self.class.aws_sdk_class)
|
13
|
+
super
|
14
|
+
if run_context
|
15
|
+
driver run_context.chef_provisioning.current_driver
|
16
|
+
chef_server run_context.cheffish.current_chef_server
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Backwards compatibility for action :destroy
|
21
|
+
def action(*args)
|
22
|
+
if args == [ :delete ]
|
23
|
+
super(:destroy)
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def action=(value)
|
29
|
+
action(value)
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# The desired driver.
|
34
|
+
#
|
35
|
+
attribute :driver, kind_of: Chef::Provisioning::Driver,
|
36
|
+
coerce: (proc do |value|
|
37
|
+
case value
|
38
|
+
when nil, Chef::Provisioning::Driver
|
39
|
+
value
|
40
|
+
else
|
41
|
+
run_context.chef_provisioning.driver_for(value)
|
42
|
+
end
|
43
|
+
end)
|
44
|
+
|
45
|
+
#
|
46
|
+
# The Chef server on which any IDs should be looked up.
|
47
|
+
#
|
48
|
+
attribute :chef_server, kind_of: Hash
|
49
|
+
|
50
|
+
#
|
51
|
+
# The managed entry store.
|
52
|
+
#
|
53
|
+
attribute :managed_entry_store, kind_of: Chef::Provisioning::ManagedEntryStore,
|
54
|
+
lazy_default: proc { Chef::Provisioning::ChefManagedEntryStore.new(chef_server) }
|
55
|
+
|
56
|
+
#
|
57
|
+
# Get the current AWS object.
|
58
|
+
#
|
59
|
+
def aws_object
|
60
|
+
raise NotImplementedError, :aws_object
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Look up an AWS options list, translating standard names using the appropriate
|
65
|
+
# classes.
|
66
|
+
#
|
67
|
+
# For example, `load_balancer_options` is passed into `lookup_options`, and if
|
68
|
+
# it looks like this: `{ subnets: `[ 'subnet1', 'subnet2' ] }`, then
|
69
|
+
# `AWSResource.lookup_options` will translate each ID with
|
70
|
+
# `AwsSubnet.get_aws_object('subnet1')`, which supports Chef names
|
71
|
+
# (`mysubnet`) as well as AWS subnet Ids (`subnet-1234abcd`) or AWS objects
|
72
|
+
# (`AWS::EC2::Subnet`).
|
73
|
+
#
|
74
|
+
# Keys that represent non-AWS-objects (such as `timeout`) are left alone.
|
75
|
+
#
|
76
|
+
def self.lookup_options(options, **handler_options)
|
77
|
+
options = options.dup
|
78
|
+
options.each do |name, value|
|
79
|
+
if name.to_s.end_with?('s')
|
80
|
+
handler_name = :"#{name[0..-2]}"
|
81
|
+
if aws_option_handlers[handler_name]
|
82
|
+
options[name] = [options[name]].flatten.map { |value| aws_option_handlers[handler_name].get_aws_object_id(value, **handler_options) }
|
83
|
+
end
|
84
|
+
else
|
85
|
+
if aws_option_handlers[name]
|
86
|
+
options[name] = aws_option_handlers[name].get_aws_object_id(value, **handler_options)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
options
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.get_aws_object(value, resource: nil, run_context: nil, driver: nil, managed_entry_store: nil, required: true)
|
94
|
+
return nil if value.nil?
|
95
|
+
|
96
|
+
if resource
|
97
|
+
run_context ||= resource.run_context
|
98
|
+
driver ||= resource.driver
|
99
|
+
managed_entry_store ||= resource.managed_entry_store
|
100
|
+
end
|
101
|
+
if value.is_a?(self)
|
102
|
+
resource = value
|
103
|
+
else
|
104
|
+
resource = new(value, run_context)
|
105
|
+
resource.driver driver if driver
|
106
|
+
resource.managed_entry_store managed_entry_store if managed_entry_store
|
107
|
+
end
|
108
|
+
result = resource.aws_object
|
109
|
+
if required && result.nil?
|
110
|
+
raise "#{self}[#{value}] does not exist!"
|
111
|
+
end
|
112
|
+
result
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.get_aws_object_id(value, **options)
|
116
|
+
aws_object = get_aws_object(value, **options)
|
117
|
+
aws_object.public_send(aws_sdk_class_id) if aws_object
|
118
|
+
end
|
119
|
+
|
120
|
+
protected
|
121
|
+
|
122
|
+
NOT_PASSED = Object.new
|
123
|
+
|
124
|
+
def self.aws_sdk_type(sdk_class,
|
125
|
+
option_names: nil,
|
126
|
+
option_name: NOT_PASSED,
|
127
|
+
load_provider: true,
|
128
|
+
id: :name,
|
129
|
+
aws_id_prefix: nil)
|
130
|
+
self.resource_name = self.dsl_name
|
131
|
+
@aws_sdk_class = sdk_class
|
132
|
+
@aws_sdk_class_id = id
|
133
|
+
@aws_id_prefix = aws_id_prefix
|
134
|
+
|
135
|
+
# Go ahead and require the provider since we're here anyway ...
|
136
|
+
require "chef/provider/#{resource_name}" if load_provider
|
137
|
+
|
138
|
+
option_name = :"#{resource_name[4..-1]}" if option_name == NOT_PASSED
|
139
|
+
@aws_sdk_option_name = option_name
|
140
|
+
|
141
|
+
option_names ||= begin
|
142
|
+
option_names = []
|
143
|
+
option_names << aws_sdk_option_name
|
144
|
+
option_names << :"#{option_name}_#{aws_sdk_class_id}" if aws_sdk_class_id
|
145
|
+
option_names
|
146
|
+
end
|
147
|
+
option_names.each do |option_name|
|
148
|
+
aws_option_handlers[option_name] = self
|
149
|
+
end
|
150
|
+
|
151
|
+
name = self.name.split('::')[-1]
|
152
|
+
eval("Chef::Provisioning::AWSDriver::Resources::#{name} = self", binding, __FILE__, __LINE__)
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.aws_sdk_class
|
156
|
+
@aws_sdk_class
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.aws_sdk_class_id
|
160
|
+
@aws_sdk_class_id
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.aws_id_prefix
|
164
|
+
@aws_id_prefix
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.aws_sdk_option_name
|
168
|
+
@aws_sdk_option_name
|
169
|
+
end
|
170
|
+
|
171
|
+
@@aws_option_handlers = {}
|
172
|
+
def self.aws_option_handlers
|
173
|
+
@@aws_option_handlers
|
174
|
+
end
|
175
|
+
|
176
|
+
# Add support for aws_id_attribute: true
|
177
|
+
def self.attribute(name, aws_id_attribute: false, **validation_opts)
|
178
|
+
@aws_id_attribute = name if aws_id_attribute
|
179
|
+
super(name, validation_opts)
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.aws_id_attribute
|
183
|
+
@aws_id_attribute
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'chef/provisioning/aws_driver/aws_resource'
|
2
|
+
require 'chef/provisioning/aws_driver/resources'
|
3
|
+
|
4
|
+
# Common AWS resource - contains metadata that all AWS resources will need
|
5
|
+
class Chef::Provisioning::AWSDriver::AWSResourceWithEntry < Chef::Provisioning::AWSDriver::AWSResource
|
6
|
+
#
|
7
|
+
# Dissociate the ID of this object from Chef.
|
8
|
+
#
|
9
|
+
# @param action_handler [Chef::Provisioning::ActionHandler] The action handler,
|
10
|
+
# which handles progress reporting, update reporting ("little green text")
|
11
|
+
# and dry run.
|
12
|
+
#
|
13
|
+
def delete_managed_entry(action_handler)
|
14
|
+
if should_have_managed_entry?
|
15
|
+
managed_entry_store.delete(self.class.resource_name, name, action_handler)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Save the ID of this object to Chef.
|
21
|
+
#
|
22
|
+
# @param aws_object [AWS::EC2::Core] The AWS object containing the ID.
|
23
|
+
# @param action_handler [Chef::Provisioning::ActionHandler] The action handler,
|
24
|
+
# which handles progress reporting, update reporting ("little green text")
|
25
|
+
# and dry run.
|
26
|
+
# @param existing_entry [Chef::Provisioning::ManagedEntry] The existing entry
|
27
|
+
# (if any). If this is passed in, and no values are changed, we will
|
28
|
+
# not attempt to update it (this prevents us from retrieving it twice).
|
29
|
+
#
|
30
|
+
def save_managed_entry(aws_object, action_handler, existing_entry: nil)
|
31
|
+
if should_have_managed_entry?
|
32
|
+
managed_entry = existing_entry ||
|
33
|
+
managed_entry_store.new_entry(self.class.resource_name, name)
|
34
|
+
updated = update_managed_entry(aws_object, managed_entry)
|
35
|
+
if updated || !existing_entry
|
36
|
+
managed_entry.save(action_handler)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_id_from_managed_entry
|
42
|
+
if should_have_managed_entry?
|
43
|
+
entry = managed_entry_store.get(self.class.managed_entry_type, name)
|
44
|
+
if entry
|
45
|
+
driver = self.driver
|
46
|
+
if entry.driver_url != driver.driver_url
|
47
|
+
# TODO some people don't send us run_context (like Drivers). We might need
|
48
|
+
# to exit early here if the driver_url doesn't match the provided driver.
|
49
|
+
driver = run_context.chef_provisioning.driver_for(entry.driver_url)
|
50
|
+
end
|
51
|
+
[ driver, entry.reference[self.class.managed_entry_id_name], entry ]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Formatted output for logging statements - contains resource type, resource name and aws object id (if available)
|
57
|
+
def to_s
|
58
|
+
id = get_driver_and_id[1]
|
59
|
+
"#{declared_type}[#{@name}] (#{ id ? id : 'no AWS object id'})"
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
#
|
65
|
+
# Update an existing ManagedEntry object.
|
66
|
+
#
|
67
|
+
# @return true if the entry was changed, and false if not
|
68
|
+
#
|
69
|
+
def update_managed_entry(aws_object, managed_entry)
|
70
|
+
new_value = { self.class.managed_entry_id_name => aws_object.public_send(self.class.aws_sdk_class_id) }
|
71
|
+
if managed_entry.reference != new_value
|
72
|
+
managed_entry.reference = new_value
|
73
|
+
changed = true
|
74
|
+
end
|
75
|
+
if managed_entry.driver_url != driver.driver_url
|
76
|
+
managed_entry.driver_url = driver.driver_url
|
77
|
+
changed = true
|
78
|
+
end
|
79
|
+
changed
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_driver_and_id
|
83
|
+
driver, id, entry = get_id_from_managed_entry
|
84
|
+
# If the value isn't already stored, look up the user-specified public_ip
|
85
|
+
driver, id = self.driver, self.public_send(self.class.aws_id_attribute) if !id
|
86
|
+
[ driver, id ]
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.aws_sdk_type(sdk_class,
|
90
|
+
id: :id,
|
91
|
+
managed_entry_type: nil,
|
92
|
+
managed_entry_id_name: 'id',
|
93
|
+
backcompat_data_bag_name: nil,
|
94
|
+
**options)
|
95
|
+
super(sdk_class, id: id, **options)
|
96
|
+
@managed_entry_type = managed_entry_type || resource_name.to_sym
|
97
|
+
@managed_entry_id_name = managed_entry_id_name
|
98
|
+
if backcompat_data_bag_name
|
99
|
+
Chef::Provisioning::ChefManagedEntryStore.type_names_for_backcompat[resource_name] = backcompat_data_bag_name
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.managed_entry_type
|
104
|
+
@managed_entry_type
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.managed_entry_id_name
|
108
|
+
@managed_entry_id_name
|
109
|
+
end
|
110
|
+
|
111
|
+
def should_have_managed_entry?
|
112
|
+
name != public_send(self.class.aws_id_attribute)
|
113
|
+
end
|
114
|
+
end
|