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 +4 -4
- data/lib/chef/provisioning/aws_driver/credentials2.rb +2 -1
- data/lib/chef/provisioning/aws_driver/driver.rb +53 -6
- data/lib/chef/provisioning/aws_driver/version.rb +1 -1
- data/lib/chef/resource/aws_network_interface.rb +1 -1
- data/lib/chef/resource/aws_subnet.rb +1 -1
- data/spec/integration/machine_spec.rb +261 -0
- metadata +5 -7
- data/spec/acceptance/aws_ebs_volume/nodes/ettores-mbp.lan.json +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e520aad6f6cafb84d380454daf8dd65285e194cd
|
4
|
+
data.tar.gz: b2ec1a747718d0cad0c4bdc9ca6561d1e0daeb6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
700
|
-
|
701
|
-
bootstrap_options[:
|
702
|
-
|
703
|
-
|
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
|
@@ -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.
|
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-
|
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.
|
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.
|
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.
|
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:
|