func()

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
	}
}