예제 #1
0
        public override async Task DoRequestAsync(IndexRequest request)
        {
            try
            {
                RegistryCredentials credentials = null;

                // if the request was submitted by a user, it must have auth info included
                if (!string.IsNullOrEmpty(request.Authorization))
                {
                    var authResult = authDecoder.AuthenticateAsync(request.Authorization).Result;
                    if (authResult.Succeeded)
                    {
                        credentials = authResult.Principal.ToRegistryCredentials();
                    }
                }
                // if the request came via an event sink, there is no auth provided, and we need to have a default user configured
                else
                {
                    credentials = config.GetCatalogCredentials() ?? throw new ArgumentException("The indexing request had no included authorization, and no default catalog user is configured.");
                }

                if (credentials == null)
                {
                    logger.LogWarning("Authorization failed for the work item. A token may have expired since it was first submitted.");
                }
                else
                {
                    await authHandler.LoginAsync(credentials);

                    var client = clientFactory.GetClient(authHandler);

                    // if deep indexing is configured, ignore target paths
                    if (config.DeepIndexing)
                    {
                        request.TargetPaths = new string[0];
                    }

                    var imageSet = await client.GetImageSetAsync(request.TargetRepo, request.TargetDigest);

                    if ((imageSet?.Images?.Count() ?? 0) != 1)
                    {
                        throw new Exception($"Couldn't find a valid image for {request.TargetRepo}:{request.TargetDigest}");
                    }
                    var image = imageSet.Images.First();

                    using (var @lock = await cacheFactory.Get <object>().TakeLockAsync($"idx:{image.Digest}", TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)))
                    {
                        if (!indexStore.IndexExists(image.Digest, request.TargetPaths.ToArray()))
                        {
                            logger.LogInformation($"Starting index for {request.TargetRepo}:{request.TargetDigest}");
                            var indexes = client.GetIndexes(request.TargetRepo, image, request.TargetPaths.ToArray());
                            indexStore.SetIndex(indexes, image.Digest, request.TargetPaths.ToArray());
                            logger.LogInformation($"Completed indexing {indexes.Max(i => i.Depth)} layer(s) from {request.TargetRepo}:{request.TargetDigest} {(request.TargetPaths.Count() == 0 ? "" : $"({string.Join(", ", request.TargetPaths)})")}");
                        }
                        else
                        {
                            logger.LogInformation($"Index already exists for {request.TargetRepo}:{request.TargetDigest}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"Processing failed for work item\n {Newtonsoft.Json.JsonConvert.SerializeObject(request)}");
            }
        }
예제 #2
0
        public async Task <IActionResult> GetFilesAsync(string repository, string digest, string targets)
        {
            if (string.IsNullOrEmpty(digest))
            {
                return(BadRequest("An image digest is required."));
            }
            if (!digest.IsDigest())
            {
                return(BadRequest("Digest appears invalid."));
            }

            try
            {
                if (string.IsNullOrEmpty(RegistryCredentials.Registry))
                {
                    return(BadRequest("Session is missing registry information. Try creating a new session."));
                }

                var targetList = string.IsNullOrEmpty(targets) ? Array.Empty <string>() : targets.Split(';');

                var client   = clientFactory.GetClient(AuthHandler);
                var imageSet = await client.GetImageSetAsync(repository, digest);

                if (imageSet.Images.Count() != 1)
                {
                    return(NotFound("No image was found with the given digest."));
                }

                // if we have a complete index, return it
                if (indexStore.IndexExists(digest))
                {
                    return(Ok(indexStore.GetIndex(digest)));
                }
                // otherwise, if they've requested a targeted index, look for that
                else if (indexStore.IndexExists(digest, targetList))
                {
                    return(Ok(indexStore.GetIndex(digest, targetList)));
                }
                // no dice, queue an indexing request
                else
                {
                    var request = new IndexRequest
                    {
                        Authorization = Request.Headers["Authorization"],
                        CreatedTime   = DateTime.UtcNow,
                        TargetRepo    = repository,
                        TargetDigest  = digest,
                        TargetPaths   = targetList
                    };
                    if (!indexQueue.Contains(request))
                    {
                        indexQueue.Push(request);
                    }

                    return(StatusCode(202, new { Status = RequestStatus.Pending }));
                }
            }
            catch (RedisConnectionException)
            {
                return(StatusCode(503, "Cannot access cache"));
            }
            catch (Client.NotFoundException)
            {
                return(NotFound());
            }
            catch (Client.AuthenticationException)
            {
                return(Unauthorized());
            }
        }