tools/code/common/WorkspacePolicy.cs (134 lines of code) (raw):

using Azure.Core.Pipeline; using Flurl; using LanguageExt; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; namespace common; public sealed record WorkspacePolicyName : ResourceName { private WorkspacePolicyName(string value) : base(value) { } public static WorkspacePolicyName From(string value) => new(value); } public sealed record WorkspacePoliciesUri : ResourceUri { public required WorkspaceUri Parent { get; init; } private static string PathSegment { get; } = "policies"; protected override Uri Value => Parent.ToUri().AppendPathSegment(PathSegment).ToUri(); public static WorkspacePoliciesUri From(WorkspaceName name, ManagementServiceUri serviceUri) => new() { Parent = WorkspaceUri.From(name, serviceUri) }; } public sealed record WorkspacePolicyUri : ResourceUri { public required WorkspacePoliciesUri Parent { get; init; } public required WorkspacePolicyName Name { get; init; } protected override Uri Value => Parent.ToUri().AppendPathSegment(Name.ToString()).ToUri(); public static WorkspacePolicyUri From(WorkspacePolicyName name, WorkspaceName workspaceName, ManagementServiceUri serviceUri) => new() { Parent = WorkspacePoliciesUri.From(workspaceName, serviceUri), Name = name }; } public sealed record WorkspacePolicyFile : ResourceFile { public required WorkspaceDirectory Parent { get; init; } public required WorkspacePolicyName Name { get; init; } protected override FileInfo Value => Parent.ToDirectoryInfo().GetChildFile($"{Name}.xml"); public static WorkspacePolicyFile From(WorkspacePolicyName name, WorkspaceName workspaceName, ManagementServiceDirectory serviceDirectory) => new() { Parent = WorkspaceDirectory.From(workspaceName, serviceDirectory), Name = name }; public static Option<WorkspacePolicyFile> TryParse(FileInfo? file, ManagementServiceDirectory serviceDirectory) => from name in TryParseWorkspacePolicyName(file) from parent in WorkspaceDirectory.TryParse(file?.Directory, serviceDirectory) select new WorkspacePolicyFile { Name = name, Parent = parent }; internal static Option<WorkspacePolicyName> TryParseWorkspacePolicyName(FileInfo? file) => file?.Name.EndsWith(".xml", StringComparison.Ordinal) switch { true => WorkspacePolicyName.From(Path.GetFileNameWithoutExtension(file.Name)), _ => Option<WorkspacePolicyName>.None }; } public sealed record WorkspacePolicyDto { [JsonPropertyName("properties")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public required WorkspacePolicyContract Properties { get; init; } public sealed record WorkspacePolicyContract { [JsonPropertyName("description")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string? Description { get; init; } [JsonPropertyName("format")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string? Format { get; init; } [JsonPropertyName("value")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string? Value { get; init; } } } public static class WorkspacePolicyModule { public static async IAsyncEnumerable<WorkspacePolicyName> ListNames(this WorkspacePoliciesUri uri, HttpPipeline pipeline, [EnumeratorCancellation] CancellationToken cancellationToken) { // The REST API call to list policy names returns incorrectly formatted names. // For now, we'll return the single policy named "policy" if it exists var policyName = WorkspacePolicyName.From("policy"); var policyUri = uri.ToUri().AppendPathSegment(policyName.Value).ToUri(); var option = await pipeline.GetJsonObjectOption(policyUri, cancellationToken); if (option.IsSome) { yield return policyName; } } public static IAsyncEnumerable<(WorkspacePolicyName Name, WorkspacePolicyDto Dto)> List(this WorkspacePoliciesUri workspacePoliciesUri, HttpPipeline pipeline, CancellationToken cancellationToken) => workspacePoliciesUri.ListNames(pipeline, cancellationToken) .SelectAwait(async name => { var uri = new WorkspacePolicyUri { Parent = workspacePoliciesUri, Name = name }; var dto = await uri.GetDto(pipeline, cancellationToken); return (name, dto); }); public static async ValueTask<WorkspacePolicyDto> GetDto(this WorkspacePolicyUri uri, HttpPipeline pipeline, CancellationToken cancellationToken) { var contentUri = uri.ToUri().AppendQueryParam("format", "rawxml").ToUri(); var content = await pipeline.GetContent(contentUri, cancellationToken); return content.ToObjectFromJson<WorkspacePolicyDto>(); } public static async ValueTask Delete(this WorkspacePolicyUri uri, HttpPipeline pipeline, CancellationToken cancellationToken) => await pipeline.DeleteResource(uri.ToUri(), waitForCompletion: true, cancellationToken); public static async ValueTask PutDto(this WorkspacePolicyUri uri, WorkspacePolicyDto dto, HttpPipeline pipeline, CancellationToken cancellationToken) { var content = BinaryData.FromObjectAsJson(dto); await pipeline.PutContent(uri.ToUri(), content, cancellationToken); } public static IEnumerable<WorkspacePolicyFile> ListPolicyFiles(WorkspaceName workspaceName, ManagementServiceDirectory serviceDirectory) { var workspaceDirectory = WorkspaceDirectory.From(workspaceName, serviceDirectory); return workspaceDirectory.ToDirectoryInfo() .ListFiles("*") .Choose(WorkspacePolicyFile.TryParseWorkspacePolicyName) .Select(name => new WorkspacePolicyFile { Name = name, Parent = workspaceDirectory }); } public static async ValueTask WritePolicy(this WorkspacePolicyFile file, string policy, CancellationToken cancellationToken) { var content = BinaryData.FromString(policy); await file.ToFileInfo().OverwriteWithBinaryData(content, cancellationToken); } public static async ValueTask<string> ReadPolicy(this WorkspacePolicyFile file, CancellationToken cancellationToken) { var content = await file.ToFileInfo().ReadAsBinaryData(cancellationToken); return content.ToString(); } }