func (i *InstanceBeta) Cleanup() error {
	return i.Client.DeleteInstance(i.Project, i.Zone, i.Name)
}
Cleanup deletes the InstanceBeta.
package gcp
import (
	"context"
	"fmt"
	"strings"
	"time"
	apiBeta "google.golang.org/api/compute/v0.beta"
	api "google.golang.org/api/compute/v1"
	daisyCompute "github.com/GoogleCloudPlatform/compute-image-tools/daisy/compute"
)
type Instance struct {
	*api.Instance
	Client        daisyCompute.Client
	Project, Zone string
	IsWindows     bool
}
type InstanceBeta struct {
	*apiBeta.Instance
	Client        daisyCompute.Client
	Project, Zone string
	IsWindows     bool
}
func (i *Instance) Cleanup() error {
	return i.Client.DeleteInstance(i.Project, i.Zone, i.Name)
}
func (i *Instance) RestartWithScriptCode(script string) error {
	err := i.Client.StopInstance(i.Project, i.Zone, i.Name)
	if err != nil {
		return err
	}
	return i.StartWithScriptCode(script, nil)
}
func (i *Instance) StartWithScriptCode(script string, instanceMetadata map[string]string) error {
	if instanceMetadata == nil {
		instanceMetadata = make(map[string]string)
	}
	if i.IsWindows {
		instanceMetadata["windows-startup-script-ps1"] = script
	} else {
		instanceMetadata["startup-script"] = script
	}
	var metadataItems []*api.MetadataItems
	for k, v := range instanceMetadata {
		metadataItems = append(metadataItems, BuildInstanceMetadataItem(k, v))
	}
	err := i.Client.SetInstanceMetadata(i.Project, i.Zone,
		i.Name, &api.Metadata{Items: metadataItems, Fingerprint: i.Metadata.Fingerprint})
	if err != nil {
		return err
	}
	if err = i.Client.StartInstance(i.Project, i.Zone, i.Name); err != nil {
		return err
	}
	return nil
}
func (i *Instance) WaitForSerialOutput(match string, failureMatches []string, port int64, interval, timeout time.Duration) error {
	return WaitForSerialOutput(match, failureMatches, port, interval, timeout, i.Project, i.Zone, i.Name, i.Client)
}
func (i *InstanceBeta) WaitForSerialOutput(match string, failureMatches []string, port int64, interval, timeout time.Duration) error {
	return WaitForSerialOutput(match, failureMatches, port, interval, timeout, i.Project, i.Zone, i.Name, i.Client)
}
func WaitForSerialOutput(successMatch string, failureMatches []string, port int64, interval, timeout time.Duration, project, zone, instanceName string, client daisyCompute.Client) error {
	var start int64
	var errs int
	tick := time.Tick(interval)
	timedout := time.Tick(timeout)
	for {
		select {
		case <-timedout:
			return fmt.Errorf("timed out waiting for %q", successMatch)
		case <-tick:
			resp, err := client.GetSerialPortOutput(project, zone, instanceName, port, start)
			if err != nil {
				status, sErr := client.InstanceStatus(project, zone, instanceName)
				if sErr != nil {
					err = fmt.Errorf("%v, error getting InstanceStatus: %v", err, sErr)
				} else {
					err = fmt.Errorf("%v, InstanceStatus: %q", err, status)
				}
				if status == "TERMINATED" || status == "STOPPED" || status == "STOPPING" {
					continue
				}
				if errs < 3 {
					errs++
					continue
				}
				return err
			}
			start = resp.Next
			for _, ln := range strings.Split(resp.Contents, "\n") {
				if len(failureMatches) > 0 {
					for _, failureMatch := range failureMatches {
						if i := strings.Index(ln, failureMatch); i != -1 {
							errMsg := strings.TrimSpace(ln[i:])
							format := "WaitForSerialOutput FailureMatch found for %q: %q"
							return fmt.Errorf(format, instanceName, errMsg)
						}
					}
				}
				if successMatch != "" {
					if i := strings.Index(strings.ToLower(ln), strings.ToLower(successMatch)); i != -1 {
						return nil
					}
				}
			}
			errs = 0
		}
	}
}
func SetMetadata(ctx context.Context, project, zone, name, key, value string, isWindows bool) (*Instance, error) {
	i, err := CreateInstanceObject(ctx, project, zone, name, isWindows)
	if err != nil {
		return nil, err
	}
	err = i.Client.SetInstanceMetadata(i.Project, i.Zone,
		i.Name, &api.Metadata{Items: []*api.MetadataItems{BuildInstanceMetadataItem(
			key, value)},
			Fingerprint: i.Metadata.Fingerprint})
	return i, err
}
func CreateInstanceObject(ctx context.Context, project string, zone string, name string, isWindows bool) (*Instance, error) {
	client, err := daisyCompute.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	var apiInstance *api.Instance
	apiInstance, err = client.GetInstance(project, zone, name)
	return &Instance{apiInstance, client, project, zone, isWindows}, err
}
func CreateInstanceBetaObject(ctx context.Context, project string, zone string, name string, isWindows bool) (*InstanceBeta, error) {
	client, err := daisyCompute.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	var apiInstance *apiBeta.Instance
	apiInstance, err = client.GetInstanceBeta(project, zone, name)
	return &InstanceBeta{apiInstance, client, project, zone, isWindows}, err
}
func CreateMachineImageObject(ctx context.Context, project string, name string) (*apiBeta.MachineImage, error) {
	client, err := daisyCompute.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	return client.GetMachineImage(project, name)
}
func CreateInstanceBeta(ctx context.Context, project string, zone string, name string,
	isWindows bool, machineImageName string) (*InstanceBeta, error) {
	client, err := daisyCompute.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	apiBetaInstance := &apiBeta.Instance{
		SourceMachineImage: fmt.Sprintf("projects/%s/global/machineImages/%s", project, machineImageName),
		Name:               name,
		Zone:               zone,
	}
	i := &InstanceBeta{apiBetaInstance, client, project, zone, isWindows}
	if err := client.CreateInstanceBeta(i.Project, i.Zone, i.Instance); err != nil {
		return i, err
	}
	return i, nil
}
func BuildInstanceMetadataItem(key, value string) *api.MetadataItems {
	return &api.MetadataItems{
		Key:   key,
		Value: func() *string { v := value; return &v }(),
	}
}
func (i *InstanceBeta) StartWithScriptCode(script string, instanceMetadata map[string]string) error {
	if instanceMetadata == nil {
		instanceMetadata = make(map[string]string)
	}
	if i.IsWindows {
		instanceMetadata["windows-startup-script-ps1"] = script
	} else {
		instanceMetadata["startup-script"] = script
	}
	var metadataItems []*api.MetadataItems
	for k, v := range instanceMetadata {
		metadataItems = append(metadataItems, BuildInstanceMetadataItem(k, v))
	}
	err := i.Client.SetInstanceMetadata(i.Project, i.Zone,
		i.Name, &api.Metadata{Items: metadataItems, Fingerprint: i.Metadata.Fingerprint})
	if err != nil {
		return err
	}
	if err = i.Client.StartInstance(i.Project, i.Zone, i.Name); err != nil {
		return err
	}
	return nil
}