Ejemplo n.º 1
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);
                    }
        }
Ejemplo n.º 2
0
 /**
  * Saves a manifest and container configuration for a V2.2 or OCI image.
  *
  * @param imageReference the image reference to save the manifest and container configuration for
  * @param manifestTemplate the V2.2 or OCI manifest
  * @param containerConfigurationTemplate the container configuration
  * @throws IOException if an I/O exception occurs
  */
 public async Task WriteMetadataAsync(
     IImageReference imageReference,
     IBuildableManifestTemplate manifestTemplate,
     ContainerConfigurationTemplate containerConfigurationTemplate)
 {
     await cacheStorageWriter.WriteMetadataAsync(
         imageReference, manifestTemplate, containerConfigurationTemplate).ConfigureAwait(false);
 }
Ejemplo n.º 3
0
        /**
         * Pushes the image manifest for a specific tag.
         *
         * @param manifestTemplate the image manifest
         * @param imageTag the tag to push on
         * @return the digest of the pushed image
         * @throws IOException if communicating with the endpoint fails
         * @throws RegistryException if communicating with the endpoint fails
         */
        public async Task <DescriptorDigest> PushManifestAsync(IBuildableManifestTemplate manifestTemplate, string imageTag)
        {
            ManifestPusher   pusher           = new ManifestPusher(registryEndpointRequestProperties, manifestTemplate, imageTag, eventHandlers);
            DescriptorDigest descriptorDigest = await CallRegistryEndpointAsync(pusher).ConfigureAwait(false);

            Debug.Assert(descriptorDigest != null);
            return(descriptorDigest);
        }
Ejemplo n.º 4
0
 public ManifestPusher(
     RegistryEndpointRequestProperties registryEndpointRequestProperties,
     IBuildableManifestTemplate manifestTemplate,
     string imageTag,
     IEventHandlers eventHandlers)
 {
     this.registryEndpointRequestProperties = registryEndpointRequestProperties;
     this.manifestTemplate = manifestTemplate;
     this.imageTag         = imageTag;
     this.eventHandlers    = eventHandlers;
 }
        /** Tests translation of image to {@link BuildableManifestTemplate}. */
        private async Task TestGetManifestAsync(
            ManifestFormat manifestTemplateClass, string translatedJsonFilename)
        {
            // Loads the expected JSON string.
            SystemPath jsonFile     = Paths.Get(TestResources.GetResource(translatedJsonFilename).ToURI());
            string     expectedJson = Encoding.UTF8.GetString(Files.ReadAllBytes(jsonFile));

            // Translates the image to the manifest and writes the JSON string.
            ContainerConfigurationTemplate containerConfiguration = imageToJsonTranslator.GetContainerConfiguration();
            BlobDescriptor blobDescriptor = await Digests.ComputeJsonDescriptorAsync(containerConfiguration).ConfigureAwait(false);

            IBuildableManifestTemplate manifestTemplate =
                imageToJsonTranslator.GetManifestTemplate(manifestTemplateClass, blobDescriptor);

            Assert.AreEqual(expectedJson, JsonTemplateMapper.ToUtf8String(manifestTemplate));
        }
Ejemplo n.º 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));
        }
Ejemplo n.º 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);
            }
        }
Ejemplo n.º 8
0
        /**
         * Saves the manifest and container configuration for a V2.2 or OCI image.
         *
         * @param imageReference the image reference to store the metadata for
         * @param manifestTemplate the manifest
         * @param containerConfiguration the container configuration
         */
        public async Task WriteMetadataAsync(
            IImageReference imageReference,
            IBuildableManifestTemplate manifestTemplate,
            ContainerConfigurationTemplate containerConfiguration)
        {
            manifestTemplate = manifestTemplate ?? throw new ArgumentNullException(nameof(manifestTemplate));
            Preconditions.CheckNotNull(manifestTemplate.GetContainerConfiguration());
            Preconditions.CheckNotNull(manifestTemplate.GetContainerConfiguration().Digest);

            SystemPath imageDirectory = cacheStorageFiles.GetImageDirectory(imageReference);

            Files.CreateDirectories(imageDirectory);

            using (LockFile ignored1 = LockFile.Create(imageDirectory.Resolve("lock")))
            {
                await WriteMetadataAsync(manifestTemplate, imageDirectory.Resolve("manifest.json")).ConfigureAwait(false);
                await WriteMetadataAsync(containerConfiguration, imageDirectory.Resolve("config.json")).ConfigureAwait(false);
            }
        }
Ejemplo n.º 9
0
        public async Task TestWriteMetadata_v22Async()
        {
            SystemPath containerConfigurationJsonFile =
                Paths.Get(
                    TestResources.GetResource("core/json/containerconfig.json").ToURI());
            ContainerConfigurationTemplate containerConfigurationTemplate =
                JsonTemplateMapper.ReadJsonFromFile <ContainerConfigurationTemplate>(
                    containerConfigurationJsonFile);
            SystemPath manifestJsonFile =
                Paths.Get(TestResources.GetResource("core/json/v22manifest.json").ToURI());
            IBuildableManifestTemplate manifestTemplate =
                JsonTemplateMapper.ReadJsonFromFile <V22ManifestTemplate>(manifestJsonFile);
            ImageReference imageReference = ImageReference.Parse("image.reference/project/thing:tag");

            await new CacheStorageWriter(cacheStorageFiles)
            .WriteMetadataAsync(imageReference, manifestTemplate, containerConfigurationTemplate).ConfigureAwait(false);

            SystemPath savedManifestPath =
                cacheRoot.Resolve("images/image.reference/project/thing!tag/manifest.json");
            SystemPath savedConfigPath =
                cacheRoot.Resolve("images/image.reference/project/thing!tag/config.json");

            Assert.IsTrue(Files.Exists(savedManifestPath));
            Assert.IsTrue(Files.Exists(savedConfigPath));

            V22ManifestTemplate savedManifest =
                JsonTemplateMapper.ReadJsonFromFile <V22ManifestTemplate>(savedManifestPath);

            Assert.AreEqual(
                "8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad",
                savedManifest.GetContainerConfiguration().Digest.GetHash());

            ContainerConfigurationTemplate savedContainerConfig =
                JsonTemplateMapper.ReadJsonFromFile <ContainerConfigurationTemplate>(savedConfigPath);

            Assert.AreEqual("wasm", savedContainerConfig.Architecture);
        }
Ejemplo n.º 10
0
        /**
         * Pulls the base image.
         *
         * @param registryAuthorization authentication credentials to possibly use
         * @param progressEventDispatcher the {@link ProgressEventDispatcher} for emitting {@link
         *     ProgressEvent}s
         * @return the pulled image
         * @throws IOException when an I/O exception occurs during the pulling
         * @throws RegistryException if communicating with the registry caused a known error
         * @throws LayerCountMismatchException if the manifest and configuration contain conflicting layer
         *     information
         * @throws LayerPropertyNotFoundException if adding image layers fails
         * @throws BadContainerConfigurationFormatException if the container configuration is in a bad
         *     format
         */
        private async Task <Image> PullBaseImageAsync(
            Authorization registryAuthorization,
            ProgressEventDispatcher progressEventDispatcher)
        {
            RegistryClient registryClient =
                buildConfiguration
                .NewBaseImageRegistryClientFactory()
                .SetAuthorization(registryAuthorization)
                .NewRegistryClient();

            IManifestTemplate manifestTemplate =
                await registryClient.PullManifestAsync(buildConfiguration.GetBaseImageConfiguration().GetImageTag()).ConfigureAwait(false);

            // TODO: Make schema version be enum.
            switch (manifestTemplate.SchemaVersion)
            {
            case 1:
                V21ManifestTemplate v21ManifestTemplate = (V21ManifestTemplate)manifestTemplate;
                await buildConfiguration
                .GetBaseImageLayersCache()
                .WriteMetadataAsync(
                    buildConfiguration.GetBaseImageConfiguration().GetImage(), v21ManifestTemplate).ConfigureAwait(false);

                return(JsonToImageTranslator.ToImage(v21ManifestTemplate));

            case 2:
                IBuildableManifestTemplate buildableManifestTemplate =
                    (IBuildableManifestTemplate)manifestTemplate;
                if (buildableManifestTemplate.GetContainerConfiguration() == null ||
                    buildableManifestTemplate.GetContainerConfiguration().Digest == null)
                {
                    throw new UnknownManifestFormatException(
                              "Invalid container configuration in Docker V2.2/OCI manifest: \n"
                              + JsonTemplateMapper.ToUtf8String(buildableManifestTemplate));
                }

                DescriptorDigest containerConfigurationDigest =
                    buildableManifestTemplate.GetContainerConfiguration().Digest;

                using (ThrottledProgressEventDispatcherWrapper progressEventDispatcherWrapper =
                           new ThrottledProgressEventDispatcherWrapper(
                               progressEventDispatcher.NewChildProducer(),
                               "pull container configuration " + containerConfigurationDigest))
                {
                    string containerConfigurationString =
                        await Blobs.WriteToStringAsync(
                            registryClient.PullBlob(
                                containerConfigurationDigest,
                                progressEventDispatcherWrapper.SetProgressTarget,
                                progressEventDispatcherWrapper.DispatchProgress)).ConfigureAwait(false);

                    ContainerConfigurationTemplate containerConfigurationTemplate =
                        JsonTemplateMapper.ReadJson <ContainerConfigurationTemplate>(
                            containerConfigurationString);
                    await buildConfiguration
                    .GetBaseImageLayersCache()
                    .WriteMetadataAsync(
                        buildConfiguration.GetBaseImageConfiguration().GetImage(),
                        buildableManifestTemplate,
                        containerConfigurationTemplate).ConfigureAwait(false);

                    return(JsonToImageTranslator.ToImage(
                               buildableManifestTemplate, containerConfigurationTemplate));
                }
            }

            throw new InvalidOperationException(Resources.PullBaseImageStepUnknownManifestErrorMessage);
        }