public async Task PushArtifactAsync(Configuration.RootConfiguration configuration, OciArtifactModuleReference moduleReference, StreamDescriptor config, params StreamDescriptor[] layers)
        {
            // TODO: How do we choose this? Does it ever change?
            var algorithmIdentifier = DescriptorFactory.AlgorithmIdentifierSha256;

            var blobClient = this.CreateBlobClient(configuration, moduleReference);

            config.ResetStream();
            var configDescriptor = DescriptorFactory.CreateDescriptor(algorithmIdentifier, config);

            config.ResetStream();
            var configUploadResult = await blobClient.UploadBlobAsync(config.Stream);

            var layerDescriptors = new List <OciDescriptor>(layers.Length);

            foreach (var layer in layers)
            {
                layer.ResetStream();
                var layerDescriptor = DescriptorFactory.CreateDescriptor(algorithmIdentifier, layer);
                layerDescriptors.Add(layerDescriptor);

                layer.ResetStream();
                var layerUploadResult = await blobClient.UploadBlobAsync(layer.Stream);
            }

            var manifest = new OciManifest(2, configDescriptor, layerDescriptors);

            using var manifestStream = new MemoryStream();
            OciSerialization.Serialize(manifestStream, manifest);

            manifestStream.Position = 0;
            // BUG: the client closes the stream :( (is it still the case?)
            var manifestUploadResult = await blobClient.UploadManifestAsync(manifestStream, new UploadManifestOptions { Tag = moduleReference.Tag });
        }
示例#2
0
 private static OciManifest DeserializeManifest(Stream stream)
 {
     try
     {
         return(OciSerialization.Deserialize <OciManifest>(stream));
     }
     catch (Exception exception)
     {
         throw new InvalidModuleException("Unable to deserialize the module manifest.", exception);
     }
 }
        protected override void WriteModuleContent(OciArtifactModuleReference reference, OciArtifactResult result)
        {
            /*
             * this should be kept in sync with the IsModuleRestoreRequired() implementation
             */

            // write main.bicep
            this.FileResolver.Write(this.GetModuleFileUri(reference, ModuleFileType.ModuleMain), result.ModuleStream);

            // write manifest
            // it's important to write the original stream here rather than serialize the manifest object
            // this way we guarantee the manifest hash will match
            this.FileResolver.Write(this.GetModuleFileUri(reference, ModuleFileType.Manifest), result.ManifestStream);

            // write metadata
            var metadata = new ModuleMetadata(result.ManifestDigest);
            using var metadataStream = new MemoryStream();
            OciSerialization.Serialize(metadataStream, metadata);
            metadataStream.Position = 0;
            this.FileResolver.Write(this.GetModuleFileUri(reference, ModuleFileType.Metadata), metadataStream);
        }
        public AndConstraint <MockRegistryAssertions> HaveModule(string tag, Stream expectedModuleContent)
        {
            using (new AssertionScope())
            {
                this.Subject.ManifestTags.Should().ContainKey(tag, $"tag '{tag}' should exist");

                string manifestDigest = this.Subject.ManifestTags[tag];

                this.Subject.Manifests.Should().ContainKey(manifestDigest, $"tag '{tag}' resolves to digest '{manifestDigest}' that should exist");

                var manifestBytes = this.Subject.Manifests[manifestDigest];
                using var manifestStream = MockRegistryBlobClient.WriteStream(manifestBytes);
                var manifest = OciSerialization.Deserialize <OciManifest>(manifestStream);

                var config = manifest.Config;
                config.MediaType.Should().Be("application/vnd.ms.bicep.module.config.v1+json", "config media type should be correct");
                config.Size.Should().Be(0, "config should be empty");

                this.Subject.Blobs.Should().ContainKey(config.Digest, "config digest should exist");

                var configBytes = this.Subject.Blobs[config.Digest];
                configBytes.Should().BeEmpty("config should be empty");

                manifest.Layers.Should().HaveCount(1, "modules should have a single layer");
                var layer = manifest.Layers.Single();

                layer.MediaType.Should().Be("application/vnd.ms.bicep.module.layer.v1+json", "layer media type should be correct");
                this.Subject.Blobs.Should().ContainKey(layer.Digest);

                var layerBytes = this.Subject.Blobs[layer.Digest];
                ((long)layerBytes.Length).Should().Be(layer.Size);

                var actual   = MockRegistryBlobClient.WriteStream(layerBytes).FromJsonStream <JToken>();
                var expected = expectedModuleContent.FromJsonStream <JToken>();

                actual.Should().DeepEqual(expected, "module content should match");
            }

            return(new(this));
        }