chef-provisioning-aws 1.4.0 → 1.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19f4ffce05e2b12c1256593ed8132affc94376f8
4
- data.tar.gz: e606311b2689000c0e5098087d5debaff8c2997d
3
+ metadata.gz: e520aad6f6cafb84d380454daf8dd65285e194cd
4
+ data.tar.gz: b2ec1a747718d0cad0c4bdc9ca6561d1e0daeb6f
5
5
  SHA512:
6
- metadata.gz: a37d0a594d564b0a6da4f84b8a4d9d6222654e7bc2ddedb68d22d830cdfea1321cfb4b3d024264e14c81a7462b1f47b3c311ebff79972deb8bba2b4558847f57
7
- data.tar.gz: 8dd82f47ac3c83b52b124d75a316c1c54a348d755c2e892213cd245fdf5f5cfeabebfb67bc81eed26c9362d62ba6c4dbfa3f07a7ecf40dfcc7d00668d00aa800
6
+ metadata.gz: 0c3d1891e4c22d14f3b03506f39105a884dae7bc00ad7dc2ace729f5325f7fbc935b29be11631387563529b19efcad224bb0e2447b77a0365dfd5f6969cfcc1c
7
+ data.tar.gz: a52717acff8c3ccf2945863f616fd8fce022b11fa813b0c8ace68b737be6a797dbb8364cdd94d74884e206357ea786741c657cc1d581ec90502459e8d7e1f6b4
@@ -26,7 +26,8 @@ module AWSDriver
26
26
  # Try to load the credentials from an ordered list of sources and return the first one that
27
27
  # can be loaded successfully.
28
28
  def get_credentials
29
- shared_creds = ::Aws::SharedCredentials.new(:profile_name => profile_name)
29
+ # http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment
30
+ shared_creds = ::Aws::SharedCredentials.new(:profile_name => profile_name, :path => ENV["AWS_CONFIG_FILE"])
30
31
  instance_profile_creds = ::Aws::InstanceProfileCredentials.new(:retries => 1)
31
32
 
32
33
  if ENV["AWS_ACCESS_KEY_ID"] && ENV["AWS_SECRET_ACCESS_KEY"]
@@ -24,10 +24,11 @@ require 'aws-sdk-v1'
24
24
  require 'aws-sdk'
25
25
  require 'retryable'
26
26
  require 'ubuntu_ami'
27
+ require 'base64'
27
28
 
28
29
  # loads the entire aws-sdk
29
30
  AWS.eager_autoload!
30
- AWS_V2_SERVICES = {"EC2" => "ec2", "S3" => "s3", "ElasticLoadBalancing" => "elb"}
31
+ AWS_V2_SERVICES = {"EC2" => "ec2", "S3" => "s3", "ElasticLoadBalancing" => "elb", "IAM" => "iam"}
31
32
  Aws.eager_autoload!(:services => AWS_V2_SERVICES.keys)
32
33
 
33
34
  # Need to load the resources after the SDK because `aws_sdk_types` can mess
@@ -691,19 +692,65 @@ EOD
691
692
  bootstrap_options[:instance_type] ||= default_instance_type
692
693
  image_id = machine_options[:from_image] || bootstrap_options[:image_id] || machine_options[:image_id] || default_ami_for_region(aws_config.region)
693
694
  bootstrap_options[:image_id] = image_id
695
+ bootstrap_options.delete(:key_path)
694
696
  if !bootstrap_options[:key_name]
695
697
  Chef::Log.debug('No key specified, generating a default one...')
696
698
  bootstrap_options[:key_name] = default_aws_keypair(action_handler, machine_spec)
697
699
  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
+ if bootstrap_options[:user_data]
704
+ bootstrap_options[:user_data] = Base64.encode64(bootstrap_options[:user_data])
705
+ end
698
706
 
699
- if machine_options[:is_windows]
700
- Chef::Log.debug "Setting WinRM userdata..."
701
- bootstrap_options[:user_data] = user_data if bootstrap_options[:user_data].nil?
702
- else
703
- Chef::Log.debug "Non-windows, not setting userdata"
707
+ # V1 -> V2 backwards compatability support
708
+ unless bootstrap_options.fetch(:monitoring_enabled, nil).nil?
709
+ bootstrap_options[:monitoring] = {enabled: bootstrap_options.delete(:monitoring_enabled)}
710
+ end
711
+ placement = {}
712
+ if bootstrap_options[:availability_zone]
713
+ placement[:availability_zone] = bootstrap_options.delete(:availability_zone)
714
+ end
715
+ if bootstrap_options[:placement_group]
716
+ placement[:group_name] = bootstrap_options.delete(:placement_group)
717
+ end
718
+ unless bootstrap_options.fetch(:dedicated_tenancy, nil).nil?
719
+ placement[:tenancy] = bootstrap_options.delete(:dedicated_tenancy) ? "dedicated" : "default"
720
+ end
721
+ unless placement.empty?
722
+ bootstrap_options[:placement] = placement
723
+ end
724
+ if bootstrap_options[:subnet]
725
+ bootstrap_options[:subnet_id] = bootstrap_options.delete(:subnet)
704
726
  end
705
727
 
706
728
  bootstrap_options = AWSResource.lookup_options(bootstrap_options, managed_entry_store: machine_spec.managed_entry_store, driver: self)
729
+
730
+ # In the migration from V1 to V2 we still support associate_public_ip_address at the top level
731
+ # we do this after the lookup because we have to copy any present subnets, etc. into the
732
+ # network interfaces block
733
+ unless bootstrap_options.fetch(:associate_public_ip_address, nil).nil?
734
+ if bootstrap_options[:network_interfaces]
735
+ raise "If you specify network_interfaces you must specify associate_public_ip_address in that list"
736
+ end
737
+ network_interface = {
738
+ :device_index => 0,
739
+ :associate_public_ip_address => bootstrap_options.delete(:associate_public_ip_address),
740
+ :delete_on_termination => true
741
+ }
742
+ if bootstrap_options[:subnet_id]
743
+ network_interface[:subnet_id] = bootstrap_options.delete(:subnet_id)
744
+ end
745
+ if bootstrap_options[:private_ip_address]
746
+ network_interface[:private_ip_address] = bootstrap_options.delete(:private_ip_address)
747
+ end
748
+ if bootstrap_options[:security_group_ids]
749
+ network_interface[:groups] = bootstrap_options.delete(:security_group_ids)
750
+ end
751
+ bootstrap_options[:network_interfaces] = [network_interface]
752
+ end
753
+
707
754
  Chef::Log.debug "AWS Bootstrap options: #{bootstrap_options.inspect}"
708
755
  bootstrap_options
709
756
  end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module AWSDriver
4
- VERSION = '1.4.0'
4
+ VERSION = '1.4.1'
5
5
  end
6
6
  end
7
7
  end
@@ -5,7 +5,7 @@ require 'chef/resource/aws_eip_address'
5
5
  class Chef::Resource::AwsNetworkInterface < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
6
6
  include Chef::Provisioning::AWSDriver::AWSTaggable
7
7
 
8
- aws_sdk_type AWS::EC2::NetworkInterface
8
+ aws_sdk_type AWS::EC2::NetworkInterface, option_names: []
9
9
 
10
10
  attribute :name, kind_of: String, name_attribute: true
11
11
 
@@ -16,7 +16,7 @@ require 'chef/provisioning/aws_driver/aws_resource_with_entry'
16
16
  class Chef::Resource::AwsSubnet < Chef::Provisioning::AWSDriver::AWSResourceWithEntry
17
17
  include Chef::Provisioning::AWSDriver::AWSTaggable
18
18
 
19
- aws_sdk_type AWS::EC2::Subnet
19
+ aws_sdk_type AWS::EC2::Subnet, :id => :id
20
20
 
21
21
  require 'chef/resource/aws_vpc'
22
22
  require 'chef/resource/aws_network_acl'
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'openssl'
2
3
 
3
4
  describe Chef::Resource::Machine do
4
5
  extend AWSSupport
@@ -53,6 +54,224 @@ describe Chef::Resource::Machine do
53
54
  ).and be_idempotent
54
55
  end
55
56
 
57
+ it "base64 encodes the user data", :super_slow do
58
+ uniq = Random.rand(100)
59
+ expect_recipe {
60
+ machine "test_machine_#{uniq}" do
61
+ machine_options bootstrap_options: {
62
+ subnet_id: 'test_public_subnet',
63
+ key_name: 'test_key_pair',
64
+ user_data: 'echo \'foo\''
65
+ }
66
+ action :allocate
67
+ end
68
+ }.to create_an_aws_instance("test_machine_#{uniq}"
69
+ ).and be_idempotent
70
+ expect(
71
+ driver.ec2_client.describe_instance_attribute(
72
+ instance_id: driver.ec2_resource.instances(filters: [{name: "tag:Name", values:["test_machine_#{uniq}"]}]).first.id,
73
+ attribute: "userData"
74
+ ).user_data.value
75
+ ).to eq("ZWNobyAnZm9vJw==\n")
76
+ end
77
+
78
+ it "respects the network_interfaces block with maximum attributes", :super_slow do
79
+ private_ip_address_start = Random.rand(30)+10
80
+ expect_recipe {
81
+ machine "test_machine" do
82
+ machine_options bootstrap_options: {
83
+ key_name: 'test_key_pair',
84
+ instance_type: 'm3.medium',
85
+ network_interfaces: [
86
+ {
87
+ # Cannot set associate_public_ip_address and network_interface_id
88
+ # network_interface_id: "eth0",
89
+ device_index: 0,
90
+ subnet_id: test_public_subnet.aws_object.id,
91
+ description: "network interface description",
92
+ private_ip_address: "10.0.0.#{private_ip_address_start}",
93
+ delete_on_termination: true,
94
+ groups: [test_security_group.aws_object.id],
95
+ private_ip_addresses: [
96
+ {
97
+ private_ip_address: "10.0.0.#{private_ip_address_start+1}",
98
+ primary: false
99
+ },
100
+ {
101
+ private_ip_address: "10.0.0.#{private_ip_address_start+2}",
102
+ primary: false
103
+ }
104
+ ],
105
+ # cannot specify both `private_ip_addresses` and `secondary_private_ip_address_count`
106
+ #secondary_private_ip_address_count: 2,
107
+ associate_public_ip_address: true
108
+ }
109
+ ]
110
+ }
111
+ action :ready
112
+ end
113
+ }.to create_an_aws_instance("test_machine",
114
+ network_interfaces: [{
115
+ network_interface_id: /^eni-/,
116
+ subnet_id: test_public_subnet.aws_object.id,
117
+ vpc_id: test_vpc.aws_object.id,
118
+ description: "network interface description",
119
+ status: "in-use",
120
+ private_ip_address: "10.0.0.#{private_ip_address_start}",
121
+ groups: [{group_name: 'test_security_group'}],
122
+ attachment: {
123
+ device_index: 0,
124
+ delete_on_termination: true,
125
+ status: "attached"
126
+ },
127
+ private_ip_addresses: [
128
+ {
129
+ private_ip_address: "10.0.0.#{private_ip_address_start}",
130
+ primary: true,
131
+ # the action must be :ready to give the public ip time to be assigned
132
+ association: {
133
+ public_ip: /\d+/
134
+ }
135
+ },
136
+ {
137
+ private_ip_address: "10.0.0.#{private_ip_address_start+1}",
138
+ primary: false
139
+ },
140
+ {
141
+ private_ip_address: "10.0.0.#{private_ip_address_start+2}",
142
+ primary: false
143
+ }
144
+ ]
145
+ }]
146
+ ).and be_idempotent
147
+ end
148
+
149
+ it "converts associate_public_ip_address at the top level to the network interface", :super_slow do
150
+ private_ip_address_start = Random.rand(30)+10
151
+ expect_recipe {
152
+ machine "test_machine" do
153
+ machine_options bootstrap_options: {
154
+ key_name: 'test_key_pair',
155
+ instance_type: 'm3.medium',
156
+ associate_public_ip_address: true,
157
+ subnet_id: test_public_subnet.aws_object.id,
158
+ security_group_ids: [test_security_group.aws_object.id],
159
+ private_ip_address: "10.0.0.#{private_ip_address_start}"
160
+ }
161
+ action :ready
162
+ end
163
+ }.to create_an_aws_instance("test_machine",
164
+ network_interfaces: [{
165
+ network_interface_id: /^eni-/,
166
+ subnet_id: test_public_subnet.aws_object.id,
167
+ vpc_id: test_vpc.aws_object.id,
168
+ status: "in-use",
169
+ private_ip_address: "10.0.0.#{private_ip_address_start}",
170
+ groups: [{group_name: 'test_security_group'}],
171
+ attachment: {
172
+ device_index: 0,
173
+ delete_on_termination: true,
174
+ status: "attached"
175
+ },
176
+ private_ip_addresses: [
177
+ {
178
+ private_ip_address: "10.0.0.#{private_ip_address_start}",
179
+ primary: true,
180
+ association: {
181
+ public_ip: /\d+/
182
+ }
183
+ }
184
+ ]
185
+ }]
186
+ ).and be_idempotent
187
+ end
188
+
189
+ context "with a placement group" do
190
+ before(:context) {
191
+ driver.ec2_client.create_placement_group({
192
+ group_name: "agroup",
193
+ strategy: "cluster"
194
+ })
195
+ }
196
+
197
+ # Must do after the context so we have waited for the instance to terminate
198
+ after(:context) {
199
+ driver.ec2_client.delete_placement_group group_name: "agroup"
200
+ }
201
+
202
+ it "converts V1 keys to V2 keys", :super_slow do
203
+ expect_recipe {
204
+ machine "test_machine" do
205
+ machine_options bootstrap_options: {
206
+ key_name: 'test_key_pair',
207
+ instance_type: 'm4.large',
208
+ monitoring_enabled: false,
209
+ availability_zone: test_public_subnet.aws_object.availability_zone_name,
210
+ placement_group: "agroup",
211
+ dedicated_tenancy: false, # cannot do true, was getting API error
212
+ subnet: 'test_public_subnet'
213
+ }
214
+ action :allocate
215
+ end
216
+ }.to create_an_aws_instance("test_machine",
217
+ monitoring: {state: "disabled"},
218
+ placement: {
219
+ availability_zone: test_public_subnet.aws_object.availability_zone_name,
220
+ group_name: "agroup",
221
+ tenancy: "default",
222
+ },
223
+ subnet_id: test_public_subnet.aws_object.id
224
+ ).and be_idempotent
225
+ end
226
+ end
227
+
228
+ context "with a custom iam role" do
229
+ # TODO when we have IAM support, use the resources
230
+ before(:context) do
231
+ assume_role_policy_document = '{"Version":"2008-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]}'
232
+ driver.iam_client.create_role({
233
+ role_name: "machine_test_custom_role",
234
+ assume_role_policy_document: assume_role_policy_document
235
+ }).role
236
+ driver.iam_client.create_instance_profile({
237
+ instance_profile_name: "machine_test_custom_role"
238
+ })
239
+ driver.iam_client.add_role_to_instance_profile({
240
+ instance_profile_name: "machine_test_custom_role",
241
+ role_name: "machine_test_custom_role"
242
+ })
243
+ sleep 5 # grrrrrr, the resource should take care of the polling for us
244
+ end
245
+
246
+ after(:context) do
247
+ driver.iam_client.remove_role_from_instance_profile({
248
+ instance_profile_name: "machine_test_custom_role",
249
+ role_name: "machine_test_custom_role"
250
+ })
251
+ driver.iam_client.delete_instance_profile({
252
+ instance_profile_name: "machine_test_custom_role"
253
+ })
254
+ driver.iam_client.delete_role({
255
+ role_name: "machine_test_custom_role"
256
+ })
257
+ end
258
+
259
+ it "converts iam_instance_profile from a string to a hash", :super_slow do
260
+ expect_recipe {
261
+ machine 'test_machine' do
262
+ machine_options bootstrap_options: {
263
+ subnet_id: 'test_public_subnet',
264
+ key_name: 'test_key_pair',
265
+ iam_instance_profile: "machine_test_custom_role"
266
+ }
267
+ action :allocate
268
+ end
269
+ }.to create_an_aws_instance('test_machine',
270
+ iam_instance_profile: {arn: /machine_test_custom_role/}
271
+ ).and be_idempotent
272
+ end
273
+ end
274
+
56
275
  it "machine with from_image option is created from correct image", :super_slow do
57
276
  expect_recipe {
58
277
 
@@ -113,6 +332,48 @@ describe Chef::Resource::Machine do
113
332
  end
114
333
  }.converge }.to_not raise_error
115
334
  end
335
+
336
+ # https://github.com/chef/chef-provisioning-aws/pull/295
337
+ context "with a custom key" do
338
+ let(:private_key) {
339
+ k = OpenSSL::PKey::RSA.new(2048)
340
+ f = Pathname.new(private_key_path)
341
+ f.write(k.to_pem)
342
+ k
343
+ }
344
+ let(:public_key) {private_key.public_key}
345
+ let(:private_key_path) {
346
+ Pathname.new(ENV['HOME']).join(".ssh", key_pair_name).expand_path
347
+ }
348
+ let(:key_pair_name) { "test_key_pair_#{Random.rand(100)}" }
349
+
350
+ before do
351
+ driver.ec2_client.import_key_pair({
352
+ key_name: key_pair_name, # required
353
+ public_key_material: "#{public_key.ssh_type} #{[public_key.to_blob].pack('m0')}", # required
354
+ })
355
+ end
356
+
357
+ after do
358
+ driver.ec2_client.delete_key_pair({
359
+ key_name: key_pair_name, # required
360
+ })
361
+ Pathname.new(private_key_path).delete
362
+ end
363
+
364
+ it "strips key_path from the bootstrap options when creating the machine", :super_slow do
365
+ expect_recipe {
366
+ machine 'test_machine' do
367
+ machine_options bootstrap_options: {
368
+ key_name: key_pair_name,
369
+ key_path: private_key_path
370
+ }
371
+ end
372
+ }.to create_an_aws_instance('test_machine'
373
+ ).and be_idempotent
374
+ end
375
+ end
376
+
116
377
  end
117
378
  end
118
379
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-provisioning-aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Ewart
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-16 00:00:00.000000000 Z
11
+ date: 2015-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-provisioning
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: '1.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
26
+ version: '1.4'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: aws-sdk-v1
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -233,7 +233,6 @@ files:
233
233
  - lib/chef/resource/aws_subnet.rb
234
234
  - lib/chef/resource/aws_vpc.rb
235
235
  - lib/chef/resource/aws_vpc_peering_connection.rb
236
- - spec/acceptance/aws_ebs_volume/nodes/ettores-mbp.lan.json
237
236
  - spec/aws_support.rb
238
237
  - spec/aws_support/aws_resource_run_wrapper.rb
239
238
  - spec/aws_support/deep_matcher.rb
@@ -290,9 +289,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
290
289
  version: '0'
291
290
  requirements: []
292
291
  rubyforge_project:
293
- rubygems_version: 2.4.5
292
+ rubygems_version: 2.4.7
294
293
  signing_key:
295
294
  specification_version: 4
296
295
  summary: Provisioner for creating aws containers in Chef Provisioning.
297
296
  test_files: []
298
- has_rdoc:
@@ -1,3 +0,0 @@
1
- {
2
- "name": "ettores-mbp.lan"
3
- }