stemcell 0.11.11 → 0.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: be5d265d86505b9f9510c4a49e32edcd3818ad2d
4
- data.tar.gz: fe8c43abeb21b2e0d0aba92c9cb7f96ccfabfda9
2
+ SHA256:
3
+ metadata.gz: e65ab6388e741e11ab2f46af451098bd7fe70cb847f3ea8f1b9b9d229c860c2c
4
+ data.tar.gz: 568f4aecc9c7518ed156355035b39843b04d006bec7876438d707e097e071d30
5
5
  SHA512:
6
- metadata.gz: 9c9636e89c8892261da6372741985d6a0cd4759eadeebe3450bdc8f5093906a776d9cf3ed17cb0e53329a53d9e1493d6f469636d638dc3f4254248b4a8effa94
7
- data.tar.gz: d8cafabc54c274f5952aa2b8f4406eeabd73b39f45cb6e0b7161ccdb01b5526ac687df43de80dde0926bd63bdb46f2574643d07dcb9b601ee0118d3b7a5c9970
6
+ metadata.gz: 53d4581e807c8c1373189437a5e0afb42e0dc00c62b3b2b18797a31ae72d483ac066af02c455cfc3fc9a98dcc5452f433bfef618b8f8e56643f5748cff22ce12
7
+ data.tar.gz: 431fe9ee22ac0f42ff40227f1ce39e74a88af53af1fb4dc571cace78d167e346d125a2615d35799060853767801412a8c8d4ba35603d269ebc1b5232ec4bbda5
data/.travis.yml CHANGED
@@ -2,9 +2,8 @@ sudo: false
2
2
  language: ruby
3
3
  cache: bundler
4
4
  rvm:
5
- - 1.9.3
6
5
  - 2.1.2
7
6
  - 2.2.4
8
7
  - 2.3.1
9
8
  before_install:
10
- - gem install bundler
9
+ - gem install bundler -v 1.16.3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # 0.13.0
2
+ - Migrate to AWS SDK to v3
3
+ - Drop support for ClassicLink
4
+ - Removed `necrosis` script
5
+
6
+ # 0.12.2
7
+ - Support for using a custom EC2 endpoint
8
+
9
+ # 0.12.1
10
+ - Add support for Amazon Linux to the default bootstrap script
11
+ - Allow setting backing_store options per region
12
+ - Display private ip for launched instances
13
+
14
+ # 0.12.0
15
+ - Require Nokogiri ~> 1.8.2 due to vulnerability CVE-2017-15412
16
+ - Require ruby version >= 2.1 for Nokogiri compatibility
17
+
1
18
  # 0.11.11
2
19
  - Fix set_classic_link issue - vpc_id could be nil or false
3
20
 
data/Gemfile CHANGED
@@ -9,4 +9,4 @@ group :test do
9
9
  gem 'rake', '~> 10.3.2'
10
10
  end
11
11
 
12
- gem 'nokogiri', '< 1.7.0'
12
+ gem 'nokogiri', '~> 1.8.2'
data/README.md CHANGED
@@ -77,10 +77,10 @@ $ stemcell $your_chef_role --tail
77
77
 
78
78
  ### Terminating:
79
79
 
80
- To terminate, use the necrosis command and pass a space separated list of instance ids:
80
+ To terminate, use the AWS CLI and pass a space separated list of instance ids:
81
81
 
82
82
  ```bash
83
- $ necrosis i-12345678 i-12345679 i-12345670
83
+ $ aws ec2 terminate-instances --instance-ids i-12345678 i-12345679 i-12345670
84
84
  ```
85
85
 
86
86
  ## Automation ##
@@ -9,10 +9,14 @@
9
9
 
10
10
  "backing_store": {
11
11
  "ebs": {
12
- "image_id": "ami-23d9a94a"
12
+ "us-east-1": {
13
+ "image_id": "ami-23d9a94a"
14
+ }
13
15
  },
14
16
  "instance_store": {
15
- "image_id": "ami-d9d6a6b0"
17
+ "us-east-1": {
18
+ "image_id": "ami-d9d6a6b0"
19
+ }
16
20
  }
17
21
  },
18
22
 
@@ -1,4 +1,5 @@
1
- require 'aws-sdk-v1'
1
+ require 'aws-sdk-ec2'
2
+ require 'base64'
2
3
  require 'logger'
3
4
  require 'erb'
4
5
  require 'set'
@@ -48,7 +49,6 @@ module Stemcell
48
49
  'security_groups',
49
50
  'security_group_ids',
50
51
  'tags',
51
- 'classic_link',
52
52
  'iam_role',
53
53
  'ebs_optimized',
54
54
  'termination_protection',
@@ -75,6 +75,7 @@ module Stemcell
75
75
 
76
76
  @region = opts['region']
77
77
  @vpc_id = opts['vpc_id']
78
+ @ec2_endpoint = opts['ec2_endpoint']
78
79
  @aws_access_key = opts['aws_access_key']
79
80
  @aws_secret_key = opts['aws_secret_key']
80
81
  @aws_session_token = opts['aws_session_token']
@@ -89,7 +90,7 @@ module Stemcell
89
90
  opts['git_key'] = try_file(opts['git_key'])
90
91
  opts['chef_data_bag_secret'] = try_file(opts['chef_data_bag_secret'])
91
92
 
92
- # generate tags and merge in any that were specefied as inputs
93
+ # generate tags and merge in any that were specified as inputs
93
94
  tags = {
94
95
  'Name' => "#{opts['chef_role']}-#{opts['chef_environment']}",
95
96
  'Group' => "#{opts['chef_role']}-#{opts['chef_environment']}",
@@ -105,31 +106,38 @@ module Stemcell
105
106
  :image_id => opts['image_id'],
106
107
  :instance_type => opts['instance_type'],
107
108
  :key_name => opts['key_name'],
108
- :count => opts['count'],
109
+ :min_count => opts['count'],
110
+ :max_count => opts['count'],
109
111
  }
110
112
 
113
+
114
+ # Associate Public IP can only bet set on network_interfaces, and if present
115
+ # security groups and subnet should be set on the interface. VPC-only.
116
+ # Primary network interface
117
+ network_interface = {
118
+ device_index: 0,
119
+ }
120
+ launch_options[:network_interfaces] = [network_interface]
121
+
111
122
  if opts['security_group_ids'] && !opts['security_group_ids'].empty?
112
- launch_options[:security_group_ids] = opts['security_group_ids']
123
+ network_interface[:groups] = opts['security_group_ids']
113
124
  end
114
125
 
115
126
  if opts['security_groups'] && !opts['security_groups'].empty?
116
- if @vpc_id
117
- # convert sg names to sg ids as VPC only accepts ids
118
- security_group_ids = get_vpc_security_group_ids(@vpc_id, opts['security_groups'])
119
- launch_options[:security_group_ids] ||= []
120
- launch_options[:security_group_ids].concat(security_group_ids)
121
- else
122
- launch_options[:security_groups] = opts['security_groups']
123
- end
127
+ # convert sg names to sg ids as VPC only accepts ids
128
+ security_group_ids = get_vpc_security_group_ids(@vpc_id, opts['security_groups'])
129
+ network_interface[:groups] ||= []
130
+ network_interface[:groups].concat(security_group_ids)
124
131
  end
125
132
 
133
+ launch_options[:placement] = placement = {}
126
134
  # specify availability zone (optional)
127
135
  if opts['availability_zone']
128
- launch_options[:availability_zone] = opts['availability_zone']
136
+ placement[:availability_zone] = opts['availability_zone']
129
137
  end
130
138
 
131
139
  if opts['subnet']
132
- launch_options[:subnet] = opts['subnet']
140
+ network_interface[:subnet_id] = opts['subnet']
133
141
  end
134
142
 
135
143
  if opts['private_ip_address']
@@ -137,23 +145,23 @@ module Stemcell
137
145
  end
138
146
 
139
147
  if opts['dedicated_tenancy']
140
- launch_options[:dedicated_tenancy] = opts['dedicated_tenancy']
148
+ placement[:tenancy] = 'dedicated'
141
149
  end
142
150
 
143
151
  if opts['associate_public_ip_address']
144
- launch_options[:associate_public_ip_address] = opts['associate_public_ip_address']
152
+ network_interface[:associate_public_ip_address] = opts['associate_public_ip_address']
145
153
  end
146
154
 
147
155
  # specify IAM role (optional)
148
156
  if opts['iam_role']
149
- launch_options[:iam_instance_profile] = opts['iam_role']
157
+ launch_options[:iam_instance_profile] = {
158
+ name: opts['iam_role']
159
+ }
150
160
  end
151
161
 
152
162
  # specify placement group (optional)
153
163
  if opts['placement_group']
154
- launch_options[:placement] = {
155
- :group_name => opts['placement_group'],
156
- }
164
+ placement[:group_name] = opts['placement_group']
157
165
  end
158
166
 
159
167
  # specify an EBS-optimized instance (optional)
@@ -181,35 +189,31 @@ module Stemcell
181
189
  end
182
190
  end
183
191
 
192
+ if opts['termination_protection']
193
+ launch_options[:disable_api_termination] = true
194
+ end
195
+
184
196
  # generate user data script to bootstrap instance, include in launch
185
197
  # options UNLESS we have manually set the user-data (ie. for ec2admin)
186
- launch_options[:user_data] = opts.fetch('user_data', render_template(opts))
198
+ launch_options[:user_data] = Base64.encode64(opts.fetch('user_data', render_template(opts)))
199
+
200
+ # add tags to launch options so we don't need to make a separate CreateTags call
201
+ launch_options[:tag_specifications] = [{
202
+ resource_type: 'instance',
203
+ tags: tags.map { |k, v| { key: k, value: v } }
204
+ }]
187
205
 
188
206
  # launch instances
189
207
  instances = do_launch(launch_options)
190
208
 
191
209
  # everything from here on out must succeed, or we kill the instances we just launched
192
210
  begin
193
- # set tags on all instances launched
194
- set_tags(instances, tags)
195
- @log.info "sent ec2 api tag requests successfully"
196
-
197
- # link to classiclink
198
- unless @vpc_id
199
- set_classic_link(instances, opts['classic_link'])
200
- @log.info "successfully applied classic link settings (if any)"
201
- end
202
-
203
- # turn on termination protection
204
- # we do this now to make sure all other settings worked
205
- if opts['termination_protection']
206
- enable_termination_protection(instances)
207
- @log.info "successfully enabled termination protection"
208
- end
209
-
210
211
  # wait for aws to report instance stats
211
212
  if opts.fetch('wait', true)
212
- wait(instances)
213
+ instance_ids = instances.map(&:instance_id)
214
+ @log.info "Waiting up to #{MAX_RUNNING_STATE_WAIT_TIME} seconds for #{instances.count} " \
215
+ "instance(s): (#{instance_ids})"
216
+ instances = wait(instance_ids)
213
217
  print_run_info(instances)
214
218
  @log.info "launched instances successfully"
215
219
  end
@@ -226,19 +230,18 @@ module Stemcell
226
230
  return instances
227
231
  end
228
232
 
229
- def kill(instances, opts={})
230
- return if !instances || instances.empty?
233
+ def kill(instance_ids, opts={})
234
+ return if !instance_ids || instance_ids.empty?
231
235
 
232
- errors = run_batch_operation(instances) do |instance|
233
- begin
234
- @log.warn "Terminating instance #{instance.id}"
235
- instance.terminate
236
- nil # nil == success
237
- rescue AWS::EC2::Errors::InvalidInstanceID::NotFound => e
238
- opts[:ignore_not_found] ? nil : e
239
- end
240
- end
241
- check_errors(:kill, instances.map(&:id), errors)
236
+ @log.warn "Terminating instances #{instance_ids}"
237
+ ec2.terminate_instances(instance_ids: instance_ids)
238
+ nil # nil == success
239
+ rescue Aws::EC2::Errors::InvalidInstanceIDNotFound => e
240
+ raise unless opts[:ignore_not_found]
241
+
242
+ invalid_ids = e.message.scan(/i-[a-z0-9]+/)
243
+ instance_ids -= invalid_ids
244
+ retry unless instance_ids.empty? || invalid_ids.empty? # don't retry if we couldn't find any instance ids
242
245
  end
243
246
 
244
247
  # this is made public for ec2admin usage
@@ -248,7 +251,7 @@ module Stemcell
248
251
  erb_template = ERB.new(template_file)
249
252
  last_bootstrap_line = LAST_BOOTSTRAP_LINE
250
253
  generated_template = erb_template.result(binding)
251
- @log.debug "genereated template is #{generated_template}"
254
+ @log.debug "generated template is #{generated_template}"
252
255
  return generated_template
253
256
  end
254
257
 
@@ -258,22 +261,23 @@ module Stemcell
258
261
  puts "\nhere is the info for what's launched:"
259
262
  instances.each do |instance|
260
263
  puts "\tinstance_id: #{instance.instance_id}"
261
- puts "\tpublic ip: #{instance.public_ip_address}"
264
+ puts "\tpublic ip: #{instance.public_ip_address || 'none'}"
265
+ puts "\tprivate ip: #{instance.private_ip_address || 'none'}"
262
266
  puts
263
267
  end
264
268
  puts "install logs will be in /var/log/init and /var/log/init.err"
265
269
  end
266
270
 
267
- def wait(instances)
268
- @log.info "Waiting up to #{MAX_RUNNING_STATE_WAIT_TIME} seconds for #{instances.count} " \
269
- "instance(s): (#{instances.inspect})"
270
-
271
- times_out_at = Time.now + MAX_RUNNING_STATE_WAIT_TIME
272
- until instances.all?{ |i| i.status == :running }
273
- wait_time_expire_or_sleep(times_out_at)
271
+ def wait(instance_ids)
272
+ started_at = Time.now
273
+ result = ec2.wait_until(:instance_running, instance_ids: instance_ids) do |w|
274
+ w.max_attempts = nil
275
+ w.delay = RUNNING_STATE_WAIT_SLEEP_TIME
276
+ w.before_wait do |attempts, response|
277
+ throw :failure if Time.now - started_at > MAX_RUNNING_STATE_WAIT_TIME
278
+ end
274
279
  end
275
-
276
- @log.info "all instances in running state"
280
+ result.map { |page| page.reservations.map(&:instances) }.flatten
277
281
  end
278
282
 
279
283
  def verify_required_options(params, required_options)
@@ -289,35 +293,22 @@ module Stemcell
289
293
  def do_launch(opts={})
290
294
  @log.debug "about to launch instance(s) with options #{opts}"
291
295
  @log.info "launching instances"
292
- instances = ec2.instances.create(opts)
293
- instances = [instances] unless Array === instances
296
+ instances = ec2.run_instances(opts).instances
294
297
  instances.each do |instance|
295
298
  @log.info "launched instance #{instance.instance_id}"
296
299
  end
297
300
  return instances
298
301
  end
299
302
 
300
- def set_tags(instances=[], tags)
301
- @log.info "setting tags on instance(s)"
302
- errors = run_batch_operation(instances) do |instance|
303
- begin
304
- instance.tags.set(tags)
305
- nil # nil == success
306
- rescue AWS::EC2::Errors::InvalidInstanceID::NotFound => e
307
- e
308
- end
309
- end
310
- check_errors(:set_tags, instances.map(&:id), errors)
311
- end
312
-
313
303
  # Resolve security group names to their ids in the given VPC
314
304
  def get_vpc_security_group_ids(vpc_id, group_names)
315
305
  group_map = {}
316
306
  @log.info "resolving security groups #{group_names} in #{vpc_id}"
317
- vpc = AWS::EC2::VPC.new(vpc_id, :ec2_endpoint => "ec2.#{@region}.amazonaws.com")
318
- vpc.security_groups.each do |sg|
319
- next if sg.vpc_id != vpc_id
320
- group_map[sg.name] = sg.group_id
307
+ ec2.describe_security_groups(filters: [{ name: 'vpc-id', values: [vpc_id] }]).
308
+ each do |response|
309
+ response.security_groups.each do |sg|
310
+ group_map[sg.group_name] = sg.group_id
311
+ end
321
312
  end
322
313
  group_ids = []
323
314
  group_names.each do |sg_name|
@@ -327,129 +318,15 @@ module Stemcell
327
318
  group_ids
328
319
  end
329
320
 
330
- def set_classic_link(left_to_process, classic_link)
331
- return unless classic_link
332
- return unless classic_link['vpc_id']
333
-
334
- security_group_ids = classic_link['security_group_ids'] || []
335
- security_group_names = classic_link['security_groups'] || []
336
- return if security_group_ids.empty? && security_group_names.empty?
337
-
338
- if !security_group_names.empty?
339
- extra_group_ids = get_vpc_security_group_ids(classic_link['vpc_id'], security_group_names)
340
- security_group_ids = security_group_ids + extra_group_ids
341
- end
342
-
343
- @log.info "applying classic link settings on #{left_to_process.count} instance(s)"
344
-
345
- errors = []
346
- processed = []
347
- times_out_at = Time.now + MAX_RUNNING_STATE_WAIT_TIME
348
- until left_to_process.empty?
349
- wait_time_expire_or_sleep(times_out_at)
350
-
351
- # we can only apply classic link when instances are in the running state
352
- # lets apply classiclink as instances become available so we don't wait longer than necessary
353
- recently_running = left_to_process.select{ |inst| inst.status == :running }
354
- left_to_process = left_to_process.reject{ |inst| recently_running.include?(inst) }
355
-
356
- processed += recently_running
357
- errors += run_batch_operation(recently_running) do |instance|
358
- begin
359
- result = ec2.client.attach_classic_link_vpc({
360
- :instance_id => instance.id,
361
- :vpc_id => classic_link['vpc_id'],
362
- :groups => security_group_ids,
363
- })
364
- result.error
365
- rescue StandardError => e
366
- e
367
- end
368
- end
369
- end
370
-
371
- check_errors(:set_classic_link, processed.map(&:id), errors)
372
- end
373
-
374
- def enable_termination_protection(instances)
375
- @log.info "enabling termination protection on instance(s)"
376
- errors = run_batch_operation(instances) do |instance|
377
- begin
378
- resp = ec2.client.modify_instance_attribute({
379
- :instance_id => instance.id,
380
- :disable_api_termination => {
381
- :value => true
382
- }
383
- })
384
- resp.error # returns nil (success) unless there was an error
385
- rescue StandardError => e
386
- e
387
- end
388
- end
389
- check_errors(:enable_termination_protection, instances.map(&:id), errors)
390
- end
391
-
392
321
  # attempt to accept keys as file paths
393
322
  def try_file(opt="")
394
323
  File.read(File.expand_path(opt)) rescue opt
395
324
  end
396
325
 
397
- INITIAL_RETRY_SEC = 1
398
-
399
- # Return a Hash of instance => error. Empty hash indicates "no error"
400
- # for code block:
401
- # - if block returns nil, success
402
- # - if block returns non-nil value (e.g., exception), retry 3 times w/ backoff
403
- # - if block raises exception, fail
404
- def run_batch_operation(instances)
405
- instances.map do |instance|
406
- begin
407
- attempt = 0
408
- result = nil
409
- while attempt < @max_attempts
410
- # sleep idempotently except for the first attempt
411
- sleep(INITIAL_RETRY_SEC * 2 ** attempt) if attempt != 0
412
- result = yield(instance)
413
- break if result.nil? # nil indicates success
414
- attempt += 1
415
- end
416
- result # result for this instance is nil or returned exception
417
- rescue => e
418
- e # result for this instance is caught exception
419
- end
420
- end
421
- end
422
-
423
- def check_errors(operation, instance_ids, errors)
424
- return if errors.all?(&:nil?)
425
- raise IncompleteOperation.new(
426
- operation,
427
- instance_ids,
428
- instance_ids.zip(errors).reject { |i, e| e.nil? }
429
- )
430
- end
431
-
432
326
  def ec2
433
- return @ec2 if @ec2
434
-
435
- # calculate our ec2 url
436
- ec2_url = "ec2.#{@region}.amazonaws.com"
437
-
438
- if @vpc_id
439
- @ec2 = AWS::EC2::VPC.new(@vpc_id, :ec2_endpoint => ec2_url)
440
- else
441
- @ec2 = AWS::EC2.new(:ec2_endpoint => ec2_url)
442
- end
443
-
444
- @ec2
445
- end
446
-
447
- def wait_time_expire_or_sleep(times_out_at)
448
- now = Time.now
449
- if now >= times_out_at
450
- raise TimeoutError, "exceded timeout of #{MAX_RUNNING_STATE_WAIT_TIME} seconds"
451
- else
452
- sleep [RUNNING_STATE_WAIT_SLEEP_TIME, times_out_at - now].min
327
+ @ec2 ||= begin
328
+ opts = @ec2_endpoint ? { endpoint: @ec2_endpoint } : {}
329
+ Aws::EC2::Client.new(opts)
453
330
  end
454
331
  end
455
332
 
@@ -463,7 +340,7 @@ module Stemcell
463
340
  aws_configs.merge!({
464
341
  :session_token => @aws_session_token,
465
342
  }) if @aws_session_token
466
- AWS.config(aws_configs)
343
+ Aws.config.update(aws_configs)
467
344
  end
468
345
  end
469
346
  end
@@ -101,6 +101,7 @@ module Stemcell
101
101
  'region' => options['region'],
102
102
  'vpc_id' => options['vpc_id'],
103
103
  'max_attempts' => options['batch_operation_retries'],
104
+ 'ec2_endpoint' => options['ec2_endpoint'],
104
105
  })
105
106
  # Slice off just the options used for launching.
106
107
  launch_options = {}
@@ -21,10 +21,10 @@ module Stemcell
21
21
  validate_configutation
22
22
  end
23
23
 
24
- def options_for_backing_store(backing_store)
24
+ def options_for_backing_store(backing_store, region)
25
25
  options = backing_store_options[backing_store]
26
26
  raise UnknownBackingStoreError.new(backing_store) if options.nil?
27
- options
27
+ options.fetch(region, options)
28
28
  end
29
29
 
30
30
  def random_az_for_region(region)
@@ -84,9 +84,14 @@ module Stemcell
84
84
  backing_store ||= config.default_options['backing_store']
85
85
  backing_store ||= DEFAULT_BACKING_STORE
86
86
 
87
+ backing_store_region = override_options['region']
88
+ backing_store_region ||= role_options.to_hash['region'] if role_options
89
+ backing_store_region ||= config.default_options['region']
90
+ backing_store_region ||= DEFAULT_OPTIONS['region']
91
+
87
92
  # Step 3: Retrieve the backing store options from the defaults.
88
93
 
89
- backing_store_options = config.options_for_backing_store(backing_store)
94
+ backing_store_options = config.options_for_backing_store(backing_store, backing_store_region)
90
95
  backing_store_options['backing_store'] = backing_store
91
96
 
92
97
  # Step 4: Merge the options together in priority order.
@@ -42,6 +42,12 @@ module Stemcell
42
42
  :env => 'AWS_SESSION_TOKEN',
43
43
  :hide => true
44
44
  },
45
+ {
46
+ :name => 'ec2_endpoint',
47
+ :desc => 'EC2 endpoint',
48
+ :type => String,
49
+ :env => 'EC2_ENDPOINT',
50
+ },
45
51
  {
46
52
  :name => 'region',
47
53
  :desc => "ec2 region to launch in",
@@ -90,24 +96,6 @@ module Stemcell
90
96
  :type => String,
91
97
  :env => 'VPC_ID'
92
98
  },
93
- {
94
- :name => 'classic_link_vpc_id',
95
- :desc => 'VPC ID to which this instance will be classic-linked',
96
- :type => String,
97
- :env => 'CLASSIC_LINK_VPC_ID',
98
- },
99
- {
100
- :name => 'classic_link_security_group_ids',
101
- :desc => 'comma-separated list of security group IDs to link into ClassicLink; not used unless classic_link_vpc_id is set',
102
- :type => String,
103
- :env => 'CLASSIC_LINK_SECURITY_GROUP_IDS',
104
- },
105
- {
106
- :name => 'classic_link_security_groups',
107
- :desc => 'comma-separated list of security groups to link into ClassicLink; not used unless classic_link_vpc_id is set',
108
- :type => String,
109
- :env => 'CLASSIC_LINK_SECURITY_GROUPS',
110
- },
111
99
  {
112
100
  :name => 'subnet',
113
101
  :desc => "VPC subnet for which to launch this instance",
@@ -424,17 +412,6 @@ module Stemcell
424
412
  # convert chef_cookbook_attributes from comma separated string to ruby array
425
413
  options['chef_cookbook_attributes'] &&= options['chef_cookbook_attributes'].split(',')
426
414
 
427
- # format the classic link options
428
- if options['classic_link_vpc_id']
429
- options['classic_link']['vpc_id'] = options['classic_link_vpc_id']
430
- end
431
- if options['classic_link_security_group_ids']
432
- options['classic_link']['security_group_ids'] = options['classic_link_security_group_ids'].split(',')
433
- end
434
- if options['classic_link_security_groups']
435
- options['classic_link']['security_groups'] = options['classic_link_security_groups'].split(',')
436
- end
437
-
438
415
  options
439
416
  end
440
417