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)