lib/chef/knife/ec2_server_create.rb in knife-ec2-0.10.0 vs lib/chef/knife/ec2_server_create.rb in knife-ec2-0.11.0.rc.0
- old
+ new
@@ -185,11 +185,10 @@
:long => "--run-list RUN_LIST",
:description => "Comma separated list of roles/recipes to apply",
:proc => lambda { |o| o.split(/[\s,]+/) }
option :secret,
- :short => "-s SECRET",
:long => "--secret ",
:description => "The secret key to use to encrypt data bag item values",
:proc => lambda { |s| Chef::Config[:knife][:secret] = s }
option :secret_file,
@@ -207,11 +206,10 @@
:long => "--json-attributes JSON",
:description => "A JSON string to be added to the first run of chef-client",
:proc => lambda { |o| JSON.parse(o) }
option :subnet_id,
- :short => "-s SUBNET-ID",
:long => "--subnet SUBNET-ID",
:description => "create node in this Virtual Private Cloud Subnet ID (implies VPC mode)",
:proc => Proc.new { |key| Chef::Config[:knife][:subnet_id] = key }
option :private_ip_address,
@@ -291,21 +289,47 @@
option :validation_key_url,
:long => "--validation-key-url URL",
:description => "Path to the validation key",
:proc => proc { |m| Chef::Config[:validation_key_url] = m }
+ option :ebs_encrypted,
+ :long => "--ebs-encrypted",
+ :description => "Enables EBS volume encryption",
+ :boolean => true,
+ :default => false
+
+ option :spot_price,
+ :long => "--spot-price PRICE",
+ :description => "The maximum hourly USD price for the instance",
+ :default => nil
+
def run
$stdout.sync = true
validate!
requested_elastic_ip = config[:associate_eip] if config[:associate_eip]
# For VPC EIP assignment we need the allocation ID so fetch full EIP details
elastic_ip = connection.addresses.detect{|addr| addr if addr.public_ip == requested_elastic_ip}
- @server = connection.servers.create(create_server_def)
+ if locate_config_value(:spot_price)
+ spot_request = connection.spot_requests.create(create_server_def)
+ msg_pair("Spot Request ID", spot_request.id)
+ msg_pair("Spot Request Type", spot_request.request_type)
+ msg_pair("Spot Price", spot_request.price)
+ print ui.color("Waiting for Spot Request fulfillment: ", :cyan)
+ spot_request.wait_for do
+ @spinner ||= %w{| / - \\}
+ print "\b" + @spinner.rotate!.first
+ ready?
+ end
+ puts("\n")
+ @server = connection.servers.get(spot_request.instance_id)
+ else
+ @server = connection.servers.create(create_server_def)
+ end
hashed_tags={}
tags.map{ |t| key,val=t.split('='); hashed_tags[key]=val} unless tags.nil?
# Always set the Name tag
@@ -427,10 +451,22 @@
msg_pair("Root Device Name", device_map['deviceName'])
msg_pair("Root Device Delete on Terminate", device_map['deleteOnTermination'])
msg_pair("Standard or Provisioned IOPS", device_map['volumeType'])
msg_pair("IOPS rate", device_map['iops'])
+ print "\n#{ui.color("Block devices", :magenta)}\n"
+ print "#{ui.color("===========================", :magenta)}\n"
+ @server.block_device_mapping.each do |device_map|
+ msg_pair("Device Name", device_map['deviceName'])
+ msg_pair("Volume ID", device_map['volumeId'])
+ msg_pair("Delete on Terminate", device_map['deleteOnTermination'].to_s)
+ msg_pair("Standard or Provisioned IOPS", device_map['volumeType'])
+ msg_pair("IOPS rate", device_map['iops'])
+ print "\n"
+ end
+ print "#{ui.color("===========================", :magenta)}\n"
+
if config[:ebs_size]
if ami.block_device_mapping.first['volumeSize'].to_i < config[:ebs_size].to_i
volume_too_large_warning = "#{config[:ebs_size]}GB " +
"EBS volume size is larger than size set in AMI of " +
"#{ami.block_device_mapping.first['volumeSize']}GB.\n" +
@@ -627,10 +663,31 @@
if config[:ebs_volume_type] and ! %w(gp2 io1 standard).include?(config[:ebs_volume_type])
ui.error("--ebs-volume-type must be 'standard' or 'io1' or 'gp2'")
msg opt_parser
exit 1
end
+
+ if(config[:security_groups] && config[:security_groups].class == String)
+ 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']")
+ exit 1
+ end
+
+ if(config[:security_group_ids] && config[:security_group_ids].class == String)
+ 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']")
+ exit 1
+ end
+
+ if (locate_config_value(:ebs_encrypted) and !locate_config_value(:flavor))
+ ui.error("--ebs_encrypted option requires valid flavor to be specified.")
+ exit 1
+ elsif (locate_config_value(:ebs_encrypted) and ! %w(m3.medium m3.large m3.xlarge m3.2xlarge c4.large c4.xlarge
+ c4.2xlarge c4.4xlarge c4.8xlarge c3.large c3.xlarge c3.2xlarge
+ c3.4xlarge c3.8xlarge cr1.8xlarge r3.large r3.xlarge r3.2xlarge
+ r3.4xlarge r3.8xlarge i2.xlarge i2.2xlarge i2.4xlarge i2.8xlarge g2.2xlarge).include?(locate_config_value(:flavor)))
+ ui.error("--ebs_encrypted option is not supported for #{locate_config_value(:flavor)} flavor.")
+ exit 1
+ end
end
def tags
tags = locate_config_value(:tags)
if !tags.nil? and tags.length != tags.to_s.count('=')
@@ -653,11 +710,12 @@
:image_id => locate_config_value(:image),
:groups => config[:security_groups],
:security_group_ids => locate_config_value(:security_group_ids),
:flavor_id => locate_config_value(:flavor),
:key_name => Chef::Config[:knife][:aws_ssh_key_id],
- :availability_zone => locate_config_value(:availability_zone)
+ :availability_zone => locate_config_value(:availability_zone),
+ :price => locate_config_value(:spot_price)
}
server_def[:subnet_id] = locate_config_value(:subnet_id) if vpc_mode?
server_def[:private_ip_address] = locate_config_value(:private_ip_address) if vpc_mode?
server_def[:placement_group] = locate_config_value(:placement_group)
server_def[:iam_instance_profile_name] = locate_config_value(:iam_instance_profile)
@@ -677,11 +735,16 @@
else
server_def[:ebs_optimized] = "false"
end
if ami.root_device_type == "ebs"
- ami_map = ami.block_device_mapping.first
+ if locate_config_value(:ebs_encrypted)
+ ami_map = ami.block_device_mapping[1]
+ else
+ ami_map = ami.block_device_mapping.first
+ end
+
ebs_size = begin
if config[:ebs_size]
Integer(config[:ebs_size]).to_s
else
ami_map["volumeSize"].to_s
@@ -714,10 +777,11 @@
'Ebs.VolumeSize' => ebs_size,
'Ebs.DeleteOnTermination' => delete_term,
'Ebs.VolumeType' => config[:ebs_volume_type],
}]
server_def[:block_device_mapping].first['Ebs.Iops'] = iops_rate unless iops_rate.empty?
+ server_def[:block_device_mapping].first['Ebs.Encrypted'] = true if locate_config_value(:ebs_encrypted)
end
(config[:ephemeral] || []).each_with_index do |device_name, i|
server_def[:block_device_mapping] = (server_def[:block_device_mapping] || []) << {'VirtualName' => "ephemeral#{i}", 'DeviceName' => device_name}
end
@@ -799,11 +863,11 @@
# SSH keys.
ssh_gateway_config = Net::SSH::Config.for(gw_host)
gw_user ||= ssh_gateway_config[:user]
# Always use the gateway keys from the SSH Config
- gateway_keys = ssh_gateway_config[:keys]
+ gateway_keys = ssh_gateway_config[:keys]
# Use the keys specificed on the command line if available (overrides SSH Config)
if config[:ssh_gateway_identity]
gateway_keys = Array(locate_config_value(:ssh_gateway_identity))
end
@@ -833,10 +897,10 @@
server.send(config[:server_connect_attribute])
else
if vpc_mode? && !config[:associate_public_ip]
server.private_ip_address
else
- server.dns_name
+ server.dns_name || server.public_ip_address
end
end
end
def create_tags(hashed_tags)