in step_create_instances.go [158:231]
func (ci *CreateInstances) run(ctx context.Context, s *Step) DError {
var wg sync.WaitGroup
w := s.w
eChan := make(chan DError)
createInstance := func(ii InstanceInterface, ib *InstanceBase) {
// Just try to delete it, a 404 here indicates the instance doesn't exist.
if ib.OverWrite {
if err := ii.delete(w.ComputeClient, true); err != nil {
if apiErr, ok := err.(*googleapi.Error); !ok || apiErr.Code != 404 {
eChan <- Errf("error deleting existing instance: %v", err)
return
}
}
}
// Get the source machine image link if using a source machine image.
if ii.getSourceMachineImage() != "" {
if image, ok := w.machineImages.get(ii.getSourceMachineImage()); ok {
ii.setSourceMachineImage(image.link)
}
}
defer wg.Done()
ii.updateDisksAndNetworksBeforeCreate(w)
w.LogStepInfo(s.name, "CreateInstances", "Creating instance %q.", ii.getName())
if err := ii.create(w.ComputeClient); err != nil {
// Fallback to no-external-ip mode to workaround organization policy.
if ib.RetryWhenExternalIPDenied && isExternalIPDeniedByOrganizationPolicy(err) {
w.LogStepInfo(s.name, "CreateInstances", "Falling back to no-external-ip mode "+
"for creating instance %v due to the fact that external IP is denied by organization policy.", ii.getName())
UpdateInstanceNoExternalIP(s)
err = ii.create(w.ComputeClient)
}
if err != nil {
eChan <- newErr("failed to create instances", err)
return
}
}
ib.createdInWorkflow = true
for _, port := range ib.SerialPortsToLog {
go logSerialOutput(ctx, s, ii, ib, port, 3*time.Second)
}
}
if ci.instanceUsesBetaFeatures() {
for _, i := range ci.InstancesBeta {
wg.Add(1)
go createInstance(i, &i.InstanceBase)
}
} else {
for _, i := range ci.Instances {
wg.Add(1)
go createInstance(i, &i.InstanceBase)
}
}
go func() {
wg.Wait()
eChan <- nil
}()
select {
case err := <-eChan:
return err
case <-w.Cancel:
// Wait so instances being created now can be deleted.
wg.Wait()
return nil
}
}