func RunWorkflowWithCancelSignal(ctx context.Context, w *daisy.Workflow) error {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func(w *daisy.Workflow) {
		select {
		case <-c:
			w.LogWorkflowInfo("\nCtrl-C caught, sending cancel signal to %q...\n", w.Name)
			w.CancelWorkflow()
		case <-w.Cancel:
		}
	}(w)
	return w.Run(ctx)
}
RunWorkflowWithCancelSignal runs Daisy workflow with accepting Ctrl-C signal
package daisyutils
import (
	"context"
	"errors"
	"fmt"
	"os"
	"os/signal"
	"regexp"
	"sort"
	"strings"
	stringutils "github.com/GoogleCloudPlatform/compute-image-tools/cli_tools/common/utils/string"
	"github.com/GoogleCloudPlatform/compute-image-tools/daisy"
)
const (
	BuildIDOSEnvVarName   = "BUILD_ID"
	translateFailedPrefix = "TranslateFailed"
)
type TranslationSettings struct {
	GcloudOsFlag string
	LicenseURI string
	WorkflowPath string
}
var (
	supportedOS = []TranslationSettings{
		{
			GcloudOsFlag: "centos-7",
			WorkflowPath: "enterprise_linux/translate_centos_7.wf.json",
			LicenseURI:   "projects/centos-cloud/global/licenses/centos-7",
		}, {
			GcloudOsFlag: "centos-8",
			WorkflowPath: "enterprise_linux/translate_centos_8.wf.json",
			LicenseURI:   "projects/centos-cloud/global/licenses/centos-8",
		}, {
			GcloudOsFlag: "rhel-6",
			WorkflowPath: "enterprise_linux/translate_rhel_6_licensed.wf.json",
			LicenseURI:   "projects/rhel-cloud/global/licenses/rhel-6-server",
		}, {
			GcloudOsFlag: "rhel-6-byol",
			WorkflowPath: "enterprise_linux/translate_rhel_6_byol.wf.json",
			LicenseURI:   "projects/rhel-cloud/global/licenses/rhel-6-byol",
		}, {
			GcloudOsFlag: "rhel-7",
			WorkflowPath: "enterprise_linux/translate_rhel_7_licensed.wf.json",
			LicenseURI:   "projects/rhel-cloud/global/licenses/rhel-7-server",
		}, {
			GcloudOsFlag: "rhel-7-byol",
			WorkflowPath: "enterprise_linux/translate_rhel_7_byol.wf.json",
			LicenseURI:   "projects/rhel-cloud/global/licenses/rhel-7-byol",
		}, {
			GcloudOsFlag: "rhel-8",
			WorkflowPath: "enterprise_linux/translate_rhel_8_licensed.wf.json",
			LicenseURI:   "projects/rhel-cloud/global/licenses/rhel-8-server",
		}, {
			GcloudOsFlag: "rhel-8-byol",
			WorkflowPath: "enterprise_linux/translate_rhel_8_byol.wf.json",
			LicenseURI:   "projects/rhel-cloud/global/licenses/rhel-8-byos",
		}, {
			GcloudOsFlag: "rocky-8",
			WorkflowPath: "enterprise_linux/translate_rocky_8.wf.json",
			LicenseURI:   "projects/rocky-linux-cloud/global/licenses/rocky-linux-8",
		},
		{
			GcloudOsFlag: "opensuse-15",
			WorkflowPath: "suse/translate_opensuse_15.wf.json",
			LicenseURI:   "projects/opensuse-cloud/global/licenses/opensuse-leap-42",
		}, {
			GcloudOsFlag: "sles-12",
			WorkflowPath: "suse/translate_sles_12.wf.json",
			LicenseURI:   "projects/suse-cloud/global/licenses/sles-12",
		}, {
			GcloudOsFlag: "sles-12-byol",
			WorkflowPath: "suse/translate_sles_12_byol.wf.json",
			LicenseURI:   "projects/suse-byos-cloud/global/licenses/sles-12-byos",
		}, {
			GcloudOsFlag: "sles-sap-12",
			WorkflowPath: "suse/translate_sles_sap_12.wf.json",
			LicenseURI:   "projects/suse-sap-cloud/global/licenses/sles-sap-12",
		}, {
			GcloudOsFlag: "sles-sap-12-byol",
			WorkflowPath: "suse/translate_sles_sap_12_byol.wf.json",
			LicenseURI:   "projects/suse-byos-cloud/global/licenses/sles-sap-12-byos",
		}, {
			GcloudOsFlag: "sles-15",
			WorkflowPath: "suse/translate_sles_15.wf.json",
			LicenseURI:   "projects/suse-cloud/global/licenses/sles-15",
		}, {
			GcloudOsFlag: "sles-15-byol",
			WorkflowPath: "suse/translate_sles_15_byol.wf.json",
			LicenseURI:   "projects/suse-byos-cloud/global/licenses/sles-15-byos",
		}, {
			GcloudOsFlag: "sles-sap-15",
			WorkflowPath: "suse/translate_sles_sap_15.wf.json",
			LicenseURI:   "projects/suse-sap-cloud/global/licenses/sles-sap-15",
		}, {
			GcloudOsFlag: "sles-sap-15-byol",
			WorkflowPath: "suse/translate_sles_sap_15_byol.wf.json",
			LicenseURI:   "projects/suse-byos-cloud/global/licenses/sles-sap-15-byos",
		},
		{
			GcloudOsFlag: "debian-8",
			WorkflowPath: "debian/translate_debian_8.wf.json",
			LicenseURI:   "projects/debian-cloud/global/licenses/debian-8-jessie",
		}, {
			GcloudOsFlag: "debian-9",
			WorkflowPath: "debian/translate_debian_9.wf.json",
			LicenseURI:   "projects/debian-cloud/global/licenses/debian-9-stretch",
		}, {
			GcloudOsFlag: "debian-10",
			WorkflowPath: "debian/translate_debian_10.wf.json",
			LicenseURI:   "projects/debian-cloud/global/licenses/debian-10-buster",
		}, {
			GcloudOsFlag: "debian-11",
			WorkflowPath: "debian/translate_debian_11.wf.json",
			LicenseURI:   "projects/debian-cloud/global/licenses/debian-11-bullseye",
		},
		{
			GcloudOsFlag: "ubuntu-1404",
			WorkflowPath: "ubuntu/translate_ubuntu_1404.wf.json",
			LicenseURI:   "projects/ubuntu-os-cloud/global/licenses/ubuntu-1404-trusty",
		}, {
			GcloudOsFlag: "ubuntu-1604",
			WorkflowPath: "ubuntu/translate_ubuntu_1604.wf.json",
			LicenseURI:   "projects/ubuntu-os-cloud/global/licenses/ubuntu-1604-xenial",
		}, {
			GcloudOsFlag: "ubuntu-1804",
			WorkflowPath: "ubuntu/translate_ubuntu_1804.wf.json",
			LicenseURI:   "projects/ubuntu-os-cloud/global/licenses/ubuntu-1804-lts",
		}, {
			GcloudOsFlag: "ubuntu-2004",
			WorkflowPath: "ubuntu/translate_ubuntu_2004.wf.json",
			LicenseURI:   "projects/ubuntu-os-cloud/global/licenses/ubuntu-2004-lts",
		},
		{
			GcloudOsFlag: "windows-7-x64-byol",
			WorkflowPath: "windows/translate_windows_7_x64_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-7-x64-byol",
		}, {
			GcloudOsFlag: "windows-7-x86-byol",
			WorkflowPath: "windows/translate_windows_7_x86_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-7-x86-byol",
		}, {
			GcloudOsFlag: "windows-8-x64-byol",
			WorkflowPath: "windows/translate_windows_8_x64_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-8-x64-byol",
		}, {
			GcloudOsFlag: "windows-8-x86-byol",
			WorkflowPath: "windows/translate_windows_8_x86_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-8-x86-byol",
		}, {
			GcloudOsFlag: "windows-10-x64-byol",
			WorkflowPath: "windows/translate_windows_10_x64_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-10-x64-byol",
		}, {
			GcloudOsFlag: "windows-10-x86-byol",
			WorkflowPath: "windows/translate_windows_10_x86_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-10-x86-byol",
		}, {
			GcloudOsFlag: "windows-2008r2",
			WorkflowPath: "windows/translate_windows_2008_r2.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2008-r2-dc",
		}, {
			GcloudOsFlag: "windows-2008r2-byol",
			WorkflowPath: "windows/translate_windows_2008_r2_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2008-r2-byol",
		}, {
			GcloudOsFlag: "windows-2012",
			WorkflowPath: "windows/translate_windows_2012.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2012-dc",
		}, {
			GcloudOsFlag: "windows-2012-byol",
			WorkflowPath: "windows/translate_windows_2012_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2012-byol",
		}, {
			GcloudOsFlag: "windows-2012r2",
			WorkflowPath: "windows/translate_windows_2012_r2.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2012-r2-dc",
		}, {
			GcloudOsFlag: "windows-2012r2-byol",
			WorkflowPath: "windows/translate_windows_2012_r2_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2012-r2-byol",
		}, {
			GcloudOsFlag: "windows-2016",
			WorkflowPath: "windows/translate_windows_2016.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2016-dc",
		}, {
			GcloudOsFlag: "windows-2016-byol",
			WorkflowPath: "windows/translate_windows_2016_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2016-byol",
		}, {
			GcloudOsFlag: "windows-2019",
			WorkflowPath: "windows/translate_windows_2019.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2019-dc",
		}, {
			GcloudOsFlag: "windows-2019-byol",
			WorkflowPath: "windows/translate_windows_2019_byol.wf.json",
			LicenseURI:   "projects/windows-cloud/global/licenses/windows-server-2019-byol",
		},
	}
	legacyIDs = map[string]string{
		"windows-7-byol":       "windows-7-x64-byol",
		"windows-8-1-x64-byol": "windows-8-x64-byol",
		"windows-10-byol":      "windows-10-x64-byol",
	}
	privacyRegex    = regexp.MustCompile(`\[Privacy\->.*?<\-Privacy\]`)
	privacyTagRegex = regexp.MustCompile(`(\[Privacy\->)|(<\-Privacy\])`)
	debianWorkerRegex = regexp.MustCompile("projects/compute-image-tools/global/images/family/debian-\\d+-worker")
)
func GetSortedOSIDs() []string {
	choices := make([]string, 0, len(supportedOS))
	for _, k := range supportedOS {
		choices = append(choices, k.GcloudOsFlag)
	}
	sort.Strings(choices)
	return choices
}
func ValidateOS(osID string) error {
	_, err := GetTranslationSettings(osID)
	return err
}
func GetTranslationSettings(osID string) (spec TranslationSettings, err error) {
	if osID == "" {
		return spec, errors.New("osID is empty")
	}
	if replacement := legacyIDs[osID]; replacement != "" {
		osID = replacement
	}
	for _, choice := range supportedOS {
		if choice.GcloudOsFlag == osID {
			return choice, nil
		}
	}
	allowedValuesMsg := fmt.Sprintf("Allowed values: %v", GetSortedOSIDs())
	return spec, daisy.Errf("os `%v` is invalid. "+allowedValuesMsg, osID)
}
func UpdateToUEFICompatible(workflow *daisy.Workflow) {
	workflow.IterateWorkflowSteps(func(step *daisy.Step) {
		if step.CreateDisks != nil {
			for _, disk := range *step.CreateDisks {
				if debianWorkerRegex.MatchString(disk.SourceImage) {
					continue
				}
				if strings.Contains(disk.SourceImage, "projects/windows-cloud/global/images/family/windows-2019-core") && strings.Contains(disk.Name, "disk-bootstrap") {
					continue
				}
				disk.Disk.GuestOsFeatures = daisy.CombineGuestOSFeatures(disk.Disk.GuestOsFeatures, "UEFI_COMPATIBLE")
			}
		}
		if step.CreateImages != nil {
			for _, image := range step.CreateImages.Images {
				image.GuestOsFeatures = stringutils.CombineStringSlices(image.GuestOsFeatures, "UEFI_COMPATIBLE")
				image.Image.GuestOsFeatures = daisy.CombineGuestOSFeatures(image.Image.GuestOsFeatures, "UEFI_COMPATIBLE")
			}
			for _, image := range step.CreateImages.ImagesBeta {
				image.GuestOsFeatures = stringutils.CombineStringSlices(image.GuestOsFeatures, "UEFI_COMPATIBLE")
				image.Image.GuestOsFeatures = daisy.CombineGuestOSFeaturesBeta(image.Image.GuestOsFeatures, "UEFI_COMPATIBLE")
			}
		}
	})
}
func RemovePrivacyLogInfo(message string) string {
	if strings.Contains(message, translateFailedPrefix) {
		return translateFailedPrefix
	}
	message = privacyRegex.ReplaceAllString(message, "")
	return message
}
func RemovePrivacyLogTag(message string) string {
	message = privacyTagRegex.ReplaceAllString(message, "")
	return message
}
func PostProcessDErrorForNetworkFlag(action string, err error, network string, w *daisy.Workflow) {
	if derr, ok := err.(daisy.DError); ok {
		if derr.CausedByErrType("networkResourceDoesNotExist") && network == "" {
			w.LogWorkflowInfo("A VPC network is required for running %v,"+
				" and the default VPC network does not exist in your project. You will need to"+
				" specify a VPC network with the --network flag. For more information about"+
				" VPC networks, see https://cloud.google.com/vpc.", action)
		}
	}
}