- 
                Notifications
    You must be signed in to change notification settings 
- Fork 715
          Add support for creating files and folders in a container via docker/podman cp
          #8121
        
          New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
f7858a9
              63fe575
              486f74a
              3bf355b
              28f6bd5
              e55a237
              a404ed1
              8371b8e
              61f414b
              745c543
              238509f
              cb411b6
              6d8b35f
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|  | ||
| using System.Diagnostics; | ||
|  | ||
| namespace Aspire.Hosting.ApplicationModel; | ||
|  | ||
| /// <summary> | ||
| /// Represents a base class for file system entries in a container. | ||
| /// </summary> | ||
| public abstract class ContainerFileSystemItem | ||
| { | ||
| /// <summary> | ||
| /// The name of the file or directory. | ||
| /// </summary> | ||
| public required string Name { get; set; } | ||
|  | ||
| /// <summary> | ||
| /// The UID of the owner of the file or directory. If set to null, the UID will be inherited from the parent directory or defaults. | ||
| /// </summary> | ||
| public int? Owner { get; set; } | ||
|  | ||
| /// <summary> | ||
| /// The GID of the group of the file or directory. If set to null, the GID will be inherited from the parent directory or defaults. | ||
| /// </summary> | ||
| public int? Group { get; set; } | ||
|  | ||
| /// <summary> | ||
| /// The permissions of the file or directory. If set to 0, the permissions will be inherited from the parent directory or defaults. | ||
| /// </summary> | ||
| public UnixFileMode Mode { get; set; } | ||
| } | ||
|  | ||
| /// <summary> | ||
| /// Represents a file in the container file system. | ||
| /// </summary> | ||
| public sealed class ContainerFile : ContainerFileSystemItem | ||
| { | ||
| /// <summary> | ||
| /// The contents of the file to create in the container. | ||
| /// </summary> | ||
| public string? Contents { get; set; } | ||
| } | ||
|  | ||
| /// <summary> | ||
| /// Represents a directory in the container file system. | ||
| /// </summary> | ||
| public sealed class ContainerDirectory : ContainerFileSystemItem | ||
| { | ||
| /// <summary> | ||
| /// The contents of the directory to create in the container. | ||
| /// </summary> | ||
| public List<ContainerFileSystemItem> Entries { get; set; } = new(); | ||
| } | ||
|  | ||
| /// <summary> | ||
| /// Represents an annotation that indicates the creation of a file in a container. | ||
| /// </summary> | ||
| [DebuggerDisplay("Type = {GetType().Name,nw}")] | ||
| public sealed class ContainerCreateFileAnnotation : IResourceAnnotation | ||
| { | ||
| /// <summary> | ||
| /// The (absolute) base path to create the new file (and any parent directories) in the container. | ||
| /// This path should already exist in the container. | ||
| /// </summary> | ||
| public required string DestinationPath { get; init; } | ||
|  | ||
| /// <summary> | ||
| /// The UID of the default owner for files/directories to be created or updated in the container. Defaults to 0 for root. | ||
| /// </summary> | ||
| public int DefaultOwner { get; init; } | ||
|  | ||
| /// <summary> | ||
| /// The GID of the default group for files/directories to be created or updated in the container. Defaults to 0 for root. | ||
| /// </summary> | ||
| public int DefaultGroup { get; init; } | ||
|  | ||
| /// <summary> | ||
| /// The default permissions for files/directories to be created or updated in the container. 0 will be treated as 0600. | ||
| /// </summary> | ||
| public UnixFileMode DefaultMode { get; init; } | ||
|  | ||
| /// <summary> | ||
| /// The list of file system entries to create in the container. | ||
| /// </summary> | ||
| public List<ContainerFileSystemItem> Entries { get; init; } = new(); | ||
|         
                  danegsta marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -699,6 +699,76 @@ public static IResourceBuilder<T> WithBuildSecret<T>(this IResourceBuilder<T> bu | |
| return builder; | ||
| } | ||
|  | ||
| /// <summary> | ||
| /// Creates or updates files and/or folders at the destination path in the container. | ||
| /// </summary> | ||
| /// <typeparam name="T">The type of container resource.</typeparam> | ||
| /// <param name="builder">The resource builder for the container resource.</param> | ||
| /// <param name="destinationPath">The destination (absolute) path in the container.</param> | ||
| /// <param name="entries">The file system entries to create.</param> | ||
| /// <param name="defaultOwner">The default owner UID for the created or updated file system. Defaults to 0 for root.</param> | ||
| /// <param name="defaultGroup">The default group ID for the created or updated file system. Defaults to 0 for root.</param> | ||
| /// <param name="defaultMode">The default <see cref="UnixFileMode"/> ownership permissions for the created or updated file system. <see cref="UnixFileMode.None"/> will be treated as 0600 by DCP.</param> | ||
| /// <returns>The <see cref="IResourceBuilder{T}"/>.</returns> | ||
| /// <remarks> | ||
| /// <para> | ||
| /// For containers with a <see cref="ContainerLifetime.Persistent"/> lifetime, changing the contents of create file entries will result in the container being recreated. | ||
| /// Make sure any data being written to containers is idempotent for a given app model configuration. Specifically, be careful not to include any data that will be | ||
| /// unique on a per-run basis. | ||
| /// </para> | ||
| /// </remarks> | ||
| /// <example> | ||
| /// Create a directory called <c>custom-entry</c> in the container's file system at the path <c>/usr/data</c> and create a file called <c>entrypoint.sh</c> inside it with the content <c>echo hello world</c>. | ||
| /// The default permissions for these files will be for the user or group to be able to read and write to the files, but not execute them. entrypoint.sh will be created with execution permissions for the owner. | ||
| /// <code language="csharp"> | ||
| /// var builder = DistributedApplication.CreateBuilder(args); | ||
| /// | ||
| /// builder.AddContainer("mycontainer", "myimage") | ||
| /// .WithCreateFile("/usr/data", new() | ||
| /// { | ||
| /// new ContainerDirectory | ||
| /// { | ||
| /// Name = "custom-entry", | ||
| /// Entries = new() | ||
| /// { | ||
| /// new ContainerFile | ||
| /// { | ||
| /// Name = "entrypoint.sh", | ||
| /// Contents = "echo hello world", | ||
| /// Mode = UnixFileMode.UserExecute | UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite, | ||
| /// }, | ||
| /// }, | ||
| /// }, | ||
| /// }, | ||
| /// defaultOwner: 1000, | ||
| /// defaultMode: UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite); | ||
| /// </code> | ||
| /// </example> | ||
| public static IResourceBuilder<T> WithCreateFile<T>(this IResourceBuilder<T> builder, string destinationPath, List<ContainerFileSystemItem> entries, int defaultOwner = 0, int defaultGroup = 0, UnixFileMode defaultMode = UnixFileMode.None) where T : ContainerResource | ||
|          | ||
| { | ||
| ArgumentNullException.ThrowIfNull(builder); | ||
| ArgumentNullException.ThrowIfNull(destinationPath); | ||
| ArgumentNullException.ThrowIfNull(entries); | ||
|  | ||
| foreach (var existingAnnotation in builder.Resource.Annotations.OfType<ContainerCreateFileAnnotation>().Where(a => string.Equals(a.DestinationPath, destinationPath, StringComparison.Ordinal))) | ||
| { | ||
| builder.Resource.Annotations.Remove(existingAnnotation); | ||
| } | ||
|  | ||
| var annotation = new ContainerCreateFileAnnotation | ||
| { | ||
| DestinationPath = destinationPath, | ||
| Entries = entries, | ||
| DefaultOwner = defaultOwner, | ||
| DefaultGroup = defaultGroup, | ||
| DefaultMode = defaultMode, | ||
| }; | ||
|  | ||
| builder.Resource.Annotations.Add(annotation); | ||
|  | ||
| return builder; | ||
| } | ||
|  | ||
| /// <summary> | ||
| /// Set whether a container resource can use proxied endpoints or whether they should be disabled for all endpoints belonging to the container. | ||
| /// If set to <c>false</c>, endpoints belonging to the container resource will ignore the configured proxy settings and run proxy-less. | ||
|  | ||
Uh oh!
There was an error while loading. Please reload this page.