#pragma warning disable CS1998
        public async Task ReleaseContainerInstance(ContainerInstanceReference containerInstance)
        {
            _ = containerInstance ?? throw new ArgumentNullException("Container instance reference cannot be null.");
            var foundInstance = GetExistingInstanceByName(containerInstance.Name);

            foundInstance.Available = true;
        }
        public async Task StopContainerGroupAsync(ContainerInstanceReference containerInstance, ILogger log)
        {
            _ = containerInstance ?? throw new ArgumentNullException("Container instance reference cannot be null.");
            var aci = await GetContainerGroupAsync(containerInstance, log);

            await aci.StopAsync();
        }
        #pragma warning disable CS1998
        public async Task <ContainerInstanceReference> ReserveEmptyContainerGroupReference(string name)
        {
            var instance = new ContainerInstanceReference()
            {
                Name = name
            };

            Instances.Add(instance);
            return(instance);
        }
        public async Task StartContainerGroupAsync(ContainerInstanceReference containerInstance, ILogger log)
        {
            _ = containerInstance ?? throw new ArgumentNullException("Container instance reference cannot be null.");
            log.LogInformation("(Re)Starting container instance from exsiting registration...");

            await _azure.ContainerGroups.StartAsync(containerInstance.ResourceGroupName, containerInstance.Name);

            var containerGroup = await _azure.ContainerGroups.GetByIdAsync(containerInstance.InstanceId);

            await RunStateVerify(containerGroup, 5000, log);

            containerInstance.IpAddress = containerGroup.Refresh().IPAddress;
            log.LogInformation("Container instance made available.");
        }
        private async Task <ContainerInstanceReference> CreateNewContainer(
            ContainerInstanceReference instanceReference,
            string commandLine
            )
        {
            var acrHost           = _config["ACRHost"];
            var acrImageName      = _config["ACRImgName"];
            var resourceGroupName = _config["ACIResourceGroup"];

            _ = acrHost ?? throw new ArgumentNullException("ACR Host cannot be null");
            _ = acrImageName ?? throw new ArgumentNullException("ACR Image Name cannot be null");
            _ = resourceGroupName ?? throw new ArgumentNullException("Resource Group name cannot be null");

            _log.LogWarning("No previous container instances available. Creating new one...");
            var containerGroup = await _containerRunner.CreateContainerGroupAsync(instanceReference.Name,
                                                                                  resourceGroupName,
                                                                                  $"{acrHost}/{acrImageName}",
                                                                                  commandLine,
                                                                                  _log);

            return(containerGroup);
        }
        public async Task <string> SendRequestToContainerInstance(ContainerInstanceReference containerInstance, string path, string content, ILogger log)
        {
            var url = $"http://{containerInstance.IpAddress}:{containerInstance.ExternalPort}{path}";

            log.LogWarning(url);
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    var method  = new HttpMethod("GET");
                    var request = new HttpRequestMessage(method, url);

                    if (content != null && content != string.Empty)
                    {
                        method = new HttpMethod("POST");

                        log.LogWarning(content);

                        request = new HttpRequestMessage(method, url)
                        {
                            Content = new StringContent(content, Encoding.UTF8, "application/json")
                        };
                    }

                    using (HttpResponseMessage response = client.SendAsync(request).Result)
                    {
                        response.EnsureSuccessStatusCode();
                        return(await response.Content.ReadAsStringAsync());
                    }
                }
            }
            catch (Exception ex)
            {
                throw new UnableToRecoverException(ex.Message);
            }
        }
 public async Task StopContainerActivityAsync([ActivityTrigger] ContainerInstanceReference containerInstance)
 {
     await _containerRunner.StopContainerGroupAsync(containerInstance, _log);
 }
示例#8
0
        public async Task <bool> RunSubOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            ContainerInstanceReference instanceRef = null;
            var entityId = new EntityId("ContainerInstanceStatusEntity", "ContainerInstanceStatusEntity");
            var entity   = context.CreateEntityProxy <IContainerInstanceStatusEntity>(entityId);

            try
            {
                var retryOptions = new RetryOptions(TimeSpan.FromSeconds(15), 5)
                {
                    BackoffCoefficient = 1.5,
                    Handle             = (ex) => ex.InnerException.Message == TriggerRetryException.DefaultMessage
                };

                _log.LogInformation("Starting new orchestration run...");

                var blobPayload = context.GetInput <EventGridEventPayload>();

                var containerGroupPrefix = _configuration["ContainerGroupPrefix"] ?? "aci-container-group";

                var containerGroupName = SdkContext.RandomResourceName($"{containerGroupPrefix}-", 6);

                var instanceCount = 0;
                ContainerInstanceReference instance = null;

                using (await context.LockAsync(entityId))
                {
                    instance = await entity.GetNextAvailableContainerGroupAsync();

                    if (instance == null)
                    {
                        instanceCount = await entity.GetContainerGroupCountAsync();

                        var maxInstances = int.Parse(_configuration["MaxNumberOfInstances"]);

                        if (instanceCount >= maxInstances)
                        {
                            _log.LogInformation("Maximum number of parallel container instances reached. Triggering retry.");
                            throw new TriggerRetryException();
                        }

                        instance = await entity.ReserveEmptyContainerGroupReference(containerGroupName);
                    }
                }

                bool isNew;
                (isNew, instanceRef) = await context.CallActivityWithRetryAsync <(bool, ContainerInstanceReference)>(
                    "Container_Setup_Activity",
                    retryOptions,
                    (instance, string.Empty)
                    );

                if (isNew)
                {
                    using (await context.LockAsync(entityId))
                    {
                        await entity.FillEmptyContainerGroupReference(instanceRef);
                    }
                }

                var externalEventTriggerEventName = _configuration["WorkDoneCallbackKeyword"];

                var response = await context.CallActivityWithRetryAsync <string>(
                    "Container_StartWork_Activity",
                    retryOptions,
                    (
                        context.InstanceId,
                        externalEventTriggerEventName,
                        blobPayload.Data.Url,
                        instanceRef
                    )
                    );

                var workDoneEvent = await context.WaitForExternalEvent <ContainerResponse>(externalEventTriggerEventName);

                if (!workDoneEvent.Success)
                {
                    throw new TriggerRetryException();
                }

                _log.LogInformation("Work done successfully");

                await context.CallActivityAsync("Container_Stop_Activity", instanceRef);

                await entity.ReleaseContainerInstance(instanceRef);

                return(true);
            }
            catch (Exception ex)
            {
                var rethrowEx = ex;
                if (ex is TriggerRetryException)
                {
                    _log.LogWarning("Container was unable to execute tasks. Triggering retry.");
                    throw ex;
                }

                if (instanceRef != null)
                {
                    _log.LogWarning("Shutting down container instance due to unrecoverable error.");
                    await context.CallActivityAsync("Container_Stop_Activity", instanceRef);

                    await entity.ReleaseContainerInstance(instanceRef);
                }

                throw rethrowEx;
            }
        }
        #pragma warning disable CS1998
        public async Task FillEmptyContainerGroupReference(ContainerInstanceReference containerReference)
        {
            var idx = Instances.FindIndex(instance => instance.Name == containerReference.Name);

            Instances[idx] = containerReference;
        }
 public async Task <IContainerGroup> GetContainerGroupAsync(ContainerInstanceReference containerInstance, ILogger log)
 {
     _ = containerInstance ?? throw new ArgumentNullException("Container instance reference cannot be null.");
     return(await _azure.ContainerGroups.GetByIdAsync(containerInstance.InstanceId));
 }