Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Commit

Permalink
Add extensions functionality for C# refactor (#2218)
Browse files Browse the repository at this point in the history
* Add extensions functionality

* Small cleanup

* Use context, fix typo
  • Loading branch information
tevoinea authored Aug 4, 2022
1 parent d0f0fc5 commit 3a0e8bb
Show file tree
Hide file tree
Showing 8 changed files with 373 additions and 77 deletions.
1 change: 1 addition & 0 deletions src/ApiService/ApiService/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public async static Async.Task Main() {
.AddScoped<INodeTasksOperations, NodeTasksOperations>()
.AddScoped<INodeMessageOperations, NodeMessageOperations>()
.AddScoped<IRequestHandling, RequestHandling>()
.AddScoped<IImageOperations, ImageOperations>()
.AddScoped<IOnefuzzContext, OnefuzzContext>()
.AddScoped<IEndpointAuthorization, EndpointAuthorization>()
.AddScoped<INodeMessageOperations, NodeMessageOperations>()
Expand Down
255 changes: 178 additions & 77 deletions src/ApiService/ApiService/onefuzzlib/Extension.cs

Large diffs are not rendered by default.

115 changes: 115 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/ImageOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System.Threading.Tasks;
using Azure;
using Azure.ResourceManager.Compute;

namespace Microsoft.OneFuzz.Service;

public interface IImageOperations {
public Async.Task<OneFuzzResult<Os>> GetOs(string region, string image);
}

public class ImageOperations : IImageOperations {
private IOnefuzzContext _context;
private ILogTracer _logTracer;

public ImageOperations(ILogTracer logTracer, IOnefuzzContext context) {
_logTracer = logTracer;
_context = context;
}
public async Task<OneFuzzResult<Os>> GetOs(string region, string image) {
string? name = null;
try {
var parsed = _context.Creds.ParseResourceId(image);
parsed = await _context.Creds.GetData(parsed);
if (string.Equals(parsed.Id.ResourceType, "galleries", StringComparison.OrdinalIgnoreCase)) {
try {
// This is not _exactly_ the same as the python code
// because in C# we don't have access to child_name_1
var gallery = await _context.Creds.GetResourceGroupResource().GetGalleries().GetAsync(
parsed.Data.Name
);

var galleryImage = gallery.Value.GetGalleryImages()
.ToEnumerable()
.Where(galleryImage => string.Equals(galleryImage.Id, parsed.Id, StringComparison.OrdinalIgnoreCase))
.First();

galleryImage = await galleryImage.GetAsync();

name = galleryImage.Data?.OSType?.ToString().ToLowerInvariant()!;

} catch (Exception ex) when (
ex is RequestFailedException ||
ex is NullReferenceException
) {
return OneFuzzResult<Os>.Error(
ErrorCode.INVALID_IMAGE,
ex.ToString()
);
}
} else {
try {
name = (await _context.Creds.GetResourceGroupResource().GetImages().GetAsync(
parsed.Data.Name
)).Value.Data.StorageProfile.OSDisk.OSType.ToString().ToLowerInvariant();
} catch (Exception ex) when (
ex is RequestFailedException ||
ex is NullReferenceException
) {
return OneFuzzResult<Os>.Error(
ErrorCode.INVALID_IMAGE,
ex.ToString()
);
}
}
} catch (FormatException) {
var imageParts = image.Split(":");

// The python code would throw if more than 4 parts are found in the split
System.Diagnostics.Trace.Assert(imageParts.Length == 4, $"Expected 4 ':' separated parts in {image}");

var publisher = imageParts[0];
var offer = imageParts[1];
var sku = imageParts[2];
var version = imageParts[3];

try {
var subscription = await _context.Creds.ArmClient.GetDefaultSubscriptionAsync();
if (string.Equals(version, "latest", StringComparison.Ordinal)) {
version = (await subscription.GetVirtualMachineImagesAsync(
region,
publisher,
offer,
sku,
top: 1
).FirstAsync()).Name;
}

name = (await subscription.GetVirtualMachineImageAsync(
region,
publisher,
offer,
sku
, version
)).Value.OSDiskImageOperatingSystem.ToString().ToLower();
} catch (RequestFailedException ex) {
return OneFuzzResult<Os>.Error(
ErrorCode.INVALID_IMAGE,
ex.ToString()
);
}
}

if (name != null) {
name = string.Concat(name[0].ToString().ToUpper(), name.AsSpan(1));
if (Enum.TryParse(name, out Os os)) {
return OneFuzzResult<Os>.Ok(os);
}
}

return OneFuzzResult<Os>.Error(
ErrorCode.INVALID_IMAGE,
$"Unexpected image os type: {name}"
);
}
}
2 changes: 2 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/OnefuzzContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public interface IOnefuzzContext {
IRequestHandling RequestHandling { get; }
INsgOperations NsgOperations { get; }
ISubnet Subnet { get; }
IImageOperations ImageOperations { get; }
}

public class OnefuzzContext : IOnefuzzContext {
Expand Down Expand Up @@ -81,4 +82,5 @@ public OnefuzzContext(IServiceProvider serviceProvider) {
public IRequestHandling RequestHandling => _serviceProvider.GetRequiredService<IRequestHandling>();
public INsgOperations NsgOperations => _serviceProvider.GetRequiredService<INsgOperations>();
public ISubnet Subnet => _serviceProvider.GetRequiredService<ISubnet>();
public IImageOperations ImageOperations => _serviceProvider.GetRequiredService<IImageOperations>();
}
11 changes: 11 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/Reports.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;

namespace Microsoft.OneFuzz.Service;

public interface IReports {
public Async.Task<IReport?> GetReportOrRegression(Container container, string fileName, bool expectReports = false, params string[] args);
public Async.Task<Report?> GetReport(Container container, string fileName);
}

public class Reports : IReports {
Expand All @@ -15,6 +17,15 @@ public Reports(ILogTracer log, IContainers containers) {
_containers = containers;
}

public async Task<Report?> GetReport(Container container, string fileName) {
var result = await GetReportOrRegression(container, fileName);
if (result != null && result is Report) {
return result as Report;
}

return null;
}

public async Async.Task<IReport?> GetReportOrRegression(Container container, string fileName, bool expectReports = false, params string[] args) {
var filePath = String.Join("/", new[] { container.ContainerName, fileName });
if (!fileName.EndsWith(".json", StringComparison.Ordinal)) {
Expand Down
62 changes: 62 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/VmExtensionWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Azure.Core;
using Azure.ResourceManager.Compute;

namespace Microsoft.OneFuzz.Service {
public class VMExtensionWrapper {
public AzureLocation? Location { get; init; }
public string? Name { get; init; }
public string? TypePropertiesType { get; init; }
public string? Publisher { get; init; }
public string? TypeHandlerVersion { get; init; }
public string? ForceUpdateTag { get; init; }
public bool? AutoUpgradeMinorVersion { get; init; }
public bool? EnableAutomaticUpgrade { get; init; }
public BinaryData? Settings { get; init; }
public BinaryData? ProtectedSettings { get; init; }

public (string, VirtualMachineExtensionData) GetAsVirtualMachineExtension() {
if (Location == null) { // EnsureNotNull does not satisfy the nullability checker
throw new ArgumentNullException("Location required for VirtualMachineExtension");
}
TypePropertiesType.EnsureNotNull("TypePropertiesType required for VirtualMachineExtension");
Publisher.EnsureNotNull("Publisher required for VirtualMachineExtension");
TypeHandlerVersion.EnsureNotNull("TypeHandlerVersion required for VirtualMachineExtension");
AutoUpgradeMinorVersion.EnsureNotNull("AutoUpgradeMinorVersion required for VirtualMachineExtension");
Settings.EnsureNotNull("Settings required for VirtualMachineExtension");
ProtectedSettings.EnsureNotNull("ProtectedSettings required for VirtualMachineExtension");

return (Name!, new VirtualMachineExtensionData(Location.Value) {
TypePropertiesType = TypePropertiesType,
Publisher = Publisher,
TypeHandlerVersion = TypeHandlerVersion,
AutoUpgradeMinorVersion = AutoUpgradeMinorVersion,
EnableAutomaticUpgrade = EnableAutomaticUpgrade,
ForceUpdateTag = ForceUpdateTag,
Settings = Settings,
ProtectedSettings = ProtectedSettings
});
}

public VirtualMachineScaleSetExtensionData GetAsVirtualMachineScaleSetExtension() {
Name.EnsureNotNull("Name required for VirtualMachineScaleSetExtension");
TypePropertiesType.EnsureNotNull("TypePropertiesType required for VirtualMachineScaleSetExtension");
Publisher.EnsureNotNull("Publisher required for VirtualMachineScaleSetExtension");
TypeHandlerVersion.EnsureNotNull("TypeHandlerVersion required for VirtualMachineScaleSetExtension");
AutoUpgradeMinorVersion.EnsureNotNull("AutoUpgradeMinorVersion required for VirtualMachineScaleSetExtension");
Settings.EnsureNotNull("Settings required for VirtualMachineScaleSetExtension");
ProtectedSettings.EnsureNotNull("ProtectedSettings required for VirtualMachineScaleSetExtension");
return new VirtualMachineScaleSetExtensionData() {
Name = Name,
TypePropertiesType = TypePropertiesType,
Publisher = Publisher,
TypeHandlerVersion = TypeHandlerVersion,
AutoUpgradeMinorVersion = AutoUpgradeMinorVersion,
EnableAutomaticUpgrade = EnableAutomaticUpgrade,
ForceUpdateTag = ForceUpdateTag,
Settings = Settings,
ProtectedSettings = ProtectedSettings
};
}
}

}
2 changes: 2 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/orm/Orm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ public StatefulOrm(ILogTracer logTracer, IOnefuzzContext context) : base(logTrac
if (func != null) {
_logTracer.Info($"processing state update: {typeof(T)} - PartitionKey {_partitionKeyGetter?.Value()} {_rowKeyGetter?.Value()} - %s");
return await func(entity);
} else {
_logTracer.Info($"State function for state: '{state}' not found on type {typeof(T)}");
}
return null;
}
Expand Down
2 changes: 2 additions & 0 deletions src/ApiService/IntegrationTests/Fakes/TestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,6 @@ public Async.Task InsertAll(params EntityBase[] objs)
public INsgOperations NsgOperations => throw new NotImplementedException();

public ISubnet Subnet => throw new NotImplementedException();

public IImageOperations ImageOperations => throw new NotImplementedException();
}

0 comments on commit 3a0e8bb

Please sign in to comment.