chef-provisioning-aws 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -87,6 +87,15 @@ module AWSDriver
87
87
  end
88
88
  end
89
89
 
90
+ def load_env_variables
91
+ if ENV["AWS_ACCESS_KEY_ID"] && ENV["AWS_SECRET_ACCESS_KEY"]
92
+ @credentials["default"] = {
93
+ aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"],
94
+ aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"]
95
+ }
96
+ end
97
+ end
98
+
90
99
  def load_default
91
100
  config_file = ENV['AWS_CONFIG_FILE'] || File.expand_path('~/.aws/config')
92
101
  credentials_file = ENV['AWS_CREDENTIAL_FILE'] || File.expand_path('~/.aws/credentials')
@@ -97,6 +106,9 @@ module AWSDriver
97
106
  load_inis(config_file)
98
107
  end
99
108
  end
109
+ if @credentials.size == 0
110
+ load_env_variables
111
+ end
100
112
  end
101
113
 
102
114
  def self.method_missing(name, *args, &block)
@@ -28,7 +28,13 @@ require 'base64'
28
28
 
29
29
  # loads the entire aws-sdk
30
30
  AWS.eager_autoload!
31
- AWS_V2_SERVICES = {"EC2" => "ec2", "S3" => "s3", "ElasticLoadBalancing" => "elb", "IAM" => "iam"}
31
+ AWS_V2_SERVICES = {
32
+ "EC2" => "ec2",
33
+ "Route53" => "route53",
34
+ "S3" => "s3",
35
+ "ElasticLoadBalancing" => "elb",
36
+ "IAM" => "iam",
37
+ }
32
38
  Aws.eager_autoload!(:services => AWS_V2_SERVICES.keys)
33
39
 
34
40
  # Need to load the resources after the SDK because `aws_sdk_types` can mess
@@ -53,6 +59,24 @@ class Resource
53
59
  end
54
60
  end
55
61
 
62
+ require 'chef/provider/load_balancer'
63
+ class Chef
64
+ class Provider
65
+ class LoadBalancer
66
+ # We override this so we can specify a machine name as `i-123456`
67
+ # This is totally a hack until we move away from base resources
68
+ def get_machine_spec!(machine_name)
69
+ if machine_name =~ /^i-[a-f0-9]{8}$/
70
+ Struct.new(:name, :reference).new(machine_name, {'instance_id' => machine_name})
71
+ else
72
+ Chef::Log.debug "Getting machine spec for #{machine_name}"
73
+ Provisioning.chef_managed_entry_store(new_resource.chef_server).get!(:machine, machine_name)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
56
80
  Chef::Provider::Machine.additional_machine_option_keys << :aws_tags
57
81
  Chef::Provider::MachineImage.additional_image_option_keys << :aws_tags
58
82
  Chef::Provider::LoadBalancer.additional_lb_option_keys << :aws_tags
@@ -66,7 +90,7 @@ module AWSDriver
66
90
  include Chef::Mixin::ShellOut
67
91
  include Chef::Mixin::DeepMerge
68
92
 
69
- attr_reader :aws_config
93
+ attr_reader :aws_config, :aws_config_2
70
94
 
71
95
  # URL scheme:
72
96
  # aws:profilename:region
@@ -97,7 +121,7 @@ module AWSDriver
97
121
  # Right now we are supporting both V1 and V2, so we create 2 config sets
98
122
  credentials2 = Credentials2.new(:profile_name => profile_name)
99
123
  Chef::Config.chef_provisioning ||= {}
100
- ::Aws.config.update(
124
+ @aws_config_2 = {
101
125
  credentials: credentials2.get_credentials,
102
126
  region: region || ENV["AWS_DEFAULT_REGION"] || credentials[:region],
103
127
  # TODO when we get rid of V1 replace the credentials class with something that knows how
@@ -105,7 +129,27 @@ module AWSDriver
105
129
  :http_proxy => credentials[:proxy_uri] || nil,
106
130
  logger: Chef::Log.logger,
107
131
  retry_limit: Chef::Config.chef_provisioning[:aws_retry_limit] || 5
108
- )
132
+ }
133
+
134
+ driver = self
135
+ Chef::Resource::Machine.send(:define_method, :aws_object) do
136
+ resource = Chef::Resource::AwsInstance.new(name, nil)
137
+ resource.driver driver
138
+ resource.managed_entry_store Chef::Provisioning.chef_managed_entry_store
139
+ resource.aws_object
140
+ end
141
+ Chef::Resource::MachineImage.send(:define_method, :aws_object) do
142
+ resource = Chef::Resource::AwsImage.new(name, nil)
143
+ resource.driver driver
144
+ resource.managed_entry_store Chef::Provisioning.chef_managed_entry_store
145
+ resource.aws_object
146
+ end
147
+ Chef::Resource::LoadBalancer.send(:define_method, :aws_object) do
148
+ resource = Chef::Resource::AwsLoadBalancer.new(name, nil)
149
+ resource.driver driver
150
+ resource.managed_entry_store Chef::Provisioning.chef_managed_entry_store
151
+ resource.aws_object
152
+ end
109
153
  end
110
154
 
111
155
  def self.canonicalize_url(driver_url, config)
@@ -141,7 +185,10 @@ module AWSDriver
141
185
  updates << " with tags #{lb_options[:aws_tags]}" if lb_options[:aws_tags]
142
186
 
143
187
  action_handler.perform_action updates do
144
- actual_elb = elb.load_balancers.create(lb_spec.name, lb_options)
188
+ # IAM says the server certificate exists, but ELB throws this error
189
+ Chef::Provisioning::AWSDriver::AWSProvider.retry_with_backoff(AWS::ELB::Errors::CertificateNotFound) do
190
+ actual_elb = elb.load_balancers.create(lb_spec.name, lb_options)
191
+ end
145
192
 
146
193
  lb_spec.reference = {
147
194
  'driver_version' => Chef::Provisioning::AWSDriver::VERSION,
@@ -157,22 +204,9 @@ module AWSDriver
157
204
  end
158
205
 
159
206
  # TODO: refactor this whole giant method into many smaller method calls
160
- # TODO if we update scheme, we don't need to run any of the other updates.
161
- # Also, if things aren't specified (such as machines / listeners), we
162
- # need to grab them from the actual load balancer so we don't lose them.
163
- # i.e. load_balancer 'blah' do
164
- # lb_options: { scheme: 'other_scheme' }
165
- # end
166
- # TODO we will leak the actual_elb if we fail to finish creating it
167
- # Update scheme - scheme is immutable once set, so if it is changing we need to delete the old
168
- # ELB and create a new one
169
207
  if lb_options[:scheme] && lb_options[:scheme].downcase != actual_elb.scheme
170
- desc = [" updating scheme to #{lb_options[:scheme]}"]
171
- desc << " WARN: scheme is immutable, so deleting and re-creating the ELB"
172
- perform_action.call(desc) do
173
- old_elb = actual_elb
174
- actual_elb = elb.load_balancers.create(lb_spec.name, lb_options)
175
- end
208
+ # TODO CloudFormation automatically recreates the load_balancer, we should too
209
+ raise "Scheme is immutable - you need to :destroy and :create the load_balancer to recreated it with the new scheme"
176
210
  end
177
211
 
178
212
  # Update security groups
@@ -248,12 +282,13 @@ module AWSDriver
248
282
  load_balancer_name: actual_elb.name,
249
283
  subnets: attach_subnets
250
284
  )
251
- rescue AWS::ELB::Errors::InvalidConfigurationRequest
252
- raise "You cannot currently move from 1 subnet to another in the same availability zone. " +
285
+ rescue AWS::ELB::Errors::InvalidConfigurationRequest => e
286
+ Chef::Log.error "You cannot currently move from 1 subnet to another in the same availability zone. " +
253
287
  "Amazon does not have an atomic operation which allows this. You must create a new " +
254
288
  "ELB with the correct subnets and move instances into it. Tried to attach subets " +
255
289
  "#{attach_subnets.join(', ')} (availability zones #{enable_zones.join(', ')}) to " +
256
290
  "existing ELB named #{actual_elb.name}"
291
+ raise e
257
292
  end
258
293
  end
259
294
  end
@@ -591,11 +626,11 @@ EOD
591
626
  class_eval <<-META
592
627
 
593
628
  def #{short_name}_client
594
- @#{short_name}_client ||= ::Aws::#{load_name}::Client.new
629
+ @#{short_name}_client ||= ::Aws::#{load_name}::Client.new(**aws_config_2)
595
630
  end
596
631
 
597
632
  def #{short_name}_resource
598
- @#{short_name}_resource ||= ::Aws::#{load_name}::Resource.new(#{short_name}_client)
633
+ @#{short_name}_resource ||= ::Aws::#{load_name}::Resource.new(**(aws_config_2.merge({client: #{short_name}_client})))
599
634
  end
600
635
 
601
636
  META
@@ -621,10 +656,6 @@ EOD
621
656
  @s3 ||= AWS::S3.new(config: aws_config)
622
657
  end
623
658
 
624
- def rds
625
- @rds ||= AWS::RDS.new(config: aws_config)
626
- end
627
-
628
659
  def sns
629
660
  @sns ||= AWS::SNS.new(config: aws_config)
630
661
  end
@@ -697,9 +728,6 @@ EOD
697
728
  Chef::Log.debug('No key specified, generating a default one...')
698
729
  bootstrap_options[:key_name] = default_aws_keypair(action_handler, machine_spec)
699
730
  end
700
- if bootstrap_options[:iam_instance_profile] && bootstrap_options[:iam_instance_profile].is_a?(String)
701
- bootstrap_options[:iam_instance_profile] = {name: bootstrap_options[:iam_instance_profile]}
702
- end
703
731
  if bootstrap_options[:user_data]
704
732
  bootstrap_options[:user_data] = Base64.encode64(bootstrap_options[:user_data])
705
733
  end
@@ -727,6 +755,12 @@ EOD
727
755
 
728
756
  bootstrap_options = AWSResource.lookup_options(bootstrap_options, managed_entry_store: machine_spec.managed_entry_store, driver: self)
729
757
 
758
+ # We do this after the lookup_options because we need the aws_iam_instance_profile resource to
759
+ # only be passed a String during resource lookup, not `{name: ...}`
760
+ if bootstrap_options[:iam_instance_profile] && bootstrap_options[:iam_instance_profile].is_a?(String)
761
+ bootstrap_options[:iam_instance_profile] = {name: bootstrap_options[:iam_instance_profile]}
762
+ end
763
+
730
764
  # In the migration from V1 to V2 we still support associate_public_ip_address at the top level
731
765
  # we do this after the lookup because we have to copy any present subnets, etc. into the
732
766
  # network interfaces block
@@ -1007,7 +1041,7 @@ EOD
1007
1041
  image ||= image_for(image_spec)
1008
1042
  time_elapsed = 0
1009
1043
  sleep_time = 10
1010
- max_wait_time = 300
1044
+ max_wait_time = Chef::Config.chef_provisioning[:image_max_wait_time] || 300
1011
1045
  if !yield(image)
1012
1046
  action_handler.report_progress "waiting for #{image_spec.name} (#{image.id} on #{driver_url}) to be ready ..."
1013
1047
  while time_elapsed < max_wait_time && !yield(image)
@@ -1030,8 +1064,7 @@ EOD
1030
1064
 
1031
1065
  def wait_until_machine(action_handler, machine_spec, output_msg, instance=nil, &block)
1032
1066
  instance ||= instance_for(machine_spec)
1033
- # TODO make these configurable from Chef::Config
1034
- max_attempts = 12
1067
+ max_attempts = ((Chef::Config.chef_provisioning[:machine_max_wait_time] || 120) / 10).floor
1035
1068
  delay = 10
1036
1069
  log_progress = Proc.new do |attempts, response|
1037
1070
  action_handler.report_progress "been waiting #{delay*attempts}/#{delay*max_attempts} -- sleeping #{delay} seconds for #{machine_spec.name} (#{instance.id} on #{driver_url}) to #{output_msg} ..."
@@ -1054,7 +1087,7 @@ EOD
1054
1087
  instance = instance_for(machine_spec)
1055
1088
  time_elapsed = 0
1056
1089
  sleep_time = 10
1057
- max_wait_time = 120
1090
+ max_wait_time = Chef::Config.chef_provisioning[:machine_max_wait_time] || 120
1058
1091
  transport = transport_for(machine_spec, machine_options, instance)
1059
1092
  unless transport.available?
1060
1093
  if action_handler.should_perform_actions
@@ -1178,12 +1211,24 @@ EOD
1178
1211
  end
1179
1212
 
1180
1213
  def create_instance_and_reference(bootstrap_options, action_handler, machine_spec, machine_options)
1181
- instance = ec2_resource.create_instances(bootstrap_options.to_hash)[0]
1214
+ instance = nil
1215
+ # IAM says the instance profile is ready, but EC2 doesn't think it is
1216
+ # Not using retry_with_backoff here because we need to match on a string
1217
+ Retryable.retryable(
1218
+ :tries => 10,
1219
+ :sleep => lambda { |n| [2**n, 16].min },
1220
+ :on => ::Aws::EC2::Errors::InvalidParameterValue,
1221
+ :matching => /Invalid IAM Instance Profile name/
1222
+ ) do |retries, exception|
1223
+ Chef::Log.debug("Instance creation InvalidParameterValue exception is #{exception.inspect}")
1224
+ instance = ec2_resource.create_instances(bootstrap_options.to_hash)[0]
1225
+ end
1226
+
1182
1227
  # Make sure the instance is ready to be tagged
1183
1228
  instance.wait_until_exists
1184
1229
 
1185
1230
  # Sometimes tagging fails even though the instance 'exists'
1186
- Retryable.retryable(:tries => 12, :sleep => 5, :on => [::Aws::EC2::Errors::InvalidInstanceIDNotFound]) do
1231
+ Chef::Provisioning::AWSDriver::AWSProvider.retry_with_backoff(::Aws::EC2::Errors::InvalidInstanceIDNotFound) do
1187
1232
  instance.create_tags({tags: [{key: "Name", value: machine_spec.name}]})
1188
1233
  end
1189
1234
  if machine_options.has_key?(:source_dest_check)
@@ -5,60 +5,73 @@ module Provisioning
5
5
  module AWSDriver
6
6
  class SuperLWRP < Chef::Resource::LWRPBase
7
7
  #
8
- # Add the :lazy_default and :coerce validation_opts to `attribute`
8
+ # Add the :default lazy { ... } and :coerce validation_opts to `attribute`
9
9
  #
10
- def self.attribute(attr_name, validation_opts={})
11
- lazy_default = validation_opts.delete(:lazy_default)
12
- coerce = validation_opts.delete(:coerce)
13
- if lazy_default || coerce
14
- define_method(attr_name) do |arg=nil|
15
- arg = instance_exec(arg, &coerce) if coerce && !arg.nil?
10
+ if self.respond_to?(:properties)
11
+ # in Chef 12.5+, properties replace attributes and these respond to
12
+ # coerce and default with a lazy block - no need for overwriting!
13
+ else
14
+ def self.attribute(attr_name, validation_opts={})
15
+ if validation_opts[:default].is_a?(Chef::DelayedEvaluator)
16
+ lazy_default = validation_opts.delete(:default)
17
+ end
18
+ coerce = validation_opts.delete(:coerce)
19
+ if lazy_default || coerce
20
+ define_method(attr_name) do |arg=nil|
21
+ arg = instance_exec(arg, &coerce) if coerce && !arg.nil?
16
22
 
17
- result = set_or_return(attr_name.to_sym, arg, validation_opts)
23
+ result = set_or_return(attr_name.to_sym, arg, validation_opts)
18
24
 
19
- if result.nil? && arg.nil?
20
- result = instance_eval(&lazy_default) if lazy_default
21
- end
25
+ if result.nil? && arg.nil?
26
+ result = instance_eval(&lazy_default) if lazy_default
27
+ end
22
28
 
23
- result
24
- end
25
- define_method(:"#{attr_name}=") do |arg|
26
- if arg.nil?
27
- remove_instance_variable(:"@#{arg}")
28
- else
29
- set_or_return(attr_name.to_sym, arg, validation_opts)
29
+ result
30
+ end
31
+ define_method(:"#{attr_name}=") do |arg|
32
+ if arg.nil?
33
+ remove_instance_variable(:"@#{arg}")
34
+ else
35
+ set_or_return(attr_name.to_sym, arg, validation_opts)
36
+ end
30
37
  end
38
+ else
39
+ super
31
40
  end
32
- else
33
- super
34
41
  end
35
- end
36
42
 
37
- # FUUUUUU cloning - this works for Chef 11 or 12.1
38
- def load_prior_resource(*args)
39
- Chef::Log.debug "Overloading #{self.resource_name} load_prior_resource with NOOP"
43
+ # Below chef 12.5 you cannot do `default lazy: { ... }` - this adds that
44
+ def self.lazy(&block)
45
+ Chef::DelayedEvaluator.new(&block)
46
+ end
40
47
  end
41
- end
42
- end
43
- end
44
- end
45
48
 
46
- module NoResourceCloning
47
- def prior_resource
48
- if resource_class <= Chef::Provisioning::AWSDriver::SuperLWRP
49
- Chef::Log.debug "Canceling resource cloning for #{resource_class}"
50
- nil
51
- else
52
- super
49
+ # copy from Chef 12.5 params_validate.rb at http://redirx.me/?t35q.
50
+ if !method_defined?(:_pv_is)
51
+ def _pv_is(opts, key, to_be, raise_error: true)
52
+ return true if !opts.has_key?(key.to_s) && !opts.has_key?(key.to_sym)
53
+ value = _pv_opts_lookup(opts, key)
54
+ to_be = [ to_be ].flatten(1)
55
+ to_be.each do |tb|
56
+ case tb
57
+ when Proc
58
+ return true if instance_exec(value, &tb)
59
+ when Property
60
+ validate(opts, { key => tb.validation_options })
61
+ return true
62
+ else
63
+ return true if tb === value
64
+ end
65
+ end
66
+
67
+ if raise_error
68
+ raise ::Chef::Exceptions::ValidationFailed, "Option #{key} must be one of: #{to_be.join(", ")}! You passed #{value.inspect}."
69
+ else
70
+ false
71
+ end
72
+ end
53
73
  end
54
74
  end
55
- def emit_cloned_resource_warning; end
56
- def emit_harmless_cloning_debug; end
57
75
  end
58
-
59
- # Chef 12.2 changed `load_prior_resource` logic to be in the Chef::ResourceBuilder class
60
- # but that class only exists in 12.2 and up
61
- if defined? Chef::ResourceBuilder
62
- # Ruby 2.0.0 has prepend as a protected method
63
- Chef::ResourceBuilder.send(:prepend, NoResourceCloning)
76
+ end
64
77
  end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module AWSDriver
4
- VERSION = '1.4.1'
4
+ VERSION = '1.5.0'
5
5
  end
6
6
  end
7
7
  end
@@ -47,7 +47,7 @@ class Chef::Resource::AwsDhcpOptions < Chef::Provisioning::AWSDriver::AWSResourc
47
47
  #
48
48
  attribute :netbios_node_type, kind_of: Integer
49
49
 
50
- attribute :dhcp_options_id, kind_of: String, aws_id_attribute: true, lazy_default: proc {
50
+ attribute :dhcp_options_id, kind_of: String, aws_id_attribute: true, default: lazy {
51
51
  name =~ /^dopt-[a-f0-9]{8}$/ ? name : nil
52
52
  }
53
53
 
@@ -19,7 +19,7 @@ class Chef::Resource::AwsEbsVolume < Chef::Provisioning::AWSDriver::AWSResourceW
19
19
  attribute :encrypted, kind_of: [ TrueClass, FalseClass ]
20
20
  attribute :device, kind_of: String
21
21
 
22
- attribute :volume_id, kind_of: String, aws_id_attribute: true, lazy_default: proc {
22
+ attribute :volume_id, kind_of: String, aws_id_attribute: true, default: lazy {
23
23
  name =~ /^vol-[a-f0-9]{8}$/ ? name : nil
24
24
  }
25
25
 
@@ -26,7 +26,7 @@ class Chef::Resource::AwsEipAddress < Chef::Provisioning::AWSDriver::AWSResource
26
26
  # ```
27
27
  #
28
28
  attribute :public_ip, kind_of: String, aws_id_attribute: true, coerce: proc { |v| IPAddr.new(v); v },
29
- lazy_default: proc {
29
+ default: lazy {
30
30
  begin
31
31
  IPAddr.new(name)
32
32
  name
@@ -0,0 +1,33 @@
1
+ require 'chef/provisioning/aws_driver/aws_resource'
2
+
3
+ #
4
+ # An AWS IAM instance profile, a container for an IAM role that you can use to
5
+ # pass role information to an EC2 instance when the instance starts..
6
+ #
7
+ # `name` is unique for an AWS account.
8
+ #
9
+ # API documentation for the AWS Ruby SDK for IAM instance profiles (and the object returned from `aws_object`) can be found here:
10
+ #
11
+ # - http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/InstanceProfile.html
12
+ #
13
+ class Chef::Resource::AwsIamInstanceProfile < Chef::Provisioning::AWSDriver::AWSResource
14
+ aws_sdk_type ::Aws::IAM::InstanceProfile
15
+
16
+ #
17
+ # The name of the instance profile to create.
18
+ #
19
+ attribute :name, kind_of: String, name_attribute: true
20
+
21
+ #
22
+ # The path to the instance profile. For more information about paths, see http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html
23
+ #
24
+ attribute :path, kind_of: String
25
+
26
+ attribute :role, kind_of: [ String, AwsIamRole, ::Aws::IAM::Role]
27
+
28
+ def aws_object
29
+ result = driver.iam_resource.instance_profile(name)
30
+ result && result.exists? ? result : nil
31
+ end
32
+
33
+ end