chef-provisioning-aws 1.4.1 → 1.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -0
  3. data/README.md +26 -39
  4. data/Rakefile +13 -5
  5. data/lib/chef/provider/aws_iam_instance_profile.rb +60 -0
  6. data/lib/chef/provider/aws_iam_role.rb +98 -0
  7. data/lib/chef/provider/aws_image.rb +1 -1
  8. data/lib/chef/provider/aws_internet_gateway.rb +75 -0
  9. data/lib/chef/provider/aws_route_table.rb +3 -2
  10. data/lib/chef/provider/aws_s3_bucket.rb +4 -1
  11. data/lib/chef/provider/aws_security_group.rb +1 -1
  12. data/lib/chef/provider/aws_vpc.rb +50 -45
  13. data/lib/chef/provisioning/aws_driver.rb +22 -1
  14. data/lib/chef/provisioning/aws_driver/aws_provider.rb +13 -5
  15. data/lib/chef/provisioning/aws_driver/aws_resource.rb +173 -165
  16. data/lib/chef/provisioning/aws_driver/credentials.rb +12 -0
  17. data/lib/chef/provisioning/aws_driver/driver.rb +82 -37
  18. data/lib/chef/provisioning/aws_driver/super_lwrp.rb +56 -43
  19. data/lib/chef/provisioning/aws_driver/version.rb +1 -1
  20. data/lib/chef/resource/aws_dhcp_options.rb +1 -1
  21. data/lib/chef/resource/aws_ebs_volume.rb +1 -1
  22. data/lib/chef/resource/aws_eip_address.rb +1 -1
  23. data/lib/chef/resource/aws_iam_instance_profile.rb +33 -0
  24. data/lib/chef/resource/aws_iam_role.rb +55 -0
  25. data/lib/chef/resource/aws_image.rb +1 -1
  26. data/lib/chef/resource/aws_instance.rb +1 -1
  27. data/lib/chef/resource/aws_internet_gateway.rb +36 -6
  28. data/lib/chef/resource/aws_load_balancer.rb +1 -1
  29. data/lib/chef/resource/aws_network_acl.rb +1 -1
  30. data/lib/chef/resource/aws_network_interface.rb +1 -1
  31. data/lib/chef/resource/aws_route53_hosted_zone.rb +261 -0
  32. data/lib/chef/resource/aws_route53_record_set.rb +162 -0
  33. data/lib/chef/resource/aws_route_table.rb +1 -1
  34. data/lib/chef/resource/aws_security_group.rb +1 -1
  35. data/lib/chef/resource/aws_sns_topic.rb +1 -1
  36. data/lib/chef/resource/aws_subnet.rb +1 -1
  37. data/lib/chef/resource/aws_vpc.rb +1 -1
  38. data/lib/chef/resource/aws_vpc_peering_connection.rb +1 -1
  39. data/spec/aws_support.rb +11 -13
  40. data/spec/aws_support/matchers/create_an_aws_object.rb +7 -1
  41. data/spec/aws_support/matchers/have_aws_object_tags.rb +1 -1
  42. data/spec/aws_support/matchers/match_an_aws_object.rb +7 -1
  43. data/spec/aws_support/matchers/update_an_aws_object.rb +8 -2
  44. data/spec/integration/aws_eip_address_spec.rb +74 -0
  45. data/spec/integration/aws_iam_instance_profile_spec.rb +159 -0
  46. data/spec/integration/aws_iam_role_spec.rb +177 -0
  47. data/spec/integration/aws_internet_gateway_spec.rb +161 -0
  48. data/spec/integration/aws_network_interface_spec.rb +3 -4
  49. data/spec/integration/aws_route53_hosted_zone_spec.rb +522 -0
  50. data/spec/integration/aws_route_table_spec.rb +52 -4
  51. data/spec/integration/aws_s3_bucket_spec.rb +1 -1
  52. data/spec/integration/load_balancer_spec.rb +303 -8
  53. data/spec/integration/machine_batch_spec.rb +1 -0
  54. data/spec/integration/machine_image_spec.rb +32 -17
  55. data/spec/integration/machine_spec.rb +11 -29
  56. data/spec/unit/chef/provisioning/aws_driver/driver_spec.rb +0 -1
  57. data/spec/unit/chef/provisioning/aws_driver/route53_spec.rb +105 -0
  58. metadata +48 -6
@@ -5,7 +5,7 @@ require 'retryable'
5
5
 
6
6
  class Chef::Provider::AwsVpc < Chef::Provisioning::AWSDriver::AWSProvider
7
7
  include Chef::Provisioning::AWSDriver::TaggingStrategy::EC2ConvergeTags
8
-
8
+
9
9
  provides :aws_vpc
10
10
 
11
11
  class NeverObtainedExistence < RuntimeError; end
@@ -134,12 +134,13 @@ class Chef::Provider::AwsVpc < Chef::Provisioning::AWSDriver::AWSProvider
134
134
  # Detach or destroy the internet gateway
135
135
  ig = vpc.internet_gateway
136
136
  if ig
137
- converge_by "detach Internet gateway #{ig.id} in #{region} from #{new_resource.to_s}" do
138
- ig.detach(vpc.id)
139
- end
140
- if ig.tags['OwnedByVPC'] == vpc.id
141
- converge_by "destroy Internet gateway #{ig.id} in #{region} (owned by #{new_resource.to_s})" do
142
- ig.delete
137
+ Cheffish.inline_resource(self, action) do
138
+ aws_internet_gateway ig do
139
+ if ig.tags['OwnedByVPC'] == vpc.id
140
+ action :purge
141
+ else
142
+ action :detach
143
+ end
143
144
  end
144
145
  end
145
146
  end
@@ -179,47 +180,49 @@ class Chef::Provider::AwsVpc < Chef::Provisioning::AWSDriver::AWSProvider
179
180
  def update_internet_gateway(vpc)
180
181
  current_ig = vpc.internet_gateway
181
182
  case new_resource.internet_gateway
182
- when String, Chef::Resource::AwsInternetGateway, AWS::EC2::InternetGateway
183
- new_ig = Chef::Resource::AwsInternetGateway.get_aws_object(new_resource.internet_gateway, resource: new_resource)
184
- if !current_ig
185
- converge_by "attach Internet gateway #{new_resource.internet_gateway} to VPC #{vpc.id}" do
186
- new_ig.attach(vpc.id)
187
- end
188
- elsif current_ig != new_ig
189
- converge_by "replace Internet gateway #{current_ig.id} on VPC #{vpc.id} with new Internet gateway #{new_ig.id}" do
190
- current_ig.detach(vpc.id)
191
- new_ig.attach(vpc.id)
192
- end
193
- if current_ig.tags['OwnedByVPC'] == vpc.id
194
- converge_by "destroy Internet gateway #{current_ig.id} in #{region} (owned by VPC #{vpc.id})" do
195
- current_ig.delete
183
+ when String, Chef::Resource::AwsInternetGateway, AWS::EC2::InternetGateway
184
+ new_ig = Chef::Resource::AwsInternetGateway.get_aws_object(new_resource.internet_gateway, resource: new_resource)
185
+ if !current_ig
186
+ Cheffish.inline_resource(self, action) do
187
+ aws_internet_gateway new_ig do
188
+ vpc vpc.id
189
+ end
196
190
  end
197
- end
198
- end
199
- when true
200
- if !current_ig
201
- converge_by "attach Internet gateway to VPC #{vpc.id}" do
202
- current_ig = AWS.ec2(config: vpc.config).internet_gateways.create
203
- retry_with_backoff(NeverObtainedExistence) do
204
- raise NeverObtainedExistence.new("Internet gateway for VPC #{vpc.id} never obtained existence") unless current_ig.exists?
191
+ elsif current_ig != new_ig
192
+ Cheffish.inline_resource(self, action) do
193
+ aws_internet_gateway current_ig do
194
+ if current_ig.tags['OwnedByVPC'] == vpc.id
195
+ action :destroy
196
+ else
197
+ action :detach
198
+ end
199
+ end
200
+ aws_internet_gateway new_ig do
201
+ vpc vpc.id
202
+ end
205
203
  end
206
- action_handler.report_progress "create Internet gateway #{current_ig.id}"
207
- current_ig.tags['OwnedByVPC'] = vpc.id
208
- action_handler.report_progress "tag Internet gateway #{current_ig.id} as OwnedByVpc: #{vpc.id}"
209
- vpc.internet_gateway = current_ig
210
204
  end
211
- end
212
- when false
213
- if current_ig
214
- converge_by "detach Internet gateway #{current_ig.id} from VPC #{vpc.id}" do
215
- current_ig.detach(vpc.id)
205
+ when true
206
+ if !current_ig
207
+ Cheffish.inline_resource(self, action) do
208
+ aws_internet_gateway "igw-managed-by-#{vpc.id}" do
209
+ vpc vpc.id
210
+ aws_tags 'OwnedByVPC' => vpc.id
211
+ end
212
+ end
216
213
  end
217
- if current_ig.tags['OwnedByVPC'] == vpc.id
218
- converge_by "destroy Internet gateway #{current_ig.id} in #{region} (owned by VPC #{vpc.id})" do
219
- current_ig.delete
214
+ when false
215
+ if current_ig
216
+ Cheffish.inline_resource(self, action) do
217
+ aws_internet_gateway current_ig.id do
218
+ if current_ig.tags['OwnedByVPC'] == vpc.id
219
+ action :destroy
220
+ else
221
+ action :detach
222
+ end
223
+ end
220
224
  end
221
225
  end
222
- end
223
226
  end
224
227
  end
225
228
 
@@ -247,9 +250,11 @@ class Chef::Provider::AwsVpc < Chef::Provisioning::AWSDriver::AWSProvider
247
250
  # creating the VPC
248
251
  main_route_table ||= vpc.route_tables.main_route_table
249
252
  main_routes = new_resource.main_routes
250
- aws_route_table main_route_table.id do
251
- vpc vpc
252
- routes main_routes
253
+ Cheffish.inline_resource(self, action) do
254
+ aws_route_table main_route_table.id do
255
+ vpc vpc
256
+ routes main_routes
257
+ end
253
258
  end
254
259
  main_route_table
255
260
  end
@@ -9,6 +9,8 @@ require "chef/resource/aws_cloudsearch_domain"
9
9
  require "chef/resource/aws_dhcp_options"
10
10
  require "chef/resource/aws_ebs_volume"
11
11
  require "chef/resource/aws_eip_address"
12
+ require "chef/resource/aws_iam_role"
13
+ require "chef/resource/aws_iam_instance_profile"
12
14
  require "chef/resource/aws_image"
13
15
  require "chef/resource/aws_instance"
14
16
  require "chef/resource/aws_internet_gateway"
@@ -17,10 +19,10 @@ require "chef/resource/aws_launch_configuration"
17
19
  require "chef/resource/aws_load_balancer"
18
20
  require "chef/resource/aws_network_acl"
19
21
  require "chef/resource/aws_network_interface"
20
- require "chef/resource/aws_route_table"
21
22
  require "chef/resource/aws_rds_instance"
22
23
  require "chef/resource/aws_rds_subnet_group"
23
24
  require "chef/resource/aws_route_table"
25
+ require "chef/resource/aws_route53_hosted_zone"
24
26
  require "chef/resource/aws_s3_bucket"
25
27
  require "chef/resource/aws_security_group"
26
28
  require "chef/resource/aws_server_certificate"
@@ -30,3 +32,22 @@ require "chef/resource/aws_subnet"
30
32
  require "chef/resource/aws_vpc"
31
33
  require "chef/resource/aws_vpc_peering_connection"
32
34
 
35
+ module NoResourceCloning
36
+ def prior_resource
37
+ if resource_class <= Chef::Provisioning::AWSDriver::AWSResource
38
+ Chef::Log.debug "Canceling resource cloning for #{resource_class}"
39
+ nil
40
+ else
41
+ super
42
+ end
43
+ end
44
+ def emit_cloned_resource_warning; end
45
+ def emit_harmless_cloning_debug; end
46
+ end
47
+
48
+ # Chef 12.2 changed `load_prior_resource` logic to be in the Chef::ResourceBuilder class
49
+ # but that class only exists in 12.2 and up
50
+ if defined? Chef::ResourceBuilder
51
+ # Ruby 2.0.0 has prepend as a protected method
52
+ Chef::ResourceBuilder.send(:prepend, NoResourceCloning)
53
+ end
@@ -269,11 +269,11 @@ class AWSProvider < Chef::Provider::LWRPBase
269
269
  sleep = opts[:sleep] || 5
270
270
 
271
271
  Retryable.retryable(:tries => tries, :sleep => sleep) do |retries, exception|
272
- action_handler.report_progress "waited #{retries*sleep}/#{tries*sleep}s for #{aws_object.id} state to change to #{expected_responses.inspect}..."
273
- Chef::Log.debug("Current exception is #{exception.inspect}")
272
+ action_handler.report_progress "waited #{retries*sleep}/#{tries*sleep}s for <#{aws_object.class}:#{aws_object.id}>##{query_method} state to change to #{expected_responses.inspect}..."
273
+ Chef::Log.debug("Current exception in wait_for is #{exception.inspect}")
274
274
  begin
275
275
  current_response = aws_object.send(query_method)
276
- Chef::Log.debug("Current response from [#{query_method}] is #{current_response}")
276
+ Chef::Log.debug("Current response in wait_for from [#{query_method}] is #{current_response}")
277
277
  unless expected_responses.include?(current_response)
278
278
  raise StatusTimeoutError.new(aws_object, current_response, expected_responses)
279
279
  end
@@ -285,8 +285,16 @@ class AWSProvider < Chef::Provider::LWRPBase
285
285
  # Retry a block with an doubling backoff time (maximum wait of 10 seconds).
286
286
  # @param retry_on [Exception] An exception to retry on, defaults to RuntimeError
287
287
  #
288
- def retry_with_backoff(retry_on = RuntimeError, &block)
289
- Retryable.retryable(:tries => 10, :sleep => lambda { |n| [2**n, 16].min }, :on => retry_on, &block)
288
+ def self.retry_with_backoff(*retry_on)
289
+ retry_on ||= [RuntimeError]
290
+ Retryable.retryable(:tries => 10, :sleep => lambda { |n| [2**n, 16].min }, :on => retry_on) do |retries, exception|
291
+ Chef::Log.debug("Current exception in retry_with_backoff is #{exception.inspect}")
292
+ yield
293
+ end
294
+ end
295
+
296
+ def retry_with_backoff(*retry_on, &block)
297
+ self.class.retry_with_backoff(*retry_on, &block)
290
298
  end
291
299
 
292
300
  end
@@ -5,199 +5,207 @@ require 'chef/provisioning/chef_managed_entry_store'
5
5
  require 'chef/provisioning/aws_driver/aws_taggable'
6
6
 
7
7
  # Common AWS resource - contains metadata that all AWS resources will need
8
- module Chef::Provisioning::AWSDriver
9
- class AWSResource < Chef::Provisioning::AWSDriver::SuperLWRP
10
- actions :create, :destroy, :purge, :nothing
11
- default_action :create
12
-
13
- def initialize(name, run_context=nil)
14
- name = name.public_send(self.class.aws_sdk_class_id) if name.is_a?(self.class.aws_sdk_class)
15
- super
16
- if run_context
17
- driver run_context.chef_provisioning.current_driver
18
- chef_server run_context.cheffish.current_chef_server
8
+ class Chef
9
+ module Provisioning
10
+ module AWSDriver
11
+ class AWSResource < Chef::Provisioning::AWSDriver::SuperLWRP
12
+ actions :create, :destroy, :purge, :nothing
13
+ default_action :create
14
+
15
+ def initialize(name, run_context=nil)
16
+ name = name.public_send(self.class.aws_sdk_class_id) if name.is_a?(self.class.aws_sdk_class)
17
+ super
18
+ if run_context
19
+ driver run_context.chef_provisioning.current_driver
20
+ chef_server run_context.cheffish.current_chef_server
21
+ end
19
22
  end
20
- end
21
23
 
22
- # Backwards compatibility for action :destroy
23
- def action(*args)
24
- if args == [ :delete ]
25
- super(:destroy)
26
- else
27
- super
24
+ # Backwards compatibility for action :destroy
25
+ def action(*args)
26
+ if args == [ :delete ]
27
+ super(:destroy)
28
+ else
29
+ super
30
+ end
28
31
  end
29
- end
30
32
 
31
- # In Chef < 12.4 we need to define this method. In > 12.4 this method is
32
- # already defined for us so we don't need to overwrite it.
33
- unless defined?(:action=)
34
- def action=(value)
35
- action(value)
33
+ # In Chef < 12.4 we need to define this method. In > 12.4 this method is
34
+ # already defined for us so we don't need to overwrite it.
35
+ unless defined?(:action=)
36
+ def action=(value)
37
+ action(value)
38
+ end
36
39
  end
37
- end
38
40
 
39
- #
40
- # The desired driver.
41
- #
42
- attribute :driver, kind_of: Chef::Provisioning::Driver,
43
- coerce: (proc do |value|
44
- case value
45
- when nil, Chef::Provisioning::Driver
46
- value
47
- else
48
- run_context.chef_provisioning.driver_for(value)
49
- end
50
- end)
51
-
52
- #
53
- # The Chef server on which any IDs should be looked up.
54
- #
55
- attribute :chef_server, kind_of: Hash
56
-
57
- #
58
- # The managed entry store.
59
- #
60
- attribute :managed_entry_store, kind_of: Chef::Provisioning::ManagedEntryStore,
61
- lazy_default: proc { Chef::Provisioning::ChefManagedEntryStore.new(chef_server) }
62
-
63
- #
64
- # Get the current AWS object. This should return the aws_object even if it has
65
- # a status like 'deleted' or 'inactive'. If there is an aws_object, we return it.
66
- # Callers will need to check the status if they care.
67
- #
68
- def aws_object
69
- raise NotImplementedError, :aws_object
70
- end
41
+ #
42
+ # The desired driver.
43
+ #
44
+ attribute :driver, kind_of: Chef::Provisioning::Driver,
45
+ coerce: (proc do |value|
46
+ case value
47
+ when nil, Chef::Provisioning::Driver
48
+ value
49
+ else
50
+ run_context.chef_provisioning.driver_for(value)
51
+ end
52
+ end)
53
+
54
+ #
55
+ # The Chef server on which any IDs should be looked up.
56
+ #
57
+ attribute :chef_server, kind_of: Hash
58
+
59
+ #
60
+ # The managed entry store.
61
+ #
62
+ attribute :managed_entry_store, kind_of: Chef::Provisioning::ManagedEntryStore,
63
+ default: lazy { Chef::Provisioning::ChefManagedEntryStore.new(chef_server) }
64
+
65
+ #
66
+ # Get the current AWS object. This should return the aws_object even if it has
67
+ # a status like 'deleted' or 'inactive'. If there is an aws_object, we return it.
68
+ # Callers will need to check the status if they care.
69
+ #
70
+ def aws_object
71
+ raise NotImplementedError, :aws_object
72
+ end
71
73
 
72
- def aws_object_id
73
- @aws_object_id ||= begin
74
- o = aws_object
75
- o.public_send(self.class.aws_sdk_class_id) if o
74
+ def aws_object_id
75
+ @aws_object_id ||= begin
76
+ o = aws_object
77
+ o.public_send(self.class.aws_sdk_class_id) if o
78
+ end
76
79
  end
77
- end
78
80
 
79
- #
80
- # Look up an AWS options list, translating standard names using the appropriate
81
- # classes.
82
- #
83
- # For example, `load_balancer_options` is passed into `lookup_options`, and if
84
- # it looks like this: `{ subnets: `[ 'subnet1', 'subnet2' ] }`, then
85
- # `AWSResource.lookup_options` will translate each ID with
86
- # `AwsSubnet.get_aws_object('subnet1')`, which supports Chef names
87
- # (`mysubnet`) as well as AWS subnet Ids (`subnet-1234abcd`) or AWS objects
88
- # (`AWS::EC2::Subnet`).
89
- #
90
- # Keys that represent non-AWS-objects (such as `timeout`) are left alone.
91
- #
92
- def self.lookup_options(options, **handler_options)
93
- options = options.dup
94
- options.each do |name, value|
95
- if name.to_s.end_with?('s')
96
- handler_name = :"#{name[0..-2]}"
97
- if aws_option_handlers[handler_name]
98
- options[name] = [options[name]].flatten.map { |value| aws_option_handlers[handler_name].get_aws_object_id(value, **handler_options) }
99
- end
100
- else
101
- if aws_option_handlers[name]
102
- options[name] = aws_option_handlers[name].get_aws_object_id(value, **handler_options)
81
+ #
82
+ # Look up an AWS options list, translating standard names using the appropriate
83
+ # classes.
84
+ #
85
+ # For example, `load_balancer_options` is passed into `lookup_options`, and if
86
+ # it looks like this: `{ subnets: `[ 'subnet1', 'subnet2' ] }`, then
87
+ # `AWSResource.lookup_options` will translate each ID with
88
+ # `AwsSubnet.get_aws_object('subnet1')`, which supports Chef names
89
+ # (`mysubnet`) as well as AWS subnet Ids (`subnet-1234abcd`) or AWS objects
90
+ # (`AWS::EC2::Subnet`).
91
+ #
92
+ # Keys that represent non-AWS-objects (such as `timeout`) are left alone.
93
+ #
94
+ def self.lookup_options(options = Hash.new, **handler_options)
95
+ options = options.dup
96
+ options.each do |name, value|
97
+ if name.to_s.end_with?('s')
98
+ handler_name = :"#{name[0..-2]}"
99
+ if aws_option_handlers[handler_name]
100
+ options[name] = [options[name]].flatten.map { |value| aws_option_handlers[handler_name].get_aws_object_id(value, **handler_options) }
101
+ end
102
+ else
103
+ if aws_option_handlers[name]
104
+ options[name] = aws_option_handlers[name].get_aws_object_id(value, **handler_options)
105
+ end
103
106
  end
104
107
  end
108
+ options
105
109
  end
106
- options
107
- end
108
110
 
109
- def self.get_aws_object(value, resource: nil, run_context: nil, driver: nil, managed_entry_store: nil, required: true)
110
- return nil if value.nil?
111
+ def self.get_aws_object(value, resource: nil, run_context: nil, driver: nil, managed_entry_store: nil, required: true)
112
+ return nil if value.nil?
111
113
 
112
- if resource
113
- run_context ||= resource.run_context
114
- driver ||= resource.driver
115
- managed_entry_store ||= resource.managed_entry_store
116
- end
117
- if value.is_a?(self)
118
- resource = value
119
- else
120
- resource = new(value, run_context)
121
- resource.driver driver if driver
122
- resource.managed_entry_store managed_entry_store if managed_entry_store
123
- end
114
+ if resource
115
+ run_context ||= resource.run_context
116
+ driver ||= resource.driver
117
+ managed_entry_store ||= resource.managed_entry_store
118
+ end
119
+ if value.is_a?(self)
120
+ resource = value
121
+ else
122
+ resource = new(value, run_context)
123
+ resource.driver driver if driver
124
+ resource.managed_entry_store managed_entry_store if managed_entry_store
125
+ end
124
126
 
125
- result = resource.aws_object
126
- if required && result.nil?
127
- raise "#{self}[#{value}] does not exist!"
127
+ result = resource.aws_object
128
+ if required && result.nil?
129
+ raise "#{self}[#{value}] does not exist!"
130
+ end
131
+ result
128
132
  end
129
- result
130
- end
131
133
 
132
- def self.get_aws_object_id(value, **options)
133
- aws_object = get_aws_object(value, **options)
134
- aws_object.public_send(aws_sdk_class_id) if aws_object
135
- end
136
-
137
- protected
138
-
139
- NOT_PASSED = Object.new
140
-
141
- def self.aws_sdk_type(sdk_class,
142
- option_names: nil,
143
- option_name: NOT_PASSED,
144
- load_provider: true,
145
- id: :name,
146
- aws_id_prefix: nil)
147
- self.resource_name = convert_to_snake_case(self.name.split('::')[-1])
148
- @aws_sdk_class = sdk_class
149
- @aws_sdk_class_id = id
150
- @aws_id_prefix = aws_id_prefix
151
-
152
- # Go ahead and require the provider since we're here anyway ...
153
- require "chef/provider/#{resource_name}" if load_provider
134
+ def self.get_aws_object_id(value, **options)
135
+ aws_object = get_aws_object(value, **options)
136
+ aws_object.public_send(aws_sdk_class_id) if aws_object
137
+ end
154
138
 
155
- option_name = :"#{resource_name[4..-1]}" if option_name == NOT_PASSED
156
- @aws_sdk_option_name = option_name
139
+ protected
140
+
141
+ # This supports the introduction of the NOT_PASSED chef constant
142
+ # in chef 12.5
143
+ # TODO remove when we make 12.5 and higher a dependency
144
+ NOT_PASSED = Object.new unless defined?(NOT_PASSED)
145
+
146
+ def self.aws_sdk_type(sdk_class,
147
+ option_names: nil,
148
+ option_name: NOT_PASSED,
149
+ load_provider: true,
150
+ id: :name,
151
+ aws_id_prefix: nil)
152
+ self.resource_name = convert_to_snake_case(self.name.split('::')[-1])
153
+ @aws_sdk_class = sdk_class
154
+ @aws_sdk_class_id = id
155
+ @aws_id_prefix = aws_id_prefix
156
+
157
+ # Go ahead and require the provider since we're here anyway ...
158
+ require "chef/provider/#{resource_name}" if load_provider
159
+
160
+ option_name = :"#{resource_name[4..-1]}" if option_name == NOT_PASSED
161
+ @aws_sdk_option_name = option_name
162
+
163
+ option_names ||= begin
164
+ option_names = []
165
+ option_names << aws_sdk_option_name
166
+ option_names << :"#{option_name}_#{aws_sdk_class_id}" if aws_sdk_class_id
167
+ option_names
168
+ end
169
+ option_names.each do |option_name|
170
+ aws_option_handlers[option_name] = self
171
+ end
157
172
 
158
- option_names ||= begin
159
- option_names = []
160
- option_names << aws_sdk_option_name
161
- option_names << :"#{option_name}_#{aws_sdk_class_id}" if aws_sdk_class_id
162
- option_names
163
- end
164
- option_names.each do |option_name|
165
- aws_option_handlers[option_name] = self
173
+ name = self.name.split('::')[-1]
174
+ eval("Chef::Provisioning::AWSDriver::Resources::#{name} = self", binding, __FILE__, __LINE__)
166
175
  end
167
176
 
168
- name = self.name.split('::')[-1]
169
- eval("Chef::Provisioning::AWSDriver::Resources::#{name} = self", binding, __FILE__, __LINE__)
170
- end
177
+ def self.aws_sdk_class
178
+ @aws_sdk_class
179
+ end
171
180
 
172
- def self.aws_sdk_class
173
- @aws_sdk_class
174
- end
181
+ def self.aws_sdk_class_id
182
+ @aws_sdk_class_id
183
+ end
175
184
 
176
- def self.aws_sdk_class_id
177
- @aws_sdk_class_id
178
- end
185
+ def self.aws_id_prefix
186
+ @aws_id_prefix
187
+ end
179
188
 
180
- def self.aws_id_prefix
181
- @aws_id_prefix
182
- end
189
+ def self.aws_sdk_option_name
190
+ @aws_sdk_option_name
191
+ end
183
192
 
184
- def self.aws_sdk_option_name
185
- @aws_sdk_option_name
186
- end
193
+ @@aws_option_handlers = {}
194
+ def self.aws_option_handlers
195
+ @@aws_option_handlers
196
+ end
187
197
 
188
- @@aws_option_handlers = {}
189
- def self.aws_option_handlers
190
- @@aws_option_handlers
191
- end
198
+ # Add support for aws_id_attribute: true
199
+ def self.attribute(name, aws_id_attribute: false, **validation_opts)
200
+ @aws_id_attribute = name if aws_id_attribute
201
+ super(name, validation_opts)
202
+ end
192
203
 
193
- # Add support for aws_id_attribute: true
194
- def self.attribute(name, aws_id_attribute: false, **validation_opts)
195
- @aws_id_attribute = name if aws_id_attribute
196
- super(name, validation_opts)
204
+ def self.aws_id_attribute
205
+ @aws_id_attribute
206
+ end
197
207
  end
198
208
 
199
- def self.aws_id_attribute
200
- @aws_id_attribute
201
- end
209
+ end
202
210
  end
203
211
  end