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;
}
}
}