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

Commit 8a7a0b0

Browse files
authored
[Bug Fix] Create Wrapper Function To Handle GUID Table Properties (#2898)
* Investigating Proxy Issues. * Creating and using wrapper function that converts GUIDs to strings. * Remove log statements. * Removing logging statements. * Formatting imports. * Removing more logging. * Adding unit test for filter. * Remove comment.
1 parent e653f9b commit 8a7a0b0

File tree

7 files changed

+55
-29
lines changed

7 files changed

+55
-29
lines changed

src/ApiService/ApiService/Functions/Proxy.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ private ProxyGetResult GetResult(ProxyForward proxyForward, VmProxy? proxy) {
3838
) {
3939
return new ProxyGetResult(null, Forward: forward);
4040
}
41-
4241
return new ProxyGetResult(proxy.Ip, forward);
4342
}
4443

src/ApiService/ApiService/onefuzzlib/NodeOperations.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Threading.Tasks;
33
using ApiService.OneFuzzLib.Orm;
44
using Azure;
5-
using Azure.Data.Tables;
65

76
namespace Microsoft.OneFuzz.Service;
87

@@ -238,8 +237,8 @@ public async Task<CanProcessNewWorkResponse> CanProcessNewWork(Node node) {
238237
/// fuzzing tasks with patch reboot cycles.
239238
public async Async.Task ReimageLongLivedNodes(Guid scaleSetId) {
240239
var timeFilter = Query.OlderThan("initialized_at", DateTimeOffset.UtcNow - INodeOperations.NODE_REIMAGE_TIME);
241-
//force ToString(), since all GUIDs are strings in the table
242-
await foreach (var node in QueryAsync(Query.And(TableClient.CreateQueryFilter($"scaleset_id eq {scaleSetId.ToString()}"), timeFilter))) {
240+
241+
await foreach (var node in QueryAsync(Query.And(Query.CreateQueryFilter($"scaleset_id eq {scaleSetId}"), timeFilter))) {
243242
if (node.DebugKeepNode) {
244243
_logTracer.Info($"removing debug_keep_node for expired node. scaleset_id:{node.ScalesetId} machine_id:{node.MachineId}");
245244
}
@@ -280,15 +279,15 @@ public static string SearchOutdatedQuery(
280279
List<string> queryParts = new();
281280

282281
if (poolId is not null) {
283-
queryParts.Add(TableClient.CreateQueryFilter($"(pool_id eq {poolId})"));
282+
queryParts.Add(Query.CreateQueryFilter($"(pool_id eq {poolId})"));
284283
}
285284

286285
if (poolName is not null) {
287-
queryParts.Add(TableClient.CreateQueryFilter($"(pool_name eq {poolName.String})"));
286+
queryParts.Add(Query.CreateQueryFilter($"(pool_name eq {poolName.String})"));
288287
}
289288

290289
if (scalesetId is not null) {
291-
queryParts.Add(TableClient.CreateQueryFilter($"(scaleset_id eq {scalesetId})"));
290+
queryParts.Add(Query.CreateQueryFilter($"(scaleset_id eq {scalesetId})"));
292291
}
293292

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

583582
public IAsyncEnumerable<Node> SearchByPoolName(PoolName poolName) {
584-
return QueryAsync(TableClient.CreateQueryFilter($"(pool_name eq {poolName.String})"));
583+
return QueryAsync(Query.CreateQueryFilter($"(pool_name eq {poolName.String})"));
585584
}
586585

587586

src/ApiService/ApiService/onefuzzlib/ProxyForwardOperations.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Threading.Tasks;
22
using ApiService.OneFuzzLib.Orm;
3-
using Azure.Data.Tables;
43

54
namespace Microsoft.OneFuzz.Service;
65

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

2625
var conditions =
2726
new[] {
28-
scalesetId is not null ? TableClient.CreateQueryFilter($"scaleset_id eq {scalesetId}") : null,
29-
region is not null ? TableClient.CreateQueryFilter($"PartitionKey eq {region.String}") : null ,
30-
machineId is not null ? TableClient.CreateQueryFilter($"machine_id eq {machineId}") : null ,
31-
proxyId is not null ? TableClient.CreateQueryFilter($"proxy_id eq {proxyId}") : null ,
32-
dstPort is not null ? TableClient.CreateQueryFilter($"dst_port eq {dstPort}") : null ,
27+
scalesetId is not null ? Query.CreateQueryFilter($"scaleset_id eq {scalesetId}") : null,
28+
region is not null ? Query.CreateQueryFilter($"PartitionKey eq {region.String}") : null ,
29+
machineId is not null ? Query.CreateQueryFilter($"machine_id eq {machineId}") : null ,
30+
proxyId is not null ? Query.CreateQueryFilter($"proxy_id eq {proxyId}") : null ,
31+
dstPort is not null ? Query.CreateQueryFilter($"dst_port eq {dstPort}") : null ,
3332
}.Where(x => x != null);
3433

3534
var filter = Query.And(conditions!);
36-
3735
return QueryAsync(filter);
3836
}
3937

src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Threading.Tasks;
22
using ApiService.OneFuzzLib.Orm;
3-
using Azure.Data.Tables;
43
using Azure.ResourceManager.Compute.Models;
54
using Azure.Storage.Sas;
65
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
@@ -41,7 +40,7 @@ public ProxyOperations(ILogTracer log, IOnefuzzContext context)
4140

4241
public async Async.Task<Proxy> GetOrCreate(Region region) {
4342
{
44-
var proxyList = QueryAsync(filter: TableClient.CreateQueryFilter($"PartitionKey eq {region.String} and outdated eq false"));
43+
var proxyList = QueryAsync(filter: Query.CreateQueryFilter($"PartitionKey eq {region.String} and outdated eq false"));
4544
await foreach (var proxy in proxyList) {
4645
if (IsOutdated(proxy)) {
4746
var r1 = await Replace(proxy with { Outdated = true });

src/ApiService/ApiService/onefuzzlib/VmssOperations.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using System.Net;
22
using System.Threading.Tasks;
3+
using ApiService.OneFuzzLib.Orm;
34
using Azure;
45
using Azure.Core;
5-
using Azure.Data.Tables;
66
using Azure.ResourceManager.Compute;
77
using Azure.ResourceManager.Compute.Models;
88
using Azure.ResourceManager.Models;
@@ -420,7 +420,7 @@ public Async.Task<IReadOnlyList<string>> ListAvailableSkus(Region region)
420420
entry = entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(10));
421421

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

425425
var skuNames = new List<string>();
426426
await foreach (var sku in skus) {

src/ApiService/ApiService/onefuzzlib/orm/Queries.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Text.Json;
1+
using System.Runtime.CompilerServices;
2+
using System.Text.Json;
23
using Azure.Data.Tables;
34
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
45

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

12+
public static string CreateQueryFilter(FormattableString input) {
13+
var args = input.GetArguments();
14+
15+
for (int i = 0; i < args.Length; i++) {
16+
if (args[i] is Guid g) {
17+
args[i] = g.ToString();
18+
}
19+
}
20+
21+
return TableClient.CreateQueryFilter(FormattableStringFactory.Create(input.Format, args));
22+
}
1123
public static string PartitionKey(string partitionKey)
12-
=> TableClient.CreateQueryFilter($"PartitionKey eq {partitionKey}");
24+
=> CreateQueryFilter($"PartitionKey eq {partitionKey}");
1325

1426
public static string RowKey(string rowKey)
15-
=> TableClient.CreateQueryFilter($"RowKey eq {rowKey}");
27+
=> CreateQueryFilter($"RowKey eq {rowKey}");
1628

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

2335
public static string SingleEntity(string partitionKey, string rowKey)
24-
=> TableClient.CreateQueryFilter($"(PartitionKey eq {partitionKey}) and (RowKey eq {rowKey})");
36+
=> CreateQueryFilter($"(PartitionKey eq {partitionKey}) and (RowKey eq {rowKey})");
2537

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

6072
public static string TimestampNewerThan(DateTimeOffset t) {
61-
return TableClient.CreateQueryFilter($"Timestamp gt {t}");
73+
return CreateQueryFilter($"Timestamp gt {t}");
6274
}
6375
public static string NewerThan(string field, DateTimeOffset t) {
64-
return $"{field} gt {TableClient.CreateQueryFilter($"{t}")}";
76+
return $"{field} gt {CreateQueryFilter($"{t}")}";
6577
}
6678
public static string TimestampOlderThan(DateTimeOffset t) {
67-
return TableClient.CreateQueryFilter($"Timestamp lt {t}");
79+
return CreateQueryFilter($"Timestamp lt {t}");
6880
}
6981

7082
public static string OlderThan(string field, DateTimeOffset t) {
71-
return $"{field} lt {TableClient.CreateQueryFilter($"{t}")}";
83+
return $"{field} lt {CreateQueryFilter($"{t}")}";
7284
}
7385

7486
public static string StartsWith(string property, string prefix) {

src/ApiService/Tests/QueryTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,25 @@ public void NodeOperationsSearchStatesQuery() {
3030
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);
3131
}
3232

33+
[Fact]
34+
public void QueryFilterTest() {
35+
36+
var scalesetId = Guid.Parse("3b0426d3-9bde-4ae8-89ac-4edf0d3b3618");
37+
var proxyId = Guid.Parse("4c96dd6b-9bdb-4758-9720-1010c244fa4b");
38+
var region = "westus2";
39+
var outdated = false;
40+
41+
var string1 = Query.CreateQueryFilter($"scaleset_id eq {scalesetId}");
42+
Assert.Equal("scaleset_id eq '3b0426d3-9bde-4ae8-89ac-4edf0d3b3618'", string1);
43+
44+
var string2 = Query.CreateQueryFilter($"proxy_id eq {proxyId}");
45+
Assert.NotEqual("proxy_id eq guid'4c96dd6b-9bdb-4758-9720-1010c244fa4b'", string2);
46+
47+
var string3 = Query.CreateQueryFilter($"PartitionKey eq {region} and outdated eq {outdated} and scaleset_id eq {scalesetId} and proxy_id eq {proxyId}");
48+
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);
49+
50+
}
51+
3352
[Fact]
3453
public void StartsWithTests() {
3554
var query = Query.StartsWith("prop", "prefix");

0 commit comments

Comments
 (0)