Beispiel #1
0
        public sealed override bool Execute()
        {
            try
            {
                HelixApi     = GetHelixApi();
                AnonymousApi = ApiFactory.GetAnonymous(BaseUri);
                System.Threading.Tasks.Task.Run(() => ExecuteCore(_cancel.Token)).GetAwaiter().GetResult();
            }
            catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Unauthorized)
            {
                Log.LogError(FailureCategory.Build, "Helix operation returned 'Unauthorized'. Did you forget to set HelixAccessToken?");
            }
            catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Forbidden)
            {
                Log.LogError(FailureCategory.Build, "Helix operation returned 'Forbidden'.");
            }
            catch (OperationCanceledException ocex) when(ocex.CancellationToken == _cancel.Token)
            {
                // Canceled
                return(false);
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(FailureCategory.Helix, ex, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
Beispiel #2
0
        public async Task <IActionResult> GetAgentDefinition(string agentDefinitionId)
        {
            try
            {
                _logger.LogTrace($"Looking helix queue named {agentDefinitionId}");

                IHelixApi api       = GetHelixApi(false);
                var       queueInfo = await api.Information.QueueInfoAsync(agentDefinitionId);

                // Filter the queue info based on the allowable helix queues.
                if (!IsAllowableQueue(queueInfo))
                {
                    return(NotFound());
                }

                return(new JsonResult(
                           new AgentDefinitionItem(queueInfo, GetAgentDefinitionUrl(queueInfo.QueueId))
                           ));
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"Failed to obtain information on Helix queue {agentDefinitionId}");
                return(BadRequest());
            }
        }
Beispiel #3
0
        public async Task <IActionResult> ListAgentDefinitions()
        {
            try
            {
                _logger.LogTrace($"Looking up available helix queues.");

                using (IHelixApi api = GetHelixApi(false))
                {
                    var helixQueues = await api.Information.QueueInfoListAsync();

                    AgentDefinitionsItem agentDefinitions = new AgentDefinitionsItem()
                    {
                        value = helixQueues.Where(q => IsAllowableQueue(q))
                                .Select <QueueInfo, AgentDefinitionItem>(q =>
                                                                         new AgentDefinitionItem(q, GetAgentDefinitionUrl(q.QueueId))).ToList()
                    };
                    return(new JsonResult(agentDefinitions));
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"Failed to obtain information on available Helix queues");
                return(BadRequest());
            }
        }
Beispiel #4
0
        public async Task <IActionResult> GetAgentRequestStatus([FromBody] AgentRequestStatusItem agentRequestStatusItem)
        {
            // Need to know the job correlation id and work item id.
            // Work item id is the agent id, and job correlation is in the agent data.
            string workItemId    = agentRequestStatusItem.agentId;
            string correlationId = agentRequestStatusItem.agentData.correlationId;

            WorkItemDetails workItemDetails;

            try
            {
                _logger.LogTrace($"Looking up work item details for agent {workItemId} in Helix Job {correlationId}");

                using (IHelixApi api = GetHelixApi(agentRequestStatusItem.agentData.isPublicQueue))
                {
                    workItemDetails = await api.WorkItem.DetailsAsync(correlationId, workItemId);
                }
            }
            catch (Exception e)
            {
                _logger.LogError($"Failed to find work item {workItemId} in Helix Job {correlationId}:{Environment.NewLine}{e.ToString()}");
                return(BadRequest());
            }

            _logger.LogTrace($"Work item {workItemId} in Helix job {correlationId} is {workItemDetails.State}");

            switch (workItemDetails.State.ToLowerInvariant())
            {
            case "running":
            case "finished":
            case "passed":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Helix work item in job {correlationId} for agent {workItemId} was picked up by machine {workItemDetails.MachineName} and is {workItemDetails.State}"
                }));

            case "unscheduled":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Helix work item in job {correlationId} for agent {workItemId} is currently {workItemDetails.State} or does not exist."
                }));

            case "waiting":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Helix work item in job {correlationId} for agent {workItemId} is currently waiting for a machine."
                }));

            case "failed":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Helix work item in job {correlationId} for agent {workItemId} failed.  Please check the logs."
                }));

            default:
                throw new NotImplementedException(
                          $"Got unexpected state '{workItemDetails.State}' for agent {workItemId} in job {correlationId}");
            }
        }
Beispiel #5
0
        /// <summary>
        /// Get the HelixApi based on the settings of this pool provider
        /// </summary>
        /// <returns>For now, just an unauthenticated api client</returns>
        private IHelixApi GetHelixApi()
        {
            IHelixApi api = ApiFactory.GetAuthenticated(_configuration.ApiAuthorizationPat);

            // Alter the base URI based on configuration.  It's also useful to note that in the current version of the API, the endpoint isn't
            // defaulted to https, and so unless this is done every request will fail.
            api.BaseUri = new Uri(_configuration.HelixEndpoint);
            return(api);
        }
Beispiel #6
0
 protected HelixJobCreator(AgentAcquireItem agentRequestItem, QueueInfo queueInfo, IHelixApi api,
                           ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment,
                           Config configuration)
 {
     _agentRequestItem = agentRequestItem;
     _queueInfo        = queueInfo;
     _api                = api;
     _logger             = loggerFactory.CreateLogger <HelixJobCreator>();
     _configuration      = configuration;
     _hostingEnvironment = hostingEnvironment;
 }
Beispiel #7
0
 public sealed override bool Execute()
 {
     try
     {
         HelixApi = GetHelixApi();
         return(System.Threading.Tasks.Task.Run(ExecuteCore).GetAwaiter().GetResult());
     }
     catch (Exception ex)
     {
         Log.LogErrorFromException(ex, true, true, null);
         return(false);
     }
 }
Beispiel #8
0
        public sealed override bool Execute()
        {
            try
            {
                HelixApi     = GetHelixApi();
                AnonymousApi = ApiFactory.GetAnonymous(BaseUri);
                System.Threading.Tasks.Task.Run(() => ExecuteCore(_cancel.Token)).GetAwaiter().GetResult();
            }
            catch (RestApiException ex) when(ex.Response.Status == (int)HttpStatusCode.Unauthorized)
            {
                Log.LogError(FailureCategory.Build, "Helix operation returned 'Unauthorized'. Did you forget to set HelixAccessToken?");
            }
            catch (RestApiException ex) when(ex.Response.Status == (int)HttpStatusCode.Forbidden)
            {
                Log.LogError(FailureCategory.Build, "Helix operation returned 'Forbidden'.");
            }
            catch (OperationCanceledException ocex) when(ocex.CancellationToken == _cancel.Token)
            {
                // Canceled
                return(false);
            }
            catch (ArgumentException argEx) when(argEx.Message.StartsWith("Helix API does not contain an entry "))
            {
                if (FailOnMissingTargetQueue)
                {
                    Log.LogError(FailureCategory.Build, argEx.Message);
                }
                else
                {
                    Log.LogWarning($"{argEx.Message} (FailOnMissingTargetQueue is false, so this is just a warning.)");
                }
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(FailureCategory.Helix, ex, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
Beispiel #9
0
        public sealed override bool Execute()
        {
            try
            {
                HelixApi = GetHelixApi();
                System.Threading.Tasks.Task.Run(ExecuteCore).GetAwaiter().GetResult();
            }
            catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Unauthorized)
            {
                Log.LogError("Helix operation returned 'Unauthorized'. Did you forget to set HelixAccessToken?");
            }
            catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Forbidden)
            {
                Log.LogError("Helix operation returned 'Forbidden'.");
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            try
            {
                HelixApi     = GetHelixApi();
                AnonymousApi = ApiFactory.GetAnonymous(BaseUri);

                if (!InAzurePipeline)
                {
                    Log.LogError("This task must be run inside an Azure Pipelines Build");
                }
                else
                {
                    using (var client = CreateHttpClient())
                    {
                        ExecuteCoreAsync(client, _cancel.Token).GetAwaiter().GetResult();
                    }
                }
            }
            catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Unauthorized)
            {
                Log.LogError("Helix operation returned 'Unauthorized'. Did you forget to set HelixAccessToken?");
            }
            catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Forbidden)
            {
                Log.LogError("Helix operation returned 'Forbidden'.");
            }
            catch (OperationCanceledException ocex) when(ocex.CancellationToken == _cancel.Token)
            {
                // Canceled
                return(false);
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
Beispiel #11
0
        public async ValueTask GetHelixPayloads(string jobId, List <string> workItems, string downloadDir)
        {
            if (!Path.IsPathFullyQualified(downloadDir))
            {
                downloadDir = Path.Combine(Environment.CurrentDirectory, downloadDir);
            }

            IHelixApi  helixApi   = _token.IsNone ? ApiFactory.GetAnonymous() : ApiFactory.GetAuthenticated(_token.Token);
            JobDetails jobDetails = await helixApi.Job.DetailsAsync(jobId).ConfigureAwait(false);

            string?jobListFile = jobDetails.JobList;

            if (string.IsNullOrEmpty(jobListFile))
            {
                throw new ArgumentException($"Couldn't find job list for job {jobId}, if it is an internal job, please use a helix access token from https://helix.dot.net/Account/Tokens");
            }

            using MemoryStream memoryStream = await _client.DownloadFileAsync(jobListFile).ConfigureAwait(false);

            using StreamReader reader = new StreamReader(memoryStream);
            string jobListJson = await reader.ReadToEndAsync().ConfigureAwait(false);

            WorkItemInfo[] workItemsInfo = JsonConvert.DeserializeObject <WorkItemInfo[]>(jobListJson);

            if (workItemsInfo.Length > 0)
            {
                Directory.CreateDirectory(downloadDir);
                string correlationDir = Path.Combine(downloadDir, "correlation-payload");
                Directory.CreateDirectory(correlationDir);

                // download correlation payload
                JObject correlationPayload = workItemsInfo[0].CorrelationPayloadUrisWithDestinations ?? new JObject();
                foreach (JProperty property in correlationPayload.Children())
                {
                    string url             = property.Name;
                    Uri    uri             = new Uri(url);
                    string fileName        = uri.Segments[^ 1];
Beispiel #12
0
 public HelixMacOSJobCreator(AgentAcquireItem agentRequestItem, QueueInfo queueInfo, IHelixApi api,
                             ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment,
                             Config configuration)
     : base(agentRequestItem, queueInfo, api, loggerFactory, hostingEnvironment, configuration)
 {
 }
Beispiel #13
0
        public async Task <IActionResult> GetAgentRequestStatus([FromBody] AgentRequestStatusItem agentRequestStatusItem)
        {
            // Need to know the job correlation id and work item id.
            // Work item id is the agent id, and job correlation is in the agent data.
            string workItemId    = agentRequestStatusItem.agentId;
            string correlationId = agentRequestStatusItem.agentData?.correlationId;

            if (string.IsNullOrEmpty(correlationId))
            {
                // This means the call came back before we've provisioned it.  We don't have any meaningful
                // response right now, so return the empty string to reflect "no status".
                _logger.LogInformation("Status request has no agentData, returning empty status");
                return(NoContent());
            }

            WorkItemDetails workItemDetails;

            try
            {
                _logger.LogTrace($"Looking up work item details for agent {workItemId} in Helix Job {correlationId}");

                IHelixApi api = GetHelixApi(agentRequestStatusItem.agentData.isPublicQueue);
                workItemDetails = await api.WorkItem.DetailsAsync(correlationId, workItemId);
            }
            catch (Exception e)
            {
                _logger.LogError($"Failed to find work item {workItemId} in Helix Job {correlationId}:{Environment.NewLine}{e.ToString()}");
                return(BadRequest());
            }

            _logger.LogTrace($"Work item {workItemId} in Helix job {correlationId} is {workItemDetails.State}");

            switch (workItemDetails.State.ToLowerInvariant())
            {
            case "running":
            case "finished":
            case "passed":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Work is in progress or complete. (Helix work item in job {correlationId} for agent {workItemId} was picked up by machine {workItemDetails.MachineName} and is {workItemDetails.State})"
                }));

            case "unscheduled":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Work has been submitted to the Helix API, but has not started yet (Helix work item in job {correlationId} for agent {workItemId} is currently in state '{workItemDetails.State}')"
                }));

            case "waiting":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Work has been submitted to the Helix API, and is waiting for a machine (Helix work item in job {correlationId} for agent {workItemId} is currently waiting for a machine.)"
                }));

            case "failed":
                return(Json(new AgentStatusItem()
                {
                    statusMessage = $"Error state: Please contact dnceng with Job Id (Helix work item in job {correlationId} for agent {workItemId} failed. Please check the logs.)"
                }));

            default:
                throw new NotImplementedException(
                          $"Got unexpected state '{workItemDetails.State}' for agent {workItemId} in job {correlationId}");
            }
        }
Beispiel #14
0
 public HelixLinuxOSJobCreator(AgentAcquireItem agentRequestItem, QueueInfo queueInfo, IHelixApi api,
                               ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment,
                               Config configuration, string orchestrationId, string jobName)
     : base(agentRequestItem, queueInfo, api, loggerFactory, hostingEnvironment, configuration, orchestrationId, jobName)
 {
 }
Beispiel #15
0
 public ApiBlobHelper(IStorage helixApiStorage)
 {
     _helixApiStorage = helixApiStorage;
     _helixApi        = ((IServiceOperations <HelixApi>)helixApiStorage).Client;
 }
Beispiel #16
0
 public HelixBase()
 {
     _api = ApiFactory.GetAuthenticated(GetEnvironmentVariable("MONO_HELIX_API_KEY"));
 }