Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/ApiService/ApiService/Functions/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ private ProxyGetResult GetResult(ProxyForward proxyForward, VmProxy? proxy) {
) {
return new ProxyGetResult(null, Forward: forward);
}

return new ProxyGetResult(proxy.Ip, forward);
}

Expand Down
15 changes: 7 additions & 8 deletions src/ApiService/ApiService/onefuzzlib/NodeOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
using Azure;
using Azure.Data.Tables;

namespace Microsoft.OneFuzz.Service;

Expand Down Expand Up @@ -238,8 +237,8 @@ public async Task<CanProcessNewWorkResponse> CanProcessNewWork(Node node) {
/// fuzzing tasks with patch reboot cycles.
public async Async.Task ReimageLongLivedNodes(Guid scaleSetId) {
var timeFilter = Query.OlderThan("initialized_at", DateTimeOffset.UtcNow - INodeOperations.NODE_REIMAGE_TIME);
//force ToString(), since all GUIDs are strings in the table
await foreach (var node in QueryAsync(Query.And(TableClient.CreateQueryFilter($"scaleset_id eq {scaleSetId.ToString()}"), timeFilter))) {

await foreach (var node in QueryAsync(Query.And(Query.CreateQueryFilter($"scaleset_id eq {scaleSetId}"), timeFilter))) {
if (node.DebugKeepNode) {
_logTracer.Info($"removing debug_keep_node for expired node. scaleset_id:{node.ScalesetId} machine_id:{node.MachineId}");
}
Expand Down Expand Up @@ -280,15 +279,15 @@ public static string SearchOutdatedQuery(
List<string> queryParts = new();

if (poolId is not null) {
queryParts.Add(TableClient.CreateQueryFilter($"(pool_id eq {poolId})"));
queryParts.Add(Query.CreateQueryFilter($"(pool_id eq {poolId})"));
}

if (poolName is not null) {
queryParts.Add(TableClient.CreateQueryFilter($"(pool_name eq {poolName.String})"));
queryParts.Add(Query.CreateQueryFilter($"(pool_name eq {poolName.String})"));
}

if (scalesetId is not null) {
queryParts.Add(TableClient.CreateQueryFilter($"(scaleset_id eq {scalesetId})"));
queryParts.Add(Query.CreateQueryFilter($"(scaleset_id eq {scalesetId})"));
}

if (states is not null) {
Expand All @@ -304,7 +303,7 @@ public static string SearchOutdatedQuery(
//# azure table query always return false when the column does not exist
//# We write the query this way to allow us to get the nodes where the
//# version is not defined as well as the nodes with a mismatched version
var versionQuery = TableClient.CreateQueryFilter($"not (version eq {oneFuzzVersion})");
var versionQuery = Query.CreateQueryFilter($"not (version eq {oneFuzzVersion})");
queryParts.Add(versionQuery);
return Query.And(queryParts);
}
Expand Down Expand Up @@ -581,7 +580,7 @@ public IAsyncEnumerable<Node> SearchStates(
}

public IAsyncEnumerable<Node> SearchByPoolName(PoolName poolName) {
return QueryAsync(TableClient.CreateQueryFilter($"(pool_name eq {poolName.String})"));
return QueryAsync(Query.CreateQueryFilter($"(pool_name eq {poolName.String})"));
}


Expand Down
12 changes: 5 additions & 7 deletions src/ApiService/ApiService/onefuzzlib/ProxyForwardOperations.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
using Azure.Data.Tables;

namespace Microsoft.OneFuzz.Service;

Expand All @@ -25,15 +24,14 @@ public IAsyncEnumerable<ProxyForward> SearchForward(Guid? scalesetId = null, Reg

var conditions =
new[] {
scalesetId is not null ? TableClient.CreateQueryFilter($"scaleset_id eq {scalesetId}") : null,
region is not null ? TableClient.CreateQueryFilter($"PartitionKey eq {region.String}") : null ,
machineId is not null ? TableClient.CreateQueryFilter($"machine_id eq {machineId}") : null ,
proxyId is not null ? TableClient.CreateQueryFilter($"proxy_id eq {proxyId}") : null ,
dstPort is not null ? TableClient.CreateQueryFilter($"dst_port eq {dstPort}") : null ,
scalesetId is not null ? Query.CreateQueryFilter($"scaleset_id eq {scalesetId}") : null,
region is not null ? Query.CreateQueryFilter($"PartitionKey eq {region.String}") : null ,
machineId is not null ? Query.CreateQueryFilter($"machine_id eq {machineId}") : null ,
proxyId is not null ? Query.CreateQueryFilter($"proxy_id eq {proxyId}") : null ,
dstPort is not null ? Query.CreateQueryFilter($"dst_port eq {dstPort}") : null ,
}.Where(x => x != null);

var filter = Query.And(conditions!);

return QueryAsync(filter);
}

Expand Down
3 changes: 1 addition & 2 deletions src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
using Azure.Data.Tables;
using Azure.ResourceManager.Compute.Models;
using Azure.Storage.Sas;
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
Expand Down Expand Up @@ -41,7 +40,7 @@ public ProxyOperations(ILogTracer log, IOnefuzzContext context)

public async Async.Task<Proxy> GetOrCreate(Region region) {
{
var proxyList = QueryAsync(filter: TableClient.CreateQueryFilter($"PartitionKey eq {region.String} and outdated eq false"));
var proxyList = QueryAsync(filter: Query.CreateQueryFilter($"PartitionKey eq {region.String} and outdated eq false"));
await foreach (var proxy in proxyList) {
if (IsOutdated(proxy)) {
var r1 = await Replace(proxy with { Outdated = true });
Expand Down
4 changes: 2 additions & 2 deletions src/ApiService/ApiService/onefuzzlib/VmssOperations.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Net;
using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
using Azure;
using Azure.Core;
using Azure.Data.Tables;
using Azure.ResourceManager.Compute;
using Azure.ResourceManager.Compute.Models;
using Azure.ResourceManager.Models;
Expand Down Expand Up @@ -420,7 +420,7 @@ public Async.Task<IReadOnlyList<string>> ListAvailableSkus(Region region)
entry = entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(10));

var sub = _creds.GetSubscriptionResource();
var skus = sub.GetResourceSkusAsync(filter: TableClient.CreateQueryFilter($"location eq {region.String}"));
var skus = sub.GetResourceSkusAsync(filter: Query.CreateQueryFilter($"location eq {region.String}"));

var skuNames = new List<string>();
await foreach (var sku in skus) {
Expand Down
30 changes: 21 additions & 9 deletions src/ApiService/ApiService/onefuzzlib/orm/Queries.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Azure.Data.Tables;
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;

Expand All @@ -8,11 +9,22 @@ public static class Query {
// and handles escaping the interpolated values properly. It also handles quoting the values
// where needed, so use {string} and not '{string}'.

public static string CreateQueryFilter(FormattableString input) {
var args = input.GetArguments();

for (int i = 0; i < args.Length; i++) {
if (args[i] is Guid g) {
args[i] = g.ToString();
}
}

return TableClient.CreateQueryFilter(FormattableStringFactory.Create(input.Format, args));
}
public static string PartitionKey(string partitionKey)
=> TableClient.CreateQueryFilter($"PartitionKey eq {partitionKey}");
=> CreateQueryFilter($"PartitionKey eq {partitionKey}");

public static string RowKey(string rowKey)
=> TableClient.CreateQueryFilter($"RowKey eq {rowKey}");
=> CreateQueryFilter($"RowKey eq {rowKey}");

public static string PartitionKeys(IEnumerable<string> partitionKeys)
=> Or(partitionKeys.Select(PartitionKey));
Expand All @@ -21,7 +33,7 @@ public static string RowKeys(IEnumerable<string> rowKeys)
=> Or(rowKeys.Select(RowKey));

public static string SingleEntity(string partitionKey, string rowKey)
=> TableClient.CreateQueryFilter($"(PartitionKey eq {partitionKey}) and (RowKey eq {rowKey})");
=> CreateQueryFilter($"(PartitionKey eq {partitionKey}) and (RowKey eq {rowKey})");

public static string Or(IEnumerable<string> queries)
// subqueries should already be properly escaped
Expand Down Expand Up @@ -54,21 +66,21 @@ public static string EqualEnum<T>(string property, T e) where T : Enum {
public static string TimeRange(DateTimeOffset min, DateTimeOffset max) {
// NB: this uses the auto-populated Timestamp property, and will result in a table scan
// TODO: should this be inclusive at the endpoints?
return TableClient.CreateQueryFilter($"Timestamp lt {max} and Timestamp gt {min}");
return CreateQueryFilter($"Timestamp lt {max} and Timestamp gt {min}");
}

public static string TimestampNewerThan(DateTimeOffset t) {
return TableClient.CreateQueryFilter($"Timestamp gt {t}");
return CreateQueryFilter($"Timestamp gt {t}");
}
public static string NewerThan(string field, DateTimeOffset t) {
return $"{field} gt {TableClient.CreateQueryFilter($"{t}")}";
return $"{field} gt {CreateQueryFilter($"{t}")}";
}
public static string TimestampOlderThan(DateTimeOffset t) {
return TableClient.CreateQueryFilter($"Timestamp lt {t}");
return CreateQueryFilter($"Timestamp lt {t}");
}

public static string OlderThan(string field, DateTimeOffset t) {
return $"{field} lt {TableClient.CreateQueryFilter($"{t}")}";
return $"{field} lt {CreateQueryFilter($"{t}")}";
}

public static string StartsWith(string property, string prefix) {
Expand Down
19 changes: 19 additions & 0 deletions src/ApiService/Tests/QueryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ public void NodeOperationsSearchStatesQuery() {
Assert.Equal("((pool_id eq '3b0426d3-9bde-4ae8-89ac-4edf0d3b3618')) and ((scaleset_id eq '4c96dd6b-9bdb-4758-9720-1010c244fa4b')) and (((state eq 'free') or (state eq 'done') or (state eq 'ready')))", query7);
}

[Fact]
public void QueryFilterTest() {

var scalesetId = Guid.Parse("3b0426d3-9bde-4ae8-89ac-4edf0d3b3618");
var proxyId = Guid.Parse("4c96dd6b-9bdb-4758-9720-1010c244fa4b");
var region = "westus2";
var outdated = false;

var string1 = Query.CreateQueryFilter($"scaleset_id eq {scalesetId}");
Assert.Equal("scaleset_id eq '3b0426d3-9bde-4ae8-89ac-4edf0d3b3618'", string1);

var string2 = Query.CreateQueryFilter($"proxy_id eq {proxyId}");
Assert.NotEqual("proxy_id eq guid'4c96dd6b-9bdb-4758-9720-1010c244fa4b'", string2);

var string3 = Query.CreateQueryFilter($"PartitionKey eq {region} and outdated eq {outdated} and scaleset_id eq {scalesetId} and proxy_id eq {proxyId}");
Assert.Equal("PartitionKey eq 'westus2' and outdated eq false and scaleset_id eq '3b0426d3-9bde-4ae8-89ac-4edf0d3b3618' and proxy_id eq '4c96dd6b-9bdb-4758-9720-1010c244fa4b'", string3);

}

[Fact]
public void StartsWithTests() {
var query = Query.StartsWith("prop", "prefix");
Expand Down