func populateScratchBucketGcsPath(scratchBucketGcsPath *string, zone string, mgce domain.MetadataGCEInterface,
	scratchBucketCreator domain.ScratchBucketCreatorInterface, file string, project *string,
	storageClient domain.StorageClientInterface, removeFileWhenScratchNotOwned bool) (string, error) {
	scratchBucketRegion := ""
	if *scratchBucketGcsPath == "" {
		fallbackZone := zone
		if fallbackZone == "" && mgce.OnGCE() {
			var err error
			if fallbackZone, err = mgce.Zone(); err != nil {
				fallbackZone = ""
			}
		}
		scratchBucketName, sbr, err := scratchBucketCreator.CreateScratchBucket(file, *project, fallbackZone)
		scratchBucketRegion = sbr
		if err != nil {
			return "", daisy.Errf("failed to create scratch bucket: %v", err)
		}
		*scratchBucketGcsPath = fmt.Sprintf("gs://%v/", scratchBucketName)
	} else {
		scratchBucketName, err := storage.GetBucketNameFromGCSPath(*scratchBucketGcsPath)
		if err != nil {
			return "", daisy.Errf("invalid scratch bucket GCS path %v", scratchBucketGcsPath)
		}
		if !scratchBucketCreator.IsBucketInProject(*project, scratchBucketName) {
			anonymizedErrorMessage := "Scratch bucket %q is not in project %q"
			substitutions := []interface{}{scratchBucketName, *project}
			if removeFileWhenScratchNotOwned && strings.HasPrefix(file, fmt.Sprintf("gs://%s/", scratchBucketName)) {
				err := storageClient.DeleteObject(file)
				if err == nil {
					anonymizedErrorMessage += ". Deleted %q"
					substitutions = append(substitutions, file)
				} else {
					anonymizedErrorMessage += ". Failed to delete %q: %v. " +
						"Check with the owner of gs://%q for more information"
					substitutions = append(substitutions, file, err, scratchBucketName)
				}
			}
			return "", daisy.Errf(anonymizedErrorMessage, substitutions...)
		}
		scratchBucketAttrs, err := storageClient.GetBucketAttrs(scratchBucketName)
		if err == nil {
			scratchBucketRegion = scratchBucketAttrs.Location
		}
	}
	return scratchBucketRegion, nil
}
populateScratchBucketGcsPath validates the scratch bucket, creating a new one if not
provided, and returns the region of the scratch bucket. If the scratch bucket is
already populated, and the owning project doesn't match `project`, then an error is returned.
In that case, if `file` resides in the non-owned scratch bucket and `removeFileWhenScratchNotOwned`
is specified, then `file` is deleted from GCS.
package param
import (
	"context"
	"fmt"
	"regexp"
	"strings"
	"google.golang.org/api/option"
	"github.com/GoogleCloudPlatform/compute-image-tools/cli_tools/common/domain"
	"github.com/GoogleCloudPlatform/compute-image-tools/cli_tools/common/utils/paramhelper"
	"github.com/GoogleCloudPlatform/compute-image-tools/cli_tools/common/utils/storage"
	"github.com/GoogleCloudPlatform/compute-image-tools/cli_tools/common/utils/validation"
	"github.com/GoogleCloudPlatform/compute-image-tools/daisy"
	"github.com/GoogleCloudPlatform/compute-image-tools/daisy/compute"
)
func GetProjectID(mgce domain.MetadataGCEInterface, projectFlag string) (string, error) {
	if projectFlag == "" {
		if !mgce.OnGCE() {
			return "", daisy.Errf("project cannot be determined because build is not running on GCE")
		}
		aProject, err := mgce.ProjectID()
		if err != nil || aProject == "" {
			return "", daisy.Errf("project cannot be determined %v", err)
		}
		return aProject, nil
	}
	return projectFlag, nil
}