func (t *TestVM) AddAliasIPRanges(aliasIPRange, rangeName string) error {
	if t.instance.NetworkInterfaces == nil {
		return fmt.Errorf("Must call AddCustomNetwork prior to AddAliasIPRanges")
	}
	t.instance.NetworkInterfaces[0].AliasIpRanges = append(t.instance.NetworkInterfaces[0].AliasIpRanges, &compute.AliasIpRange{
		IpCidrRange:         aliasIPRange,
		SubnetworkRangeName: rangeName,
	})
	return nil
}
AddAliasIPRanges add alias ip range to current test VMs.
package imagetest
import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"github.com/GoogleCloudPlatform/compute-image-tools/daisy"
	"github.com/google/uuid"
	"google.golang.org/api/compute/v1"
)
const (
	createVMsStepName        = "create-vms"
	createDisksStepName      = "create-disks"
	createNetworkStepName    = "create-networks"
	createFirewallStepName   = "create-firewalls"
	createSubnetworkStepName = "create-sub-networks"
	successMatch             = "FINISHED-TEST"
	DefaultSourceRange = "10.128.0.0/9"
)
type TestVM struct {
	name         string
	testWorkflow *TestWorkflow
	instance     *daisy.Instance
}
func (t *TestVM) AddUser(user, publicKey string) {
	keyline := fmt.Sprintf("%s:%s", user, publicKey)
	if keys, ok := t.instance.Metadata["ssh-keys"]; ok {
		keyline = fmt.Sprintf("%s\n%s", keys, keyline)
	}
	t.AddMetadata("ssh-keys", keyline)
}
func (t *TestWorkflow) Skip(message string) {
	t.skipped = true
	t.skippedMessage = message
}
func (t *TestWorkflow) SkippedMessage() string {
	return t.skippedMessage
}
func (t *TestWorkflow) LockProject() {
	t.lockProject = true
}
func (t *TestWorkflow) CreateTestVM(name string) (*TestVM, error) {
	parts := strings.Split(name, ".")
	vmname := strings.ReplaceAll(parts[0], "_", "-")
	createDisksStep, err := t.appendCreateDisksStep(vmname)
	if err != nil {
		return nil, err
	}
	createVMStep, i, err := t.appendCreateVMStep(vmname, name)
	if err != nil {
		return nil, err
	}
	if err := t.wf.AddDependency(createVMStep, createDisksStep); err != nil {
		return nil, err
	}
	waitStep, err := t.addWaitStep(vmname, vmname, false)
	if err != nil {
		return nil, err
	}
	if err := t.wf.AddDependency(waitStep, createVMStep); err != nil {
		return nil, err
	}
	if createSubnetworkStep, ok := t.wf.Steps[createSubnetworkStepName]; ok {
		if err := t.wf.AddDependency(createVMStep, createSubnetworkStep); err != nil {
			return nil, err
		}
	}
	if createNetworkStep, ok := t.wf.Steps[createNetworkStepName]; ok {
		if err := t.wf.AddDependency(createVMStep, createNetworkStep); err != nil {
			return nil, err
		}
	}
	return &TestVM{name: vmname, testWorkflow: t, instance: i}, nil
}
func (t *TestVM) AddMetadata(key, value string) {
	if t.instance.Metadata == nil {
		t.instance.Metadata = make(map[string]string)
	}
	t.instance.Metadata[key] = value
	return
}
func (t *TestVM) RunTests(runtest string) {
	t.AddMetadata("_test_run", runtest)
}
func (t *TestVM) SetShutdownScript(script string) {
	t.AddMetadata("shutdown-script", script)
}
func (t *TestVM) SetShutdownScriptURL(script string) error {
	fileName := fmt.Sprintf("/shutdown_script-%s", uuid.New())
	if err := ioutil.WriteFile(fileName, []byte(script), 755); err != nil {
		return err
	}
	t.testWorkflow.wf.Sources["shutdown-script"] = fileName
	t.AddMetadata("shutdown-script-url", "${SOURCESPATH}/shutdown-script")
	return nil
}
func (t *TestVM) SetStartupScript(script string) {
	t.AddMetadata("startup-script", script)
}
func (t *TestVM) Reboot() error {
	t.testWorkflow.counter++
	stepSuffix := fmt.Sprintf("%s-%d", t.name, t.testWorkflow.counter)
	lastStep, err := t.testWorkflow.getLastStepForVM(t.name)
	if err != nil {
		return fmt.Errorf("failed resolve last step")
	}
	stopInstancesStep, err := t.testWorkflow.addStopStep(stepSuffix, t.name)
	if err != nil {
		return err
	}
	if err := t.testWorkflow.wf.AddDependency(stopInstancesStep, lastStep); err != nil {
		return err
	}
	waitStopStep, err := t.testWorkflow.addWaitStep("stopped-"+stepSuffix, t.name, true)
	if err != nil {
		return err
	}
	if err := t.testWorkflow.wf.AddDependency(waitStopStep, stopInstancesStep); err != nil {
		return err
	}
	startInstancesStep, err := t.testWorkflow.addStartStep(stepSuffix, t.name)
	if err != nil {
		return err
	}
	if err := t.testWorkflow.wf.AddDependency(startInstancesStep, waitStopStep); err != nil {
		return err
	}
	waitStartedStep, err := t.testWorkflow.addWaitStep("started-"+stepSuffix, t.name, false)
	if err != nil {
		return err
	}
	if err := t.testWorkflow.wf.AddDependency(waitStartedStep, startInstancesStep); err != nil {
		return err
	}
	return nil
}
func (t *TestVM) ResizeDiskAndReboot(diskSize int) error {
	t.testWorkflow.counter++
	stepSuffix := fmt.Sprintf("%s-%d", t.name, t.testWorkflow.counter)
	lastStep, err := t.testWorkflow.getLastStepForVM(t.name)
	if err != nil {
		return fmt.Errorf("failed resolve last step")
	}
	diskResizeStep, err := t.testWorkflow.addDiskResizeStep(stepSuffix, t.name, diskSize)
	if err != nil {
		return err
	}
	if err := t.testWorkflow.wf.AddDependency(diskResizeStep, lastStep); err != nil {
		return err
	}
	return t.Reboot()
}
func (t *TestVM) EnableSecureBoot() {
	t.instance.ShieldedInstanceConfig = &compute.ShieldedInstanceConfig{
		EnableSecureBoot: true,
	}
}
func (t *TestVM) AddCustomNetwork(network *Network, subnetwork *Subnetwork) error {
	var subnetworkName string
	if subnetwork == nil {
		subnetworkName = ""
		if !*network.network.AutoCreateSubnetworks {
			return fmt.Errorf("network %s is not auto mode, subnet is required", network.name)
		}
	} else {
		subnetworkName = subnetwork.name
	}
	networkInterface := compute.NetworkInterface{
		Network:    network.name,
		Subnetwork: subnetworkName,
		AccessConfigs: []*compute.AccessConfig{
			{
				Type: "ONE_TO_ONE_NAT",
			},
		},
	}
	if t.instance.NetworkInterfaces == nil {
		t.instance.NetworkInterfaces = []*compute.NetworkInterface{&networkInterface}
	} else {
		t.instance.NetworkInterfaces = append(t.instance.NetworkInterfaces, &networkInterface)
	}
	return nil
}