knife-ec2 0.16.0 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +114 -109
- data/DOC_CHANGES.md +17 -17
- data/Gemfile +4 -4
- data/RELEASE_NOTES.md +22 -36
- data/lib/chef/knife/ec2_server_create.rb +1547 -1524
- data/lib/knife-ec2/version.rb +6 -6
- data/spec/unit/ec2_server_create_spec.rb +2644 -2631
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 902fa10935b516871981f149f29fe37890bfd3a3
|
4
|
+
data.tar.gz: 84519150709c6e46de97de7cbd1be1100bad8c50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c66211a3338d6ef2ff6c954c33dbb85f71b82faf8e625f0c07bf27f9f73e5d5c599dadf798b56e09ce1ec27ce8e8fd37cb346f78369bd843c7face475325b24a
|
7
|
+
data.tar.gz: d0d18e02338ffb8007b6b6ee6c3d8f280adfa2fd1b5c2b22109ea335ae132f9fa47fe0c9eae117fece8b6b86f141a7aa72b0126b36fdb7f0e4cee352f232e8a8
|
data/CHANGELOG.md
CHANGED
@@ -1,109 +1,114 @@
|
|
1
|
-
# knife-ec2 change log
|
2
|
-
|
3
|
-
Note: this log contains only changes from knife-ec2 release 0.8.0 and later
|
4
|
-
-- it does not contain the changes from prior releases. To view change history
|
5
|
-
prior to release 0.8.0, please visit the [source repository](https://github.com/chef/knife-ec2/commits).
|
6
|
-
|
7
|
-
|
8
|
-
## Latest Release 0.
|
9
|
-
* [knife-ec2:#
|
10
|
-
* [knife-ec2:#
|
11
|
-
* [knife-ec2:#
|
12
|
-
|
13
|
-
|
14
|
-
* [knife-ec2:#
|
15
|
-
* [knife-ec2:#
|
16
|
-
|
17
|
-
|
18
|
-
* [knife-ec2:#
|
19
|
-
* [knife-ec2:#
|
20
|
-
* [knife-ec2:#
|
21
|
-
|
22
|
-
|
23
|
-
* [knife-ec2:#
|
24
|
-
* [knife-ec2:#
|
25
|
-
* [knife-ec2:#
|
26
|
-
* [knife-ec2:#
|
27
|
-
|
28
|
-
|
29
|
-
*
|
30
|
-
* [knife-ec2:#
|
31
|
-
* [knife-ec2:#
|
32
|
-
|
33
|
-
## Release 0.
|
34
|
-
*
|
35
|
-
* [knife-ec2:#
|
36
|
-
* [knife-ec2:#
|
37
|
-
|
38
|
-
|
39
|
-
* [knife-ec2:#
|
40
|
-
* [knife-ec2:#
|
41
|
-
* [knife-ec2:#
|
42
|
-
* [knife-ec2:#
|
43
|
-
* [knife-ec2:#
|
44
|
-
* [knife-ec2:#
|
45
|
-
* [knife-ec2:#
|
46
|
-
* [knife-ec2:#
|
47
|
-
* [knife-ec2:#
|
48
|
-
* [knife-ec2:#
|
49
|
-
* [knife-ec2:#
|
50
|
-
* [knife-ec2:#
|
51
|
-
* [knife-ec2:#
|
52
|
-
* [knife-ec2:#
|
53
|
-
* [knife-ec2:#
|
54
|
-
* [knife-ec2:#
|
55
|
-
* [knife-ec2:#
|
56
|
-
* [knife-ec2:#
|
57
|
-
* [knife-ec2:#
|
58
|
-
* [knife-ec2:#
|
59
|
-
* [knife-ec2:#
|
60
|
-
* [knife-ec2:#
|
61
|
-
* [knife-ec2:#
|
62
|
-
* [knife-ec2:#
|
63
|
-
* [knife-ec2:#
|
64
|
-
* [knife-ec2:#
|
65
|
-
* [knife-ec2:#
|
66
|
-
* [knife-ec2:#
|
67
|
-
* [knife-ec2:#
|
68
|
-
|
69
|
-
|
70
|
-
* [knife-ec2:#
|
71
|
-
* [knife-ec2
|
72
|
-
* [knife-ec2
|
73
|
-
|
74
|
-
## Release: 0.
|
75
|
-
* [knife-ec2:#
|
76
|
-
* [knife-ec2
|
77
|
-
* [knife-ec2
|
78
|
-
|
79
|
-
|
80
|
-
* [knife-ec2:#
|
81
|
-
* [knife-ec2:#
|
82
|
-
* [knife-ec2:#
|
83
|
-
* [
|
84
|
-
|
85
|
-
|
86
|
-
* [
|
87
|
-
* [
|
88
|
-
*
|
89
|
-
|
90
|
-
|
91
|
-
* [
|
92
|
-
* [
|
93
|
-
|
94
|
-
|
95
|
-
*
|
96
|
-
|
97
|
-
* [KNIFE-
|
98
|
-
|
99
|
-
|
100
|
-
* [KNIFE-
|
101
|
-
|
102
|
-
* [KNIFE-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
1
|
+
# knife-ec2 change log
|
2
|
+
|
3
|
+
Note: this log contains only changes from knife-ec2 release 0.8.0 and later
|
4
|
+
-- it does not contain the changes from prior releases. To view change history
|
5
|
+
prior to release 0.8.0, please visit the [source repository](https://github.com/chef/knife-ec2/commits).
|
6
|
+
|
7
|
+
|
8
|
+
## Latest Release 0.17.0 (2018-02-07)
|
9
|
+
* [knife-ec2:#515](https://github.com/chef/knife-ec2/pull/515) Allow re-use of existing ENI for primary interface.
|
10
|
+
* [knife-ec2:#514](https://github.com/chef/knife-ec2/pull/514) Add `--instance-initiated-shutdown-behavior` option.
|
11
|
+
* [knife-ec2:#513](https://github.com/chef/knife-ec2/pull/513) require `rb-readline` to avoid ruby 2.4 warnings about `Fixnum`.
|
12
|
+
|
13
|
+
## Latest Release 0.16.0 (2017-11-07)
|
14
|
+
* [knife-ec2:#503](https://github.com/chef/knife-ec2/pull/503) Update list of instance_types that support ebs-encryption.
|
15
|
+
* [knife-ec2:#496](https://github.com/chef/knife-ec2/pull/496) Change Winrm cert to 10 year expiry.
|
16
|
+
* [knife-ec2:#492](https://github.com/chef/knife-ec2/pull/492) Added support to tag node details to chef.
|
17
|
+
* [knife-ec2:#490](https://github.com/chef/knife-ec2/pull/490) Improper alignment of EC2 flavor list.
|
18
|
+
* [knife-ec2:#489](https://github.com/chef/knife-ec2/pull/489) Added support to handle long passwords in windows.
|
19
|
+
* [knife-ec2:#488](https://github.com/chef/knife-ec2/pull/488) Added support to tag EBS volumes on node creation.
|
20
|
+
* [knife-ec2:#487](https://github.com/chef/knife-ec2/pull/487) Added new column description in EC2 AMIs list.
|
21
|
+
|
22
|
+
## Latest Release 0.15.0 (2017-02-15)
|
23
|
+
* [knife-ec2:#484](https://github.com/chef/knife-ec2/pull/484) sleep for collecting windows password
|
24
|
+
* [knife-ec2:#481](https://github.com/chef/knife-ec2/pull/481) Updated readme for EC2 AMI list
|
25
|
+
* [knife-ec2:#482](https://github.com/chef/knife-ec2/pull/482) Allow search for EC2 AMIs
|
26
|
+
* [knife-ec2:#471](https://github.com/chef/knife-ec2/pull/471) Added support to include ec2 server id in the node name using `-N "www-server-%s" or --chef-node-name "-www-server-%s"`
|
27
|
+
* [knife-ec2:#478](https://github.com/chef/knife-ec2/pull/478) Allow for hosts without public ip addresses
|
28
|
+
* [knife-ec2:#476](https://github.com/chef/knife-ec2/pull/476) Tag node in chef
|
29
|
+
* [knife-ec2:#458](https://github.com/chef/knife-ec2/pull/458) Fix where yes option wasn’t being passed to bootstrap
|
30
|
+
* [knife-ec2:#468](https://github.com/chef/knife-ec2/pull/468) In VPC mode use private IP when public IP and DNS not available
|
31
|
+
* [knife-ec2:#464](https://github.com/chef/knife-ec2/pull/464) default value and desription is changed for --ebs-volume-type
|
32
|
+
|
33
|
+
## Latest Release 0.14.0 (2016-12-02)
|
34
|
+
* `knife-ec2` requires `chef-client 12.14` or newer.
|
35
|
+
* [knife-ec2:#442](https://github.com/chef/knife-ec2/pull/442) Added support to show flavor list in json format.
|
36
|
+
* [knife-ec2:#439](https://github.com/chef/knife-ec2/pull/439) Allow to accept multiple security group ids using --security-group-id option multiple times and added deprecated message for comma seprated --security-group-ids option.
|
37
|
+
|
38
|
+
## Release 0.13.0 (2016-08-05)
|
39
|
+
* [knife-ec2:#438](https://github.com/chef/knife-ec2/pull/438) Specs for ec2 server list
|
40
|
+
* [knife-ec2:#437](https://github.com/chef/knife-ec2/pull/437) Fix --aws-credential-file issues
|
41
|
+
* [knife-ec2:#436](https://github.com/chef/knife-ec2/pull/436) basic is not a valid setting for winrm_ssl_verify_mode
|
42
|
+
* [knife-ec2:#435](https://github.com/chef/knife-ec2/pull/435) Fix for Winrm Authentication Failure issue during bootstrap
|
43
|
+
* [knife-ec2:#434](https://github.com/chef/knife-ec2/pull/434) Removed ruby2.0.0 from travis
|
44
|
+
* [knife-ec2:#431](https://github.com/chef/knife-ec2/pull/431) Pinned rack and ffi-yajl gem to older versions.
|
45
|
+
* [knife-ec2:#430](https://github.com/chef/knife-ec2/pull/430) Fixing --aws-config-file issues
|
46
|
+
* [knife-ec2:#429](https://github.com/chef/knife-ec2/pull/429) Added validation when spot-wait-mode option is given by user on CLI and spot-price option is not given.
|
47
|
+
* [knife-ec2:#428](https://github.com/chef/knife-ec2/pull/428) Fix for s3 secret not getting copied on target vm
|
48
|
+
* [knife-ec2:#427](https://github.com/chef/knife-ec2/pull/427) Addedd disable_api_termination option along with RSpecs.
|
49
|
+
* [knife-ec2:#416](https://github.com/chef/knife-ec2/pull/416) Modified help for option --security-group-ids
|
50
|
+
* [knife-ec2:#409](https://github.com/chef/knife-ec2/pull/409) Passing encrypted\_data\_bag\_secret and encrypted\_databag\_secret\_file
|
51
|
+
* [knife-ec2:#405](https://github.com/chef/knife-ec2/pull/405) Updated README file - added description of aws\_config\_file option
|
52
|
+
* [knife-ec2:#399](https://github.com/chef/knife-ec2/pull/399) Adding support for aws-config-file
|
53
|
+
* [knife-ec2:#400](https://github.com/chef/knife-ec2/pull/400) Added --json-for-attributes-file
|
54
|
+
* [knife-ec2:#393](https://github.com/chef/knife-ec2/pull/393) Please also read aws\_session\_token from credentials file - [Richard Morrisey](https://github.com/datascope)
|
55
|
+
* [knife-ec2:#395](https://github.com/chef/knife-ec2/pull/395) Fix security groups for spot requests in a VPC and make user input optional - [Mikhail Bautin](https://github.com/mbautin)
|
56
|
+
* [knife-ec2:#322](https://github.com/chef/knife-ec2/pull/322) Implement support for ClassicLink [Quention de Metz](https://github.com/quentindemetz)
|
57
|
+
* [knife-ec2:#391](https://github.com/chef/knife-ec2/pull/391) adding missing m4,d2,t2,and g2 ebs encryption flavors - [Mario Harvey](https://github.com/badmadrad)
|
58
|
+
* [knife-ec2:#390](https://github.com/chef/knife-ec2/pull/390) Modified create\_ssl\_listener option as per Mixlib-CLI.
|
59
|
+
* [knife-ec2:#375](https://github.com/chef/knife-ec2/pull/375) Attach network interfaces before bootstrap - [Eric Herot](https://github.com/eherot)
|
60
|
+
* [knife-ec2:#389](https://github.com/chef/knife-ec2/pull/389) --server-connect-attribute cleanup
|
61
|
+
* [knife-ec2:#388](https://github.com/chef/knife-ec2/pull/388) Updated Readme for --server-connect-attribute option
|
62
|
+
* [knife-ec2:#384](https://github.com/chef/knife-ec2/pull/384) server list in json format
|
63
|
+
* [knife-ec2:#378](https://github.com/chef/knife-ec2/pull/378) Readme improvements
|
64
|
+
* [knife-ec2:#376](https://github.com/chef/knife-ec2/pull/376) Remove instance colors
|
65
|
+
* [knife-ec2:#377](https://github.com/chef/knife-ec2/pull/377) Require fog-aws vs. fog
|
66
|
+
* [knife-ec2:#368](https://github.com/chef/knife-ec2/pull/368) Handle Errno::ENOTCONN when testing for sshd access - [Eugene Bolshakov](https://github.com/eugenebolshakov)
|
67
|
+
* [knife-ec2:#373](https://github.com/chef/knife-ec2/pull/373) Update contributing docs
|
68
|
+
* [knife-ec2:#374](https://github.com/chef/knife-ec2/pull/374) Avoid sending nil runlist to Chef::Knife::Boostrap
|
69
|
+
* [knife-ec2:#372](https://github.com/chef/knife-ec2/pull/372) Cache gems in travis, update links and opscode -> chef
|
70
|
+
* [knife-ec2:#371](https://github.com/chef/knife-ec2/pull/371) fix typo in readme - [Kyle West](https://github.com/kylewest)
|
71
|
+
* [knife-ec2:#363](https://github.com/chef/knife-ec2/pull/363) Add ssl config user data for ssl transport, if required append to user\_data script specified by user.
|
72
|
+
* [knife-ec2:#319](https://github.com/chef/knife-ec2/pull/319) Pointing docs at itself. This is better then the non-existent chef.io docs.
|
73
|
+
|
74
|
+
## Release: 0.12.0 (2015-10-1)
|
75
|
+
* [knife-ec2:#305](https://github.com/chef/knife-ec2/pull/305) Updates to support standard .aws/credentials file
|
76
|
+
* [knife-ec2 #354](https://github.com/chef/knife-ec2/pull/354) knife-windows 1.0.0 dependency, support for validatorless bootstrap, other Chef 12 bootstrap options
|
77
|
+
* [knife-ec2 #356](https://github.com/chef/knife-ec2/pull/356) Added --forward-agent option
|
78
|
+
|
79
|
+
## Release: 0.11.0 (2015-08-24)
|
80
|
+
* [knife-ec2:#330](https://github.com/chef/knife-ec2/pull/330) Modification for attribute precedence issue
|
81
|
+
* [knife-ec2:#293](https://github.com/chef/knife-ec2/pull/293) s3_source: Lazy load fog library
|
82
|
+
* [knife-ec2:#284](https://github.com/chef/knife-ec2/pull/284) Enable Spot Pricing
|
83
|
+
* [knife-ec2:#280](https://github.com/chef/knife-ec2/pull/280) Support for EBS volume encryption in knife-ec2 server create options
|
84
|
+
* [knife-ec2:#273](https://github.com/chef/knife-ec2/pull/273) Remove -s option for data bag secret and subnets
|
85
|
+
* [knife-ec2:#268](https://github.com/chef/knife-ec2/pull/268) Updated gemspec to use fog v1.25
|
86
|
+
* [knife-ec2:#265](https://github.com/chef/knife-ec2/pull/265) showing error message for incorrect option input
|
87
|
+
* [knife-ec2:#261](https://github.com/chef/knife-ec2/pull/261) Remove 'em-winrm' gem dependency
|
88
|
+
* [KNIFE-464](https://tickets.opscode.com/browse/KNIFE-464) Support EC2 STS, i.e. AWS Federation tokens for authentication
|
89
|
+
|
90
|
+
## Release: 0.10.0.rc.1 (2014-10-08)
|
91
|
+
* [Issue:#237](https://github.com/chef/knife-ec2/issues/237) Provide a way to the validation key and data bag secret from S3
|
92
|
+
* [Issue:#243](https://github.com/chef/knife-ec2/issues/243) Support new AWS CLI configuration file format
|
93
|
+
* Update `knife-windows` gem dependency to `knife-windows 0.8.rc.0` for improved Windows authentication integration
|
94
|
+
* Update `fog` gem dependency to `fog 1.23.0`
|
95
|
+
* Provisioned IOPS support via the `--provisioned-iops` and `--ebs-volume-type` options
|
96
|
+
* [KNIFE-466](https://tickets.opscode.com/browse/KNIFE-466) Knife ec2 should use gateway from net::ssh config if available
|
97
|
+
* [KNIFE-422](https://tickets.opscode.com/browse/KNIFE-422) Knife ec2 server create doesn't respect identity file of gateway server from ssh\_config
|
98
|
+
|
99
|
+
## Release: 0.8.0 (2014-03-10)
|
100
|
+
* [KNIFE-458](https://tickets.opscode.com/browse/KNIFE-458) Docs: Increase detail about necessary
|
101
|
+
options for VPC instance creation
|
102
|
+
* [KNIFE-456](https://tickets.opscode.com/browse/KNIFE-456) Documentation for :aws\_credential\_file difficult to read
|
103
|
+
* [KNIFE-455](https://tickets.opscode.com/browse/KNIFE-455) knife ec2 may try to use private ip for vpc bootstrap even with --associate-public-ip flag
|
104
|
+
* [KNIFE-453](https://tickets.opscode.com/browse/KNIFE-453) knife-ec2 doesn't handle aws credentials files with windows line endings
|
105
|
+
* [KNIFE-451](https://tickets.opscode.com/browse/KNIFE-451) Update Fog version to 1.20.0
|
106
|
+
* [KNIFE-430](https://tickets.opscode.com/browse/KNIFE-430) server creation tunnelling should wait for a valid banner before continuing
|
107
|
+
* [KNIFE-381](https://tickets.opscode.com/browse/KNIFE-381) Gabriel Rosendorf Add ability to associate public ip with VPC
|
108
|
+
instance on creation
|
109
|
+
|
110
|
+
## Releases prior to 0.8.0
|
111
|
+
Please see <https://github.com/chef/knife-ec2/commits> to view changes in
|
112
|
+
the form of commits to the source repository for releases before 0.8.0.
|
113
|
+
|
114
|
+
|
data/DOC_CHANGES.md
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
<!---
|
2
|
-
This file is reset everytime when a new release is done. Contents of this file is for the currently unreleased version.
|
3
|
-
-->
|
4
|
-
|
5
|
-
# knife-ec2 doc changes
|
6
|
-
|
7
|
-
Documentation changes are given below for **knife-ec2 version 0.
|
8
|
-
|
9
|
-
## `knife ec2 server create` subcommand changes
|
10
|
-
|
11
|
-
### `--
|
12
|
-
|
13
|
-
The `--
|
14
|
-
|
15
|
-
### `--
|
16
|
-
|
17
|
-
|
1
|
+
<!---
|
2
|
+
This file is reset everytime when a new release is done. Contents of this file is for the currently unreleased version.
|
3
|
+
-->
|
4
|
+
|
5
|
+
# knife-ec2 doc changes
|
6
|
+
|
7
|
+
Documentation changes are given below for **knife-ec2 version 0.17.0**.
|
8
|
+
|
9
|
+
## `knife ec2 server create` subcommand changes
|
10
|
+
|
11
|
+
### `--instance-initiated-shutdown-behavior` option
|
12
|
+
|
13
|
+
The `--instance-initiated-shutdown-behavior` option indicates whether an instance stops or terminates when you initiate shutdown from the instance. Possible values are 'stop' and 'terminate', default is 'stop'.
|
14
|
+
|
15
|
+
### `--primary-eni` option
|
16
|
+
|
17
|
+
Specify a pre-existing ENI for primary interface when building the instance.
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
gemspec
|
3
|
-
|
4
|
-
gem 'rb-readline'
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
gem 'rb-readline', '>= 0.5.5'
|
data/RELEASE_NOTES.md
CHANGED
@@ -1,36 +1,22 @@
|
|
1
|
-
<!---
|
2
|
-
This file is reset every time a new release is done. The contents of this file are for the currently unreleased version.
|
3
|
-
|
4
|
-
Example Note:
|
5
|
-
|
6
|
-
## Example Heading
|
7
|
-
Details about the thing that changed that needs to get included in the Release Notes in markdown.
|
8
|
-
-->
|
9
|
-
|
10
|
-
# knife-ec2 0.
|
11
|
-
In this release we have added features for
|
12
|
-
|
13
|
-
## Features added in knife-ec2 0.
|
14
|
-
|
15
|
-
* Added support to
|
16
|
-
|
17
|
-
* Added support to
|
18
|
-
|
19
|
-
|
20
|
-
## Enhancement in knife-ec2 0.
|
21
|
-
|
22
|
-
*
|
23
|
-
|
24
|
-
* Enhanced Winrm cert to 10 year expiry PR: [496](https://github.com/chef/knife-ec2/pull/496).
|
25
|
-
|
26
|
-
* Improper alignment of EC2 flavor list command `knife ec2 flavor list` PR: [490](https://github.com/chef/knife-ec2/pull/490)
|
27
|
-
|
28
|
-
* Added new column description in EC2 AMIs list command `knife ec2 ami list` PR: [487](https://github.com/chef/knife-ec2/pull/487)
|
29
|
-
|
30
|
-
## Fixed issue in knife-ec2 0.16.0
|
31
|
-
|
32
|
-
* Update bundler to resolve travis failure PR: [502](https://github.com/chef/knife-ec2/pull/502)
|
33
|
-
|
34
|
-
* Fix issue Tag node in Chef PR: [492](https://github.com/chef/knife-ec2/pull/492) issue: [234](https://github.com/chef/knife-ec2/issues/234).
|
35
|
-
|
36
|
-
* Added support to handle long passwords in windows PR: [489](https://github.com/chef/knife-ec2/pull/489) issue: [470](https://github.com/chef/knife-ec2/issues/470)
|
1
|
+
<!---
|
2
|
+
This file is reset every time a new release is done. The contents of this file are for the currently unreleased version.
|
3
|
+
|
4
|
+
Example Note:
|
5
|
+
|
6
|
+
## Example Heading
|
7
|
+
Details about the thing that changed that needs to get included in the Release Notes in markdown.
|
8
|
+
-->
|
9
|
+
|
10
|
+
# knife-ec2 0.17.0 release notes:
|
11
|
+
In this release we have added features for adding exisiting ENI to server using `--primary-eni option`. Also added option `--instance-initiated-shutdown-behavior` to stop or terminate the instance on shutdown. There are a couple of bug fixes and enhancement as well.
|
12
|
+
|
13
|
+
## Features added in knife-ec2 0.17.0
|
14
|
+
|
15
|
+
* Added support to add existing ENI to server while node creation using `--primary-eni` option. PR: [515](https://github.com/chef/knife-ec2/pull/515).
|
16
|
+
|
17
|
+
* Added support to set the `--instance-initiated-shutdown-behavior` with the option to set "stop" or "terminate" the instance on shutdown. The default is "stop". PR: [514](https://github.com/chef/knife-ec2/pull/514).
|
18
|
+
|
19
|
+
|
20
|
+
## Enhancement in knife-ec2 0.17.0
|
21
|
+
|
22
|
+
* require `rb-readline` to avoid ruby 2.4 warnings about `Fixnum` PR: [513](https://github.com/chef/knife-ec2/pull/513)
|
@@ -1,1524 +1,1547 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Adam Jacob (<adam@chef.io>)
|
3
|
-
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
4
|
-
# Copyright:: Copyright (c) 2010-2015 Chef Software, Inc.
|
5
|
-
# License:: Apache License, Version 2.0
|
6
|
-
#
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
-
# you may not use this file except in compliance with the License.
|
9
|
-
# You may obtain a copy of the License at
|
10
|
-
#
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
#
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
#
|
19
|
-
|
20
|
-
require 'chef/knife/ec2_base'
|
21
|
-
require 'chef/knife/s3_source'
|
22
|
-
require 'chef/knife/winrm_base'
|
23
|
-
require 'chef/knife/bootstrap_windows_base'
|
24
|
-
|
25
|
-
class Chef
|
26
|
-
class Knife
|
27
|
-
class Ec2ServerCreate < Knife
|
28
|
-
|
29
|
-
include Knife::Ec2Base
|
30
|
-
include Knife::WinrmBase
|
31
|
-
include Knife::BootstrapWindowsBase
|
32
|
-
deps do
|
33
|
-
require 'tempfile'
|
34
|
-
require 'fog/aws'
|
35
|
-
require 'uri'
|
36
|
-
require 'readline'
|
37
|
-
require 'chef/json_compat'
|
38
|
-
require 'chef/knife/bootstrap'
|
39
|
-
Chef::Knife::Bootstrap.load_deps
|
40
|
-
end
|
41
|
-
|
42
|
-
banner "knife ec2 server create (options)"
|
43
|
-
|
44
|
-
attr_accessor :initial_sleep_delay
|
45
|
-
attr_reader :server
|
46
|
-
|
47
|
-
option :flavor,
|
48
|
-
:short => "-f FLAVOR",
|
49
|
-
:long => "--flavor FLAVOR",
|
50
|
-
:description => "The flavor of server (m1.small, m1.medium, etc)",
|
51
|
-
:proc => Proc.new { |f| Chef::Config[:knife][:flavor] = f }
|
52
|
-
|
53
|
-
option :image,
|
54
|
-
:short => "-I IMAGE",
|
55
|
-
:long => "--image IMAGE",
|
56
|
-
:description => "The AMI for the server",
|
57
|
-
:proc => Proc.new { |i| Chef::Config[:knife][:image] = i }
|
58
|
-
|
59
|
-
option :iam_instance_profile,
|
60
|
-
:long => "--iam-profile NAME",
|
61
|
-
:description => "The IAM instance profile to apply to this instance."
|
62
|
-
|
63
|
-
option :security_groups,
|
64
|
-
:short => "-G X,Y,Z",
|
65
|
-
:long => "--groups X,Y,Z",
|
66
|
-
:description => "The security groups for this server; not allowed when using VPC",
|
67
|
-
:proc => Proc.new { |groups| groups.split(',') }
|
68
|
-
|
69
|
-
option :security_group_ids,
|
70
|
-
:long => "--security-group-ids 'X,Y,Z'",
|
71
|
-
:description => "The security group ids for this server; required when using VPC. Provide values in format --security-group-ids 'X,Y,Z'. [DEPRECATED] This option will be removed in future release. Use the new --security-group-id option. ",
|
72
|
-
:proc => Proc.new { |security_group_ids|
|
73
|
-
ui.warn('[DEPRECATED] This option will be removed in future release. Use the new --security-group-id option multiple times when specifying multiple groups for e.g. -g sg-e985168d -g sg-e7f06383 -g sg-ec1b7e88.')
|
74
|
-
if security_group_ids.gsub(' ', '').split(',').size > 1
|
75
|
-
Chef::Config[:knife][:security_group_ids] = security_group_ids.gsub(' ', '').split(',')
|
76
|
-
else
|
77
|
-
Chef::Config[:knife][:security_group_ids] ||= []
|
78
|
-
Chef::Config[:knife][:security_group_ids].push(security_group_ids)
|
79
|
-
Chef::Config[:knife][:security_group_ids]
|
80
|
-
end
|
81
|
-
}
|
82
|
-
|
83
|
-
option :security_group_id,
|
84
|
-
:short => "-g SECURITY_GROUP_ID",
|
85
|
-
:long => "--security-group-id ID",
|
86
|
-
:description => "The security group id for this server; required when using VPC. Use the --security-group-id option multiple times when specifying multiple groups for e.g. -g sg-e985168d -g sg-e7f06383 -g sg-ec1b7e88.",
|
87
|
-
:proc => Proc.new { |security_group_id|
|
88
|
-
Chef::Config[:knife][:security_group_ids] ||= []
|
89
|
-
Chef::Config[:knife][:security_group_ids].push(security_group_id)
|
90
|
-
Chef::Config[:knife][:security_group_ids]
|
91
|
-
}
|
92
|
-
|
93
|
-
option :associate_eip,
|
94
|
-
:long => "--associate-eip IP_ADDRESS",
|
95
|
-
:description => "Associate existing elastic IP address with instance after launch"
|
96
|
-
|
97
|
-
option :dedicated_instance,
|
98
|
-
:long => "--dedicated_instance",
|
99
|
-
:description => "Launch as a Dedicated instance (VPC ONLY)"
|
100
|
-
|
101
|
-
option :placement_group,
|
102
|
-
:long => "--placement-group PLACEMENT_GROUP",
|
103
|
-
:description => "The placement group to place a cluster compute instance",
|
104
|
-
:proc => Proc.new { |pg| Chef::Config[:knife][:placement_group] = pg }
|
105
|
-
|
106
|
-
option :
|
107
|
-
:
|
108
|
-
:
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
:
|
114
|
-
:
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
:
|
120
|
-
:
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
:
|
126
|
-
:
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
:
|
132
|
-
:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
:
|
138
|
-
:
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
:
|
143
|
-
:
|
144
|
-
|
145
|
-
|
146
|
-
:
|
147
|
-
|
148
|
-
|
149
|
-
:
|
150
|
-
:
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
:
|
156
|
-
:
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
:
|
161
|
-
:
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
:long => "--
|
166
|
-
:description => "
|
167
|
-
|
168
|
-
option :
|
169
|
-
:long => "--
|
170
|
-
:description => "
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
:
|
175
|
-
:
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
:
|
180
|
-
:
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
option :
|
200
|
-
:long => "--
|
201
|
-
:description => "
|
202
|
-
|
203
|
-
option :
|
204
|
-
:long => "--ebs-
|
205
|
-
:description => "
|
206
|
-
|
207
|
-
option :
|
208
|
-
:long => "--ebs-
|
209
|
-
:description => "
|
210
|
-
|
211
|
-
option :
|
212
|
-
:
|
213
|
-
:
|
214
|
-
|
215
|
-
|
216
|
-
:
|
217
|
-
|
218
|
-
|
219
|
-
:
|
220
|
-
:
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
:
|
225
|
-
:
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
:
|
230
|
-
:
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
:
|
235
|
-
:
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
:
|
240
|
-
:
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
:
|
245
|
-
:
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
:
|
251
|
-
:
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
:
|
257
|
-
:
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
:
|
263
|
-
:
|
264
|
-
|
265
|
-
|
266
|
-
:
|
267
|
-
|
268
|
-
|
269
|
-
:
|
270
|
-
:
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
:
|
285
|
-
:
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
:
|
291
|
-
:
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
:
|
297
|
-
:
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
:
|
303
|
-
:
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
:
|
309
|
-
:
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
:
|
314
|
-
:
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
:
|
319
|
-
:
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
:
|
325
|
-
:
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
:
|
330
|
-
:
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
:
|
335
|
-
:
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
:
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
:
|
350
|
-
:
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
:
|
365
|
-
:
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
:
|
370
|
-
:
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
:
|
375
|
-
:
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
:
|
380
|
-
:
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
:
|
385
|
-
:
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
:
|
390
|
-
:
|
391
|
-
|
392
|
-
option :
|
393
|
-
:long => '--bootstrap-vault-
|
394
|
-
:description => 'A JSON
|
395
|
-
|
396
|
-
option :
|
397
|
-
:long => '--bootstrap-vault-
|
398
|
-
:description => 'A
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
:
|
414
|
-
:
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
:
|
420
|
-
:
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
:
|
426
|
-
:
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
:
|
432
|
-
:
|
433
|
-
|
434
|
-
option :
|
435
|
-
:long => "--classic-link-vpc-
|
436
|
-
:description => "
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
:
|
441
|
-
:
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
:
|
447
|
-
:
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
:
|
452
|
-
:
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
@
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
msg_pair("
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
msg_pair("
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
msg_pair("
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
print
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
msg_pair("
|
635
|
-
msg_pair("
|
636
|
-
msg_pair("
|
637
|
-
msg_pair("
|
638
|
-
msg_pair("
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
@server.block_device_mapping.
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
print "#{ui.color("===========================", :magenta)}\n"
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
msg_pair("
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
bootstrap.config[:
|
744
|
-
bootstrap.config[:
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
bootstrap.config[:
|
750
|
-
bootstrap.config[:
|
751
|
-
bootstrap.config[:
|
752
|
-
bootstrap.config[:
|
753
|
-
bootstrap.config[:
|
754
|
-
bootstrap.config[:
|
755
|
-
bootstrap.config[:
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
bootstrap.config[:
|
761
|
-
bootstrap.config[:
|
762
|
-
bootstrap.config[:
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
bootstrap
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
bootstrap =
|
794
|
-
bootstrap.config[:
|
795
|
-
bootstrap.config[:
|
796
|
-
bootstrap.config[:
|
797
|
-
bootstrap.config[:
|
798
|
-
bootstrap.config[:
|
799
|
-
bootstrap.config[:
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
end
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
bootstrap =
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
bootstrap
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
bootstrap.config[:
|
834
|
-
|
835
|
-
bootstrap.config[:
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
exit 1
|
908
|
-
end
|
909
|
-
|
910
|
-
if config[:
|
911
|
-
ui.error("
|
912
|
-
exit 1
|
913
|
-
end
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
exit 1
|
919
|
-
end
|
920
|
-
|
921
|
-
if config[:
|
922
|
-
ui.error("
|
923
|
-
exit 1
|
924
|
-
end
|
925
|
-
|
926
|
-
if
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
ui.error("--ebs-encrypted option
|
948
|
-
exit 1
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
end
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
if
|
980
|
-
ui.error("
|
981
|
-
exit 1
|
982
|
-
end
|
983
|
-
|
984
|
-
if (locate_config_value(:
|
985
|
-
ui.
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
}
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
$
|
1044
|
-
$
|
1045
|
-
$
|
1046
|
-
|
1047
|
-
|
1048
|
-
$
|
1049
|
-
$
|
1050
|
-
$
|
1051
|
-
$
|
1052
|
-
$
|
1053
|
-
$
|
1054
|
-
$
|
1055
|
-
$
|
1056
|
-
$
|
1057
|
-
$
|
1058
|
-
$
|
1059
|
-
$
|
1060
|
-
$
|
1061
|
-
$
|
1062
|
-
$
|
1063
|
-
$
|
1064
|
-
|
1065
|
-
$
|
1066
|
-
$
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
server_def
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
if
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
end
|
1328
|
-
|
1329
|
-
def
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
end
|
1351
|
-
|
1352
|
-
def
|
1353
|
-
|
1354
|
-
connection.
|
1355
|
-
end
|
1356
|
-
end
|
1357
|
-
|
1358
|
-
def
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
#
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
end
|
1409
|
-
|
1410
|
-
def
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
sleep 2
|
1452
|
-
false
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@chef.io>)
|
3
|
+
# Author:: Seth Chisamore (<schisamo@chef.io>)
|
4
|
+
# Copyright:: Copyright (c) 2010-2015 Chef Software, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/knife/ec2_base'
|
21
|
+
require 'chef/knife/s3_source'
|
22
|
+
require 'chef/knife/winrm_base'
|
23
|
+
require 'chef/knife/bootstrap_windows_base'
|
24
|
+
|
25
|
+
class Chef
|
26
|
+
class Knife
|
27
|
+
class Ec2ServerCreate < Knife
|
28
|
+
|
29
|
+
include Knife::Ec2Base
|
30
|
+
include Knife::WinrmBase
|
31
|
+
include Knife::BootstrapWindowsBase
|
32
|
+
deps do
|
33
|
+
require 'tempfile'
|
34
|
+
require 'fog/aws'
|
35
|
+
require 'uri'
|
36
|
+
require 'readline'
|
37
|
+
require 'chef/json_compat'
|
38
|
+
require 'chef/knife/bootstrap'
|
39
|
+
Chef::Knife::Bootstrap.load_deps
|
40
|
+
end
|
41
|
+
|
42
|
+
banner "knife ec2 server create (options)"
|
43
|
+
|
44
|
+
attr_accessor :initial_sleep_delay
|
45
|
+
attr_reader :server
|
46
|
+
|
47
|
+
option :flavor,
|
48
|
+
:short => "-f FLAVOR",
|
49
|
+
:long => "--flavor FLAVOR",
|
50
|
+
:description => "The flavor of server (m1.small, m1.medium, etc)",
|
51
|
+
:proc => Proc.new { |f| Chef::Config[:knife][:flavor] = f }
|
52
|
+
|
53
|
+
option :image,
|
54
|
+
:short => "-I IMAGE",
|
55
|
+
:long => "--image IMAGE",
|
56
|
+
:description => "The AMI for the server",
|
57
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:image] = i }
|
58
|
+
|
59
|
+
option :iam_instance_profile,
|
60
|
+
:long => "--iam-profile NAME",
|
61
|
+
:description => "The IAM instance profile to apply to this instance."
|
62
|
+
|
63
|
+
option :security_groups,
|
64
|
+
:short => "-G X,Y,Z",
|
65
|
+
:long => "--groups X,Y,Z",
|
66
|
+
:description => "The security groups for this server; not allowed when using VPC",
|
67
|
+
:proc => Proc.new { |groups| groups.split(',') }
|
68
|
+
|
69
|
+
option :security_group_ids,
|
70
|
+
:long => "--security-group-ids 'X,Y,Z'",
|
71
|
+
:description => "The security group ids for this server; required when using VPC. Provide values in format --security-group-ids 'X,Y,Z'. [DEPRECATED] This option will be removed in future release. Use the new --security-group-id option. ",
|
72
|
+
:proc => Proc.new { |security_group_ids|
|
73
|
+
ui.warn('[DEPRECATED] This option will be removed in future release. Use the new --security-group-id option multiple times when specifying multiple groups for e.g. -g sg-e985168d -g sg-e7f06383 -g sg-ec1b7e88.')
|
74
|
+
if security_group_ids.gsub(' ', '').split(',').size > 1
|
75
|
+
Chef::Config[:knife][:security_group_ids] = security_group_ids.gsub(' ', '').split(',')
|
76
|
+
else
|
77
|
+
Chef::Config[:knife][:security_group_ids] ||= []
|
78
|
+
Chef::Config[:knife][:security_group_ids].push(security_group_ids)
|
79
|
+
Chef::Config[:knife][:security_group_ids]
|
80
|
+
end
|
81
|
+
}
|
82
|
+
|
83
|
+
option :security_group_id,
|
84
|
+
:short => "-g SECURITY_GROUP_ID",
|
85
|
+
:long => "--security-group-id ID",
|
86
|
+
:description => "The security group id for this server; required when using VPC. Use the --security-group-id option multiple times when specifying multiple groups for e.g. -g sg-e985168d -g sg-e7f06383 -g sg-ec1b7e88.",
|
87
|
+
:proc => Proc.new { |security_group_id|
|
88
|
+
Chef::Config[:knife][:security_group_ids] ||= []
|
89
|
+
Chef::Config[:knife][:security_group_ids].push(security_group_id)
|
90
|
+
Chef::Config[:knife][:security_group_ids]
|
91
|
+
}
|
92
|
+
|
93
|
+
option :associate_eip,
|
94
|
+
:long => "--associate-eip IP_ADDRESS",
|
95
|
+
:description => "Associate existing elastic IP address with instance after launch"
|
96
|
+
|
97
|
+
option :dedicated_instance,
|
98
|
+
:long => "--dedicated_instance",
|
99
|
+
:description => "Launch as a Dedicated instance (VPC ONLY)"
|
100
|
+
|
101
|
+
option :placement_group,
|
102
|
+
:long => "--placement-group PLACEMENT_GROUP",
|
103
|
+
:description => "The placement group to place a cluster compute instance",
|
104
|
+
:proc => Proc.new { |pg| Chef::Config[:knife][:placement_group] = pg }
|
105
|
+
|
106
|
+
option :primary_eni,
|
107
|
+
:long => "--primary-eni ENI_ID",
|
108
|
+
:description => "Specify a pre-existing eni to use when building the instance."
|
109
|
+
|
110
|
+
option :tags,
|
111
|
+
:short => "-T T=V[,T=V,...]",
|
112
|
+
:long => "--tags Tag=Value[,Tag=Value...]",
|
113
|
+
:description => "The tags for this server",
|
114
|
+
:proc => Proc.new { |tags| tags.split(',') }
|
115
|
+
|
116
|
+
option :availability_zone,
|
117
|
+
:short => "-Z ZONE",
|
118
|
+
:long => "--availability-zone ZONE",
|
119
|
+
:description => "The Availability Zone",
|
120
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:availability_zone] = key }
|
121
|
+
|
122
|
+
option :chef_node_name,
|
123
|
+
:short => "-N NAME",
|
124
|
+
:long => "--node-name NAME",
|
125
|
+
:description => "The Chef node name for your new node",
|
126
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:chef_node_name] = key }
|
127
|
+
|
128
|
+
option :ssh_key_name,
|
129
|
+
:short => "-S KEY",
|
130
|
+
:long => "--ssh-key KEY",
|
131
|
+
:description => "The AWS SSH key id",
|
132
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_key_name] = key }
|
133
|
+
|
134
|
+
option :ssh_user,
|
135
|
+
:short => "-x USERNAME",
|
136
|
+
:long => "--ssh-user USERNAME",
|
137
|
+
:description => "The ssh username",
|
138
|
+
:default => "root"
|
139
|
+
|
140
|
+
option :ssh_password,
|
141
|
+
:short => "-P PASSWORD",
|
142
|
+
:long => "--ssh-password PASSWORD",
|
143
|
+
:description => "The ssh password"
|
144
|
+
|
145
|
+
option :ssh_port,
|
146
|
+
:short => "-p PORT",
|
147
|
+
:long => "--ssh-port PORT",
|
148
|
+
:description => "The ssh port",
|
149
|
+
:default => "22",
|
150
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
|
151
|
+
|
152
|
+
option :ssh_gateway,
|
153
|
+
:short => "-w GATEWAY",
|
154
|
+
:long => "--ssh-gateway GATEWAY",
|
155
|
+
:description => "The ssh gateway server. Any proxies configured in your ssh config are automatically used by default.",
|
156
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
|
157
|
+
|
158
|
+
option :ssh_gateway_identity,
|
159
|
+
:long => "--ssh-gateway-identity IDENTITY_FILE",
|
160
|
+
:description => "The private key for ssh gateway server",
|
161
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway_identity] = key }
|
162
|
+
|
163
|
+
option :identity_file,
|
164
|
+
:short => "-i IDENTITY_FILE",
|
165
|
+
:long => "--identity-file IDENTITY_FILE",
|
166
|
+
:description => "The SSH identity file used for authentication"
|
167
|
+
|
168
|
+
option :prerelease,
|
169
|
+
:long => "--prerelease",
|
170
|
+
:description => "Install the pre-release chef gems"
|
171
|
+
|
172
|
+
option :bootstrap_version,
|
173
|
+
:long => "--bootstrap-version VERSION",
|
174
|
+
:description => "The version of Chef to install",
|
175
|
+
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
176
|
+
|
177
|
+
option :bootstrap_proxy,
|
178
|
+
:long => "--bootstrap-proxy PROXY_URL",
|
179
|
+
:description => "The proxy server for the node being bootstrapped",
|
180
|
+
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
181
|
+
|
182
|
+
option :distro,
|
183
|
+
:short => "-d DISTRO",
|
184
|
+
:long => "--distro DISTRO",
|
185
|
+
:description => "Bootstrap a distro using a template. [DEPRECATED] Use --bootstrap-template option instead.",
|
186
|
+
:proc => Proc.new { |v|
|
187
|
+
Chef::Log.warn("[DEPRECATED] -d / --distro option is deprecated. Use --bootstrap-template option instead.")
|
188
|
+
v
|
189
|
+
}
|
190
|
+
|
191
|
+
option :template_file,
|
192
|
+
:long => "--template-file TEMPLATE",
|
193
|
+
:description => "Full path to location of template to use. [DEPRECATED] Use -t / --bootstrap-template option instead.",
|
194
|
+
:proc => Proc.new { |v|
|
195
|
+
Chef::Log.warn("[DEPRECATED] --template-file option is deprecated. Use -t / --bootstrap-template option instead.")
|
196
|
+
v
|
197
|
+
}
|
198
|
+
|
199
|
+
option :bootstrap_template,
|
200
|
+
:long => "--bootstrap-template TEMPLATE",
|
201
|
+
:description => "Bootstrap Chef using a built-in or custom template. Set to the full path of an erb template or use one of the built-in templates."
|
202
|
+
|
203
|
+
option :ebs_size,
|
204
|
+
:long => "--ebs-size SIZE",
|
205
|
+
:description => "The size of the EBS volume in GB, for EBS-backed instances"
|
206
|
+
|
207
|
+
option :ebs_optimized,
|
208
|
+
:long => "--ebs-optimized",
|
209
|
+
:description => "Enabled optimized EBS I/O"
|
210
|
+
|
211
|
+
option :ebs_no_delete_on_term,
|
212
|
+
:long => "--ebs-no-delete-on-term",
|
213
|
+
:description => "Do not delete EBS volume on instance termination"
|
214
|
+
|
215
|
+
option :run_list,
|
216
|
+
:short => "-r RUN_LIST",
|
217
|
+
:long => "--run-list RUN_LIST",
|
218
|
+
:description => "Comma separated list of roles/recipes to apply",
|
219
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
220
|
+
:default => []
|
221
|
+
|
222
|
+
option :secret,
|
223
|
+
:long => "--secret ",
|
224
|
+
:description => "The secret key to use to encrypt data bag item values",
|
225
|
+
:proc => lambda { |s| Chef::Config[:knife][:secret] = s }
|
226
|
+
|
227
|
+
option :secret_file,
|
228
|
+
:long => "--secret-file SECRET_FILE",
|
229
|
+
:description => "A file containing the secret key to use to encrypt data bag item values",
|
230
|
+
:proc => lambda { |sf| Chef::Config[:knife][:secret_file] = sf }
|
231
|
+
|
232
|
+
option :s3_secret,
|
233
|
+
:long => '--s3-secret S3_SECRET_URL',
|
234
|
+
:description => 'S3 URL (e.g. s3://bucket/file) for the encrypted_data_bag_secret_file',
|
235
|
+
:proc => lambda { |url| Chef::Config[:knife][:s3_secret] = url }
|
236
|
+
|
237
|
+
option :subnet_id,
|
238
|
+
:long => "--subnet SUBNET-ID",
|
239
|
+
:description => "create node in this Virtual Private Cloud Subnet ID (implies VPC mode)",
|
240
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:subnet_id] = key }
|
241
|
+
|
242
|
+
option :private_ip_address,
|
243
|
+
:long => "--private-ip-address IP-ADDRESS",
|
244
|
+
:description => "allows to specify the private IP address of the instance in VPC mode",
|
245
|
+
:proc => Proc.new { |ip| Chef::Config[:knife][:private_ip_address] = ip }
|
246
|
+
|
247
|
+
option :host_key_verify,
|
248
|
+
:long => "--[no-]host-key-verify",
|
249
|
+
:description => "Verify host key, enabled by default.",
|
250
|
+
:boolean => true,
|
251
|
+
:default => true
|
252
|
+
|
253
|
+
option :bootstrap_protocol,
|
254
|
+
:long => "--bootstrap-protocol protocol",
|
255
|
+
:description => "protocol to bootstrap windows servers. options: winrm/ssh",
|
256
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:bootstrap_protocol] = key },
|
257
|
+
:default => nil
|
258
|
+
|
259
|
+
option :fqdn,
|
260
|
+
:long => "--fqdn FQDN",
|
261
|
+
:description => "Pre-defined FQDN. This is used for Kerberos Authentication purpose only",
|
262
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:fqdn] = key },
|
263
|
+
:default => nil
|
264
|
+
|
265
|
+
option :aws_user_data,
|
266
|
+
:long => "--user-data USER_DATA_FILE",
|
267
|
+
:short => "-u USER_DATA_FILE",
|
268
|
+
:description => "The EC2 User Data file to provision the instance with",
|
269
|
+
:proc => Proc.new { |m| Chef::Config[:knife][:aws_user_data] = m },
|
270
|
+
:default => nil
|
271
|
+
|
272
|
+
option :hint,
|
273
|
+
:long => "--hint HINT_NAME[=HINT_FILE]",
|
274
|
+
:description => "Specify Ohai Hint to be set on the bootstrap target. Use multiple --hint options to specify multiple hints.",
|
275
|
+
:proc => Proc.new { |h|
|
276
|
+
Chef::Config[:knife][:hints] ||= {}
|
277
|
+
name, path = h.split("=")
|
278
|
+
Chef::Config[:knife][:hints][name] = path ? JSON.parse(::File.read(path)) : Hash.new
|
279
|
+
}
|
280
|
+
|
281
|
+
option :ephemeral,
|
282
|
+
:long => "--ephemeral EPHEMERAL_DEVICES",
|
283
|
+
:description => "Comma separated list of device locations (eg - /dev/sdb) to map ephemeral devices",
|
284
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
285
|
+
:default => []
|
286
|
+
|
287
|
+
option :server_connect_attribute,
|
288
|
+
:long => "--server-connect-attribute ATTRIBUTE",
|
289
|
+
:short => "-a ATTRIBUTE",
|
290
|
+
:description => "The EC2 server attribute to use for the SSH connection if necessary, e.g. public_ip_address or private_ip_address.",
|
291
|
+
:default => nil
|
292
|
+
|
293
|
+
option :associate_public_ip,
|
294
|
+
:long => "--associate-public-ip",
|
295
|
+
:description => "Associate public ip to VPC instance.",
|
296
|
+
:boolean => true,
|
297
|
+
:default => false
|
298
|
+
|
299
|
+
option :ebs_volume_type,
|
300
|
+
:long => "--ebs-volume-type TYPE",
|
301
|
+
:description => "Possible values are standard (magnetic) | io1 | gp2 | sc1 | st1. Default is gp2",
|
302
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ebs_volume_type] = key },
|
303
|
+
:default => "gp2"
|
304
|
+
|
305
|
+
option :ebs_provisioned_iops,
|
306
|
+
:long => "--provisioned-iops IOPS",
|
307
|
+
:description => "IOPS rate, only used when ebs volume type is 'io1'",
|
308
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:provisioned_iops] = key },
|
309
|
+
:default => nil
|
310
|
+
|
311
|
+
option :auth_timeout,
|
312
|
+
:long => "--windows-auth-timeout MINUTES",
|
313
|
+
:description => "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 25 minutes.",
|
314
|
+
:default => 25
|
315
|
+
|
316
|
+
option :validation_key_url,
|
317
|
+
:long => "--validation-key-url URL",
|
318
|
+
:description => "Path to the validation key",
|
319
|
+
:proc => proc { |m| Chef::Config[:validation_key_url] = m }
|
320
|
+
|
321
|
+
option :ebs_encrypted,
|
322
|
+
:long => "--ebs-encrypted",
|
323
|
+
:description => "Enables EBS volume encryption",
|
324
|
+
:boolean => true,
|
325
|
+
:default => false
|
326
|
+
|
327
|
+
option :spot_price,
|
328
|
+
:long => "--spot-price PRICE",
|
329
|
+
:description => "The maximum hourly USD price for the instance",
|
330
|
+
:default => nil
|
331
|
+
|
332
|
+
option :spot_request_type,
|
333
|
+
:long => "--spot-request-type TYPE",
|
334
|
+
:description => "The Spot Instance request type. Possible values are 'one-time' and 'persistent', default value is 'one-time'",
|
335
|
+
:default => "one-time"
|
336
|
+
|
337
|
+
option :spot_wait_mode,
|
338
|
+
:long => "--spot-wait-mode MODE",
|
339
|
+
:description =>
|
340
|
+
"Whether we should wait for spot request fulfillment. Could be 'wait', 'exit', or " \
|
341
|
+
"'prompt' (default). For any of the above mentioned choices, ('wait') - if the " \
|
342
|
+
"instance does not get allocated before the command itself times-out or ('exit') the " \
|
343
|
+
"user needs to manually bootstrap the instance in the future after it gets allocated.",
|
344
|
+
:default => "prompt"
|
345
|
+
|
346
|
+
option :aws_connection_timeout,
|
347
|
+
:long => "--aws-connection-timeout MINUTES",
|
348
|
+
:description => "The maximum time in minutes to wait to for aws connection. Default is 10 min",
|
349
|
+
:proc => proc {|t| t = t.to_i * 60; Chef::Config[:aws_connection_timeout] = t},
|
350
|
+
:default => 600
|
351
|
+
|
352
|
+
option :node_ssl_verify_mode,
|
353
|
+
:long => "--node-ssl-verify-mode [peer|none]",
|
354
|
+
:description => "Whether or not to verify the SSL cert for all HTTPS requests.",
|
355
|
+
:proc => Proc.new { |v|
|
356
|
+
valid_values = ["none", "peer"]
|
357
|
+
unless valid_values.include?(v)
|
358
|
+
raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}"
|
359
|
+
end
|
360
|
+
}
|
361
|
+
|
362
|
+
option :node_verify_api_cert,
|
363
|
+
:long => "--[no-]node-verify-api-cert",
|
364
|
+
:description => "Verify the SSL cert for HTTPS requests to the Chef server API.",
|
365
|
+
:boolean => true
|
366
|
+
|
367
|
+
option :bootstrap_no_proxy,
|
368
|
+
:long => "--bootstrap-no-proxy [NO_PROXY_URL|NO_PROXY_IP]",
|
369
|
+
:description => "Do not proxy locations for the node being bootstrapped; this option is used internally by Opscode",
|
370
|
+
:proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
|
371
|
+
|
372
|
+
option :bootstrap_url,
|
373
|
+
:long => "--bootstrap-url URL",
|
374
|
+
:description => "URL to a custom installation script",
|
375
|
+
:proc => Proc.new { |u| Chef::Config[:knife][:bootstrap_url] = u }
|
376
|
+
|
377
|
+
option :bootstrap_install_command,
|
378
|
+
:long => "--bootstrap-install-command COMMANDS",
|
379
|
+
:description => "Custom command to install chef-client",
|
380
|
+
:proc => Proc.new { |ic| Chef::Config[:knife][:bootstrap_install_command] = ic }
|
381
|
+
|
382
|
+
option :bootstrap_wget_options,
|
383
|
+
:long => "--bootstrap-wget-options OPTIONS",
|
384
|
+
:description => "Add options to wget when installing chef-client",
|
385
|
+
:proc => Proc.new { |wo| Chef::Config[:knife][:bootstrap_wget_options] = wo }
|
386
|
+
|
387
|
+
option :bootstrap_curl_options,
|
388
|
+
:long => "--bootstrap-curl-options OPTIONS",
|
389
|
+
:description => "Add options to curl when install chef-client",
|
390
|
+
:proc => Proc.new { |co| Chef::Config[:knife][:bootstrap_curl_options] = co }
|
391
|
+
|
392
|
+
option :bootstrap_vault_file,
|
393
|
+
:long => '--bootstrap-vault-file VAULT_FILE',
|
394
|
+
:description => 'A JSON file with a list of vault(s) and item(s) to be updated'
|
395
|
+
|
396
|
+
option :bootstrap_vault_json,
|
397
|
+
:long => '--bootstrap-vault-json VAULT_JSON',
|
398
|
+
:description => 'A JSON string with the vault(s) and item(s) to be updated'
|
399
|
+
|
400
|
+
option :bootstrap_vault_item,
|
401
|
+
:long => '--bootstrap-vault-item VAULT_ITEM',
|
402
|
+
:description => 'A single vault and item to update as "vault:item"',
|
403
|
+
:proc => Proc.new { |i|
|
404
|
+
(vault, item) = i.split(/:/)
|
405
|
+
Chef::Config[:knife][:bootstrap_vault_item] ||= {}
|
406
|
+
Chef::Config[:knife][:bootstrap_vault_item][vault] ||= []
|
407
|
+
Chef::Config[:knife][:bootstrap_vault_item][vault].push(item)
|
408
|
+
Chef::Config[:knife][:bootstrap_vault_item]
|
409
|
+
}
|
410
|
+
|
411
|
+
option :use_sudo_password,
|
412
|
+
:long => "--use-sudo-password",
|
413
|
+
:description => "Execute the bootstrap via sudo with password",
|
414
|
+
:boolean => false
|
415
|
+
|
416
|
+
option :forward_agent,
|
417
|
+
:short => "-A",
|
418
|
+
:long => "--forward-agent",
|
419
|
+
:description => "Enable SSH agent forwarding",
|
420
|
+
:boolean => true
|
421
|
+
|
422
|
+
option :create_ssl_listener,
|
423
|
+
:long => "--[no-]create-ssl-listener",
|
424
|
+
:description => "Create ssl listener, enabled by default.",
|
425
|
+
:boolean => true,
|
426
|
+
:default => true
|
427
|
+
|
428
|
+
option :network_interfaces,
|
429
|
+
:short => '-n',
|
430
|
+
:long => '--attach-network-interface ENI1,ENI2',
|
431
|
+
:description => 'Attach additional network interfaces during bootstrap',
|
432
|
+
:proc => proc { |nics| nics.split(',') }
|
433
|
+
|
434
|
+
option :classic_link_vpc_id,
|
435
|
+
:long => "--classic-link-vpc-id VPC_ID",
|
436
|
+
:description => "Enable ClassicLink connection with a VPC"
|
437
|
+
|
438
|
+
option :classic_link_vpc_security_group_ids,
|
439
|
+
:long => "--classic-link-vpc-security-groups-ids X,Y,Z",
|
440
|
+
:description => "Comma-separated list of security group ids for ClassicLink",
|
441
|
+
:proc => Proc.new { |groups| groups.split(',') }
|
442
|
+
|
443
|
+
option :disable_api_termination,
|
444
|
+
:long => "--disable-api-termination",
|
445
|
+
:description => "Disable termination of the instance using the Amazon EC2 console, CLI and API.",
|
446
|
+
:boolean => true,
|
447
|
+
:default => false
|
448
|
+
|
449
|
+
option :volume_tags,
|
450
|
+
:long => "--volume-tags Tag=Value[,Tag=Value...]",
|
451
|
+
:description => "Tag the Root volume",
|
452
|
+
:proc => Proc.new { |volume_tags| volume_tags.split(',') }
|
453
|
+
|
454
|
+
option :tag_node_in_chef,
|
455
|
+
:long => "--tag-node-in-chef",
|
456
|
+
:description => "Flag for tagging node in ec2 and chef both",
|
457
|
+
:boolean => true,
|
458
|
+
:default => false
|
459
|
+
|
460
|
+
option :instance_initiated_shutdown_behavior,
|
461
|
+
:long => "--instance-initiated-shutdown-behavior SHUTDOWN_BEHAVIOR",
|
462
|
+
:description => "Indicates whether an instance stops or terminates when you initiate shutdown from the instance. Possible values are 'stop' and 'terminate', default is 'stop'."
|
463
|
+
|
464
|
+
def run
|
465
|
+
$stdout.sync = true
|
466
|
+
validate!
|
467
|
+
|
468
|
+
requested_elastic_ip = config[:associate_eip] if config[:associate_eip]
|
469
|
+
|
470
|
+
# For VPC EIP assignment we need the allocation ID so fetch full EIP details
|
471
|
+
elastic_ip = connection.addresses.detect{|addr| addr if addr.public_ip == requested_elastic_ip}
|
472
|
+
|
473
|
+
if locate_config_value(:spot_price)
|
474
|
+
server_def = create_server_def
|
475
|
+
server_def[:groups] = server_def[:security_group_ids] if vpc_mode?
|
476
|
+
spot_request = connection.spot_requests.create(server_def)
|
477
|
+
msg_pair("Spot Request ID", spot_request.id)
|
478
|
+
msg_pair("Spot Request Type", spot_request.request_type)
|
479
|
+
msg_pair("Spot Price", spot_request.price)
|
480
|
+
|
481
|
+
case config[:spot_wait_mode]
|
482
|
+
when 'prompt', '', nil
|
483
|
+
wait_msg = "Do you want to wait for Spot Instance Request fulfillment? (Y/N) \n"
|
484
|
+
wait_msg += "Y - Wait for Spot Instance request fulfillment\n"
|
485
|
+
wait_msg += "N - Do not wait for Spot Instance request fulfillment. "
|
486
|
+
wait_msg += ui.color("[WARN :: Request would be alive on AWS ec2 side but execution of Chef Bootstrap on the target instance will get skipped.]\n", :red, :bold)
|
487
|
+
wait_msg += ui.color("\n[WARN :: For any of the above mentioned choices, (Y) - if the instance does not get allocated before the command itself times-out or (N) - user decides to exit, then in both cases user needs to manually bootstrap the instance in the future after it gets allocated.]\n\n", :cyan, :bold)
|
488
|
+
confirm(wait_msg)
|
489
|
+
when 'wait'
|
490
|
+
# wait for the node and run Chef bootstrap
|
491
|
+
when 'exit'
|
492
|
+
ui.color("The 'exit' option was specified for --spot-wait-mode, exiting.", :cyan)
|
493
|
+
exit
|
494
|
+
else
|
495
|
+
raise "Invalid value for --spot-wait-mode: '#{config[:spot_wait_mode]}', " \
|
496
|
+
"valid values: wait, exit, prompt"
|
497
|
+
end
|
498
|
+
|
499
|
+
print ui.color("Waiting for Spot Request fulfillment: ", :cyan)
|
500
|
+
spot_request.wait_for do
|
501
|
+
@spinner ||= %w{| / - \\}
|
502
|
+
print "\b" + @spinner.rotate!.first
|
503
|
+
ready?
|
504
|
+
end
|
505
|
+
puts("\n")
|
506
|
+
@server = connection.servers.get(spot_request.instance_id)
|
507
|
+
else
|
508
|
+
begin
|
509
|
+
@server = connection.servers.create(create_server_def)
|
510
|
+
rescue => error
|
511
|
+
error.message.sub("download completed, but downloaded file not found", "Verify that you have public internet access.")
|
512
|
+
ui.error error.message
|
513
|
+
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
514
|
+
exit
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
hashed_tags={}
|
519
|
+
tags.map{ |t| key,val=t.split('='); hashed_tags[key]=val} unless tags.nil?
|
520
|
+
|
521
|
+
# Always set the Name tag
|
522
|
+
unless hashed_tags.keys.include? "Name"
|
523
|
+
if locate_config_value(:chef_node_name)
|
524
|
+
hashed_tags["Name"] = evaluate_node_name(locate_config_value(:chef_node_name))
|
525
|
+
else
|
526
|
+
hashed_tags["Name"] = server.id
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
printed_tags = hashed_tags.map{ |tag, val| "#{tag}: #{val}" }.join(", ")
|
531
|
+
|
532
|
+
hashed_volume_tags={}
|
533
|
+
volume_tags = locate_config_value(:volume_tags)
|
534
|
+
volume_tags.map{ |t| key,val=t.split('='); hashed_volume_tags[key]=val} unless volume_tags.nil?
|
535
|
+
printed_volume_tags = hashed_volume_tags.map{ |tag, val| "#{tag}: #{val}" }.join(", ")
|
536
|
+
|
537
|
+
msg_pair("Instance ID", @server.id)
|
538
|
+
msg_pair("Flavor", @server.flavor_id)
|
539
|
+
msg_pair("Image", @server.image_id)
|
540
|
+
msg_pair("Region", connection.instance_variable_get(:@region))
|
541
|
+
msg_pair("Availability Zone", @server.availability_zone)
|
542
|
+
|
543
|
+
# If we don't specify a security group or security group id, Fog will
|
544
|
+
# pick the appropriate default one. In case of a VPC we don't know the
|
545
|
+
# default security group id at this point unless we look it up, hence
|
546
|
+
# 'default' is printed if no id was specified.
|
547
|
+
printed_security_groups = "default"
|
548
|
+
printed_security_groups = @server.groups.join(", ") if @server.groups
|
549
|
+
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? or (@server.groups.nil? and @server.security_group_ids)
|
550
|
+
|
551
|
+
printed_security_group_ids = "default"
|
552
|
+
printed_security_group_ids = @server.security_group_ids.join(", ") if @server.security_group_ids
|
553
|
+
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? or @server.security_group_ids
|
554
|
+
|
555
|
+
msg_pair("IAM Profile", locate_config_value(:iam_instance_profile))
|
556
|
+
|
557
|
+
msg_pair("Tags", printed_tags)
|
558
|
+
msg_pair("Volume Tags", printed_volume_tags)
|
559
|
+
msg_pair("SSH Key", @server.key_name)
|
560
|
+
|
561
|
+
print "\n#{ui.color("Waiting for EC2 to create the instance", :magenta)}"
|
562
|
+
|
563
|
+
# wait for instance to come up before acting against it
|
564
|
+
@server.wait_for(locate_config_value(:aws_connection_timeout)) { print "."; ready? }
|
565
|
+
|
566
|
+
puts("\n")
|
567
|
+
|
568
|
+
# occasionally 'ready?' isn't, so retry a couple times if needed.
|
569
|
+
tries = 6
|
570
|
+
begin
|
571
|
+
create_tags(hashed_tags) unless hashed_tags.empty?
|
572
|
+
create_volume_tags(hashed_volume_tags) unless hashed_volume_tags.empty?
|
573
|
+
associate_eip(elastic_ip) if config[:associate_eip]
|
574
|
+
enable_classic_link(config[:classic_link_vpc_id], config[:classic_link_vpc_security_group_ids]) if config[:classic_link_vpc_id]
|
575
|
+
rescue Fog::Compute::AWS::NotFound, Fog::Errors::Error
|
576
|
+
raise if (tries -= 1) <= 0
|
577
|
+
ui.warn("server not ready, retrying tag application (retries left: #{tries})")
|
578
|
+
sleep 5
|
579
|
+
retry
|
580
|
+
end
|
581
|
+
|
582
|
+
attach_nics if config[:network_interfaces]
|
583
|
+
|
584
|
+
if vpc_mode?
|
585
|
+
msg_pair("Subnet ID", @server.subnet_id)
|
586
|
+
msg_pair("Tenancy", @server.tenancy)
|
587
|
+
if config[:associate_public_ip]
|
588
|
+
msg_pair("Public DNS Name", @server.dns_name)
|
589
|
+
end
|
590
|
+
if elastic_ip
|
591
|
+
msg_pair("Public IP Address", @server.public_ip_address)
|
592
|
+
end
|
593
|
+
else
|
594
|
+
msg_pair("Public DNS Name", @server.dns_name)
|
595
|
+
msg_pair("Public IP Address", @server.public_ip_address)
|
596
|
+
msg_pair("Private DNS Name", @server.private_dns_name)
|
597
|
+
end
|
598
|
+
msg_pair("Private IP Address", @server.private_ip_address)
|
599
|
+
|
600
|
+
if Chef::Config[:knife][:validation_key_url]
|
601
|
+
download_validation_key(validation_key_path)
|
602
|
+
Chef::Config[:validation_key] = validation_key_path
|
603
|
+
end
|
604
|
+
|
605
|
+
#Check if Server is Windows or Linux
|
606
|
+
if is_image_windows?
|
607
|
+
protocol = locate_config_value(:bootstrap_protocol)
|
608
|
+
protocol ||= 'winrm'
|
609
|
+
if protocol == 'winrm'
|
610
|
+
load_winrm_deps
|
611
|
+
print "\n#{ui.color("Waiting for winrm access to become available", :magenta)}"
|
612
|
+
print(".") until tcp_test_winrm(ssh_connect_host, locate_config_value(:winrm_port)) {
|
613
|
+
sleep 10
|
614
|
+
puts("done")
|
615
|
+
}
|
616
|
+
else
|
617
|
+
print "\n#{ui.color("Waiting for sshd access to become available", :magenta)}"
|
618
|
+
#If FreeSSHd, winsshd etc are available
|
619
|
+
print(".") until tcp_test_ssh(ssh_connect_host, config[:ssh_port]) {
|
620
|
+
sleep @initial_sleep_delay ||= (vpc_mode? ? 40 : 10)
|
621
|
+
puts("done")
|
622
|
+
}
|
623
|
+
ssh_override_winrm
|
624
|
+
end
|
625
|
+
bootstrap_for_windows_node(@server, ssh_connect_host).run
|
626
|
+
else
|
627
|
+
print "\n#{ui.color("Waiting for sshd access to become available", :magenta)}"
|
628
|
+
wait_for_sshd(ssh_connect_host)
|
629
|
+
ssh_override_winrm
|
630
|
+
bootstrap_for_linux_node(@server, ssh_connect_host).run
|
631
|
+
end
|
632
|
+
|
633
|
+
puts "\n"
|
634
|
+
msg_pair("Instance ID", @server.id)
|
635
|
+
msg_pair("Flavor", @server.flavor_id)
|
636
|
+
msg_pair("Placement Group", @server.placement_group) unless @server.placement_group.nil?
|
637
|
+
msg_pair("Image", @server.image_id)
|
638
|
+
msg_pair("Region", connection.instance_variable_get(:@region))
|
639
|
+
msg_pair("Availability Zone", @server.availability_zone)
|
640
|
+
msg_pair("Security Groups", printed_security_groups) unless vpc_mode? or (@server.groups.nil? and @server.security_group_ids)
|
641
|
+
msg_pair("Security Group Ids", printed_security_group_ids) if vpc_mode? or @server.security_group_ids
|
642
|
+
msg_pair("IAM Profile", locate_config_value(:iam_instance_profile)) if locate_config_value(:iam_instance_profile)
|
643
|
+
msg_pair("Primary ENI", locate_config_value(:primary_eni)) if locate_config_value(:primary_eni)
|
644
|
+
msg_pair("Tags", printed_tags)
|
645
|
+
msg_pair("SSH Key", @server.key_name)
|
646
|
+
msg_pair("Root Device Type", @server.root_device_type)
|
647
|
+
msg_pair("Root Volume Tags", printed_volume_tags)
|
648
|
+
if @server.root_device_type == "ebs"
|
649
|
+
device_map = @server.block_device_mapping.first
|
650
|
+
msg_pair("Root Volume ID", device_map['volumeId'])
|
651
|
+
msg_pair("Root Device Name", device_map['deviceName'])
|
652
|
+
msg_pair("Root Device Delete on Terminate", device_map['deleteOnTermination'])
|
653
|
+
msg_pair("Standard or Provisioned IOPS", device_map['volumeType'])
|
654
|
+
msg_pair("IOPS rate", device_map['iops'])
|
655
|
+
|
656
|
+
print "\n#{ui.color("Block devices", :magenta)}\n"
|
657
|
+
print "#{ui.color("===========================", :magenta)}\n"
|
658
|
+
@server.block_device_mapping.each do |device_map|
|
659
|
+
msg_pair("Device Name", device_map['deviceName'])
|
660
|
+
msg_pair("Volume ID", device_map['volumeId'])
|
661
|
+
msg_pair("Delete on Terminate", device_map['deleteOnTermination'].to_s)
|
662
|
+
msg_pair("Standard or Provisioned IOPS", device_map['volumeType'])
|
663
|
+
msg_pair("IOPS rate", device_map['iops'])
|
664
|
+
print "\n"
|
665
|
+
end
|
666
|
+
print "#{ui.color("===========================", :magenta)}\n"
|
667
|
+
|
668
|
+
if config[:ebs_size]
|
669
|
+
if ami.block_device_mapping.first['volumeSize'].to_i < config[:ebs_size].to_i
|
670
|
+
volume_too_large_warning = "#{config[:ebs_size]}GB " +
|
671
|
+
"EBS volume size is larger than size set in AMI of " +
|
672
|
+
"#{ami.block_device_mapping.first['volumeSize']}GB.\n" +
|
673
|
+
"Use file system tools to make use of the increased volume size."
|
674
|
+
msg_pair("Warning", volume_too_large_warning, :yellow)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
end
|
678
|
+
if config[:ebs_optimized]
|
679
|
+
msg_pair("EBS is Optimized", @server.ebs_optimized.to_s)
|
680
|
+
end
|
681
|
+
if vpc_mode?
|
682
|
+
msg_pair("Subnet ID", @server.subnet_id)
|
683
|
+
msg_pair("Tenancy", @server.tenancy)
|
684
|
+
if config[:associate_public_ip]
|
685
|
+
msg_pair("Public DNS Name", @server.dns_name)
|
686
|
+
end
|
687
|
+
else
|
688
|
+
msg_pair("Public DNS Name", @server.dns_name)
|
689
|
+
msg_pair("Public IP Address", @server.public_ip_address)
|
690
|
+
msg_pair("Private DNS Name", @server.private_dns_name)
|
691
|
+
end
|
692
|
+
msg_pair("Private IP Address", @server.private_ip_address)
|
693
|
+
msg_pair("Environment", config[:environment] || '_default')
|
694
|
+
msg_pair("Run List", (config[:run_list] || []).join(', '))
|
695
|
+
if config[:first_boot_attributes] || config[:first_boot_attributes_from_file]
|
696
|
+
msg_pair("JSON Attributes",config[:first_boot_attributes] || config[:first_boot_attributes_from_file])
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
def default_bootstrap_template
|
701
|
+
is_image_windows? ? 'windows-chef-client-msi' : 'chef-full'
|
702
|
+
end
|
703
|
+
|
704
|
+
def validation_key_path
|
705
|
+
@validation_key_path ||= begin
|
706
|
+
if URI(Chef::Config[:knife][:validation_key_url]).scheme == 'file'
|
707
|
+
URI(Chef::Config[:knife][:validation_key_url]).path
|
708
|
+
else
|
709
|
+
validation_key_tmpfile.path
|
710
|
+
end
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
def validation_key_tmpfile
|
715
|
+
@validation_key_tmpfile ||= Tempfile.new('validation_key')
|
716
|
+
end
|
717
|
+
|
718
|
+
def download_validation_key(tempfile)
|
719
|
+
Chef::Log.debug 'Downloading validation key ' \
|
720
|
+
"<#{Chef::Config[:knife][:validation_key_url]}> to file " \
|
721
|
+
"<#{tempfile}>"
|
722
|
+
|
723
|
+
case URI(Chef::Config[:knife][:validation_key_url]).scheme
|
724
|
+
when 's3'
|
725
|
+
File.open(tempfile, 'w') { |f| f.write(s3_validation_key) }
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
def s3_validation_key
|
730
|
+
@s3_validation_key ||= begin
|
731
|
+
Chef::Knife::S3Source.fetch(Chef::Config[:knife][:validation_key_url])
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
def s3_secret
|
736
|
+
@s3_secret ||= begin
|
737
|
+
return false unless locate_config_value(:s3_secret)
|
738
|
+
Chef::Knife::S3Source.fetch(locate_config_value(:s3_secret))
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
def bootstrap_common_params(bootstrap)
|
743
|
+
bootstrap.config[:run_list] = config[:run_list]
|
744
|
+
bootstrap.config[:policy_group] = locate_config_value(:policy_group)
|
745
|
+
bootstrap.config[:policy_name] = locate_config_value(:policy_name)
|
746
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
747
|
+
bootstrap.config[:distro] = locate_config_value(:distro) || default_bootstrap_template
|
748
|
+
# setting bootstrap_template value to template_file for backward compatibility
|
749
|
+
bootstrap.config[:template_file] = locate_config_value(:template_file) || locate_config_value(:bootstrap_template)
|
750
|
+
bootstrap.config[:environment] = locate_config_value(:environment)
|
751
|
+
bootstrap.config[:prerelease] = config[:prerelease]
|
752
|
+
bootstrap.config[:first_boot_attributes] = locate_config_value(:first_boot_attributes)
|
753
|
+
bootstrap.config[:first_boot_attributes_from_file] = locate_config_value(:first_boot_attributes_from_file)
|
754
|
+
bootstrap.config[:encrypted_data_bag_secret] = s3_secret || locate_config_value(:secret)
|
755
|
+
bootstrap.config[:encrypted_data_bag_secret_file] = locate_config_value(:secret_file)
|
756
|
+
# retrieving the secret from S3 is unique to knife-ec2, so we need to set "command line secret" to the value fetched from S3
|
757
|
+
# When linux vm is spawned, the chef's secret option proc function sets the value "command line secret" and this value is used by
|
758
|
+
# chef's code to check if secret option is passed through command line or not
|
759
|
+
Chef::Knife::DataBagSecretOptions.set_cl_secret(s3_secret) if locate_config_value(:s3_secret)
|
760
|
+
bootstrap.config[:secret] = s3_secret || locate_config_value(:secret)
|
761
|
+
bootstrap.config[:secret_file] = locate_config_value(:secret_file)
|
762
|
+
bootstrap.config[:node_ssl_verify_mode] = locate_config_value(:node_ssl_verify_mode)
|
763
|
+
bootstrap.config[:node_verify_api_cert] = locate_config_value(:node_verify_api_cert)
|
764
|
+
bootstrap.config[:bootstrap_no_proxy] = locate_config_value(:bootstrap_no_proxy)
|
765
|
+
bootstrap.config[:bootstrap_url] = locate_config_value(:bootstrap_url)
|
766
|
+
bootstrap.config[:bootstrap_install_command] = locate_config_value(:bootstrap_install_command)
|
767
|
+
bootstrap.config[:bootstrap_wget_options] = locate_config_value(:bootstrap_wget_options)
|
768
|
+
bootstrap.config[:bootstrap_curl_options] = locate_config_value(:bootstrap_curl_options)
|
769
|
+
bootstrap.config[:bootstrap_vault_file] = locate_config_value(:bootstrap_vault_file)
|
770
|
+
bootstrap.config[:bootstrap_vault_json] = locate_config_value(:bootstrap_vault_json)
|
771
|
+
bootstrap.config[:bootstrap_vault_item] = locate_config_value(:bootstrap_vault_item)
|
772
|
+
bootstrap.config[:use_sudo_password] = locate_config_value(:use_sudo_password)
|
773
|
+
bootstrap.config[:yes] = locate_config_value(:yes)
|
774
|
+
# Modify global configuration state to ensure hint gets set by
|
775
|
+
# knife-bootstrap
|
776
|
+
Chef::Config[:knife][:hints] ||= {}
|
777
|
+
Chef::Config[:knife][:hints]["ec2"] ||= {}
|
778
|
+
bootstrap
|
779
|
+
end
|
780
|
+
|
781
|
+
def fetch_server_fqdn(ip_addr)
|
782
|
+
require 'resolv'
|
783
|
+
Resolv.getname(ip_addr)
|
784
|
+
end
|
785
|
+
|
786
|
+
def bootstrap_for_windows_node(server, fqdn)
|
787
|
+
if locate_config_value(:bootstrap_protocol) == 'winrm' || locate_config_value(:bootstrap_protocol) == nil
|
788
|
+
if locate_config_value(:kerberos_realm)
|
789
|
+
#Fetch AD/WINS based fqdn if any for Kerberos-based Auth
|
790
|
+
fqdn = locate_config_value(:fqdn) || fetch_server_fqdn(server.private_ip_address)
|
791
|
+
end
|
792
|
+
bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
|
793
|
+
bootstrap.config[:winrm_user] = locate_config_value(:winrm_user)
|
794
|
+
bootstrap.config[:winrm_password] = windows_password
|
795
|
+
bootstrap.config[:winrm_transport] = locate_config_value(:winrm_transport)
|
796
|
+
bootstrap.config[:kerberos_keytab_file] = locate_config_value(:kerberos_keytab_file)
|
797
|
+
bootstrap.config[:kerberos_realm] = locate_config_value(:kerberos_realm)
|
798
|
+
bootstrap.config[:kerberos_service] = locate_config_value(:kerberos_service)
|
799
|
+
bootstrap.config[:ca_trust_file] = locate_config_value(:ca_trust_file)
|
800
|
+
bootstrap.config[:winrm_port] = locate_config_value(:winrm_port)
|
801
|
+
bootstrap.config[:auth_timeout] = locate_config_value(:auth_timeout)
|
802
|
+
bootstrap.config[:winrm_ssl_verify_mode] = locate_config_value(:winrm_ssl_verify_mode)
|
803
|
+
elsif locate_config_value(:bootstrap_protocol) == 'ssh'
|
804
|
+
bootstrap = Chef::Knife::BootstrapWindowsSsh.new
|
805
|
+
bootstrap.config[:ssh_user] = locate_config_value(:ssh_user)
|
806
|
+
bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
|
807
|
+
bootstrap.config[:ssh_port] = locate_config_value(:ssh_port)
|
808
|
+
bootstrap.config[:identity_file] = locate_config_value(:identity_file)
|
809
|
+
bootstrap.config[:no_host_key_verify] = locate_config_value(:no_host_key_verify)
|
810
|
+
bootstrap.config[:forward_agent] = locate_config_value(:forward_agent)
|
811
|
+
else
|
812
|
+
ui.error("Unsupported Bootstrapping Protocol. Supported : winrm, ssh")
|
813
|
+
exit 1
|
814
|
+
end
|
815
|
+
bootstrap.name_args = [fqdn]
|
816
|
+
bootstrap.config[:msi_url] = locate_config_value(:msi_url)
|
817
|
+
bootstrap.config[:install_as_service] = locate_config_value(:install_as_service)
|
818
|
+
bootstrap.config[:session_timeout] = locate_config_value(:session_timeout)
|
819
|
+
bootstrap.config[:tags] = config[:tags] if locate_config_value(:tag_node_in_chef)
|
820
|
+
|
821
|
+
if locate_config_value(:chef_node_name)
|
822
|
+
bootstrap.config[:chef_node_name] = evaluate_node_name(locate_config_value(:chef_node_name))
|
823
|
+
else
|
824
|
+
bootstrap.config[:chef_node_name] = server.id
|
825
|
+
end
|
826
|
+
bootstrap_common_params(bootstrap)
|
827
|
+
end
|
828
|
+
|
829
|
+
def bootstrap_for_linux_node(server,ssh_host)
|
830
|
+
bootstrap = Chef::Knife::Bootstrap.new
|
831
|
+
bootstrap.name_args = [ssh_host]
|
832
|
+
bootstrap.config[:ssh_user] = config[:ssh_user]
|
833
|
+
bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
|
834
|
+
bootstrap.config[:ssh_port] = config[:ssh_port]
|
835
|
+
bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
|
836
|
+
bootstrap.config[:identity_file] = config[:identity_file]
|
837
|
+
bootstrap.config[:tags] = config[:tags] if locate_config_value(:tag_node_in_chef)
|
838
|
+
|
839
|
+
if locate_config_value(:chef_node_name)
|
840
|
+
bootstrap.config[:chef_node_name] = evaluate_node_name(locate_config_value(:chef_node_name))
|
841
|
+
else
|
842
|
+
bootstrap.config[:chef_node_name] = server.id
|
843
|
+
end
|
844
|
+
bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
|
845
|
+
# may be needed for vpc_mode
|
846
|
+
bootstrap.config[:host_key_verify] = config[:host_key_verify]
|
847
|
+
bootstrap_common_params(bootstrap)
|
848
|
+
end
|
849
|
+
|
850
|
+
def vpc_mode?
|
851
|
+
# Amazon Virtual Private Cloud requires a subnet_id. If
|
852
|
+
# present, do a few things differently
|
853
|
+
!!locate_config_value(:subnet_id)
|
854
|
+
end
|
855
|
+
|
856
|
+
def ami
|
857
|
+
@ami ||= connection.images.get(locate_config_value(:image))
|
858
|
+
end
|
859
|
+
|
860
|
+
def validate!
|
861
|
+
if Chef::Config[:knife].keys.include? :aws_ssh_key_id
|
862
|
+
Chef::Config[:knife][:ssh_key_name] = Chef::Config[:knife][:aws_ssh_key_id] if !Chef::Config[:knife][:ssh_key_name]
|
863
|
+
Chef::Config[:knife].delete(:aws_ssh_key_id)
|
864
|
+
ui.warn("Use of aws_ssh_key_id option in knife.rb config is deprecated, use ssh_key_name option instead.")
|
865
|
+
end
|
866
|
+
|
867
|
+
super([:image, :ssh_key_name, :aws_access_key_id, :aws_secret_access_key])
|
868
|
+
|
869
|
+
validate_nics! if locate_config_value(:network_interfaces)
|
870
|
+
|
871
|
+
if ami.nil?
|
872
|
+
ui.error("You have not provided a valid image (AMI) value.")
|
873
|
+
exit 1
|
874
|
+
end
|
875
|
+
|
876
|
+
if vpc_mode? and !!config[:security_groups]
|
877
|
+
ui.error("You are using a VPC, security groups specified with '-G' are not allowed, specify one or more security group ids with '-g' instead.")
|
878
|
+
exit 1
|
879
|
+
end
|
880
|
+
|
881
|
+
if !vpc_mode? and !!config[:private_ip_address]
|
882
|
+
ui.error("You can only specify a private IP address if you are using VPC.")
|
883
|
+
exit 1
|
884
|
+
end
|
885
|
+
|
886
|
+
if config[:dedicated_instance] and !vpc_mode?
|
887
|
+
ui.error("You can only specify a Dedicated Instance if you are using VPC.")
|
888
|
+
exit 1
|
889
|
+
end
|
890
|
+
|
891
|
+
if !vpc_mode? and config[:associate_public_ip]
|
892
|
+
ui.error("--associate-public-ip option only applies to VPC instances, and you have not specified a subnet id.")
|
893
|
+
exit 1
|
894
|
+
end
|
895
|
+
|
896
|
+
if config[:associate_eip]
|
897
|
+
eips = connection.addresses.collect{|addr| addr if addr.domain == eip_scope}.compact
|
898
|
+
|
899
|
+
unless eips.detect{|addr| addr.public_ip == config[:associate_eip] && addr.server_id == nil}
|
900
|
+
ui.error("Elastic IP requested is not available.")
|
901
|
+
exit 1
|
902
|
+
end
|
903
|
+
end
|
904
|
+
|
905
|
+
if config[:ebs_provisioned_iops] and config[:ebs_volume_type] != 'io1'
|
906
|
+
ui.error("--provisioned-iops option is only supported for volume type of 'io1'")
|
907
|
+
exit 1
|
908
|
+
end
|
909
|
+
|
910
|
+
if config[:ebs_volume_type] == 'io1' and config[:ebs_provisioned_iops].nil?
|
911
|
+
ui.error("--provisioned-iops option is required when using volume type of 'io1'")
|
912
|
+
exit 1
|
913
|
+
end
|
914
|
+
|
915
|
+
if config[:ebs_volume_type] and ! %w(gp2 io1 standard).include?(config[:ebs_volume_type])
|
916
|
+
ui.error("--ebs-volume-type must be 'standard' or 'io1' or 'gp2'")
|
917
|
+
msg opt_parser
|
918
|
+
exit 1
|
919
|
+
end
|
920
|
+
|
921
|
+
if config[:security_groups] && config[:security_groups].class == String
|
922
|
+
ui.error("Invalid value type for knife[:security_groups] in knife configuration file (i.e knife.rb). Type should be array. e.g - knife[:security_groups] = ['sgroup1']")
|
923
|
+
exit 1
|
924
|
+
end
|
925
|
+
|
926
|
+
# Validation for security_group_ids passed through knife.rb. It will raise error if values are not provided in Array.
|
927
|
+
if locate_config_value(:security_group_ids) && locate_config_value(:security_group_ids).class == String
|
928
|
+
ui.error("Invalid value type for knife[:security_group_ids] in knife configuration file (i.e knife.rb). Type should be array. e.g - knife[:security_group_ids] = ['sgroup1']")
|
929
|
+
exit 1
|
930
|
+
end
|
931
|
+
|
932
|
+
if config[:classic_link_vpc_id].nil? ^ config[:classic_link_vpc_security_group_ids].nil?
|
933
|
+
ui.error("--classic-link-vpc-id and --classic-link-vpc-security-group-ids must be used together")
|
934
|
+
exit 1
|
935
|
+
end
|
936
|
+
|
937
|
+
if vpc_mode? and config[:classic_link_vpc_id]
|
938
|
+
ui.error("You can only use ClassicLink if you are not using a VPC")
|
939
|
+
exit 1
|
940
|
+
end
|
941
|
+
|
942
|
+
if locate_config_value(:ebs_encrypted)
|
943
|
+
error_message = ""
|
944
|
+
errors = []
|
945
|
+
# validation for flavor and ebs_encrypted
|
946
|
+
if !locate_config_value(:flavor)
|
947
|
+
ui.error("--ebs-encrypted option requires valid flavor to be specified.")
|
948
|
+
exit 1
|
949
|
+
elsif (locate_config_value(:ebs_encrypted) and ! %w(m3.medium m3.large m3.xlarge m3.2xlarge m4.large m4.xlarge
|
950
|
+
m4.2xlarge m4.4xlarge m4.10xlarge m4.16xlarge t2.nano t2.micro t2.small
|
951
|
+
t2.medium t2.large t2.xlarge t2.2xlarge d2.xlarge d2.2xlarge d2.4xlarge
|
952
|
+
d2.8xlarge c4.large c4.xlarge c4.2xlarge c4.4xlarge c4.8xlarge c3.large
|
953
|
+
c3.xlarge c3.2xlarge c3.4xlarge c3.8xlarge cr1.8xlarge r3.large r3.xlarge
|
954
|
+
r3.2xlarge r3.4xlarge r3.8xlarge r4.large r4.xlarge r4.2xlarge r4.4xlarge
|
955
|
+
r4.8xlarge r4.16xlarge x1.16xlarge x1.32xlarge i2.xlarge i2.2xlarge i2.4xlarge
|
956
|
+
i2.8xlarge i3.large i3.xlarge i3.2xlarge i3.4xlarge i3.8xlarge i3.16xlarge
|
957
|
+
f1.2xlarge f1.16xlarge g2.2xlarge g2.8xlarge p2.xlarge p2.8xlarge p2.16xlarge).include?(locate_config_value(:flavor)))
|
958
|
+
ui.error("--ebs-encrypted option is not supported for #{locate_config_value(:flavor)} flavor.")
|
959
|
+
exit 1
|
960
|
+
end
|
961
|
+
|
962
|
+
# validation for ebs_size and ebs_volume_type and ebs_encrypted
|
963
|
+
if !locate_config_value(:ebs_size)
|
964
|
+
errors << "--ebs-encrypted option requires valid --ebs-size to be specified."
|
965
|
+
elsif locate_config_value(:ebs_volume_type) == "gp2" and ! locate_config_value(:ebs_size).to_i.between?(1, 16384)
|
966
|
+
errors << "--ebs-size should be in between 1-16384 for 'gp2' ebs volume type."
|
967
|
+
elsif locate_config_value(:ebs_volume_type) == "io1" and ! locate_config_value(:ebs_size).to_i.between?(4, 16384)
|
968
|
+
errors << "--ebs-size should be in between 4-16384 for 'io1' ebs volume type."
|
969
|
+
elsif locate_config_value(:ebs_volume_type) == "standard" and ! locate_config_value(:ebs_size).to_i.between?(1, 1024)
|
970
|
+
errors << "--ebs-size should be in between 1-1024 for 'standard' ebs volume type."
|
971
|
+
end
|
972
|
+
|
973
|
+
if errors.each{|e| error_message = "#{error_message} #{e}"}.any?
|
974
|
+
ui.error(error_message)
|
975
|
+
exit 1
|
976
|
+
end
|
977
|
+
end
|
978
|
+
|
979
|
+
if locate_config_value(:spot_price) && locate_config_value(:disable_api_termination)
|
980
|
+
ui.error("spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances.")
|
981
|
+
exit 1
|
982
|
+
end
|
983
|
+
|
984
|
+
if locate_config_value(:spot_price).nil? && locate_config_value(:spot_wait_mode).downcase != 'prompt'
|
985
|
+
ui.error('spot-wait-mode option requires that a spot-price option is set.')
|
986
|
+
exit 1
|
987
|
+
end
|
988
|
+
|
989
|
+
volume_tags = locate_config_value(:volume_tags)
|
990
|
+
if !volume_tags.nil? and volume_tags.length != volume_tags.to_s.count('=')
|
991
|
+
ui.error("Volume Tags should be entered in a key = value pair")
|
992
|
+
exit 1
|
993
|
+
end
|
994
|
+
|
995
|
+
if (locate_config_value(:winrm_password).to_s.length > 14 )
|
996
|
+
ui.warn("The password provided is longer than 14 characters. Computers with Windows prior to Windows 2000 will not be able to use this account. Do you want to continue this operation? (Y/N):")
|
997
|
+
password_promt = STDIN.gets.chomp.upcase
|
998
|
+
if (password_promt == "N")
|
999
|
+
raise "Exiting as operation with password greater than 14 characters not accepted"
|
1000
|
+
elsif (password_promt == "Y")
|
1001
|
+
@allow_long_password = "/yes"
|
1002
|
+
else
|
1003
|
+
raise "The input provided is incorrect."
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
def tags
|
1010
|
+
tags = locate_config_value(:tags)
|
1011
|
+
if !tags.nil? and tags.length != tags.to_s.count('=')
|
1012
|
+
ui.error("Tags should be entered in a key = value pair")
|
1013
|
+
exit 1
|
1014
|
+
end
|
1015
|
+
tags
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
def eip_scope
|
1019
|
+
if vpc_mode?
|
1020
|
+
"vpc"
|
1021
|
+
else
|
1022
|
+
"standard"
|
1023
|
+
end
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
def ssl_config_user_data
|
1027
|
+
user_related_commands = ""
|
1028
|
+
winrm_user = locate_config_value(:winrm_user).split("\\")
|
1029
|
+
if (winrm_user[0] == ".") || (winrm_user[0] == "") ||(winrm_user.length == 1)
|
1030
|
+
user_related_commands = <<-EOH
|
1031
|
+
net user /add #{locate_config_value(:winrm_user).delete('.\\')} #{windows_password} #{@allow_long_password};
|
1032
|
+
net localgroup Administrators /add #{locate_config_value(:winrm_user).delete('.\\')};
|
1033
|
+
EOH
|
1034
|
+
end
|
1035
|
+
<<-EOH
|
1036
|
+
#{user_related_commands}
|
1037
|
+
If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
|
1038
|
+
winrm quickconfig -q
|
1039
|
+
}
|
1040
|
+
If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
|
1041
|
+
winrm delete winrm/config/listener?Address=*+Transport=HTTP
|
1042
|
+
}
|
1043
|
+
$vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
|
1044
|
+
If (-Not $vm_name) {
|
1045
|
+
$vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/local-ipv4
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
|
1049
|
+
$name.Encode("CN=$vm_name", 0)
|
1050
|
+
$key = new-object -com "X509Enrollment.CX509PrivateKey.1"
|
1051
|
+
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
|
1052
|
+
$key.KeySpec = 1
|
1053
|
+
$key.Length = 2048
|
1054
|
+
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
|
1055
|
+
$key.MachineContext = 1
|
1056
|
+
$key.Create()
|
1057
|
+
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
|
1058
|
+
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
|
1059
|
+
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
|
1060
|
+
$ekuoids.add($serverauthoid)
|
1061
|
+
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
|
1062
|
+
$ekuext.InitializeEncode($ekuoids)
|
1063
|
+
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
|
1064
|
+
$cert.InitializeFromPrivateKey(2, $key, "")
|
1065
|
+
$cert.Subject = $name
|
1066
|
+
$cert.Issuer = $cert.Subject
|
1067
|
+
$cert.NotBefore = get-date
|
1068
|
+
$cert.NotAfter = $cert.NotBefore.AddYears(10)
|
1069
|
+
$cert.X509Extensions.Add($ekuext)
|
1070
|
+
$cert.Encode()
|
1071
|
+
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
|
1072
|
+
$enrollment.InitializeFromRequest($cert)
|
1073
|
+
$certdata = $enrollment.CreateRequest(0)
|
1074
|
+
$enrollment.InstallResponse(2, $certdata, 0, "")
|
1075
|
+
|
1076
|
+
$thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
|
1077
|
+
$create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
|
1078
|
+
iex $create_listener_cmd
|
1079
|
+
netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
|
1080
|
+
EOH
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
def ssl_config_data_already_exist?
|
1084
|
+
File.read(locate_config_value(:aws_user_data)).gsub(/\\\\/,"\\").include? ssl_config_user_data.strip
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
def process_user_data(script_lines)
|
1088
|
+
if !ssl_config_data_already_exist?
|
1089
|
+
ps_start_tag = "<powershell>\n"
|
1090
|
+
ps_end_tag = "</powershell>\n"
|
1091
|
+
ps_start_tag_index = script_lines.index(ps_start_tag) || script_lines.index(ps_start_tag.strip)
|
1092
|
+
ps_end_tag_index = script_lines.index(ps_end_tag) || script_lines.index(ps_end_tag.strip)
|
1093
|
+
case
|
1094
|
+
when ( ps_start_tag_index && !ps_end_tag_index ) || ( !ps_start_tag_index && ps_end_tag_index )
|
1095
|
+
ui.error("Provided user_data file is invalid.")
|
1096
|
+
exit 1
|
1097
|
+
when ps_start_tag_index && ps_end_tag_index
|
1098
|
+
script_lines[ps_end_tag_index] = ssl_config_user_data + ps_end_tag
|
1099
|
+
when !ps_start_tag_index && !ps_end_tag_index
|
1100
|
+
script_lines.insert(-1,"\n\n" + ps_start_tag + ssl_config_user_data + ps_end_tag)
|
1101
|
+
end
|
1102
|
+
end
|
1103
|
+
script_lines
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
def create_server_def
|
1107
|
+
server_def = {
|
1108
|
+
:image_id => locate_config_value(:image),
|
1109
|
+
:groups => config[:security_groups],
|
1110
|
+
:flavor_id => locate_config_value(:flavor),
|
1111
|
+
:key_name => locate_config_value(:ssh_key_name),
|
1112
|
+
:availability_zone => locate_config_value(:availability_zone),
|
1113
|
+
:price => locate_config_value(:spot_price),
|
1114
|
+
:request_type => locate_config_value(:spot_request_type)
|
1115
|
+
}
|
1116
|
+
|
1117
|
+
if primary_eni = locate_config_value(:primary_eni)
|
1118
|
+
server_def[:network_interfaces] = [
|
1119
|
+
{
|
1120
|
+
:NetworkInterfaceId => primary_eni,
|
1121
|
+
:DeviceIndex => "0"
|
1122
|
+
}
|
1123
|
+
]
|
1124
|
+
else
|
1125
|
+
server_def[:security_group_ids] = locate_config_value(:security_group_ids)
|
1126
|
+
server_def[:subnet_id] = locate_config_value(:subnet_id) if vpc_mode?
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
server_def[:private_ip_address] = locate_config_value(:private_ip_address) if vpc_mode?
|
1130
|
+
server_def[:placement_group] = locate_config_value(:placement_group)
|
1131
|
+
server_def[:iam_instance_profile_name] = locate_config_value(:iam_instance_profile)
|
1132
|
+
server_def[:tenancy] = "dedicated" if vpc_mode? and locate_config_value(:dedicated_instance)
|
1133
|
+
server_def[:associate_public_ip] = locate_config_value(:associate_public_ip) if vpc_mode? and config[:associate_public_ip]
|
1134
|
+
|
1135
|
+
if locate_config_value(:winrm_transport) == 'ssl'
|
1136
|
+
if locate_config_value(:aws_user_data)
|
1137
|
+
begin
|
1138
|
+
user_data = File.readlines(locate_config_value(:aws_user_data))
|
1139
|
+
if config[:create_ssl_listener]
|
1140
|
+
user_data = process_user_data(user_data)
|
1141
|
+
end
|
1142
|
+
user_data = user_data.join
|
1143
|
+
server_def.merge!(:user_data => user_data)
|
1144
|
+
rescue
|
1145
|
+
ui.warn("Cannot read #{locate_config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
|
1146
|
+
end
|
1147
|
+
else
|
1148
|
+
if config[:create_ssl_listener]
|
1149
|
+
server_def.merge!(:user_data => "<powershell>\n" + ssl_config_user_data + "</powershell>\n")
|
1150
|
+
end
|
1151
|
+
end
|
1152
|
+
else
|
1153
|
+
if locate_config_value(:aws_user_data)
|
1154
|
+
begin
|
1155
|
+
server_def.merge!(:user_data => File.read(locate_config_value(:aws_user_data)))
|
1156
|
+
rescue
|
1157
|
+
ui.warn("Cannot read #{locate_config_value(:aws_user_data)}: #{$!.inspect}. Ignoring option.")
|
1158
|
+
end
|
1159
|
+
end
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
if config[:ebs_optimized]
|
1163
|
+
server_def[:ebs_optimized] = "true"
|
1164
|
+
else
|
1165
|
+
server_def[:ebs_optimized] = "false"
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
if ami.root_device_type == "ebs"
|
1169
|
+
if locate_config_value(:ebs_encrypted)
|
1170
|
+
ami_map = ami.block_device_mapping[1]
|
1171
|
+
else
|
1172
|
+
ami_map = ami.block_device_mapping.first
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
ebs_size = begin
|
1176
|
+
if config[:ebs_size]
|
1177
|
+
Integer(config[:ebs_size]).to_s
|
1178
|
+
else
|
1179
|
+
ami_map["volumeSize"].to_s
|
1180
|
+
end
|
1181
|
+
rescue ArgumentError
|
1182
|
+
puts "--ebs-size must be an integer"
|
1183
|
+
msg opt_parser
|
1184
|
+
exit 1
|
1185
|
+
end
|
1186
|
+
delete_term = if config[:ebs_no_delete_on_term]
|
1187
|
+
"false"
|
1188
|
+
else
|
1189
|
+
ami_map["deleteOnTermination"]
|
1190
|
+
end
|
1191
|
+
iops_rate = begin
|
1192
|
+
if config[:ebs_provisioned_iops]
|
1193
|
+
Integer(config[:ebs_provisioned_iops]).to_s
|
1194
|
+
else
|
1195
|
+
ami_map["iops"].to_s
|
1196
|
+
end
|
1197
|
+
rescue ArgumentError
|
1198
|
+
puts "--provisioned-iops must be an integer"
|
1199
|
+
msg opt_parser
|
1200
|
+
exit 1
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
server_def[:block_device_mapping] =
|
1204
|
+
[{
|
1205
|
+
'DeviceName' => ami_map["deviceName"],
|
1206
|
+
'Ebs.VolumeSize' => ebs_size,
|
1207
|
+
'Ebs.DeleteOnTermination' => delete_term,
|
1208
|
+
'Ebs.VolumeType' => config[:ebs_volume_type],
|
1209
|
+
}]
|
1210
|
+
server_def[:block_device_mapping].first['Ebs.Iops'] = iops_rate unless iops_rate.empty?
|
1211
|
+
server_def[:block_device_mapping].first['Ebs.Encrypted'] = true if locate_config_value(:ebs_encrypted)
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
(config[:ephemeral] || []).each_with_index do |device_name, i|
|
1215
|
+
server_def[:block_device_mapping] = (server_def[:block_device_mapping] || []) << {'VirtualName' => "ephemeral#{i}", 'DeviceName' => device_name}
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
## cannot pass disable_api_termination option to the API when using spot instances ##
|
1219
|
+
server_def[:disable_api_termination] = locate_config_value(:disable_api_termination) if locate_config_value(:spot_price).nil?
|
1220
|
+
|
1221
|
+
server_def[:instance_initiated_shutdown_behavior] = locate_config_value(:instance_initiated_shutdown_behavior)
|
1222
|
+
|
1223
|
+
server_def
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
def wait_for_sshd(hostname)
|
1227
|
+
ssh_gateway = get_ssh_gateway_for(hostname)
|
1228
|
+
ssh_gateway ? wait_for_tunnelled_sshd(ssh_gateway, hostname) : wait_for_direct_sshd(hostname, config[:ssh_port])
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
def get_ssh_gateway_for(hostname)
|
1232
|
+
if config[:ssh_gateway]
|
1233
|
+
# The ssh_gateway specified in the knife config (if any) takes
|
1234
|
+
# precedence over anything in the SSH configuration
|
1235
|
+
Chef::Log.debug("Using ssh gateway #{config[:ssh_gateway]} from knife config")
|
1236
|
+
config[:ssh_gateway]
|
1237
|
+
else
|
1238
|
+
# Next, check if the SSH configuration has a ProxyCommand
|
1239
|
+
# directive for this host. If there is one, parse out the
|
1240
|
+
# host from the proxy command
|
1241
|
+
ssh_proxy = Net::SSH::Config.for(hostname)[:proxy]
|
1242
|
+
if ssh_proxy.respond_to?(:command_line_template)
|
1243
|
+
# ssh gateway_hostname nc %h %p
|
1244
|
+
proxy_pattern = /ssh\s+(\S+)\s+nc/
|
1245
|
+
matchdata = proxy_pattern.match(ssh_proxy.command_line_template)
|
1246
|
+
if matchdata.nil?
|
1247
|
+
Chef::Log.debug("Unable to determine ssh gateway for '#{hostname}' from ssh config template: #{ssh_proxy.command_line_template}")
|
1248
|
+
nil
|
1249
|
+
else
|
1250
|
+
# Return hostname extracted from command line template
|
1251
|
+
Chef::Log.debug("Using ssh gateway #{matchdata[1]} from ssh config")
|
1252
|
+
matchdata[1]
|
1253
|
+
end
|
1254
|
+
else
|
1255
|
+
# Return nil if we cannot find an ssh_gateway
|
1256
|
+
Chef::Log.debug("No ssh gateway found, making a direct connection")
|
1257
|
+
nil
|
1258
|
+
end
|
1259
|
+
end
|
1260
|
+
end
|
1261
|
+
|
1262
|
+
def wait_for_tunnelled_sshd(ssh_gateway, hostname)
|
1263
|
+
initial = true
|
1264
|
+
print(".") until tunnel_test_ssh(ssh_gateway, hostname) {
|
1265
|
+
if initial
|
1266
|
+
initial = false
|
1267
|
+
sleep (vpc_mode? ? 40 : 10)
|
1268
|
+
else
|
1269
|
+
sleep 10
|
1270
|
+
end
|
1271
|
+
puts("done")
|
1272
|
+
}
|
1273
|
+
end
|
1274
|
+
|
1275
|
+
def tunnel_test_ssh(ssh_gateway, hostname, &block)
|
1276
|
+
status = false
|
1277
|
+
gateway = configure_ssh_gateway(ssh_gateway)
|
1278
|
+
gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port|
|
1279
|
+
status = tcp_test_ssh('localhost', local_tunnel_port, &block)
|
1280
|
+
end
|
1281
|
+
status
|
1282
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
1283
|
+
sleep 2
|
1284
|
+
false
|
1285
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
1286
|
+
false
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
def configure_ssh_gateway(ssh_gateway)
|
1290
|
+
gw_host, gw_user = ssh_gateway.split('@').reverse
|
1291
|
+
gw_host, gw_port = gw_host.split(':')
|
1292
|
+
gateway_options = { :port => gw_port || 22 }
|
1293
|
+
|
1294
|
+
# Load the SSH config for the SSH gateway host.
|
1295
|
+
# Set the gateway user if it was not part of the
|
1296
|
+
# SSH gateway string, and use any configured
|
1297
|
+
# SSH keys.
|
1298
|
+
ssh_gateway_config = Net::SSH::Config.for(gw_host)
|
1299
|
+
gw_user ||= ssh_gateway_config[:user]
|
1300
|
+
|
1301
|
+
# Always use the gateway keys from the SSH Config
|
1302
|
+
gateway_keys = ssh_gateway_config[:keys]
|
1303
|
+
|
1304
|
+
# Use the keys specificed on the command line if available (overrides SSH Config)
|
1305
|
+
if config[:ssh_gateway_identity]
|
1306
|
+
gateway_keys = Array(locate_config_value(:ssh_gateway_identity))
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
unless gateway_keys.nil?
|
1310
|
+
gateway_options[:keys] = gateway_keys
|
1311
|
+
end
|
1312
|
+
|
1313
|
+
Net::SSH::Gateway.new(gw_host, gw_user, gateway_options)
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
def wait_for_direct_sshd(hostname, ssh_port)
|
1317
|
+
initial = true
|
1318
|
+
print(".") until tcp_test_ssh(hostname, ssh_port) {
|
1319
|
+
if initial
|
1320
|
+
initial = false
|
1321
|
+
sleep (vpc_mode? ? 40 : 10)
|
1322
|
+
else
|
1323
|
+
sleep 10
|
1324
|
+
end
|
1325
|
+
puts("done")
|
1326
|
+
}
|
1327
|
+
end
|
1328
|
+
|
1329
|
+
def subnet_public_ip_on_launch?
|
1330
|
+
connection.subnets.get(server.subnet_id).map_public_ip_on_launch
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
def ssh_connect_host
|
1334
|
+
unless @ssh_connect_host
|
1335
|
+
if config[:server_connect_attribute]
|
1336
|
+
connect_attribute = config[:server_connect_attribute]
|
1337
|
+
server.send(config[:server_connect_attribute])
|
1338
|
+
elsif vpc_mode? && !(subnet_public_ip_on_launch? || config[:associate_public_ip] || config[:associate_eip])
|
1339
|
+
connect_attribute = "private_ip_address"
|
1340
|
+
server.private_ip_address
|
1341
|
+
else
|
1342
|
+
connect_attribute = server.dns_name ? "dns_name" : "public_ip_address"
|
1343
|
+
server.send(connect_attribute)
|
1344
|
+
end
|
1345
|
+
@ssh_connect_host = server.send(connect_attribute)
|
1346
|
+
end
|
1347
|
+
|
1348
|
+
puts "\nSSH Target Address: #{@ssh_connect_host}(#{connect_attribute})"
|
1349
|
+
@ssh_connect_host
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
def create_tags(hashed_tags)
|
1353
|
+
hashed_tags.each_pair do |key,val|
|
1354
|
+
connection.tags.create :key => key, :value => val, :resource_id => @server.id
|
1355
|
+
end
|
1356
|
+
end
|
1357
|
+
|
1358
|
+
def associate_eip(elastic_ip)
|
1359
|
+
connection.associate_address(server.id, elastic_ip.public_ip, nil, elastic_ip.allocation_id)
|
1360
|
+
@server.wait_for(locate_config_value(:aws_connection_timeout)) { public_ip_address == elastic_ip.public_ip }
|
1361
|
+
end
|
1362
|
+
|
1363
|
+
def validate_nics!
|
1364
|
+
valid_nic_ids = connection.network_interfaces.all(
|
1365
|
+
vpc_mode? ? { 'vpc-id' => vpc_id } : {}
|
1366
|
+
).map(&:network_interface_id)
|
1367
|
+
invalid_nic_ids =
|
1368
|
+
locate_config_value(:network_interfaces) - valid_nic_ids
|
1369
|
+
return true if invalid_nic_ids.empty?
|
1370
|
+
ui.error 'The following network interfaces are invalid: ' \
|
1371
|
+
"#{invalid_nic_ids.join(', ')}"
|
1372
|
+
exit 1
|
1373
|
+
end
|
1374
|
+
|
1375
|
+
def vpc_id
|
1376
|
+
@vpc_id ||= begin
|
1377
|
+
connection.subnets.get(locate_config_value(:subnet_id)).vpc_id
|
1378
|
+
end
|
1379
|
+
end
|
1380
|
+
|
1381
|
+
def wait_for_nic_attachment
|
1382
|
+
attached_nics_count = 0
|
1383
|
+
until attached_nics_count ==
|
1384
|
+
locate_config_value(:network_interfaces).count
|
1385
|
+
attachment_nics =
|
1386
|
+
locate_config_value(:network_interfaces).map do |nic_id|
|
1387
|
+
connection.network_interfaces.get(nic_id).attachment['status']
|
1388
|
+
end
|
1389
|
+
attached_nics_count = attachment_nics.grep('attached').count
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
def attach_nics
|
1394
|
+
attachments = []
|
1395
|
+
config[:network_interfaces].each_with_index do |nic_id, index|
|
1396
|
+
attachments << connection.attach_network_interface(nic_id,
|
1397
|
+
server.id,
|
1398
|
+
index + 1).body
|
1399
|
+
end
|
1400
|
+
wait_for_nic_attachment
|
1401
|
+
# rubocop:disable Style/RedundantReturn
|
1402
|
+
return attachments
|
1403
|
+
# rubocop:enable Style/RedundantReturn
|
1404
|
+
end
|
1405
|
+
|
1406
|
+
def enable_classic_link(vpc_id, security_group_ids)
|
1407
|
+
connection.attach_classic_link_vpc(server.id, vpc_id, security_group_ids)
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def ssh_override_winrm
|
1411
|
+
# unchanged ssh_user and changed winrm_user, override ssh_user
|
1412
|
+
if locate_config_value(:ssh_user).eql?(options[:ssh_user][:default]) &&
|
1413
|
+
!locate_config_value(:winrm_user).eql?(options[:winrm_user][:default])
|
1414
|
+
config[:ssh_user] = locate_config_value(:winrm_user)
|
1415
|
+
end
|
1416
|
+
# unchanged ssh_port and changed winrm_port, override ssh_port
|
1417
|
+
if locate_config_value(:ssh_port).eql?(options[:ssh_port][:default]) &&
|
1418
|
+
!locate_config_value(:winrm_port).eql?(options[:winrm_port][:default])
|
1419
|
+
config[:ssh_port] = locate_config_value(:winrm_port)
|
1420
|
+
end
|
1421
|
+
# unset ssh_password and set winrm_password, override ssh_password
|
1422
|
+
if locate_config_value(:ssh_password).nil? &&
|
1423
|
+
!locate_config_value(:winrm_password).nil?
|
1424
|
+
config[:ssh_password] = locate_config_value(:winrm_password)
|
1425
|
+
end
|
1426
|
+
# unset identity_file and set kerberos_keytab_file, override identity_file
|
1427
|
+
if locate_config_value(:identity_file).nil? &&
|
1428
|
+
!locate_config_value(:kerberos_keytab_file).nil?
|
1429
|
+
config[:identity_file] = locate_config_value(:kerberos_keytab_file)
|
1430
|
+
end
|
1431
|
+
end
|
1432
|
+
|
1433
|
+
def tcp_test_winrm(ip_addr, port)
|
1434
|
+
tcp_socket = TCPSocket.new(ip_addr, port)
|
1435
|
+
yield
|
1436
|
+
true
|
1437
|
+
rescue SocketError
|
1438
|
+
sleep 2
|
1439
|
+
false
|
1440
|
+
rescue Errno::ETIMEDOUT
|
1441
|
+
false
|
1442
|
+
rescue Errno::EPERM
|
1443
|
+
false
|
1444
|
+
rescue Errno::ECONNREFUSED
|
1445
|
+
sleep 2
|
1446
|
+
false
|
1447
|
+
rescue Errno::EHOSTUNREACH
|
1448
|
+
sleep 2
|
1449
|
+
false
|
1450
|
+
rescue Errno::ENETUNREACH
|
1451
|
+
sleep 2
|
1452
|
+
false
|
1453
|
+
ensure
|
1454
|
+
tcp_socket && tcp_socket.close
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
def tcp_test_ssh(hostname, ssh_port)
|
1458
|
+
tcp_socket = TCPSocket.new(hostname, ssh_port)
|
1459
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
1460
|
+
if readable
|
1461
|
+
ssh_banner = tcp_socket.gets
|
1462
|
+
if ssh_banner.nil? or ssh_banner.empty?
|
1463
|
+
false
|
1464
|
+
else
|
1465
|
+
Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{ssh_banner}")
|
1466
|
+
yield
|
1467
|
+
true
|
1468
|
+
end
|
1469
|
+
else
|
1470
|
+
false
|
1471
|
+
end
|
1472
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENOTCONN, IOError
|
1473
|
+
Chef::Log.debug("ssh failed to connect: #{hostname}")
|
1474
|
+
sleep 2
|
1475
|
+
false
|
1476
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
1477
|
+
Chef::Log.debug("ssh timed out: #{hostname}")
|
1478
|
+
false
|
1479
|
+
# This happens on some mobile phone networks
|
1480
|
+
rescue Errno::ECONNRESET
|
1481
|
+
Chef::Log.debug("ssh reset its connection: #{hostname}")
|
1482
|
+
sleep 2
|
1483
|
+
false
|
1484
|
+
ensure
|
1485
|
+
tcp_socket && tcp_socket.close
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
def decrypt_admin_password(encoded_password, key)
|
1489
|
+
require 'base64'
|
1490
|
+
require 'openssl'
|
1491
|
+
private_key = OpenSSL::PKey::RSA.new(key)
|
1492
|
+
encrypted_password = Base64.decode64(encoded_password)
|
1493
|
+
password = private_key.private_decrypt(encrypted_password)
|
1494
|
+
password
|
1495
|
+
end
|
1496
|
+
|
1497
|
+
def check_windows_password_available(server_id)
|
1498
|
+
sleep 10
|
1499
|
+
response = connection.get_password_data(server_id)
|
1500
|
+
if not response.body["passwordData"]
|
1501
|
+
return false
|
1502
|
+
end
|
1503
|
+
response.body["passwordData"]
|
1504
|
+
end
|
1505
|
+
|
1506
|
+
def windows_password
|
1507
|
+
if not locate_config_value(:winrm_password)
|
1508
|
+
if locate_config_value(:identity_file)
|
1509
|
+
print "\n#{ui.color("Waiting for Windows Admin password to be available", :magenta)}"
|
1510
|
+
print(".") until check_windows_password_available(@server.id) {
|
1511
|
+
puts("done")
|
1512
|
+
}
|
1513
|
+
response = connection.get_password_data(@server.id)
|
1514
|
+
data = File.read(locate_config_value(:identity_file))
|
1515
|
+
config[:winrm_password] = decrypt_admin_password(response.body["passwordData"], data)
|
1516
|
+
else
|
1517
|
+
ui.error("Cannot find SSH Identity file, required to fetch dynamically generated password")
|
1518
|
+
exit 1
|
1519
|
+
end
|
1520
|
+
else
|
1521
|
+
locate_config_value(:winrm_password)
|
1522
|
+
end
|
1523
|
+
end
|
1524
|
+
|
1525
|
+
def load_winrm_deps
|
1526
|
+
require 'winrm'
|
1527
|
+
require 'chef/knife/winrm'
|
1528
|
+
require 'chef/knife/bootstrap_windows_winrm'
|
1529
|
+
require 'chef/knife/bootstrap_windows_ssh'
|
1530
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
#Returns the name of node after evaluation of server id if %s is present.
|
1534
|
+
#Eg: "Test-%s" will return "Test-i-12345" in case the instance id is i-12345
|
1535
|
+
def evaluate_node_name(node_name)
|
1536
|
+
return node_name%server.id
|
1537
|
+
end
|
1538
|
+
|
1539
|
+
def create_volume_tags(hashed_volume_tags)
|
1540
|
+
hashed_volume_tags.each_pair do |key,val|
|
1541
|
+
connection.tags.create :key => key, :value => val, :resource_id => @server.block_device_mapping.first['volumeId']
|
1542
|
+
end
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
end
|
1546
|
+
end
|
1547
|
+
end
|