Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create multiple instances using one call when using machine_batch (#306) #510

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions lib/chef/provisioning/aws_driver/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1413,18 +1413,24 @@ def create_servers(action_handler, specs_and_options, parallelizer)
"machines #{machine_specs.map { |s| s.name }.join(", ")}"
end
description = [ "creating #{machine_description} on #{driver_url}" ]
bootstrap_options.each_pair { |key,value| description << " #{key}: #{value.inspect}" }

parallel_bootstrap_options = bootstrap_options.merge({:max_count => machine_specs.size, :min_count => machine_specs.size})
parallel_bootstrap_options.each_pair { |key, value| description << " #{key}: #{value.inspect}" }
action_handler.report_progress description
if action_handler.should_perform_actions
# Actually create the servers
parallelizer.parallelize(1.upto(machine_specs.size)) do |i|

instances = create_instances(parallel_bootstrap_options)

parallelizer.parallelize(1.upto(machine_specs.size)) do |i|
# Assign each one to a machine spec
machine_spec = machine_specs.pop
instance = instances.pop
instance.wait_until_exists
machine_options = specs_and_options[machine_spec]

clean_bootstrap_options = Marshal.load(Marshal.dump(bootstrap_options))
instance = create_instance_and_reference(clean_bootstrap_options, action_handler, machine_spec, machine_options)
create_instance_reference(instance, clean_bootstrap_options, action_handler, machine_spec, machine_options)
converge_ec2_tags(instance, machine_options[:aws_tags], action_handler)

action_handler.performed_action "machine #{machine_spec.name} created as #{instance.id} on #{driver_url}"
Expand Down Expand Up @@ -1459,8 +1465,9 @@ def converge_elb_tags(aws_object, tags, action_handler)
aws_tagger.converge_tags
end

def create_instance_and_reference(bootstrap_options, action_handler, machine_spec, machine_options)
instance = nil
def create_instances(bootstrap_options)
instances = []

# IAM says the instance profile is ready, but EC2 doesn't think it is
# Not using retry_with_backoff here because we need to match on a string
Retryable.retryable(
Expand All @@ -1470,12 +1477,15 @@ def create_instance_and_reference(bootstrap_options, action_handler, machine_spe
:matching => /Invalid IAM Instance Profile name/
) do |retries, exception|
Chef::Log.debug("Instance creation InvalidParameterValue exception is #{exception.inspect}")
instance = ec2_resource.create_instances(bootstrap_options.to_hash)[0]
ec2_resource.create_instances(bootstrap_options.to_hash).each do |instance|
instances << instance
end
end

# Make sure the instance is ready to be tagged
instance.wait_until_exists
instances
end

def create_instance_reference(instance, bootstrap_options, action_handler, machine_spec, machine_options)
# Sometimes tagging fails even though the instance 'exists'
Chef::Provisioning::AWSDriver::AWSProvider.retry_with_backoff(::Aws::EC2::Errors::InvalidInstanceIDNotFound) do
instance.create_tags({tags: [{key: "Name", value: machine_spec.name}]})
Expand Down Expand Up @@ -1507,6 +1517,12 @@ def create_instance_and_reference(bootstrap_options, action_handler, machine_spe
%w(is_windows winrm_username winrm_port winrm_password ssh_username sudo transport_address_location ssh_gateway).each do |key|
machine_spec.reference[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
end
end

def create_instance_and_reference(bootstrap_options, action_handler, machine_spec, machine_options)
instance = create_instances(bootstrap_options).first
instance.wait_until_exists
create_instance_reference(instance, bootstrap_options, action_handler, machine_spec, machine_options)
instance
end

Expand Down
1 change: 0 additions & 1 deletion spec/integration/machine_batch_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@
).and be_idempotent
end
end

end
end