knife-ec2 0.19.16 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/chef/knife/ec2_ami_list.rb +48 -37
- data/lib/chef/knife/ec2_base.rb +108 -36
- data/lib/chef/knife/ec2_eip_list.rb +88 -0
- data/lib/chef/knife/ec2_flavor_list.rb +3 -34
- data/lib/chef/knife/ec2_securitygroup_list.rb +68 -0
- data/lib/chef/knife/ec2_server_create.rb +429 -554
- data/lib/chef/knife/ec2_server_delete.rb +99 -48
- data/lib/chef/knife/ec2_server_list.rb +83 -44
- data/lib/chef/knife/ec2_subnet_list.rb +79 -0
- data/lib/chef/knife/ec2_vpc_list.rb +75 -0
- data/lib/chef/knife/s3_source.rb +27 -9
- data/lib/knife-ec2/version.rb +1 -1
- metadata +29 -20
@@ -35,6 +35,13 @@ class Chef
|
|
35
35
|
|
36
36
|
attr_reader :server
|
37
37
|
|
38
|
+
option :dry_run,
|
39
|
+
long: "--dry-run",
|
40
|
+
short: "-n",
|
41
|
+
boolean: true,
|
42
|
+
default: false,
|
43
|
+
description: "Don't take action, only print what would happen."
|
44
|
+
|
38
45
|
option :purge,
|
39
46
|
short: "-P",
|
40
47
|
long: "--purge",
|
@@ -54,61 +61,48 @@ class Chef
|
|
54
61
|
# necessary to make them confirm two more times.
|
55
62
|
def destroy_item(klass, name, type_name)
|
56
63
|
object = klass.load(name)
|
57
|
-
object.destroy
|
64
|
+
object.destroy unless config[:dry_run]
|
58
65
|
ui.warn("Deleted #{type_name} #{name}")
|
59
66
|
rescue Net::HTTPServerException
|
60
67
|
ui.warn("Could not find a #{type_name} named #{name} to delete!")
|
61
68
|
end
|
62
69
|
|
63
70
|
def run
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
ui.warn("
|
97
|
-
|
98
|
-
if config[:purge]
|
99
|
-
if config[:chef_node_name]
|
100
|
-
thing_to_delete = config[:chef_node_name]
|
101
|
-
else
|
102
|
-
thing_to_delete = fetch_node_name(instance_id)
|
103
|
-
end
|
104
|
-
destroy_item(Chef::Node, thing_to_delete, "node")
|
105
|
-
destroy_item(Chef::ApiClient, thing_to_delete, "client")
|
106
|
-
else
|
107
|
-
ui.warn("Corresponding node and client for the #{instance_id} server were not deleted and remain registered with the Chef Server")
|
108
|
-
end
|
109
|
-
rescue NoMethodError
|
110
|
-
ui.error("Could not locate server '#{instance_id}'. Please verify it was provisioned in the '#{locate_config_value(:region)}' region.")
|
71
|
+
validate_aws_config!
|
72
|
+
validate_instances!
|
73
|
+
|
74
|
+
server_hashes.each do |h|
|
75
|
+
instance_id = h["instance_id"]
|
76
|
+
msg_pair("Instance ID", instance_id)
|
77
|
+
msg_pair("Instance Name", h["name"])
|
78
|
+
msg_pair("Flavor", h["instance_type"])
|
79
|
+
msg_pair("Image", h["image_id"])
|
80
|
+
msg_pair("Region", fetch_region)
|
81
|
+
msg_pair("Availability Zone", h["az"])
|
82
|
+
msg_pair("Security Groups", h["security_groups"])
|
83
|
+
msg_pair("IAM Profile", h["iam_instance_profile"])
|
84
|
+
msg_pair("SSH Key", h["key_name"])
|
85
|
+
msg_pair("Root Device Type", h["root_device_type"])
|
86
|
+
msg_pair("Public DNS Name", h["public_dns_name"])
|
87
|
+
msg_pair("Public IP Address", h["public_ip_address"])
|
88
|
+
msg_pair("Private DNS Name", h["private_dns_name"])
|
89
|
+
msg_pair("Private IP Address", h["private_ip_address"])
|
90
|
+
|
91
|
+
puts "\n"
|
92
|
+
confirm("Do you really want to delete this server")
|
93
|
+
|
94
|
+
delete_instance(instance_id) unless config[:dry_run]
|
95
|
+
|
96
|
+
ui.warn("Deleted server #{instance_id}")
|
97
|
+
|
98
|
+
if config[:purge]
|
99
|
+
node_name = config[:chef_node_name] || fetch_node_name(instance_id)
|
100
|
+
destroy_item(Chef::Node, node_name, "node")
|
101
|
+
destroy_item(Chef::ApiClient, node_name, "client")
|
102
|
+
else
|
103
|
+
ui.warn("Corresponding node and client for the #{instance_id} server were not deleted and remain registered with the Chef Server")
|
111
104
|
end
|
105
|
+
puts "\n"
|
112
106
|
end
|
113
107
|
end
|
114
108
|
|
@@ -137,6 +131,63 @@ class Chef
|
|
137
131
|
def query
|
138
132
|
@query ||= Chef::Search::Query.new
|
139
133
|
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
# @return [Array<Hash>]
|
138
|
+
def server_hashes
|
139
|
+
all_data = []
|
140
|
+
|
141
|
+
servers_list = ec2_connection.describe_instances({
|
142
|
+
instance_ids: @name_args,
|
143
|
+
})
|
144
|
+
|
145
|
+
servers_list.reservations.each do |i|
|
146
|
+
server_data = {}
|
147
|
+
%w{image_id instance_id instance_type key_name root_device_type public_ip_address private_ip_address private_dns_name public_dns_name}.each do |id|
|
148
|
+
server_data[id] = i.instances[0].send(id)
|
149
|
+
end
|
150
|
+
|
151
|
+
server_data["name"] = i.instances[0].tags[0].value
|
152
|
+
server_data["az"] = i.instances[0].placement.availability_zone
|
153
|
+
server_data["iam_instance_profile"] = ( i.instances[0].iam_instance_profile.nil? ? nil : i.instances[0].iam_instance_profile.arn[/instance-profile\/(.*)/] )
|
154
|
+
server_data["security_groups"] = i.instances[0].security_groups.map { |x| x.group_name }.join(", ")
|
155
|
+
|
156
|
+
all_data << server_data
|
157
|
+
end
|
158
|
+
all_data
|
159
|
+
end
|
160
|
+
|
161
|
+
# Delete the server instance
|
162
|
+
def delete_instance(instance_id)
|
163
|
+
return nil unless instance_id || instance_id.is_a?(String)
|
164
|
+
ec2_connection.terminate_instances({
|
165
|
+
instance_ids: [
|
166
|
+
instance_id,
|
167
|
+
],
|
168
|
+
})
|
169
|
+
end
|
170
|
+
|
171
|
+
# If SERVER instance id not provided then check chef_name_tag and fetch the node
|
172
|
+
# And if the node contains instance id then add it to the name args
|
173
|
+
def validate_instances!
|
174
|
+
if @name_args.empty?
|
175
|
+
if config[:chef_node_name]
|
176
|
+
ui.info("No instance id is specified, trying to retrieve it from node name")
|
177
|
+
instance_id = fetch_instance_id(config[:chef_node_name])
|
178
|
+
|
179
|
+
if instance_id.nil?
|
180
|
+
ui.info("No instance id found.")
|
181
|
+
exit 1
|
182
|
+
else
|
183
|
+
@name_args << instance_id
|
184
|
+
end
|
185
|
+
else
|
186
|
+
ui.info("No instance id is specified.")
|
187
|
+
exit 1
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
140
191
|
end
|
141
192
|
end
|
142
193
|
end
|
@@ -34,8 +34,15 @@ class Chef
|
|
34
34
|
default: true,
|
35
35
|
description: "Do not display name tag in output"
|
36
36
|
|
37
|
+
option :iamprofile,
|
38
|
+
short: "-i",
|
39
|
+
long: "--iam-profile",
|
40
|
+
boolean: true,
|
41
|
+
default: false,
|
42
|
+
description: "Show the iam profile"
|
43
|
+
|
37
44
|
option :az,
|
38
|
-
short: "-
|
45
|
+
short: "-a",
|
39
46
|
long: "--availability-zone",
|
40
47
|
boolean: true,
|
41
48
|
default: false,
|
@@ -64,12 +71,24 @@ class Chef
|
|
64
71
|
end
|
65
72
|
end
|
66
73
|
|
74
|
+
# @return [Symbol]
|
75
|
+
def state_color(state)
|
76
|
+
case state
|
77
|
+
when "shutting-down", "terminated", "stopping", "stopped"
|
78
|
+
:red
|
79
|
+
when "pending"
|
80
|
+
:yellow
|
81
|
+
else
|
82
|
+
:green
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
67
86
|
def run
|
68
87
|
$stdout.sync = true
|
69
88
|
|
70
|
-
|
89
|
+
validate_aws_config!
|
71
90
|
|
72
|
-
|
91
|
+
servers_list = [
|
73
92
|
ui.color("Instance ID", :bold),
|
74
93
|
|
75
94
|
if config[:name]
|
@@ -94,65 +113,85 @@ class Chef
|
|
94
113
|
end
|
95
114
|
end,
|
96
115
|
|
97
|
-
|
116
|
+
if config[:iamprofile]
|
117
|
+
ui.color("IAM Profile", :bold)
|
118
|
+
end,
|
119
|
+
|
98
120
|
ui.color("State", :bold)
|
99
121
|
].flatten.compact
|
100
122
|
|
101
|
-
output_column_count =
|
123
|
+
output_column_count = servers_list.length
|
102
124
|
|
103
125
|
if !config[:region] && Chef::Config[:knife][:region].nil?
|
104
126
|
ui.warn "No region was specified in knife.rb/config.rb or as an argument. The default region, us-east-1, will be used:"
|
105
127
|
end
|
106
128
|
|
107
|
-
servers = connection.servers
|
108
129
|
if config[:format] == "summary"
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
130
|
+
server_hashes.each do |v|
|
131
|
+
servers_list << v["instance_id"]
|
132
|
+
servers_list << v["name"] if config[:name]
|
133
|
+
servers_list << v["public_ip_address"]
|
134
|
+
servers_list << v["private_ip_address"]
|
135
|
+
servers_list << v["instance_type"]
|
136
|
+
servers_list << v["az"] if config[:az]
|
137
|
+
servers_list << v["image_id"]
|
138
|
+
servers_list << v["key_name"]
|
139
|
+
servers_list << v["security_groups"].join(",")
|
140
|
+
if config[:tags]
|
141
|
+
config[:tags].split(",").collect do |tag_name|
|
142
|
+
servers_list << v["tags"].find { |tag| tag == tag_name }
|
143
|
+
end
|
114
144
|
end
|
145
|
+
servers_list << v["iam_instance_profile"].to_s if config[:iamprofile] # may be nil
|
146
|
+
servers_list << v["state"]
|
147
|
+
end
|
148
|
+
puts ui.list(servers_list, :uneven_columns_across, output_column_count)
|
149
|
+
else
|
150
|
+
output(format_for_display(server_hashes))
|
151
|
+
end
|
152
|
+
end
|
115
153
|
|
116
|
-
|
117
|
-
server_list << server.private_ip_address.to_s
|
118
|
-
server_list << server.flavor_id.to_s
|
154
|
+
private
|
119
155
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
156
|
+
# @return [Array<Hash>]
|
157
|
+
def server_hashes
|
158
|
+
all_data = []
|
159
|
+
ec2_connection.describe_instances.reservations.each do |i|
|
160
|
+
server_data = {}
|
161
|
+
%w{image_id instance_id instance_type key_name public_ip_address private_ip_address}.each do |id|
|
162
|
+
server_data[id] = i.instances[0].send(id)
|
163
|
+
end
|
126
164
|
|
127
|
-
|
128
|
-
|
129
|
-
server_list << server.groups.join(", ")
|
165
|
+
# dig into tags struct
|
166
|
+
tags = extract_tags(i.instances[0].tags)
|
130
167
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
135
|
-
end
|
168
|
+
if config[:name]
|
169
|
+
server_data["name"] = tags[0]
|
170
|
+
end
|
136
171
|
|
137
|
-
|
138
|
-
|
139
|
-
server_list << begin
|
140
|
-
state = server.state.to_s.downcase
|
141
|
-
case state
|
142
|
-
when "shutting-down", "terminated", "stopping", "stopped"
|
143
|
-
ui.color(state, :red)
|
144
|
-
when "pending"
|
145
|
-
ui.color(state, :yellow)
|
146
|
-
else
|
147
|
-
ui.color(state, :green)
|
148
|
-
end
|
149
|
-
end
|
172
|
+
if config[:az]
|
173
|
+
server_data["az"] = ui.color(i.instances[0].placement.availability_zone, azcolor(i.instances[0].placement.availability_zone))
|
150
174
|
end
|
151
175
|
|
152
|
-
|
153
|
-
|
154
|
-
|
176
|
+
server_data["iam_instance_profile"] = ( i.instances[0].iam_instance_profile.nil? ? nil : i.instances[0].iam_instance_profile.arn[/instance-profile\/(.*)/] )
|
177
|
+
|
178
|
+
server_data["state"] = ui.color(i.instances[0].state.name, state_color(i.instances[0].state.name))
|
179
|
+
|
180
|
+
if config[:tags]
|
181
|
+
server_data["tags"] = tags
|
182
|
+
end
|
183
|
+
|
184
|
+
# dig into security_groups struct
|
185
|
+
server_data["security_groups"] = i.instances[0].security_groups.map { |x| x.group_name }
|
186
|
+
|
187
|
+
all_data << server_data
|
155
188
|
end
|
189
|
+
all_data
|
190
|
+
end
|
191
|
+
|
192
|
+
# @return [Array<String>]
|
193
|
+
def extract_tags(tags_struct)
|
194
|
+
tags_struct.map { |x| x.value }
|
156
195
|
end
|
157
196
|
end
|
158
197
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2018 Chef Software, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef/knife/ec2_base"
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class Ec2SubnetList < Knife
|
24
|
+
|
25
|
+
include Knife::Ec2Base
|
26
|
+
|
27
|
+
banner "knife ec2 subnet list (options)"
|
28
|
+
|
29
|
+
def run
|
30
|
+
validate_aws_config!
|
31
|
+
custom_warnings!
|
32
|
+
|
33
|
+
subnet_list = [
|
34
|
+
ui.color("ID", :bold),
|
35
|
+
ui.color("State", :bold),
|
36
|
+
ui.color("CIDR Block", :bold),
|
37
|
+
ui.color("AZ", :bold),
|
38
|
+
ui.color("Available IPs", :bold),
|
39
|
+
ui.color("AZ Default?", :bold),
|
40
|
+
ui.color("Maps Public IP?", :bold),
|
41
|
+
ui.color("VPC ID", :bold)
|
42
|
+
].flatten.compact
|
43
|
+
|
44
|
+
output_column_count = subnet_list.length
|
45
|
+
|
46
|
+
if config[:format] == "summary"
|
47
|
+
subnet_hash.each_pair do |_k, v|
|
48
|
+
subnet_list << v["subnet_id"]
|
49
|
+
subnet_list << v["state"]
|
50
|
+
subnet_list << v["cidr_block"]
|
51
|
+
subnet_list << v["availability_zone"]
|
52
|
+
subnet_list << v["available_ip_address_count"].to_s
|
53
|
+
subnet_list << (v["default_for_az"] ? "Yes" : "No")
|
54
|
+
subnet_list << (v["map_public_ip_on_launch"] ? "Yes" : "No")
|
55
|
+
subnet_list << v["vpc_id"]
|
56
|
+
end
|
57
|
+
puts ui.list(subnet_list, :uneven_columns_across, output_column_count)
|
58
|
+
else
|
59
|
+
output(format_for_display(subnet_hash))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# @return [Hash<Hash>]
|
66
|
+
def subnet_hash
|
67
|
+
all_data = {}
|
68
|
+
ec2_connection.describe_subnets.first.subnets.each do |s|
|
69
|
+
s_data = {}
|
70
|
+
%w{subnet_id availability_zone available_ip_address_count cidr_block default_for_az map_public_ip_on_launch state vpc_id}.each do |id|
|
71
|
+
s_data[id] = s.send(id)
|
72
|
+
end
|
73
|
+
all_data[s_data["subnet_id"]] = s_data
|
74
|
+
end
|
75
|
+
all_data
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Tim Smith (<tsmith@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2018 Chef Software, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef/knife/ec2_base"
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class Ec2VpcList < Knife
|
24
|
+
|
25
|
+
include Knife::Ec2Base
|
26
|
+
|
27
|
+
banner "knife ec2 vpc list (options)"
|
28
|
+
|
29
|
+
def run
|
30
|
+
validate_aws_config!
|
31
|
+
custom_warnings!
|
32
|
+
|
33
|
+
vpcs_list = [
|
34
|
+
ui.color("ID", :bold),
|
35
|
+
ui.color("State", :bold),
|
36
|
+
ui.color("CIDR Block", :bold),
|
37
|
+
ui.color("Instance Tenancy", :bold),
|
38
|
+
ui.color("DHCP Options ID", :bold),
|
39
|
+
ui.color("Default VPC?", :bold)
|
40
|
+
].flatten.compact
|
41
|
+
|
42
|
+
output_column_count = vpcs_list.length
|
43
|
+
|
44
|
+
if config[:format] == "summary"
|
45
|
+
vpc_hash.each_pair do |_k, v|
|
46
|
+
vpcs_list << v["vpc_id"]
|
47
|
+
vpcs_list << v["state"]
|
48
|
+
vpcs_list << v["cidr_block"]
|
49
|
+
vpcs_list << v["instance_tenancy"]
|
50
|
+
vpcs_list << v["dhcp_options_id"]
|
51
|
+
vpcs_list << (v["is_default"] ? "Yes" : "No")
|
52
|
+
end
|
53
|
+
puts ui.list(vpcs_list, :uneven_columns_across, output_column_count)
|
54
|
+
else
|
55
|
+
output(format_for_display(vpc_hash))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# @return [Hash<Hash>]
|
62
|
+
def vpc_hash
|
63
|
+
all_data = {}
|
64
|
+
ec2_connection.describe_vpcs.first.vpcs.each do |v|
|
65
|
+
v_data = {}
|
66
|
+
%w{vpc_id cidr_block dhcp_options_id instance_tenancy is_default state}.each do |id|
|
67
|
+
v_data[id] = v.send(id)
|
68
|
+
end
|
69
|
+
all_data[v_data["vpc_id"]] = v_data
|
70
|
+
end
|
71
|
+
all_data
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|