func attemptCreateManagedInstanceGroupVM()

in integration_test/gce-testing-internal/gce/gce_testing.go [1418:1544]


func attemptCreateManagedInstanceGroupVM(ctx context.Context, logger *log.Logger, options VMOptions) (migVmToReturn *ManagedInstanceGroupVM, errToReturn error) {
	// We need a shorter uuid here to add suffixes and not go over the 63 character limit
	// for resource names.
	options.Name = fmt.Sprintf("%s-%s", sandboxPrefix, uuid.NewString()[:30])

	migVM := &ManagedInstanceGroupVM{
		VM: createVMFromVMOptions(options),
	}

	// Step #1 : Create vm instance template
	createTemplateArgs := []string{
		// "beta" is needed for --max-run-duration.
		"beta", "compute", "instance-templates", "create", migVM.InstanceTemplateName(),
		"--project=" + migVM.Project,
		"--machine-type=" + migVM.MachineType,
		"--network=" + migVM.Network,
		"--format=json",
	}
	additionalArgs, err := additionalCreateInstanceArgs(options, migVM.VM)
	if err != nil {
		return nil, err
	}
	createTemplateArgs = append(createTemplateArgs, additionalArgs...)

	output, err := RunGcloud(ctx, logger, "", createTemplateArgs)
	if err != nil {
		// Note: we don't try and delete the instance template or managed instance group
		// in this case because there is nothing to delete.
		return nil, err
	}

	defer func() {
		if errToReturn != nil {
			// This function is responsible for deleting the ManagedInstanceGroupVM in all error cases.
			errToReturn = multierr.Append(errToReturn, DeleteManagedInstanceGroupVM(logger, migVM))
			// Make sure to never return both a valid ManagedInstanceGroupVM object and an error.
			migVmToReturn = nil
		}
		if errToReturn == nil && migVM.VM == nil {
			errToReturn = errors.New("programming error: attemptCreateManagedInstanceGroupVM() returned nil VM and nil error")
		}
	}()

	// Step #2 : Create empty Managed Instance Group using template.
	createMIGArgs := []string{
		"compute", "instance-groups", "managed", "create", migVM.ManagedInstanceGroupName(),
		"--project=" + migVM.Project,
		"--zone=" + migVM.Zone,
		"--size=0",
		"--template=" + migVM.InstanceTemplateName(),
		"--format=json",
	}

	output, err = RunGcloud(ctx, logger, "", createMIGArgs)
	if err != nil {
		return nil, err
	}

	// Step #3 : Create test VM in Managed Instance Group.
	createVMArgs := []string{
		"compute", "instance-groups", "managed", "create-instance", migVM.ManagedInstanceGroupName(),
		"--instance=" + migVM.Name,
		"--project=" + migVM.Project,
		"--zone=" + migVM.Zone,
		"--format=json",
	}

	output, err = RunGcloud(ctx, logger, "", createVMArgs)
	if err != nil {
		return nil, err
	}

	// Step #4 : Wait until Managed Instance Group is stable with a 300s timeout.
	waitUntilStableArgs := []string{
		"compute", "instance-groups", "managed", "wait-until", migVM.ManagedInstanceGroupName(),
		"--stable",
		"--timeout=300",
		"--project=" + migVM.Project,
		"--zone=" + migVM.Zone,
		"--format=json",
	}

	output, err = RunGcloud(ctx, logger, "", waitUntilStableArgs)
	if err != nil {
		return nil, err
	}

	// Step #5 : Query newly created VM metadata.
	listVMArgs := []string{
		"compute", "instances", "list",
		"--filter=name=( '" + migVM.Name + "' ... )",
		"--project=" + migVM.Project,
		"--zones=" + migVM.Zone,
		"--format=json",
	}

	output, err = RunGcloud(ctx, logger, "", listVMArgs)
	if err != nil {
		return nil, err
	}

	// Pull the instance ID and external IP address out of the output.
	id, err := extractID(output.Stdout)
	if err != nil {
		return nil, err
	}
	migVM.ID = id

	logger.Printf("Instance Log: %v", instanceLogURL(migVM.VM))

	ipAddress, err := extractIPAddress(output.Stdout)
	if err != nil {
		return nil, err
	}
	migVM.IPAddress = ipAddress

	// This is just informational, so it's ok if it fails. Just warn and proceed.
	if _, err := DescribeVMDisk(ctx, logger, migVM.VM); err != nil {
		logger.Printf("Unable to retrieve information about the VM's boot disk: %v", err)
	}

	if err := verifyVMCreation(ctx, logger, migVM.VM); err != nil {
		return nil, err
	}

	return migVM, nil
}