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

Commit

Permalink
test hooks and a bug fix (#1879)
Browse files Browse the repository at this point in the history
Co-authored-by: stas <statis@microsoft.com>
  • Loading branch information
stishkin and stas authored May 3, 2022
1 parent 5ccd519 commit 1f276e1
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 24 deletions.
20 changes: 0 additions & 20 deletions src/ApiService/ApiService/TestHooks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,7 @@ public async Task<HttpResponseData> Info([HttpTrigger(AuthorizationLevel.Anonymo
return response;
}

[Function("InstanceConfig")]
public async Task<HttpResponseData> InstanceConfig([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/instance-config")] HttpRequestData req) {
_log.Info("Fetching instance config");
var config = await _configOps.Fetch();

if (config is null) {
_log.Error("Instance config is null");
Error err = new(ErrorCode.INVALID_REQUEST, new[] { "Instance config is null" });
var resp = req.CreateResponse(HttpStatusCode.InternalServerError);
await resp.WriteAsJsonAsync(err);
return resp;
} else {
await _events.SendEvent(new EventInstanceConfigUpdated(config));

var str = (new EntityConverter()).ToJsonString(config);

var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(str);
return resp;
}
}

[Function("GetKeyvaultAddress")]
public async Task<HttpResponseData> GetKeyVaultAddress([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/secrets/keyvaultaddress")] HttpRequestData req) {
Expand Down
35 changes: 35 additions & 0 deletions src/ApiService/ApiService/TestHooks/ContainerTestHooks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

using Microsoft.OneFuzz.Service;


namespace ApiService.TestHooks {
public class ContainerTestHooks {

private readonly ILogTracer _log;
private readonly IConfigOperations _configOps;
private readonly IContainers _containers;

public ContainerTestHooks(ILogTracer log, IConfigOperations configOps, IContainers containers) {
_log = log.WithTag("TestHooks", "ContainerTestHooks");
_configOps = configOps;
_containers = containers;
}

[Function("GetInstanceId")]
public async Task<HttpResponseData> GetInstanceId([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/containers/instanceId")] HttpRequestData req) {
_log.Info("Get instance ID");
var instanceId = await _containers.GetInstanceId();

var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(instanceId.ToString());
return resp;
}



}
}
65 changes: 65 additions & 0 deletions src/ApiService/ApiService/TestHooks/CredsTestHookks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

using Microsoft.OneFuzz.Service;



namespace ApiService.TestHooks {
public class CredsTestHookks {
private readonly ILogTracer _log;
private readonly IConfigOperations _configOps;
private readonly ICreds _creds;

public CredsTestHookks(ILogTracer log, IConfigOperations configOps, ICreds creds) {
_log = log.WithTag("TestHooks", "ContainerTestHooks");
_configOps = configOps;
_creds = creds;
}

[Function("GetSubscription")]
public async Task<HttpResponseData> GetSubscription([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/creds/subscription")] HttpRequestData req) {
_log.Info("Get subscription");
var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(_creds.GetSubscription().ToString());
return resp;
}


[Function("GetBaseResourceGroup")]
public async Task<HttpResponseData> GetBaseResourceGroup([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/creds/baseResourceGroup")] HttpRequestData req) {
_log.Info("Get base resource group");
var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(_creds.GetBaseResourceGroup().ToString());
return resp;
}

[Function("GetInstanceName")]
public async Task<HttpResponseData> GetInstanceName([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/creds/instanceName")] HttpRequestData req) {
_log.Info("Get instance name");
var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(_creds.GetInstanceName().ToString());
return resp;
}

[Function("GetBaseRegion")]
public async Task<HttpResponseData> GetBaseRegion([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/creds/baseRegion")] HttpRequestData req) {
_log.Info("Get base region");
var resp = req.CreateResponse(HttpStatusCode.OK);
var region = await _creds.GetBaseRegion();
await resp.WriteStringAsync(region);
return resp;
}

[Function("GetInstanceUrl")]
public async Task<HttpResponseData> GetInstanceUrl([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/creds/instanceUrl")] HttpRequestData req) {
_log.Info("Get instance url");
var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(_creds.GetInstanceUrl().ToString());
return resp;
}

}
}
36 changes: 36 additions & 0 deletions src/ApiService/ApiService/TestHooks/DiskOperationsTestHooks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

using Microsoft.OneFuzz.Service;



namespace ApiService.TestHooks {
public class DiskOperationsTestHooks {
private readonly ILogTracer _log;
private readonly IConfigOperations _configOps;
private readonly IDiskOperations _diskOps;
private readonly ICreds _creds;

public DiskOperationsTestHooks(ILogTracer log, IConfigOperations configOps, IDiskOperations diskOps, ICreds creds) {
_log = log.WithTag("TestHooks", "ContainerTestHooks");
_configOps = configOps;
_diskOps = diskOps;
_creds = creds;
}

[Function("GetDiskNames")]
public async Task<HttpResponseData> GetSubscription([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/disks")] HttpRequestData req) {
_log.Info("Get disk names");
var resp = req.CreateResponse(HttpStatusCode.OK);
var diskNames = _diskOps.ListDisks(_creds.GetBaseResourceGroup()).ToList().Select(x => x.Data.Name);
await resp.WriteAsJsonAsync(diskNames);
return resp;
}



}
}
72 changes: 72 additions & 0 deletions src/ApiService/ApiService/TestHooks/InstanceConfigTestHooks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.OneFuzz.Service;
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;

namespace ApiService.TestHooks {
public class InstanceConfigTestHooks {

private readonly ILogTracer _log;
private readonly IConfigOperations _configOps;

public InstanceConfigTestHooks(ILogTracer log, IConfigOperations configOps) {
_log = log.WithTag("TestHooks", "InstanceConfigTestHooks");
_configOps = configOps;
}

[Function("GetInstanceConfig")]
public async Task<HttpResponseData> Get([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/instance-config")] HttpRequestData req) {
_log.Info("Fetching instance config");
var config = await _configOps.Fetch();

if (config is null) {
_log.Error("Instance config is null");
Error err = new(ErrorCode.INVALID_REQUEST, new[] { "Instance config is null" });
var resp = req.CreateResponse(HttpStatusCode.InternalServerError);
await resp.WriteAsJsonAsync(err);
return resp;
} else {
var str = (new EntityConverter()).ToJsonString(config);

var resp = req.CreateResponse(HttpStatusCode.OK);
await resp.WriteStringAsync(str);
return resp;
}
}

[Function("PatchInstanceConfig")]
public async Task<HttpResponseData> Patch([HttpTrigger(AuthorizationLevel.Anonymous, "patch", Route = "testhooks/instance-config")] HttpRequestData req) {
_log.Info("Patch instance config");

var s = await req.ReadAsStringAsync();
var newInstanceConfig = JsonSerializer.Deserialize<InstanceConfig>(s!, EntityConverter.GetJsonSerializerOptions());

if (newInstanceConfig is null) {
var resp = req.CreateResponse();
resp.StatusCode = HttpStatusCode.BadRequest;
await resp.WriteAsJsonAsync(new { Error = "Instance config is not set" });
return resp;
} else {

var query = UriExtension.GetQueryComponents(req.Url);
bool isNew = UriExtension.GetBoolValue("isNew", query, false);
//requireEtag wont' work since our current schema does not return etag to the client when getting data form the table, so
// there is no way to know which etag to use
bool requireEtag = UriExtension.GetBoolValue("requireEtag", query, false);

await _configOps.Save(newInstanceConfig, isNew, requireEtag);

var resp = req.CreateResponse();
resp.StatusCode = HttpStatusCode.OK;
return resp;
}
}




}
}
30 changes: 30 additions & 0 deletions src/ApiService/ApiService/TestHooks/UriExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace ApiService.TestHooks {
public class UriExtension {

public static IDictionary<string, string> GetQueryComponents(System.Uri uri) {
var queryComponents = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped).Split("&");

var q =
from cs in queryComponents
where !string.IsNullOrEmpty(cs)
let i = cs.IndexOf('=')
select new KeyValuePair<string, string>(Uri.UnescapeDataString(cs.Substring(0, i)), Uri.UnescapeDataString(cs.Substring(i + 1)));

return new Dictionary<string, string>(q);
}

public static bool GetBoolValue(string key, IDictionary<string, string> query, bool defaultValue = false) {
bool v;
if (query.ContainsKey(key)) {
if (!bool.TryParse(query[key], out v)) {
v = defaultValue;
}
} else {
v = defaultValue;
}
return v;
}


}
}
10 changes: 7 additions & 3 deletions src/ApiService/ApiService/onefuzzlib/Creds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface ICreds {

public ResourceGroupResource GetResourceGroupResource();

public string GetBaseRegion();
public Async.Task<string> GetBaseRegion();

public Uri GetInstanceUrl();
}
Expand Down Expand Up @@ -74,8 +74,12 @@ public ResourceGroupResource GetResourceGroupResource() {
return ArmClient.GetResourceGroupResource(resourceId);
}

public string GetBaseRegion() {
return ArmClient.GetResourceGroupResource(GetResourceGroupResourceIdentifier()).Data.Location.Name;
public async Async.Task<string> GetBaseRegion() {
var rg = await ArmClient.GetResourceGroupResource(GetResourceGroupResourceIdentifier()).GetAsync();
if (rg.GetRawResponse().IsError) {
throw new Exception($"Failed to get base region due to [{rg.GetRawResponse().Status}] {rg.GetRawResponse().ReasonPhrase}");
}
return rg.Value.Data.Location.Name;
}

public Uri GetInstanceUrl() {
Expand Down
2 changes: 1 addition & 1 deletion src/ApiService/ApiService/onefuzzlib/ReproOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public async Async.Task<Vm> GetVm(Repro repro, InstanceConfig config) {
}

vmConfig = new TaskVm(
_creds.GetBaseRegion(),
await _creds.GetBaseRegion(),
DEFAULT_SKU,
DEFAULT_OS[task.Os],
null
Expand Down

0 comments on commit 1f276e1

Please sign in to comment.