Пример #1
0
        public async Task TestHandleResponseAsync()
        {
            using (MemoryStream blobContent = new MemoryStream(Encoding.UTF8.GetBytes("some BLOB content")))
            {
                BlobDescriptor descriptor = await Digests.ComputeDigestAsync(blobContent).ConfigureAwait(false);

                DescriptorDigest testBlobDigest = descriptor.GetDigest();
                blobContent.Position = 0;

                using (HttpResponseMessage mockResponse = new HttpResponseMessage()
                {
                    Content = new StringContent("some BLOB content")
                })
                {
                    LongAdder  byteCount  = new LongAdder();
                    BlobPuller blobPuller =
                        new BlobPuller(
                            fakeRegistryEndpointRequestProperties,
                            testBlobDigest,
                            layerOutputStream,
                            size => Assert.AreEqual("some BLOB content".Length, size),
                            byteCount.Add);
                    await blobPuller.HandleResponseAsync(mockResponse).ConfigureAwait(false);

                    Assert.AreEqual(
                        "some BLOB content",
                        Encoding.UTF8.GetString(layerContentOutputStream.ToArray()));
                    Assert.AreEqual(testBlobDigest, layerOutputStream.ComputeDigest().GetDigest());
                    Assert.AreEqual("some BLOB content".Length, byteCount.Sum());
                }
            }
        }
Пример #2
0
        /**
         * Writes an uncompressed {@code layerBlob} to the {@code layerDirectory}.
         *
         * @param uncompressedLayerBlob the uncompressed layer {@link Blob}
         * @param layerDirectory the directory for the layer
         * @return a {@link WrittenLayer} with the written layer information
         * @throws IOException if an I/O exception occurs
         */
        private async Task <WrittenLayer> WriteUncompressedLayerBlobToDirectoryAsync(
            IBlob uncompressedLayerBlob, SystemPath layerDirectory)
        {
            using (TemporaryFile temporaryLayerFile = CacheStorageFiles.GetTemporaryLayerFile(layerDirectory))
            {
                DescriptorDigest layerDiffId;
                BlobDescriptor   blobDescriptor;

                // Writes the layer with GZIP compression. The original bytes are captured as the layer's
                // diff ID and the bytes outputted from the GZIP compression are captured as the layer's
                // content descriptor.
                using (CountingDigestOutputStream compressedDigestOutputStream =
                           new CountingDigestOutputStream(
                               Files.NewOutputStream(temporaryLayerFile.Path)))
                {
                    using (GZipStream compressorStream = new GZipStream(compressedDigestOutputStream, CompressionMode.Compress, true))
                    {
                        BlobDescriptor descriptor = await uncompressedLayerBlob.WriteToAsync(compressorStream).ConfigureAwait(false);

                        layerDiffId = descriptor.GetDigest();
                    }
                    // The GZIPOutputStream must be closed in order to write out the remaining compressed data.
                    blobDescriptor = compressedDigestOutputStream.ComputeDigest();
                }
                DescriptorDigest layerDigest = blobDescriptor.GetDigest();
                long             layerSize   = blobDescriptor.GetSize();

                // Renames the temporary layer file to the correct filename.
                SystemPath layerFile = layerDirectory.Resolve(cacheStorageFiles.GetLayerFilename(layerDiffId));
                temporaryLayerFile.MoveIfDoesNotExist(layerFile);

                return(new WrittenLayer(layerDigest, layerDiffId, layerSize));
            }
        }
Пример #3
0
        public async Task TestHandleResponse_unexpectedDigestAsync()
        {
            using (MemoryStream blobContent = new MemoryStream(Encoding.UTF8.GetBytes("some BLOB content")))
            {
                BlobDescriptor descriptor = await Digests.ComputeDigestAsync(blobContent).ConfigureAwait(false);

                DescriptorDigest testBlobDigest = descriptor.GetDigest();
                blobContent.Position = 0;

                using (HttpResponseMessage mockResponse = new HttpResponseMessage()
                {
                    Content = new StringContent("some BLOB content")
                })
                {
                    try
                    {
                        await testBlobPuller.HandleResponseAsync(mockResponse).ConfigureAwait(false);

                        Assert.Fail("Receiving an unexpected digest should fail");
                    }
                    catch (UnexpectedBlobDigestException ex)
                    {
                        Assert.AreEqual(
                            "The pulled BLOB has digest '"
                            + testBlobDigest
                            + "', but the request digest was '"
                            + fakeDigest
                            + "'",
                            ex.Message);
                    }
                }
            }
        }
Пример #4
0
        public async Task TestPullAsync()
        {
            // Pulls the busybox image.
            localRegistry.PullAndPushToLocal("busybox", "busybox");
            RegistryClient registryClient =
                RegistryClient.CreateFactory(EventHandlers.NONE, "localhost:5000", "busybox")
                .SetAllowInsecureRegistries(true)
                .NewRegistryClient();
            V21ManifestTemplate manifestTemplate =
                await registryClient.PullManifestAsync <V21ManifestTemplate>("latest").ConfigureAwait(false);

            DescriptorDigest realDigest = manifestTemplate.GetLayerDigests().First();

            // Pulls a layer BLOB of the busybox image.
            LongAdder totalByteCount = new LongAdder();
            LongAdder expectedSize   = new LongAdder();
            IBlob     pulledBlob     =
                registryClient.PullBlob(
                    realDigest,
                    size =>
            {
                Assert.AreEqual(0, expectedSize.Sum());
                expectedSize.Add(size);
            },
                    totalByteCount.Add);
            BlobDescriptor blobDescriptor = await pulledBlob.WriteToAsync(Stream.Null).ConfigureAwait(false);

            Assert.AreEqual(realDigest, blobDescriptor.GetDigest());
            Assert.IsTrue(expectedSize.Sum() > 0);
            Assert.AreEqual(expectedSize.Sum(), totalByteCount.Sum());
        }
Пример #5
0
        public async Task <BuildResult> CallAsync()
        {
            IReadOnlyList <BlobDescriptor> baseImageDescriptors = await pushBaseImageLayersStep.GetFuture().ConfigureAwait(false);

            IReadOnlyList <BlobDescriptor> appLayerDescriptors = await pushApplicationLayersStep.GetFuture().ConfigureAwait(false);

            BlobDescriptor containerConfigurationBlobDescriptor = await pushContainerConfigurationStep.GetFuture().ConfigureAwait(false);

            ImmutableHashSet <string> targetImageTags = buildConfiguration.GetAllTargetImageTags();


            using (var progressEventDispatcher =
                       progressEventDispatcherFactory.Create("pushing image manifest", this.Index))
                using (var factory =
                           progressEventDispatcher.NewChildProducer()("[child progress]pushing image manifest", targetImageTags.Count))
                    using (TimerEventDispatcher ignored =
                               new TimerEventDispatcher(buildConfiguration.GetEventHandlers(), DESCRIPTION))
                    {
                        RegistryClient registryClient =
                            buildConfiguration
                            .NewTargetImageRegistryClientFactory()
                            .SetAuthorization(await authenticatePushStep.GetFuture().ConfigureAwait(false))
                            .NewRegistryClient();

                        // Constructs the image.
                        ImageToJsonTranslator imageToJsonTranslator =
                            new ImageToJsonTranslator(await buildImageStep.GetFuture().ConfigureAwait(false));

                        // Gets the image manifest to push.
                        IBuildableManifestTemplate manifestTemplate =
                            imageToJsonTranslator.GetManifestTemplate(
                                buildConfiguration.GetTargetFormat(), containerConfigurationBlobDescriptor);

                        // Pushes to all target image tags.
                        IList <Task <DescriptorDigest> > pushAllTagsFutures = new List <Task <DescriptorDigest> >();
                        var idx = 0;
                        ProgressEventDispatcher.Factory progressEventDispatcherFactory =
                            factory.NewChildProducer();
                        foreach (string tag in targetImageTags)
                        {
                            idx++;
                            using (progressEventDispatcherFactory.Create("tagging with " + tag, idx))
                            {
                                buildConfiguration.GetEventHandlers().Dispatch(LogEvent.Info("Tagging with " + tag + "..."));
                                pushAllTagsFutures.Add(registryClient.PushManifestAsync(manifestTemplate, tag));
                            }
                        }

                        DescriptorDigest imageDigest =
                            await Digests.ComputeJsonDigestAsync(manifestTemplate).ConfigureAwait(false);

                        DescriptorDigest imageId = containerConfigurationBlobDescriptor.GetDigest();
                        BuildResult      result  = new BuildResult(imageDigest, imageId);

                        await Task.WhenAll(pushAllTagsFutures).ConfigureAwait(false);

                        return(result);
                    }
        }
Пример #6
0
        /**
         * Gets a {@link BuildResult} from an {@link Image}.
         *
         * @param image the image
         * @param targetFormat the target format of the image
         * @return a new {@link BuildResult} with the image's digest and id
         * @throws IOException if writing the digest or container configuration fails
         */
        public static async Task <BuildResult> FromImageAsync(Image image, ManifestFormat targetFormat)
        {
            ImageToJsonTranslator          imageToJsonTranslator = new ImageToJsonTranslator(image);
            ContainerConfigurationTemplate configurationTemplate = imageToJsonTranslator.GetContainerConfiguration();
            BlobDescriptor containerConfigurationBlobDescriptor  =
                await Digests.ComputeJsonDescriptorAsync(configurationTemplate).ConfigureAwait(false);

            IBuildableManifestTemplate manifestTemplate =
                imageToJsonTranslator.GetManifestTemplate(
                    targetFormat, containerConfigurationBlobDescriptor);
            DescriptorDigest imageDigest =
                await Digests.ComputeJsonDigestAsync(manifestTemplate).ConfigureAwait(false);

            DescriptorDigest imageId = containerConfigurationBlobDescriptor.GetDigest();

            return(new BuildResult(imageDigest, imageId));
        }
Пример #7
0
        /**
         * Gets the manifest as a JSON template. The {@code containerConfigurationBlobDescriptor} must be
         * the {@link BlobDescriptor} obtained by writing out the container configuration JSON returned
         * from {@link #getContainerConfiguration()}.
         *
         * @param <T> child type of {@link BuildableManifestTemplate}.
         * @param manifestTemplateClass the JSON template to translate the image to.
         * @param containerConfigurationBlobDescriptor the container configuration descriptor.
         * @return the image contents serialized as JSON.
         */
        public IBuildableManifestTemplate GetManifestTemplate(
            ManifestFormat manifestFormat, BlobDescriptor containerConfigurationBlobDescriptor)
        {
            containerConfigurationBlobDescriptor =
                containerConfigurationBlobDescriptor
                ?? throw new ArgumentNullException(nameof(containerConfigurationBlobDescriptor));
            try
            {
                IBuildableManifestTemplate template;
                // ISet up the JSON template.
                switch (manifestFormat)
                {
                case ManifestFormat.V22:
                    template = new V22ManifestTemplate();
                    break;

                case ManifestFormat.OCI:
                    template = new OCIManifestTemplate();
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(manifestFormat));
                }
                IBuildableManifestTemplate buildableTemplate = template;

                // Adds the container configuration reference.
                DescriptorDigest containerConfigurationDigest =
                    containerConfigurationBlobDescriptor.GetDigest();
                long containerConfigurationSize = containerConfigurationBlobDescriptor.GetSize();
                buildableTemplate.SetContainerConfiguration(containerConfigurationSize, containerConfigurationDigest);

                // Adds the layers.
                foreach (ILayer layer in image.GetLayers())
                {
                    buildableTemplate.AddLayer(
                        layer.GetBlobDescriptor().GetSize(), layer.GetBlobDescriptor().GetDigest());
                }

                // Serializes into JSON.
                return(template);
            }
            catch (JsonException ex)
            {
                throw new ArgumentException(manifestFormat + " cannot be instantiated", ex);
            }
        }
        public async Task Test_smokeTestAsync()
        {
            foreach (KeyValuePair <string, string> knownHash in KNOWN_SHA256_HASHES)
            {
                string toHash       = knownHash.Key;
                string expectedHash = knownHash.Value;

                byte[] bytesToHash            = Encoding.UTF8.GetBytes(toHash);
                Stream underlyingOutputStream = new MemoryStream();
                using (CountingDigestOutputStream countingDigestOutputStream = new CountingDigestOutputStream(underlyingOutputStream))
                    using (Stream toHashInputStream = new MemoryStream(bytesToHash))
                    {
                        await toHashInputStream.CopyToAsync(countingDigestOutputStream).ConfigureAwait(false);

                        BlobDescriptor blobDescriptor = countingDigestOutputStream.ComputeDigest();
                        Assert.AreEqual(DescriptorDigest.FromHash(expectedHash), blobDescriptor.GetDigest());
                        Assert.AreEqual(bytesToHash.Length, blobDescriptor.GetSize());
                    }
            }
        }
Пример #9
0
        private async Task VerifyCachedLayerAsync(CachedLayer cachedLayer, IBlob uncompressedLayerBlob)
        {
            BlobDescriptor layerBlobDescriptor = await GetDigestAsync(Compress(uncompressedLayerBlob)).ConfigureAwait(false);

            BlobDescriptor layerDiffDescriptor = await GetDigestAsync(uncompressedLayerBlob).ConfigureAwait(false);

            DescriptorDigest layerDiffId = layerDiffDescriptor.GetDigest();

            // Verifies cachedLayer is correct.
            Assert.AreEqual(layerBlobDescriptor.GetDigest(), cachedLayer.GetDigest());
            Assert.AreEqual(layerDiffId, cachedLayer.GetDiffId());
            Assert.AreEqual(layerBlobDescriptor.GetSize(), cachedLayer.GetSize());
            CollectionAssert.AreEqual(
                await Blobs.WriteToByteArrayAsync(uncompressedLayerBlob).ConfigureAwait(false),
                await Blobs.WriteToByteArrayAsync(await DecompressAsync(cachedLayer.GetBlob()).ConfigureAwait(false)).ConfigureAwait(false));

            // Verifies that the files are present.
            Assert.IsTrue(
                Files.Exists(
                    cacheStorageFiles.GetLayerFile(cachedLayer.GetDigest(), cachedLayer.GetDiffId())));
        }
Пример #10
0
        public async Task TestWrite_uncompressedAsync()
        {
            IBlob          uncompressedLayerBlob = Blobs.From("uncompressedLayerBlob");
            BlobDescriptor layerDigestDescriptor = await GetDigestAsync(Compress(uncompressedLayerBlob)).ConfigureAwait(false);

            DescriptorDigest layerDigest        = layerDigestDescriptor.GetDigest();
            BlobDescriptor   selectorDescriptor = await GetDigestAsync(Blobs.From("selector")).ConfigureAwait(false);

            DescriptorDigest selector = selectorDescriptor.GetDigest();

            CachedLayer cachedLayer =
                await new CacheStorageWriter(cacheStorageFiles)
                .WriteUncompressedAsync(uncompressedLayerBlob, selector).ConfigureAwait(false);

            await VerifyCachedLayerAsync(cachedLayer, uncompressedLayerBlob).ConfigureAwait(false);

            // Verifies that the files are present.
            SystemPath selectorFile = cacheStorageFiles.GetSelectorFile(selector);

            Assert.IsTrue(Files.Exists(selectorFile));
            Assert.AreEqual(layerDigest.GetHash(), await Blobs.WriteToStringAsync(Blobs.From(selectorFile)).ConfigureAwait(false));
        }
Пример #11
0
        /** Checks that the {@link Blob} streams the expected string. */
        private async Task VerifyBlobWriteToAsync(string expected, IBlob blob)
        {
            using (MemoryStream outputStream = new MemoryStream())
            {
                BlobDescriptor blobDescriptor = await blob.WriteToAsync(outputStream).ConfigureAwait(false);

                string output = Encoding.UTF8.GetString(outputStream.ToArray());
                Assert.AreEqual(expected, output);

                byte[] expectedBytes = Encoding.UTF8.GetBytes(expected);
                Assert.AreEqual(expectedBytes.Length, blobDescriptor.GetSize());

                using (MemoryStream stream = new MemoryStream(expectedBytes))
                {
                    BlobDescriptor digestDescriptor = await Digests.ComputeDigestAsync(stream).ConfigureAwait(false);

                    DescriptorDigest expectedDigest =
                        digestDescriptor.GetDigest();
                    Assert.AreEqual(expectedDigest, blobDescriptor.GetDigest());
                }
            }
        }
Пример #12
0
        /**
         * Gets the digest of {@code blob}.
         *
         * @param blob the {@link Blob}
         * @return the {@link DescriptorDigest} of {@code blob}
         * @throws IOException if an I/O exception occurs
         */
        private static async Task <DescriptorDigest> DigestOfAsync(IBlob blob)
        {
            BlobDescriptor descriptor = await blob.WriteToAsync(Stream.Null).ConfigureAwait(false);

            return(descriptor.GetDigest());
        }
Пример #13
0
 public DescriptorDigest GetDigest()
 {
     return(blobDescriptor.GetDigest());
 }
Пример #14
0
 public Uri GetApiRoute(string apiRouteBase)
 {
     return(new Uri(
                apiRouteBase + registryEndpointRequestProperties.GetImageName() + "/blobs/" + blobDescriptor.GetDigest()));
 }