mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-18 20:58:06 +00:00
test hooks and a bug fix (#1879)
Co-authored-by: stas <statis@microsoft.com>
This commit is contained in:
@ -41,27 +41,7 @@ public class TestHooks {
|
||||
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) {
|
||||
|
35
src/ApiService/ApiService/TestHooks/ContainerTestHooks.cs
Normal file
35
src/ApiService/ApiService/TestHooks/ContainerTestHooks.cs
Normal file
@ -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
src/ApiService/ApiService/TestHooks/CredsTestHookks.cs
Normal file
65
src/ApiService/ApiService/TestHooks/CredsTestHookks.cs
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -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
src/ApiService/ApiService/TestHooks/UriExtension.cs
Normal file
30
src/ApiService/ApiService/TestHooks/UriExtension.cs
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ public interface ICreds {
|
||||
|
||||
public ResourceGroupResource GetResourceGroupResource();
|
||||
|
||||
public string GetBaseRegion();
|
||||
public Async.Task<string> GetBaseRegion();
|
||||
|
||||
public Uri GetInstanceUrl();
|
||||
}
|
||||
@ -74,8 +74,12 @@ public class Creds : ICreds {
|
||||
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() {
|
||||
|
@ -48,7 +48,7 @@ public class ReproOperations : StatefulOrm<Repro, VmState>, IReproOperations {
|
||||
}
|
||||
|
||||
vmConfig = new TaskVm(
|
||||
_creds.GetBaseRegion(),
|
||||
await _creds.GetBaseRegion(),
|
||||
DEFAULT_SKU,
|
||||
DEFAULT_OS[task.Os],
|
||||
null
|
||||
|
Reference in New Issue
Block a user