private async Task <string> GetLocationAsync(Component component, Guid subscriptionId, int runnerCPU, int runnerMemory, bool usePairedRegion = false) { var tenantId = await azureSessionService .GetTenantIdAsync() .ConfigureAwait(false); var organization = await organizationRepository .GetAsync(tenantId.ToString(), component.Organization) .ConfigureAwait(false); var location = organization.Location; if (usePairedRegion || !await IsRegionCapableAsync(location)) { var subscription = await azureResourceService .GetSubscriptionAsync(subscriptionId) .ConfigureAwait(false); var region = await subscription .GetRegionsAsync() .SingleOrDefaultAsync(r => r.Name.Equals(location)) .ConfigureAwait(false); if (region?.Paired is not null) { var pairedInfo = region.Paired .Select(pr => new { Region = pr, Capable = IsRegionCapableAsync(pr) }); await pairedInfo .Select(pi => pi.Capable) .WhenAll() .ConfigureAwait(false); location = pairedInfo .FirstOrDefault(pi => pi.Capable.Result)?.Region ?? location; } } return(location); async Task <bool> IsRegionCapableAsync(string region) { var capabilities = AzureContainerGroupResource .GetCapabilitiesAsync(azureResourceService, subscriptionId, region); return(await capabilities .AnyAsync(c => c.OsType.Equals("Linux", StringComparison.OrdinalIgnoreCase) && c.Gpu.Equals("None", StringComparison.OrdinalIgnoreCase) && c.CapabilitiesProperty.MaxCpu >= runnerCPU && c.CapabilitiesProperty.MaxMemoryInGB >= runnerMemory) .ConfigureAwait(false)); } }
public async Task <ComponentTask> Run( [ActivityTrigger] IDurableActivityContext context, ILogger log) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (log is null) { throw new ArgumentNullException(nameof(log)); } var componentTask = context.GetInput <Input>().ComponentTask; try { if (AzureResourceIdentifier.TryParse(componentTask.ResourceId, out var resourceId)) { if (!componentTask.TaskState.IsFinal()) { componentTask.TaskState = TaskState.Failed; componentTask = await componentTaskRepository .SetAsync(componentTask) .ConfigureAwait(false); } var containerGroup = await azureResourceService .GetResourceAsync <AzureContainerGroupResource>(resourceId.ToString()) .ConfigureAwait(false); if (containerGroup is not null) { try { await containerGroup .StopAsync() .ConfigureAwait(false); } catch { // swallow } finally { var location = await containerGroup .GetLocationAsync() .ConfigureAwait(false); var usageData = await AzureContainerGroupResource .GetUsageAsync(azureResourceService, containerGroup.ResourceId.SubscriptionId, location) .ConfigureAwait(false); var usage = usageData .SingleOrDefault(u => u.Unit.Equals("Count") && u.Name.Value.Equals("ContainerGroups")); var limit = usage?.Limit.GetValueOrDefault() ?? 0; var current = usage?.CurrentValue.GetValueOrDefault() ?? 0; if (current >= limit) { await containerGroup .DeleteAsync() .ConfigureAwait(false); } } } } } catch (Exception exc) { throw exc.AsSerializable(); } return(componentTask); }