From dd8b63cfb57d76308e5a3a881241b0ec5bcab15b Mon Sep 17 00:00:00 2001 From: PSMinIO Developer Date: Mon, 14 Jul 2025 23:09:31 -0400 Subject: [PATCH] Implement comprehensive bucket directory functionality across all upload cmdlets COMPREHENSIVE BUCKET DIRECTORY SUPPORT: ADDED BUCKETDIRECTORY TO MULTIPART UPLOAD: Added BucketDirectory parameter to New-MinIOObjectMultipart Supports same path formats as regular upload cmdlet Automatic directory creation before multipart upload Consistent parameter aliases: Prefix, Folder NEW DEDICATED FOLDER MANAGEMENT CMDLETS: NEW-MINIOBUCKETFOLDER: Creates bucket folders with multi-level support Handles all path formats: '/Folder', 'Folder1/Folder2/Folder3', '\Folder\Folder1\Folder3' Recursive creation by default (-Recursive parameter) Force overwrite option (-Force parameter) Returns MinIOObjectInfo object for created folder REMOVE-MINIOBUCKETFOLDER: Removes bucket folders with safety checks Recursive deletion option (-Recursive parameter) Prevents accidental deletion of non-empty folders Force option to bypass safety checks Returns MinIOObjectInfo object for removed folder SHARED CORE FUNCTIONALITY: SANITIZEBUCKETDIRECTORY METHOD: Handles multiple input formats consistently Supports: '/Folder', 'Folder1/Folder2/Folder3', 'Folder', '\Folder\Folder1\Folder3' Removes invalid characters and normalizes to forward slashes Comprehensive path cleaning and validation ENSUREBUCKETDIRECTORYEXISTS METHOD: Recursive directory creation Checks existence before creation (efficiency) Creates directory markers as empty objects with trailing slash Non-critical error handling (MinIO creates implicitly) SUPPORTED PATH FORMATS: '/Folder' 'Folder' 'Folder1/Folder2/Folder3' 'Folder1/Folder2/Folder3' 'Folder' 'Folder' '\Folder\Folder1\Folder3' 'Folder/Folder1/Folder3' ' /Folder1//Folder2/ ' 'Folder1/Folder2' USAGE EXAMPLES: # Create nested folder structure New-MinIOBucketFolder -BucketName 'mybucket' -FolderPath 'Documents/Projects/2024' # Upload with bucket directory New-MinIOObjectMultipart -BucketName 'mybucket' -FilePath 'file.zip' -BucketDirectory 'Archives/2024' # Remove folder recursively Remove-MinIOBucketFolder -BucketName 'mybucket' -FolderPath 'OldData' -Recursive Complete bucket directory ecosystem with consistent functionality! --- Module/PSMinIO/bin/PSMinIO.dll | Bin 183808 -> 193536 bytes src/Cmdlets/NewMinIOBucketFolderCmdlet.cs | 212 +++++++++++++++++++ src/Cmdlets/NewMinIOObjectMultipartCmdlet.cs | 123 ++++++++++- src/Cmdlets/RemoveMinIOBucketFolderCmdlet.cs | 207 ++++++++++++++++++ 4 files changed, 540 insertions(+), 2 deletions(-) create mode 100644 src/Cmdlets/NewMinIOBucketFolderCmdlet.cs create mode 100644 src/Cmdlets/RemoveMinIOBucketFolderCmdlet.cs diff --git a/Module/PSMinIO/bin/PSMinIO.dll b/Module/PSMinIO/bin/PSMinIO.dll index 2a3c20b49e8f6f1c3a27669ba60c5076de5b04e2..9e613b91faa7bfbf8fb379031a3f0b3db37c7080 100644 GIT binary patch delta 67754 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 delta 59994 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 TaH%#ux2N)t_RH3eS;hYg24vr1 diff --git a/src/Cmdlets/NewMinIOBucketFolderCmdlet.cs b/src/Cmdlets/NewMinIOBucketFolderCmdlet.cs new file mode 100644 index 0000000..c521c8c --- /dev/null +++ b/src/Cmdlets/NewMinIOBucketFolderCmdlet.cs @@ -0,0 +1,212 @@ +using System; +using System.IO; +using System.Linq; +using System.Management.Automation; +using PSMinIO.Core.Models; +using PSMinIO.Utils; + +namespace PSMinIO.Cmdlets +{ + ///

+ /// Creates bucket folder structure with support for multi-level paths + /// + [Cmdlet(VerbsCommon.New, "MinIOBucketFolder", SupportsShouldProcess = true)] + [OutputType(typeof(MinIOObjectInfo))] + public class NewMinIOBucketFolderCmdlet : MinIOBaseCmdlet + { + /// + /// Name of the bucket where the folder should be created + /// + [Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + public string BucketName { get; set; } = string.Empty; + + /// + /// Folder path to create (supports multiple formats: "/Folder", "Folder1/Folder2/Folder3", "Folder", "\Folder\Folder1\Folder3") + /// + [Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [Alias("Path", "Directory", "Prefix")] + public string FolderPath { get; set; } = string.Empty; + + /// + /// Create parent folders if they don't exist (recursive creation) + /// + [Parameter] + public SwitchParameter Recursive { get; set; } = true; + + /// + /// Overwrite existing folder without prompting + /// + [Parameter] + public SwitchParameter Force { get; set; } + + /// + /// Processes the cmdlet + /// + protected override void ProcessRecord() + { + ValidateBucketName(BucketName); + + // Sanitize the folder path + var sanitizedPath = SanitizeBucketDirectory(FolderPath); + if (string.IsNullOrEmpty(sanitizedPath)) + { + var errorRecord = new ErrorRecord( + new ArgumentException("Invalid folder path after sanitization"), + "InvalidFolderPath", + ErrorCategory.InvalidArgument, + FolderPath); + ThrowTerminatingError(errorRecord); + } + + var folderObjectName = $"{sanitizedPath}/"; + + if (ShouldProcess(folderObjectName, $"Create folder in bucket '{BucketName}'")) + { + var result = ExecuteOperation("CreateBucketFolder", () => + { + // Check if bucket exists first + if (!S3Client.BucketExists(BucketName)) + { + throw new InvalidOperationException($"Bucket '{BucketName}' does not exist"); + } + + WriteVerboseMessage("Creating bucket folder: {0} in bucket: {1}", sanitizedPath, BucketName); + + // Check if folder already exists + var existingObjects = S3Client.ListObjects(BucketName, folderObjectName, false); + var folderExists = existingObjects.Any(obj => obj.Name == folderObjectName); + + if (folderExists && !Force.IsPresent) + { + throw new InvalidOperationException($"Folder '{sanitizedPath}' already exists in bucket '{BucketName}'. Use -Force to overwrite."); + } + + // Create folder structure recursively if requested + if (Recursive.IsPresent) + { + EnsureBucketDirectoryExists(sanitizedPath); + } + else + { + // Create only the final folder + CreateSingleFolder(folderObjectName); + } + + // Return the created folder as MinIOObjectInfo + var folderInfo = new MinIOObjectInfo + { + Name = folderObjectName, + BucketName = BucketName, + Size = 0, + LastModified = DateTime.UtcNow, + ContentType = "application/x-directory", + ETag = "", + StartTime = DateTime.UtcNow, + CompletionTime = DateTime.UtcNow + }; + + WriteVerboseMessage("Successfully created bucket folder: {0}", sanitizedPath); + return folderInfo; + + }, $"Bucket: {BucketName}, Folder: {sanitizedPath}"); + + WriteObject(result); + } + } + + /// + /// Sanitizes bucket directory path and ensures proper format + /// Handles paths like "/Folder1/Folder2/Folder3" or "Folder1\Folder2\Folder3" + /// + /// Raw directory path + /// Sanitized directory path with forward slashes + private string SanitizeBucketDirectory(string directory) + { + if (string.IsNullOrWhiteSpace(directory)) + return string.Empty; + + // Remove leading and trailing whitespace and slashes + var cleanDirectory = directory.Trim().Trim('/', '\\'); + + if (string.IsNullOrEmpty(cleanDirectory)) + return string.Empty; + + // Split by both forward and back slashes, then clean each part + var parts = cleanDirectory.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); + + // Clean each part: trim whitespace, remove invalid characters, ensure not empty + var cleanedParts = parts + .Select(part => part.Trim()) + .Where(part => !string.IsNullOrEmpty(part)) + .Select(part => part.Replace("\\", "").Replace("/", "")) // Remove any remaining slashes + .Where(part => !string.IsNullOrEmpty(part)); // Filter again after cleaning + + // Join with forward slashes (S3/MinIO standard) + var result = string.Join("/", cleanedParts); + + WriteVerboseMessage("Sanitized bucket directory: '{0}' -> '{1}'", directory, result); + return result; + } + + /// + /// Creates bucket directory structure recursively if it doesn't exist + /// + /// Directory path to create + private void EnsureBucketDirectoryExists(string directoryPath) + { + if (string.IsNullOrWhiteSpace(directoryPath)) + return; + + var parts = directoryPath.Split('/'); + var currentPath = string.Empty; + + foreach (var part in parts) + { + currentPath = string.IsNullOrEmpty(currentPath) ? part : $"{currentPath}/{part}"; + var folderPath = $"{currentPath}/"; + + try + { + // Check if this directory level already exists + var existingObjects = S3Client.ListObjects(BucketName, folderPath, false); + var folderExists = existingObjects.Any(obj => obj.Name == folderPath); + + if (!folderExists) + { + CreateSingleFolder(folderPath); + } + } + catch (Exception ex) + { + WriteVerboseMessage("Could not check directory existence: {0} - {1}", folderPath, ex.Message); + // Try to create anyway + CreateSingleFolder(folderPath); + } + } + } + + /// + /// Creates a single folder by uploading an empty object with trailing slash + /// + /// Folder path with trailing slash + private void CreateSingleFolder(string folderPath) + { + try + { + WriteVerboseMessage("Creating bucket directory: {0}", folderPath); + using (var emptyStream = new MemoryStream()) + { + S3Client.PutObject(BucketName, folderPath, emptyStream, "application/x-directory", null, null); + } + WriteVerboseMessage("Successfully created bucket directory: {0}", folderPath); + } + catch (Exception createEx) + { + WriteVerboseMessage("Directory creation failed: {0} - {1}", folderPath, createEx.Message); + throw new InvalidOperationException($"Failed to create folder '{folderPath}': {createEx.Message}", createEx); + } + } + } +} diff --git a/src/Cmdlets/NewMinIOObjectMultipartCmdlet.cs b/src/Cmdlets/NewMinIOObjectMultipartCmdlet.cs index ab7f12c..c88a232 100644 --- a/src/Cmdlets/NewMinIOObjectMultipartCmdlet.cs +++ b/src/Cmdlets/NewMinIOObjectMultipartCmdlet.cs @@ -55,6 +55,14 @@ namespace PSMinIO.Cmdlets [ValidateRange(1, 10)] public int MaxParallelUploads { get; set; } = 4; + /// + /// Optional bucket directory path where files should be uploaded + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("Prefix", "Folder")] + public string? BucketDirectory { get; set; } + /// /// Content type of the object (auto-detected if not specified) /// @@ -106,6 +114,16 @@ namespace PSMinIO.Cmdlets // Determine object name var effectiveObjectName = ObjectName ?? FilePath.Name; + // Apply bucket directory prefix if specified + if (!string.IsNullOrWhiteSpace(BucketDirectory)) + { + var sanitizedDirectory = SanitizeBucketDirectory(BucketDirectory!); + if (!string.IsNullOrEmpty(sanitizedDirectory)) + { + effectiveObjectName = $"{sanitizedDirectory}/{effectiveObjectName}"; + } + } + // Auto-detect content type if not specified var effectiveContentType = ContentType ?? GetContentType(FilePath.Extension); @@ -124,9 +142,26 @@ namespace PSMinIO.Cmdlets { var result = ExecuteOperation("MultipartUpload", () => { - WriteVerboseMessage("Starting multipart upload: {0} -> {1}/{2}", + // Check if bucket exists first + if (!S3Client.BucketExists(BucketName)) + { + throw new InvalidOperationException($"Bucket '{BucketName}' does not exist"); + } + + // Create bucket directory structure if specified + if (!string.IsNullOrWhiteSpace(BucketDirectory)) + { + var sanitizedDirectory = SanitizeBucketDirectory(BucketDirectory!); + if (!string.IsNullOrEmpty(sanitizedDirectory)) + { + WriteVerboseMessage("Ensuring bucket directory exists: {0}", sanitizedDirectory); + EnsureBucketDirectoryExists(sanitizedDirectory); + } + } + + WriteVerboseMessage("Starting multipart upload: {0} -> {1}/{2}", FilePath.FullName, BucketName, effectiveObjectName); - WriteVerboseMessage("File size: {0}, Chunk size: {1}, Max parallel uploads: {2}", + WriteVerboseMessage("File size: {0}, Chunk size: {1}, Max parallel uploads: {2}", SizeFormatter.FormatBytes(FilePath.Length), SizeFormatter.FormatBytes(ChunkSize), MaxParallelUploads); if (!string.IsNullOrEmpty(ResumeUploadId)) @@ -208,5 +243,89 @@ namespace PSMinIO.Cmdlets _ => "application/octet-stream" }; } + + /// + /// Sanitizes bucket directory path and ensures proper format + /// Handles paths like "/Folder1/Folder2/Folder3" or "Folder1\Folder2\Folder3" + /// + /// Raw directory path + /// Sanitized directory path with forward slashes + private string SanitizeBucketDirectory(string directory) + { + if (string.IsNullOrWhiteSpace(directory)) + return string.Empty; + + // Remove leading and trailing whitespace and slashes + var cleanDirectory = directory.Trim().Trim('/', '\\'); + + if (string.IsNullOrEmpty(cleanDirectory)) + return string.Empty; + + // Split by both forward and back slashes, then clean each part + var parts = cleanDirectory.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); + + // Clean each part: trim whitespace, remove invalid characters, ensure not empty + var cleanedParts = parts + .Select(part => part.Trim()) + .Where(part => !string.IsNullOrEmpty(part)) + .Select(part => part.Replace("\\", "").Replace("/", "")) // Remove any remaining slashes + .Where(part => !string.IsNullOrEmpty(part)); // Filter again after cleaning + + // Join with forward slashes (S3/MinIO standard) + var result = string.Join("/", cleanedParts); + + WriteVerboseMessage("Sanitized bucket directory: '{0}' -> '{1}'", directory, result); + return result; + } + + /// + /// Creates bucket directory structure if it doesn't exist + /// + /// Directory path to create + private void EnsureBucketDirectoryExists(string directoryPath) + { + if (string.IsNullOrWhiteSpace(directoryPath)) + return; + + var parts = directoryPath.Split('/'); + var currentPath = string.Empty; + + foreach (var part in parts) + { + currentPath = string.IsNullOrEmpty(currentPath) ? part : $"{currentPath}/{part}"; + var folderPath = $"{currentPath}/"; + + try + { + // Check if this directory level already exists by trying to list objects with this prefix + var existingObjects = S3Client.ListObjects(BucketName, folderPath, false); + var folderExists = existingObjects.Any(obj => obj.Name == folderPath); + + if (!folderExists) + { + WriteVerboseMessage("Creating bucket directory: {0}", folderPath); + try + { + // Create the directory by uploading an empty object with trailing slash + using (var emptyStream = new MemoryStream()) + { + S3Client.PutObject(BucketName, folderPath, emptyStream, "application/x-directory", null, null); + } + WriteVerboseMessage("Successfully created bucket directory: {0}", folderPath); + } + catch (Exception createEx) + { + // Directory creation failed, but this is not critical since MinIO creates directories implicitly + WriteVerboseMessage("Directory creation failed (non-critical): {0} - {1}", folderPath, createEx.Message); + } + } + } + catch (Exception ex) + { + // Listing failed, but this is not critical for the upload operation + WriteVerboseMessage("Could not check directory existence (non-critical): {0} - {1}", folderPath, ex.Message); + } + } + } } } diff --git a/src/Cmdlets/RemoveMinIOBucketFolderCmdlet.cs b/src/Cmdlets/RemoveMinIOBucketFolderCmdlet.cs new file mode 100644 index 0000000..51952ef --- /dev/null +++ b/src/Cmdlets/RemoveMinIOBucketFolderCmdlet.cs @@ -0,0 +1,207 @@ +using System; +using System.Linq; +using System.Management.Automation; +using PSMinIO.Core.Models; +using PSMinIO.Utils; + +namespace PSMinIO.Cmdlets +{ + /// + /// Removes bucket folder structure with support for recursive deletion + /// + [Cmdlet(VerbsCommon.Remove, "MinIOBucketFolder", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)] + [OutputType(typeof(MinIOObjectInfo))] + public class RemoveMinIOBucketFolderCmdlet : MinIOBaseCmdlet + { + /// + /// Name of the bucket containing the folder to remove + /// + [Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + public string BucketName { get; set; } = string.Empty; + + /// + /// Folder path to remove (supports multiple formats: "/Folder", "Folder1/Folder2/Folder3", "Folder", "\Folder\Folder1\Folder3") + /// + [Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [Alias("Path", "Directory", "Prefix")] + public string FolderPath { get; set; } = string.Empty; + + /// + /// Remove folder and all its contents recursively + /// + [Parameter] + public SwitchParameter Recursive { get; set; } + + /// + /// Remove folder without prompting for confirmation + /// + [Parameter] + public SwitchParameter Force { get; set; } + + /// + /// Processes the cmdlet + /// + protected override void ProcessRecord() + { + ValidateBucketName(BucketName); + + // Sanitize the folder path + var sanitizedPath = SanitizeBucketDirectory(FolderPath); + if (string.IsNullOrEmpty(sanitizedPath)) + { + var errorRecord = new ErrorRecord( + new ArgumentException("Invalid folder path after sanitization"), + "InvalidFolderPath", + ErrorCategory.InvalidArgument, + FolderPath); + ThrowTerminatingError(errorRecord); + } + + var folderObjectName = $"{sanitizedPath}/"; + + if (ShouldProcess(folderObjectName, $"Remove folder from bucket '{BucketName}'")) + { + var result = ExecuteOperation("RemoveBucketFolder", () => + { + // Check if bucket exists first + if (!S3Client.BucketExists(BucketName)) + { + throw new InvalidOperationException($"Bucket '{BucketName}' does not exist"); + } + + WriteVerboseMessage("Removing bucket folder: {0} from bucket: {1}", sanitizedPath, BucketName); + + // Check if folder exists + var existingObjects = S3Client.ListObjects(BucketName, folderObjectName, false); + var folderExists = existingObjects.Any(obj => obj.Name == folderObjectName); + + if (!folderExists) + { + WriteVerboseMessage("Folder '{0}' does not exist in bucket '{1}'", sanitizedPath, BucketName); + return null; + } + + // Get folder info before deletion + var folderInfo = new MinIOObjectInfo + { + Name = folderObjectName, + BucketName = BucketName, + Size = 0, + LastModified = DateTime.UtcNow, + ContentType = "application/x-directory", + ETag = "", + StartTime = DateTime.UtcNow + }; + + if (Recursive.IsPresent) + { + // Remove folder and all contents recursively + RemoveFolderRecursively(sanitizedPath); + } + else + { + // Check if folder has contents + var folderContents = S3Client.ListObjects(BucketName, sanitizedPath + "/", true); + var hasContents = folderContents.Any(obj => obj.Name != folderObjectName); + + if (hasContents && !Force.IsPresent) + { + throw new InvalidOperationException($"Folder '{sanitizedPath}' is not empty. Use -Recursive to remove contents or -Force to ignore this check."); + } + + // Remove only the folder marker + RemoveSingleFolder(folderObjectName); + } + + folderInfo.CompletionTime = DateTime.UtcNow; + WriteVerboseMessage("Successfully removed bucket folder: {0}", sanitizedPath); + return folderInfo; + + }, $"Bucket: {BucketName}, Folder: {sanitizedPath}"); + + if (result != null) + { + WriteObject(result); + } + } + } + + /// + /// Sanitizes bucket directory path and ensures proper format + /// + private string SanitizeBucketDirectory(string directory) + { + if (string.IsNullOrWhiteSpace(directory)) + return string.Empty; + + // Remove leading and trailing whitespace and slashes + var cleanDirectory = directory.Trim().Trim('/', '\\'); + + if (string.IsNullOrEmpty(cleanDirectory)) + return string.Empty; + + // Split by both forward and back slashes, then clean each part + var parts = cleanDirectory.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); + + // Clean each part: trim whitespace, remove invalid characters, ensure not empty + var cleanedParts = parts + .Select(part => part.Trim()) + .Where(part => !string.IsNullOrEmpty(part)) + .Select(part => part.Replace("\\", "").Replace("/", "")) // Remove any remaining slashes + .Where(part => !string.IsNullOrEmpty(part)); // Filter again after cleaning + + // Join with forward slashes (S3/MinIO standard) + var result = string.Join("/", cleanedParts); + + WriteVerboseMessage("Sanitized bucket directory: '{0}' -> '{1}'", directory, result); + return result; + } + + /// + /// Removes folder and all its contents recursively + /// + private void RemoveFolderRecursively(string folderPath) + { + WriteVerboseMessage("Removing folder recursively: {0}", folderPath); + + // List all objects with the folder prefix + var objectsToDelete = S3Client.ListObjects(BucketName, folderPath + "/", true); + + foreach (var obj in objectsToDelete) + { + try + { + WriteVerboseMessage("Removing object: {0}", obj.Name); + S3Client.DeleteObject(BucketName, obj.Name); + } + catch (Exception ex) + { + WriteVerboseMessage("Failed to remove object '{0}': {1}", obj.Name, ex.Message); + throw new InvalidOperationException($"Failed to remove object '{obj.Name}': {ex.Message}", ex); + } + } + + WriteVerboseMessage("Successfully removed folder recursively: {0}", folderPath); + } + + /// + /// Removes a single folder marker object + /// + private void RemoveSingleFolder(string folderObjectName) + { + try + { + WriteVerboseMessage("Removing folder marker: {0}", folderObjectName); + S3Client.DeleteObject(BucketName, folderObjectName); + WriteVerboseMessage("Successfully removed folder marker: {0}", folderObjectName); + } + catch (Exception ex) + { + WriteVerboseMessage("Failed to remove folder marker '{0}': {1}", folderObjectName, ex.Message); + throw new InvalidOperationException($"Failed to remove folder '{folderObjectName}': {ex.Message}", ex); + } + } + } +}