lib/kitchen/driver/ec2.rb in kitchen-ec2-3.0.1 vs lib/kitchen/driver/ec2.rb in kitchen-ec2-3.1.0

- old
+ new

@@ -72,10 +72,11 @@ default_config :private_ip_address, nil default_config :iam_profile_name, nil default_config :spot_price, nil default_config :block_duration_minutes, nil default_config :retryable_tries, 60 + default_config :spot_wait, 60 default_config :retryable_sleep, 5 default_config :aws_access_key_id, nil default_config :aws_secret_access_key, nil default_config :aws_session_token, nil default_config :aws_ssh_key_id, ENV["AWS_SSH_KEY_ID"] @@ -227,22 +228,19 @@ config[:aws_ssh_key_id] = nil end if config[:spot_price] # Spot instance when a price is set - server = with_request_limit_backoff(state) { submit_spot(state) } + server = with_request_limit_backoff(state) { submit_spots(state) } else # On-demand instance server = with_request_limit_backoff(state) { submit_server } end info("Instance <#{server.id}> requested.") with_request_limit_backoff(state) do - server.wait_until_exists do |w| - w.before_attempt do |attempts| - info("Polling AWS for existence, attempt #{attempts}...") - end - end + logging_proc = ->(attempts) { info("Polling AWS for existence, attempt #{attempts}...") } + server.wait_until_exists(before_attempt: logging_proc) end # See https://github.com/aws/aws-sdk-ruby/issues/859 # Tagging can fail with a NotFound error even though we waited until the server exists # Waiting can also fail, so we have to also retry on that. If it means we re-tag the @@ -405,11 +403,11 @@ config[:ssl_verify_peer] ) end def instance_generator - @instance_generator ||= Aws::InstanceGenerator.new(config, ec2, instance.logger) + @instance_generator = Aws::InstanceGenerator.new(config, ec2, instance.logger) end # Fog AWS helper for creating the instance def submit_server instance_data = instance_generator.ec2_instance_data @@ -420,10 +418,57 @@ instance_data[:min_count] = 1 instance_data[:max_count] = 1 ec2.create_instance(instance_data) end + def config + return super unless @config + @config + end + + # Take one config and expand to multiple configs + def expand_config(conf, key) + configs = [] + + if conf[key] && conf[key].kind_of?(Array) + values = conf[key] + values.each do |value| + new_config = conf.clone + new_config[key] = value + configs.push new_config + end + else + configs.push conf + end + + configs + end + + def submit_spots(state) + configs = [config] + expanded = [] + keys = [:instance_type, :subnet_id] + + keys.each do |key| + configs.each do |conf| + expanded.push expand_config(conf, key) + end + configs = expanded.flatten + expanded = [] + end + + configs.each do |conf| + begin + @config = conf + return submit_spot(state) + rescue + end + end + + raise "Could not create a spot" + end + def submit_spot(state) debug("Creating EC2 Spot Instance..") spot_request_id = create_spot_request # deleting the instance cancels the request, but deleting the request @@ -431,25 +476,31 @@ state[:spot_request_id] = spot_request_id ec2.client.wait_until( :spot_instance_request_fulfilled, spot_instance_request_ids: [spot_request_id] ) do |w| - w.max_attempts = config[:retryable_tries] + w.max_attempts = config[:spot_wait] / config[:retryable_sleep] w.delay = config[:retryable_sleep] w.before_attempt do |attempts| c = attempts * config[:retryable_sleep] - t = config[:retryable_tries] * config[:retryable_sleep] + t = config[:spot_wait] info "Waited #{c}/#{t}s for spot request <#{spot_request_id}> to become fulfilled." end end ec2.get_instance_from_spot_request(spot_request_id) end def create_spot_request - request_duration = config[:retryable_tries] * config[:retryable_sleep] + request_duration = config[:spot_wait] + config_spot_price = config[:spot_price].to_s + if ["ondemand", "on-demand"].include?(config_spot_price) + spot_price = "" + else + spot_price = config_spot_price + end request_data = { - spot_price: config[:spot_price].to_s, + spot_price: spot_price, launch_specification: instance_generator.ec2_instance_data, valid_until: Time.now + request_duration, } if config[:block_duration_minutes] request_data[:block_duration_minutes] = config[:block_duration_minutes] @@ -591,9 +642,10 @@ { "dns" => "public_dns_name", "public" => "public_ip_address", "private" => "private_ip_address", "private_dns" => "private_dns_name", + "id" => "id", }.freeze # # Lookup hostname of provided server. If interface_type is provided use # that interface to lookup hostname. Otherwise, try ordered list of