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

Commit 75039a9

Browse files
nharper285chkeita
andauthored
[C# Port] Adding new Proxy Update Queue Function. (#1757)
* Adding QueueProxyUpdate. * Setting to serializer. * Updates. * Updating with new ORM model and [model]Operation. * Fixing return type. * Working on changes. * Tested and ready for review. * Formatting. * Removing test code. * Update src/ApiService/Tests/OrmTest.cs Co-authored-by: Cheick Keita <chkeita@microsoft.com> * Fixing tests. * Fixing tests again. * Asserting null in tests. * Adding null param. * Removing whitespace. * syntax error. Co-authored-by: Cheick Keita <chkeita@microsoft.com>
1 parent 5aceb25 commit 75039a9

File tree

7 files changed

+141
-2
lines changed

7 files changed

+141
-2
lines changed

src/ApiService/ApiService/OneFuzzTypes/Enums.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@
2626
INVALID_CONFIGURATION = 473,
2727
}
2828

29+
public enum VmState
30+
{
31+
Init,
32+
ExtensionsLaunched,
33+
ExtensionsFailed,
34+
VmAllocationFailed,
35+
Running,
36+
Stopping,
37+
Stopped
38+
}
2939

3040
public enum WebhookMessageState
3141
{

src/ApiService/ApiService/OneFuzzTypes/Model.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
22
using System;
3+
using System.Collections.Generic;
34
using PoolName = System.String;
45

56
namespace Microsoft.OneFuzz.Service;
@@ -14,6 +15,12 @@ namespace Microsoft.OneFuzz.Service;
1415
/// the "partion key" and "row key" are identified by the [PartitionKey] and [RowKey] attributes
1516
/// Guids are mapped to string in the db
1617

18+
public record Authentication
19+
(
20+
string Password,
21+
string PublicKey,
22+
string PrivateKey
23+
);
1724

1825
[SkipRename]
1926
public enum HeartbeatType
@@ -70,6 +77,13 @@ public enum NodeState
7077
Halt,
7178
}
7279

80+
public record ProxyHeartbeat
81+
(
82+
string Region,
83+
Guid ProxyId,
84+
List<ProxyForward> Forwards,
85+
DateTimeOffset TimeStamp
86+
);
7387

7488
public partial record Node
7589
(
@@ -87,6 +101,39 @@ bool DebugKeepNode
87101
) : EntityBase();
88102

89103

104+
public partial record ProxyForward
105+
(
106+
[PartitionKey] string Region,
107+
[RowKey] int DstPort,
108+
int SrcPort,
109+
string DstIp
110+
) : EntityBase();
111+
112+
public partial record ProxyConfig
113+
(
114+
Uri Url,
115+
string Notification,
116+
string Region,
117+
Guid? ProxyId,
118+
List<ProxyForward> Forwards,
119+
string InstanceTelemetryKey,
120+
string MicrosoftTelemetryKey
121+
122+
);
123+
124+
public partial record Proxy
125+
(
126+
[PartitionKey] string Region,
127+
[RowKey] Guid ProxyId,
128+
DateTimeOffset? CreatedTimestamp,
129+
VmState State,
130+
Authentication Auth,
131+
string? Ip,
132+
Error? Error,
133+
string Version,
134+
ProxyHeartbeat? heartbeat
135+
) : EntityBase();
136+
90137
public record Error(ErrorCode Code, string[]? Errors = null);
91138

92139
public record UserInfo(Guid? ApplicationId, Guid? ObjectId, String? Upn);

src/ApiService/ApiService/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static void Main()
4242
.AddSingleton<IQueue, Queue>()
4343
.AddSingleton<ICreds>(_ => new Creds())
4444
.AddSingleton<IStorage, Storage>()
45+
.AddSingleton<IProxyOperations, ProxyOperations>()
4546
)
4647
.Build();
4748

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using Microsoft.Azure.Functions.Worker;
3+
using Microsoft.Extensions.Logging;
4+
using System.Text.Json;
5+
using System.Threading.Tasks;
6+
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
7+
8+
namespace Microsoft.OneFuzz.Service;
9+
10+
public class QueueProxyHearbeat
11+
{
12+
private readonly ILogger _logger;
13+
14+
private readonly IProxyOperations _proxy;
15+
16+
public QueueProxyHearbeat(ILoggerFactory loggerFactory, IProxyOperations proxy)
17+
{
18+
_logger = loggerFactory.CreateLogger<QueueProxyHearbeat>();
19+
_proxy = proxy;
20+
}
21+
22+
[Function("QueueProxyHearbeat")]
23+
public async Task Run([QueueTrigger("myqueue-items", Connection = "AzureWebJobsStorage")] string msg)
24+
{
25+
_logger.LogInformation($"heartbeat: {msg}");
26+
27+
var hb = JsonSerializer.Deserialize<ProxyHeartbeat>(msg, EntityConverter.GetJsonSerializerOptions()).EnsureNotNull($"wrong data {msg}"); ;
28+
var newHb = hb with { TimeStamp = DateTimeOffset.UtcNow };
29+
30+
var proxy = await _proxy.GetByProxyId(newHb.ProxyId);
31+
32+
if (proxy == null)
33+
{
34+
_logger.LogWarning($"invalid proxy id: {newHb.ProxyId}");
35+
return;
36+
}
37+
var newProxy = proxy with { heartbeat = newHb };
38+
39+
await _proxy.Replace(newProxy);
40+
41+
}
42+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using ApiService.OneFuzzLib.Orm;
2+
using System;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace Microsoft.OneFuzz.Service;
8+
9+
public interface IProxyOperations : IOrm<Proxy>
10+
{
11+
Task<Proxy?> GetByProxyId(Guid proxyId);
12+
}
13+
public class ProxyOperations : Orm<Proxy>, IProxyOperations
14+
{
15+
private readonly ILogger _logger;
16+
17+
public ProxyOperations(ILoggerFactory loggerFactory, IStorage storage)
18+
: base(storage)
19+
{
20+
_logger = loggerFactory.CreateLogger<QueueProxyHearbeat>();
21+
}
22+
23+
public async Task<Proxy?> GetByProxyId(Guid proxyId)
24+
{
25+
26+
var data = QueryAsync(filter: $"RowKey eq '{proxyId}'");
27+
28+
return await data.FirstOrDefaultAsync();
29+
}
30+
}

src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ public T ToRecord<T>(TableEntity entity) where T : EntityBase
245245
else
246246
{
247247
var value = entity.GetString(fieldName);
248+
if (value == null)
249+
{
250+
return null;
251+
}
248252
return JsonSerializer.Deserialize(value, ef.type, options: _options); ;
249253
}
250254
}

src/ApiService/Tests/OrmTest.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ record Entity1(
3939
TestEnum TheEnum,
4040
TestFlagEnum TheFlag,
4141
[property: JsonPropertyName("a__special__name")] string Renamed,
42-
TestObject TheObject
42+
TestObject TheObject,
43+
TestObject? TestNull
4344
) : EntityBase();
4445

4546

@@ -60,7 +61,8 @@ public void TestConvertToTableEntity()
6061
TheName = "testobject",
6162
TheEnum = TestEnum.TheTwo,
6263
TheFlag = TestFlagEnum.FlagOne | TestFlagEnum.FlagTwo
63-
});
64+
},
65+
null);
6466
var tableEntity = converter.ToTableEntity(entity1);
6567

6668
Assert.NotNull(tableEntity);
@@ -97,6 +99,7 @@ public void TestFromtableEntity()
9799
{ "the_flag", "flag_one,flag_two"},
98100
{ "a__special__name", "renamed"},
99101
{ "the_object", "{\"the_name\": \"testName\", \"the_enum\": \"the_one\", \"the_flag\": \"flag_one,flag_two\"}"},
102+
{ "test_null", null},
100103
};
101104

102105
var entity1 = converter.ToRecord<Entity1>(tableEntity);
@@ -109,6 +112,8 @@ public void TestFromtableEntity()
109112
Assert.Equal(tableEntity.GetDouble("the_float"), entity1.TheFloat);
110113
Assert.Equal(TestEnum.TheTwo, entity1.TheEnum);
111114
Assert.Equal(tableEntity.GetString("a__special__name"), entity1.Renamed);
115+
Assert.Null(tableEntity.GetString("test_null"));
116+
Assert.Null(entity1.TestNull);
112117

113118
Assert.Equal("testName", entity1.TheObject.TheName);
114119
Assert.Equal(TestEnum.TheOne, entity1.TheObject.TheEnum);

0 commit comments

Comments
 (0)