public static async Task CreateOrStartInstanceAsync()

in sources/Google.Solutions.Testing.Apis/Integration/InstanceFactory.cs [113:261]


        public static async Task<InstanceLocator> CreateOrStartInstanceAsync(
            string name,
            string machineType,
            string imageFamily,
            bool publicIp,
            InstanceServiceAccount serviceAccount,
            IEnumerable<Metadata.ItemsData> metadataItems)
        {
            var computeEngine = TestProject.CreateComputeService();

            var metadata = new Metadata()
            {
                Items = new List<Metadata.ItemsData>(metadataItems.ToList())
            };

            // Add metadata that marks this instance as temporary.
            metadata.Add("type", "auto-cleanup");
            metadata.Add("ttl", "120"); // minutes

            var locator = new InstanceLocator(
                TestProject.ProjectId,
                TestProject.Zone,
                name);

            try
            {
                CommonTraceSource.Log.TraceVerbose(
                    "Trying to create new instance {0}...", name);

                IList<ServiceAccount>? serviceAccounts = null;
                if (serviceAccount == InstanceServiceAccount.ComputeDefault)
                {
                    serviceAccounts = new List<ServiceAccount>()
                    {
                        new ServiceAccount()
                        {
                            Email = await GetComputeEngineDefaultServiceAccountAsync()
                                .ConfigureAwait(true),
                            Scopes = new [] { Scopes.Cloud }
                        }
                    };
                }

                await computeEngine.Instances
                    .Insert(
                        new Google.Apis.Compute.v1.Data.Instance()
                        {
                            Name = name,
                            MachineType = $"zones/{locator.Zone}/machineTypes/{machineType}",
                            Disks = new[]
                            {
                                new AttachedDisk()
                                {
                                    AutoDelete = true,
                                    Boot = true,
                                    InitializeParams = new AttachedDiskInitializeParams()
                                    {
                                        SourceImage = imageFamily
                                    }
                                }
                            },
                            Metadata = metadata,
                            NetworkInterfaces = new[]
                            {
                                new NetworkInterface()
                                {
                                    AccessConfigs = publicIp
                                        ? new [] { new AccessConfig() }
                                        : null
                                }
                            },
                            Scheduling = new Scheduling()
                            {
                                Preemptible = true
                            },
                            ServiceAccounts = serviceAccounts
                        },
                        locator.ProjectId,
                        locator.Zone)
                    .ExecuteAsync()
                    .ConfigureAwait(true);

                await AwaitInstanceCreatedAndReadyAsync(
                        computeEngine.Instances,
                        locator)
                    .ConfigureAwait(true);

                return locator;
            }
            catch (GoogleApiException e) when (e.Error != null && e.Error.Code == 409)
            {
                // Instance already exists - make sure it's running then.
                var instance = await computeEngine.Instances
                    .Get(
                        locator.ProjectId,
                        locator.Zone,
                        locator.Name)
                    .ExecuteAsync()
                    .ConfigureAwait(true);

                if (instance.Status == "RUNNING" ||
                    instance.Status == "PROVISIONING" ||
                    instance.Status == "STAGING")
                {
                    CommonTraceSource.Log.TraceVerbose(
                        "Instance {0} exists and is running...", locator.Name);

                    await AwaitInstanceCreatedAndReadyAsync(
                            computeEngine.Instances,
                            locator)
                        .ConfigureAwait(true);
                    return locator;
                }
                else if (instance.Status == "TERMINATED")
                {
                    CommonTraceSource.Log.TraceVerbose(
                        "Instance {0} exists, but is TERMINATED, starting...", locator.Name);

                    // Reapply metadata.
                    await computeEngine.Instances.AddMetadataAsync(
                            locator,
                            metadata,
                            CancellationToken.None)
                        .ConfigureAwait(true);

                    await computeEngine.Instances.Start(
                            locator.ProjectId,
                            locator.Zone,
                            locator.Name)
                        .ExecuteAsync()
                        .ConfigureAwait(true);

                    await AwaitInstanceCreatedAndReadyAsync(
                            computeEngine.Instances,
                            locator)
                        .ConfigureAwait(true);
                    return locator;
                }
                else
                {
                    CommonTraceSource.Log.TraceError(
                        "Creating instance {0} failed, current status is {1}",
                        locator.Name,
                        instance.Status);
                    CommonTraceSource.Log.TraceError(e);
                    throw;
                }
            }
        }