knife-ec2 0.6.4 → 0.6.6.rc.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -32,3 +32,6 @@ Icon?
32
32
 
33
33
  *.swp
34
34
  *.swo
35
+
36
+ Gemfile.lock
37
+ .rspec
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ script: bundle exec rspec --color --format progress
data/Gemfile CHANGED
@@ -1,8 +1,2 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in knife-rackspace.gemspec
1
+ source 'http://rubygems.org'
4
2
  gemspec
5
-
6
- group :development do
7
- gem 'rspec', '~> 2.7.0'
8
- end
@@ -0,0 +1,114 @@
1
+ Knife EC2
2
+ =========
3
+ [![Gem Version](https://badge.fury.io/rb/knife-ec2.png)](http://badge.fury.io/rb/knife-ec2)
4
+ [![Build Status](https://travis-ci.org/opscode/knife-ec2.png?branch=master)](https://travis-ci.org/opscode/knife-ec2)
5
+ [![Dependency Status](https://gemnasium.com/opscode/knife-ec2.png)](https://gemnasium.com/opscode/knife-ec2)
6
+
7
+ This is the official Opscode Knife plugin for EC2. This plugin gives knife the ability to create, bootstrap, and manage EC2 instances.
8
+
9
+
10
+ Installation
11
+ ------------
12
+ If you're using bundler, simply add Chef and Knife EC2 to your `Gemfile`:
13
+
14
+ ```ruby
15
+ gem 'chef'
16
+ gem 'knife-ec2'
17
+ ```
18
+
19
+ If you are not using bundler, you can install the gem manually. Be sure you are running Chef 0.10.10 or higher, as earlier versions do not support plugins.
20
+
21
+ $ gem install chef
22
+
23
+ This plugin is distributed as a Ruby Gem. To install it, run:
24
+
25
+ $ gem install knife-ec2
26
+
27
+ Depending on your system's configuration, you may need to run this command with root privileges.
28
+
29
+
30
+ Configuration
31
+ -------------
32
+ In order to communicate with the Amazon's EC2 API you will have to tell Knife about your AWS Access Key and Secret Access Key. The easiest way to accomplish this is to create some entries in your `knife.rb` file:
33
+
34
+ ```ruby
35
+ knife[:aws_access_key_id] = "Your AWS Access Key ID"
36
+ knife[:aws_secret_access_key] = "Your AWS Secret Access Key"
37
+ ```
38
+
39
+ If your `knife.rb` file will be checked into a SCM system (ie readable by others) you may want to read the values from environment variables:
40
+
41
+ ```ruby
42
+ knife[:aws_access_key_id] = ENV['AWS_ACCESS_KEY_ID']
43
+ knife[:aws_secret_access_key] = ENV['AWS_SECRET_ACCESS_KEY']
44
+ ```
45
+
46
+ You also have the option of passing your AWS API Key/Secret into the individual knife subcommands using the `-A` (or `--aws-access-key-id`) `-K` (or `--aws-secret-access-key`) command options
47
+
48
+ ```bash
49
+ # provision a new m1.small Ubuntu 10.04 webserver
50
+ $ knife ec2 server create -r 'role[webserver]' -I ami-7000f019 -f m1.small -A 'Your AWS Access Key ID' -K "Your AWS Secret Access Key"
51
+ ```
52
+
53
+ If you are working with Amazon's command line tools, there is a good chance
54
+ you already have a file with these keys somewhere in this format:
55
+
56
+ AWSAccessKeyId=Your AWS Access Key ID
57
+ AWSSecretKey=Your AWS Secret Access Key
58
+
59
+ In this case, you can point the <tt>aws_credential_file</tt> option to
60
+ this file in your <tt>knife.rb</tt> file, like so:
61
+
62
+ knife[:aws_credential_file] = "/path/to/credentials/file/in/above/format"
63
+
64
+ Additionally the following options may be set in your `knife.rb`:
65
+
66
+ - flavor
67
+ - image
68
+ - availability_zone
69
+ - aws_ssh_key_id
70
+ - region
71
+ - distro
72
+ - template_file
73
+
74
+
75
+ Subcommands
76
+ -----------
77
+ This plugin provides the following Knife subcommands. Specific command options can be found by invoking the subcommand with a `--help` flag
78
+
79
+
80
+ #### `knife ec2 server create`
81
+ Provisions a new server in the Amazon EC2 and then perform a Chef bootstrap (using the SSH protocol). The goal of the bootstrap is to get Chef installed on the target system so it can run Chef Client with a Chef Server. The main assumption is a baseline OS installation exists (provided by the provisioning). It is primarily intended for Chef Client systems that talk to a Chef server.
82
+
83
+ #### `knife ec2 server delete`
84
+ Deletes an existing server in the currently configured AWS account. **By default, this does not delete the associated node and client objects from the Chef server. To do so, add the `--purge` flag**
85
+
86
+ #### `knife ec2 server list`
87
+ Outputs a list of all servers in the currently configured AWS account. **Note, this shows all instances associated with the account, some of which may not be currently managed by the Chef server.**
88
+
89
+ #### `knife ec2 instance data`
90
+ Generates instance metadata in meant to be used with Opscode's custom AMIs. This will read your knife configuration `~/.chef/knife.rb` for the validation certificate and Chef server URL to use and output in JSON format. The subcommand also accepts a list of roles/recipes that will be in the node's initial run list.
91
+
92
+ **Note**: Using Opscode's custom AMIs reflect an older way of launching instances in EC2 for Chef and should be considered DEPRECATED. Leveraging this plugins's `knife ec2 server create` subcommands with a base AMIs directly from your Linux distribution (ie Ubuntu AMIs from Canonical) is much preferred and more flexible. Although this subcommand will remain, the Opscode custom AMIs are currently out of date.
93
+
94
+ In-depth usage instructions can be found on the [Chef Wiki](http://wiki.opscode.com/display/chef/EC2+Bootstrap+Fast+Start+Guide).
95
+
96
+ License and Authors
97
+ -------------------
98
+ - Author:: Adam Jacob (<adam@opscode.com>)
99
+
100
+ ```text
101
+ Copyright 2009-2013 Opscode, Inc.
102
+
103
+ Licensed under the Apache License, Version 2.0 (the "License");
104
+ you may not use this file except in compliance with the License.
105
+ You may obtain a copy of the License at
106
+
107
+ http://www.apache.org/licenses/LICENSE-2.0
108
+
109
+ Unless required by applicable law or agreed to in writing, software
110
+ distributed under the License is distributed on an "AS IS" BASIS,
111
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112
+ See the License for the specific language governing permissions and
113
+ limitations under the License.
114
+ ```
data/Rakefile CHANGED
@@ -27,8 +27,9 @@ require 'rdoc/task'
27
27
 
28
28
  begin
29
29
  require 'sdoc'
30
+ require 'rdoc/task'
30
31
 
31
- Rake::RDocTask.new do |rdoc|
32
+ RDoc::Task.new do |rdoc|
32
33
  rdoc.title = "Chef Ruby API Documentation"
33
34
  rdoc.main = "README.rdoc"
34
35
  rdoc.options << '--fmt' << 'shtml' # explictly set shtml generator
@@ -1,24 +1,29 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "knife-ec2/version"
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'knife-ec2/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.name = "knife-ec2"
7
- s.version = Knife::Ec2::VERSION
8
- s.has_rdoc = true
9
- s.authors = ["Adam Jacob","Seth Chisamore"]
10
- s.email = ["adam@opscode.com","schisamo@opscode.com"]
11
- s.homepage = "http://wiki.opscode.com/display/chef"
12
- s.summary = "EC2 Support for Chef's Knife Command"
13
- s.description = s.summary
14
- s.extra_rdoc_files = ["README.rdoc", "LICENSE" ]
6
+ s.name = 'knife-ec2'
7
+ s.version = Knife::Ec2::VERSION
8
+ s.authors = ['Adam Jacob', 'Seth Chisamore']
9
+ s.email = ['adam@opscode.com', 'schisamo@opscode.com']
10
+ s.homepage = 'https://github.com/opscode/knife-ec2'
11
+ s.summary = %q{EC2 Support for Chef\'s Knife Command}
12
+ s.description = s.summary
13
+ s.license = 'Apache 2.0'
15
14
 
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.add_dependency "fog", "~> 1.6"
20
- s.add_dependency "chef", ">= 0.10.10"
21
- %w(rspec-core rspec-expectations rspec-mocks rspec_junit_formatter).each { |gem| s.add_development_dependency gem }
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
18
 
23
- s.require_paths = ["lib"]
19
+ s.add_dependency 'fog', '~> 1.15.0'
20
+ s.add_dependency 'chef', '>= 0.10.10'
21
+ s.add_dependency 'knife-windows', '>= 0.5.12'
22
+
23
+ s.add_development_dependency 'rspec', '~> 2.14'
24
+ s.add_development_dependency 'rake', '~> 10.1'
25
+ s.add_development_dependency 'sdoc', '~> 0.3'
26
+
27
+ s.require_paths = ['lib']
24
28
  end
29
+
@@ -34,6 +34,11 @@ class Chef
34
34
  require 'chef/json_compat'
35
35
  end
36
36
 
37
+ option :aws_credential_file,
38
+ :long => "--aws-credential-file FILE",
39
+ :description => "File containing AWS credentials as used by aws cmdline tools",
40
+ :proc => Proc.new { |key| Chef::Config[:knife][:aws_credential_file] = key }
41
+
37
42
  option :aws_access_key_id,
38
43
  :short => "-A ID",
39
44
  :long => "--aws-access-key-id KEY",
@@ -75,9 +80,26 @@ class Chef
75
80
  end
76
81
  end
77
82
 
83
+ def is_image_windows?
84
+ image_info = connection.images.get(@server.image_id)
85
+ return image_info.platform == 'windows'
86
+ end
87
+
78
88
  def validate!(keys=[:aws_access_key_id, :aws_secret_access_key])
79
89
  errors = []
80
90
 
91
+ unless Chef::Config[:knife][:aws_credential_file].nil?
92
+ unless (Chef::Config[:knife].keys & [:aws_access_key_id, :aws_secret_access_key]).empty?
93
+ errors << "Either provide a credentials file or the access key and secret keys but not both."
94
+ end
95
+ # File format:
96
+ # AWSAccessKeyId=somethingsomethingdarkside
97
+ # AWSSecretKey=somethingsomethingcomplete
98
+ entries = Hash[*File.read(Chef::Config[:knife][:aws_credential_file]).split(/[=\n]/)]
99
+ Chef::Config[:knife][:aws_access_key_id] = entries['AWSAccessKeyId']
100
+ Chef::Config[:knife][:aws_secret_access_key] = entries['AWSSecretKey']
101
+ end
102
+
81
103
  keys.each do |k|
82
104
  pretty_key = k.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
83
105
  if Chef::Config[:knife][k].nil?
@@ -91,7 +113,13 @@ class Chef
91
113
  end
92
114
 
93
115
  end
116
+
117
+ def iam_name_from_profile(profile)
118
+ # The IAM profile object only contains the name as part of the arn
119
+ if profile && profile.key?('arn')
120
+ name = profile['arn'].split('/')[-1]
121
+ end
122
+ name ||= ''
123
+ end
94
124
  end
95
125
  end
96
-
97
-
@@ -18,13 +18,14 @@
18
18
  #
19
19
 
20
20
  require 'chef/knife/ec2_base'
21
+ require 'chef/knife/winrm_base'
21
22
 
22
23
  class Chef
23
24
  class Knife
24
25
  class Ec2ServerCreate < Knife
25
26
 
26
27
  include Knife::Ec2Base
27
-
28
+ include Knife::WinrmBase
28
29
  deps do
29
30
  require 'fog'
30
31
  require 'readline'
@@ -50,6 +51,10 @@ class Chef
50
51
  :description => "The AMI for the server",
51
52
  :proc => Proc.new { |i| Chef::Config[:knife][:image] = i }
52
53
 
54
+ option :iam_instance_profile,
55
+ :long => "--iam-profile NAME",
56
+ :description => "The IAM instance profile to apply to this instance."
57
+
53
58
  option :security_groups,
54
59
  :short => "-G X,Y,Z",
55
60
  :long => "--groups X,Y,Z",
@@ -66,6 +71,11 @@ class Chef
66
71
  :long => "--associate-eip IP_ADDRESS",
67
72
  :description => "Associate existing elastic IP address with instance after launch"
68
73
 
74
+ option :placement_group,
75
+ :long => "--placement-group PLACEMENT_GROUP",
76
+ :description => "The placement group to place a cluster compute instance",
77
+ :proc => Proc.new { |pg| Chef::Config[:knife][:placement_group] = pg }
78
+
69
79
  option :tags,
70
80
  :short => "-T T=V[,T=V,...]",
71
81
  :long => "--tags Tag=Value[,Tag=Value...]",
@@ -127,12 +137,18 @@ class Chef
127
137
  :long => "--bootstrap-version VERSION",
128
138
  :description => "The version of Chef to install",
129
139
  :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
140
+
141
+ option :bootstrap_proxy,
142
+ :long => "--bootstrap-proxy PROXY_URL",
143
+ :description => "The proxy server for the node being bootstrapped",
144
+ :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
130
145
 
131
146
  option :distro,
132
147
  :short => "-d DISTRO",
133
148
  :long => "--distro DISTRO",
134
149
  :description => "Bootstrap a distro using a template; default is 'chef-full'",
135
- :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d }
150
+ :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
151
+ :default => "chef-full"
136
152
 
137
153
  option :template_file,
138
154
  :long => "--template-file TEMPLATE",
@@ -158,6 +174,17 @@ class Chef
158
174
  :description => "Comma separated list of roles/recipes to apply",
159
175
  :proc => lambda { |o| o.split(/[\s,]+/) }
160
176
 
177
+ option :secret,
178
+ :short => "-s SECRET",
179
+ :long => "--secret ",
180
+ :description => "The secret key to use to encrypt data bag item values",
181
+ :proc => lambda { |s| Chef::Config[:knife][:secret] = s }
182
+
183
+ option :secret_file,
184
+ :long => "--secret-file SECRET_FILE",
185
+ :description => "A file containing the secret key to use to encrypt data bag item values",
186
+ :proc => lambda { |sf| Chef::Config[:knife][:secret_file] = sf }
187
+
161
188
  option :json_attributes,
162
189
  :short => "-j JSON",
163
190
  :long => "--json-attributes JSON",
@@ -181,6 +208,18 @@ class Chef
181
208
  :boolean => true,
182
209
  :default => true
183
210
 
211
+ option :bootstrap_protocol,
212
+ :long => "--bootstrap-protocol protocol",
213
+ :description => "protocol to bootstrap windows servers. options: winrm/ssh",
214
+ :proc => Proc.new { |key| Chef::Config[:knife][:bootstrap_protocol] = key },
215
+ :default => "winrm"
216
+
217
+ option :fqdn,
218
+ :long => "--fqdn FQDN",
219
+ :description => "Pre-defined FQDN",
220
+ :proc => Proc.new { |key| Chef::Config[:knife][:fqdn] = key },
221
+ :default => nil
222
+
184
223
  option :aws_user_data,
185
224
  :long => "--user-data USER_DATA_FILE",
186
225
  :short => "-u USER_DATA_FILE",
@@ -209,6 +248,30 @@ class Chef
209
248
  :description => "The EC2 server attribute to use for SSH connection",
210
249
  :default => nil
211
250
 
251
+ def tcp_test_winrm(ip_addr, port)
252
+ tcp_socket = TCPSocket.new(ip_addr, port)
253
+ yield
254
+ true
255
+ rescue SocketError
256
+ sleep 2
257
+ false
258
+ rescue Errno::ETIMEDOUT
259
+ false
260
+ rescue Errno::EPERM
261
+ false
262
+ rescue Errno::ECONNREFUSED
263
+ sleep 2
264
+ false
265
+ rescue Errno::EHOSTUNREACH
266
+ sleep 2
267
+ false
268
+ rescue Errno::ENETUNREACH
269
+ sleep 2
270
+ false
271
+ ensure
272
+ tcp_socket && tcp_socket.close
273
+ end
274
+
212
275
  def tcp_test_ssh(hostname, ssh_port)
213
276
  tcp_socket = TCPSocket.new(hostname, ssh_port)
214
277
  readable = IO.select([tcp_socket], nil, nil, 5)
@@ -224,10 +287,60 @@ class Chef
224
287
  false
225
288
  rescue Errno::EPERM, Errno::ETIMEDOUT
226
289
  false
290
+ # This happens on some mobile phone networks
291
+ rescue Errno::ECONNRESET
292
+ sleep 2
293
+ false
227
294
  ensure
228
295
  tcp_socket && tcp_socket.close
229
296
  end
230
297
 
298
+ def decrypt_admin_password(encoded_password, key)
299
+ require 'base64'
300
+ require 'openssl'
301
+ private_key = OpenSSL::PKey::RSA.new(key)
302
+ encrypted_password = Base64.decode64(encoded_password)
303
+ password = private_key.private_decrypt(encrypted_password)
304
+ password
305
+ end
306
+
307
+ def check_windows_password_available(server_id)
308
+ response = connection.get_password_data(server_id)
309
+ if not response.body["passwordData"]
310
+ return false
311
+ end
312
+ response.body["passwordData"]
313
+ end
314
+
315
+ def windows_password
316
+ if not locate_config_value(:winrm_password)
317
+ if locate_config_value(:identity_file)
318
+ print "\n#{ui.color("Waiting for Windows Admin password to be available", :magenta)}"
319
+ print(".") until check_windows_password_available(@server.id) {
320
+ sleep 1000 #typically is available after 30 mins
321
+ puts("done")
322
+ }
323
+ response = connection.get_password_data(@server.id)
324
+ data = File.read(locate_config_value(:identity_file))
325
+ config[:winrm_password] = decrypt_admin_password(response.body["passwordData"], data)
326
+ else
327
+ ui.error("Cannot find SSH Identity file, required to fetch dynamically generated password")
328
+ exit 1
329
+ end
330
+ else
331
+ locate_config_value(:winrm_password)
332
+ end
333
+ end
334
+
335
+ def load_winrm_deps
336
+ require 'winrm'
337
+ require 'em-winrm'
338
+ require 'chef/knife/winrm'
339
+ require 'chef/knife/bootstrap_windows_winrm'
340
+ require 'chef/knife/bootstrap_windows_ssh'
341
+ require 'chef/knife/core/windows_bootstrap_context'
342
+ end
343
+
231
344
  def run
232
345
  $stdout.sync = true
233
346
 
@@ -248,6 +361,8 @@ class Chef
248
361
  hashed_tags["Name"] = locate_config_value(:chef_node_name) || @server.id
249
362
  end
250
363
 
364
+ printed_tags = hashed_tags.map{ |tag, val| "#{tag}: #{val}" }.join(", ")
365
+
251
366
  msg_pair("Instance ID", @server.id)
252
367
  msg_pair("Flavor", @server.flavor_id)
253
368
  msg_pair("Image", @server.image_id)
@@ -266,7 +381,9 @@ class Chef
266
381
  printed_security_group_ids = @server.security_group_ids.join(", ") if @server.security_group_ids
267
382
  msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? or @server.security_group_ids
268
383
 
269
- msg_pair("Tags", hashed_tags)
384
+ msg_pair("IAM Profile", locate_config_value(:iam_instance_profile))
385
+
386
+ msg_pair("Tags", printed_tags)
270
387
  msg_pair("SSH Key", @server.key_name)
271
388
 
272
389
  print "\n#{ui.color("Waiting for instance", :magenta)}"
@@ -277,7 +394,7 @@ class Chef
277
394
  puts("\n")
278
395
 
279
396
  # occasionally 'ready?' isn't, so retry a couple times if needed.
280
- tries = 6
397
+ tries = 6
281
398
  begin
282
399
  create_tags(hashed_tags) unless hashed_tags.empty?
283
400
  associate_eip(elastic_ip) if config[:associate_eip]
@@ -300,21 +417,44 @@ class Chef
300
417
  end
301
418
  msg_pair("Private IP Address", @server.private_ip_address)
302
419
 
303
- print "\n#{ui.color("Waiting for sshd", :magenta)}"
304
420
 
305
- wait_for_sshd(ssh_connect_host)
306
-
307
- bootstrap_for_node(@server,ssh_connect_host).run
421
+ #Check if Server is Windows or Linux
422
+ if is_image_windows?
423
+ protocol = locate_config_value(:bootstrap_protocol)
424
+ # Set distro to windows-chef-client-msi
425
+ config[:distro] = "windows-chef-client-msi" if (config[:distro].nil? || config[:distro] == "chef-full")
426
+ if protocol == 'winrm'
427
+ load_winrm_deps
428
+ print "\n#{ui.color("Waiting for winrm", :magenta)}"
429
+ print(".") until tcp_test_winrm(ssh_connect_host, locate_config_value(:winrm_port)) {
430
+ sleep 10
431
+ puts("done")
432
+ }
433
+ else
434
+ print "\n#{ui.color("Waiting for sshd", :magenta)}"
435
+ #If FreeSSHd, winsshd etc are available
436
+ print(".") until tcp_test_ssh(ssh_connect_host, config[:ssh_port]) {
437
+ sleep @initial_sleep_delay ||= (vpc_mode? ? 40 : 10)
438
+ puts("done")
439
+ }
440
+ end
441
+ bootstrap_for_windows_node(@server,ssh_connect_host).run
442
+ else
443
+ wait_for_sshd(ssh_connect_host)
444
+ bootstrap_for_linux_node(@server,ssh_connect_host).run
445
+ end
308
446
 
309
447
  puts "\n"
310
448
  msg_pair("Instance ID", @server.id)
311
449
  msg_pair("Flavor", @server.flavor_id)
450
+ msg_pair("Placement Group", @server.placement_group) unless @server.placement_group.nil?
312
451
  msg_pair("Image", @server.image_id)
313
452
  msg_pair("Region", connection.instance_variable_get(:@region))
314
453
  msg_pair("Availability Zone", @server.availability_zone)
315
454
  msg_pair("Security Groups", printed_security_groups) unless vpc_mode? or (@server.groups.nil? and @server.security_group_ids)
316
455
  msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? or @server.security_group_ids
317
- msg_pair("Tags", hashed_tags)
456
+ msg_pair("IAM Profile", locate_config_value(:iam_instance_profile)) if locate_config_value(:iam_instance_profile)
457
+ msg_pair("Tags", printed_tags)
318
458
  msg_pair("SSH Key", @server.key_name)
319
459
  msg_pair("Root Device Type", @server.root_device_type)
320
460
  if @server.root_device_type == "ebs"
@@ -349,29 +489,74 @@ class Chef
349
489
  msg_pair("JSON Attributes",config[:json_attributes]) unless !config[:json_attributes] || config[:json_attributes].empty?
350
490
  end
351
491
 
352
- def bootstrap_for_node(server,ssh_host)
492
+ def bootstrap_common_params(bootstrap)
493
+ bootstrap.config[:run_list] = config[:run_list]
494
+ bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
495
+ bootstrap.config[:distro] = locate_config_value(:distro)
496
+ bootstrap.config[:template_file] = locate_config_value(:template_file)
497
+ bootstrap.config[:environment] = locate_config_value(:environment)
498
+ bootstrap.config[:prerelease] = config[:prerelease]
499
+ bootstrap.config[:first_boot_attributes] = locate_config_value(:json_attributes) || {}
500
+ bootstrap.config[:encrypted_data_bag_secret] = locate_config_value(:encrypted_data_bag_secret)
501
+ bootstrap.config[:encrypted_data_bag_secret_file] = locate_config_value(:encrypted_data_bag_secret_file)
502
+ bootstrap.config[:secret] = locate_config_value(:secret)
503
+ bootstrap.config[:secret_file] = locate_config_value(:secret_file)
504
+ # Modify global configuration state to ensure hint gets set by
505
+ # knife-bootstrap
506
+ Chef::Config[:knife][:hints] ||= {}
507
+ Chef::Config[:knife][:hints]["ec2"] ||= {}
508
+ bootstrap
509
+ end
510
+
511
+ def fetch_server_fqdn(ip_addr)
512
+ require 'resolv'
513
+ Resolv.getname(ip_addr)
514
+ end
515
+
516
+ def bootstrap_for_windows_node(server, fqdn)
517
+ if locate_config_value(:bootstrap_protocol) == 'winrm'
518
+ if locate_config_value(:kerberos_realm)
519
+ #Fetch AD/WINS based fqdn if any for Kerberos-based Auth
520
+ fqdn = locate_config_value(:fqdn) || fetch_server_fqdn(server.private_ip_address)
521
+ end
522
+ bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
523
+ bootstrap.config[:winrm_user] = locate_config_value(:winrm_user)
524
+ bootstrap.config[:winrm_password] = windows_password
525
+ bootstrap.config[:winrm_transport] = locate_config_value(:winrm_transport)
526
+ bootstrap.config[:kerberos_keytab_file] = locate_config_value(:kerberos_keytab_file)
527
+ bootstrap.config[:kerberos_realm] = locate_config_value(:kerberos_realm)
528
+ bootstrap.config[:kerberos_service] = locate_config_value(:kerberos_service)
529
+ bootstrap.config[:ca_trust_file] = locate_config_value(:ca_trust_file)
530
+ bootstrap.config[:winrm_port] = locate_config_value(:winrm_port)
531
+
532
+ elsif locate_config_value(:bootstrap_protocol) == 'ssh'
533
+ bootstrap = Chef::Knife::BootstrapWindowsSsh.new
534
+ bootstrap.config[:ssh_user] = locate_config_value(:ssh_user)
535
+ bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
536
+ bootstrap.config[:ssh_port] = locate_config_value(:ssh_port)
537
+ bootstrap.config[:identity_file] = locate_config_value(:identity_file)
538
+ bootstrap.config[:no_host_key_verify] = locate_config_value(:no_host_key_verify)
539
+ else
540
+ ui.error("Unsupported Bootstrapping Protocol. Supported : winrm, ssh")
541
+ exit 1
542
+ end
543
+ bootstrap.name_args = [fqdn]
544
+ bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.id
545
+ bootstrap_common_params(bootstrap)
546
+ end
547
+
548
+ def bootstrap_for_linux_node(server,ssh_host)
353
549
  bootstrap = Chef::Knife::Bootstrap.new
354
550
  bootstrap.name_args = [ssh_host]
355
- bootstrap.config[:run_list] = locate_config_value(:run_list) || []
356
551
  bootstrap.config[:ssh_user] = config[:ssh_user]
357
552
  bootstrap.config[:ssh_port] = config[:ssh_port]
358
553
  bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
359
554
  bootstrap.config[:identity_file] = config[:identity_file]
360
555
  bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name) || server.id
361
- bootstrap.config[:prerelease] = config[:prerelease]
362
- bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
363
- bootstrap.config[:first_boot_attributes] = locate_config_value(:json_attributes) || {}
364
- bootstrap.config[:distro] = locate_config_value(:distro) || "chef-full"
365
556
  bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
366
- bootstrap.config[:template_file] = locate_config_value(:template_file)
367
- bootstrap.config[:environment] = config[:environment]
368
557
  # may be needed for vpc_mode
369
558
  bootstrap.config[:host_key_verify] = config[:host_key_verify]
370
- # Modify global configuration state to ensure hint gets set by
371
- # knife-bootstrap
372
- Chef::Config[:knife][:hints] ||= {}
373
- Chef::Config[:knife][:hints]["ec2"] ||= {}
374
- bootstrap
559
+ bootstrap_common_params(bootstrap)
375
560
  end
376
561
 
377
562
  def vpc_mode?
@@ -440,6 +625,8 @@ class Chef
440
625
  }
441
626
  server_def[:subnet_id] = locate_config_value(:subnet_id) if vpc_mode?
442
627
  server_def[:private_ip_address] = locate_config_value(:private_ip_address) if vpc_mode?
628
+ server_def[:placement_group] = locate_config_value(:placement_group)
629
+ server_def[:iam_instance_profile_name] = locate_config_value(:iam_instance_profile)
443
630
 
444
631
  if Chef::Config[:knife][:aws_user_data]
445
632
  begin