Skip to content

Commit

Permalink
Merge branch 'main' into jg/dynamicobject
Browse files Browse the repository at this point in the history
  • Loading branch information
aneojgurhem authored Dec 19, 2024
2 parents d6e75c7 + e32b6c5 commit 8f7a0f0
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 71 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ jobs:
- name: Dotnet Restore
run: |
MONITOR_PREFIX="monitor/restore/" MONITOR_CD=${{ matrix.projects }} tools/retry.sh -w 60 -- tools/monitor.sh \
MONITOR_PREFIX="monitor/restore/" tools/retry.sh -w 60 -- tools/monitor.sh \
dotnet restore
- name: Dotnet Build
run: |
MONITOR_PREFIX="monitor/build/" MONITOR_CD=${{ matrix.projects }} tools/monitor.sh \
MONITOR_PREFIX="monitor/build/" tools/monitor.sh \
dotnet build
- name: Run tests
Expand Down Expand Up @@ -314,7 +314,7 @@ jobs:
username: ${{ secrets.DOCKER_HUB_LOGIN }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Analyze for critical and high CVEs
uses: docker/scout-action@6ac950eb733f8b2811f25c05d97bfb3d181b8026 # v1
uses: docker/scout-action@b23590dc1e4d09febc00cfcbc51e9e8c0f7ee9f3 # v1
with:
command: cves
image: "${{ matrix.image }}:${{ needs.versionning.outputs.version }}"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scout-cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
username: ${{ secrets.DOCKER_HUB_LOGIN }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Analyze for critical and high CVEs
uses: docker/scout-action@6ac950eb733f8b2811f25c05d97bfb3d181b8026 # v1
uses: docker/scout-action@b23590dc1e4d09febc00cfcbc51e9e8c0f7ee9f3 # v1
with:
command: cves
image: "${{ matrix.image }}:${{ matrix.image }}"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/sonar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ jobs:
submodules: true

- name: Cache SonarCloud packages
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4
with:
path: .\.sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
Expand Down
106 changes: 106 additions & 0 deletions Common/src/DynamicLoading/CollocatedAssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// This file is part of the ArmoniK project
//
// Copyright (C) ANEO, 2021-2024. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Concurrent;
using System.IO;
using System.Reflection;

using Microsoft.Extensions.Logging;

namespace ArmoniK.Core.Common.DynamicLoading;

public class CollocatedAssemblyResolver
{
private static readonly ConcurrentDictionary<string, bool> PathDictionary = new();
private readonly ILogger logger_;


public CollocatedAssemblyResolver(ILogger logger)
{
GetLoadDirectories();
logger_ = logger;
}

private static void GetLoadDirectories()
{
AppDomain.CurrentDomain.AssemblyLoad += (_,
eventArgs) =>
{
var path = Path.GetDirectoryName(eventArgs.LoadedAssembly.Location);
if (path == null)
{
return;
}

PathDictionary[path] = true;
};

PathDictionary[Path.GetDirectoryName(Assembly.GetCallingAssembly()
.Location)!] = true;

PathDictionary[Path.GetDirectoryName(typeof(CollocatedAssemblyResolver).Assembly.Location)!] = true;
}

public Assembly? AssemblyResolve(object? sender,
ResolveEventArgs args)
{
logger_.LogDebug("RequestingAssembly {RequestingAssembly}",
args.RequestingAssembly);

if (args.RequestingAssembly?.Location is null)
{
return null;
}

var assemblyName = new AssemblyName(args.Name).Name;

if (string.IsNullOrEmpty(assemblyName))
{
logger_.LogWarning("The assembly to resolve {AssemblyToResolve} does not have a name",
args.Name);
return null;
}

var directoryName = Path.GetDirectoryName(args.RequestingAssembly.Location);

if (!string.IsNullOrEmpty(directoryName))
{
PathDictionary[directoryName] = true;
}

foreach (var path in PathDictionary.Keys)
{
var assemblyPath = Path.Combine(path,
assemblyName + ".dll");

if (File.Exists(assemblyPath))
{
logger_.LogDebug("Loading assembly {Assembly} from {Directory}",
assemblyName,
path);
return Assembly.LoadFile(assemblyPath);
}

logger_.LogDebug("Assembly {Assembly} not found in {Directory}",
assemblyName,
path);
}

return null;
}
}
54 changes: 0 additions & 54 deletions Common/src/Injection/AdapterLoadContext.cs

This file was deleted.

3 changes: 1 addition & 2 deletions Common/src/Injection/ServiceCollectionExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ public static IServiceCollection AddAdapter(this IServiceCollection services,
throw new InvalidOperationException($"{nameof(settings.ClassName)} should not be null or empty.");
}

var ctx = new AdapterLoadContext(settings.AdapterAbsolutePath);
var assembly = ctx.LoadFromAssemblyName(AssemblyName.GetAssemblyName(settings.AdapterAbsolutePath));
var assembly = Assembly.LoadFrom(settings.AdapterAbsolutePath);
logger.LogInformation("Loaded assembly {assemblyName}",
assembly.FullName);

Expand Down
64 changes: 56 additions & 8 deletions Common/tests/AdapterLoading/AdapterLoadingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using System.Collections.Generic;
using System.IO;

using ArmoniK.Core.Common.DynamicLoading;
using ArmoniK.Core.Common.Injection;
using ArmoniK.Core.Common.Injection.Options;
using ArmoniK.Core.Common.Tests.Helpers;
Expand All @@ -46,6 +47,12 @@ public class AdapterLoadingTest
private static readonly string RabbitPath =
$"{Path.DirectorySeparatorChar}Adaptors{Path.DirectorySeparatorChar}RabbitMQ{Path.DirectorySeparatorChar}src{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}Debug{Path.DirectorySeparatorChar}net8.0{Path.DirectorySeparatorChar}ArmoniK.Core.Adapters.RabbitMQ.dll";

private static readonly string SqsPath =
$"{Path.DirectorySeparatorChar}Adaptors{Path.DirectorySeparatorChar}SQS{Path.DirectorySeparatorChar}src{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}Debug{Path.DirectorySeparatorChar}net8.0{Path.DirectorySeparatorChar}ArmoniK.Core.Adapters.SQS.dll";

private static readonly string PubSubPath =
$"{Path.DirectorySeparatorChar}Adaptors{Path.DirectorySeparatorChar}PubSub{Path.DirectorySeparatorChar}src{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}Debug{Path.DirectorySeparatorChar}net8.0{Path.DirectorySeparatorChar}ArmoniK.Core.Adapters.PubSub.dll";


public static IEnumerable TestCasesQueueLocation
{
Expand All @@ -63,6 +70,8 @@ public static void BuildServiceProvider(Dictionary<string, string?> config)
var loggerProvider = new ConsoleForwardingLoggerProvider();
var logger = loggerProvider.CreateLogger("root");

AppDomain.CurrentDomain.AssemblyResolve += new CollocatedAssemblyResolver(logger).AssemblyResolve;

var configuration = new ConfigurationManager();
configuration.AddInMemoryCollection(config);

Expand Down Expand Up @@ -94,20 +103,22 @@ public void QueueShouldLoad(string path,
},
};

Assert.DoesNotThrow(() => BuildServiceProvider(config));
BuildServiceProvider(config);
}

public static IEnumerable ConfInvalidOperationException
{
get
{
yield return new TestCaseData(new Dictionary<string, string?>
yield return new TestCaseData(new InvalidOperationException(),
new Dictionary<string, string?>
{
{
"Amqp:User", "User"
},
}).SetArgDisplayNames("No components");
yield return new TestCaseData(new Dictionary<string, string?>
yield return new TestCaseData(new InvalidOperationException(),
new Dictionary<string, string?>
{
{
"Amqp:User", "User"
Expand All @@ -116,7 +127,8 @@ public static IEnumerable ConfInvalidOperationException
$"{Components.SettingSection}:{nameof(Components.QueueAdaptorSettings)}:{nameof(Components.QueueAdaptorSettings.ClassName)}", ""
},
}).SetArgDisplayNames("Empty class");
yield return new TestCaseData(new Dictionary<string, string?>
yield return new TestCaseData(new InvalidOperationException(),
new Dictionary<string, string?>
{
{
"Amqp:User", "User"
Expand All @@ -129,7 +141,8 @@ public static IEnumerable ConfInvalidOperationException
"path"
},
}).SetArgDisplayNames("Empty path");
yield return new TestCaseData(new Dictionary<string, string?>
yield return new TestCaseData(new FileNotFoundException(),
new Dictionary<string, string?>
{
{
"Amqp:User", "User"
Expand All @@ -144,7 +157,8 @@ public static IEnumerable ConfInvalidOperationException
},
}).SetArgDisplayNames("invalid path");

yield return new TestCaseData(new Dictionary<string, string?>
yield return new TestCaseData(new InvalidOperationException(),
new Dictionary<string, string?>
{
{
"Amqp:User", "User"
Expand All @@ -158,13 +172,47 @@ public static IEnumerable ConfInvalidOperationException
$"{SolutionRoot}{AmqpPath}"
},
}).SetArgDisplayNames("Not implemented");

yield return new TestCaseData(new InvalidOperationException(),
new Dictionary<string, string?>
{
{
"PubSub:hey", "hey"
},
{
$"{Components.SettingSection}:{nameof(Components.QueueAdaptorSettings)}:{nameof(Components.QueueAdaptorSettings.ClassName)}",
"ArmoniK.Core.Adapters.PubSub.QueueBuilder"
},
{
$"{Components.SettingSection}:{nameof(Components.QueueAdaptorSettings)}:{nameof(Components.QueueAdaptorSettings.AdapterAbsolutePath)}",
$"{SolutionRoot}{PubSubPath}"
},
}).SetArgDisplayNames("PubSub no credentials");

yield return new TestCaseData(new MissingMethodException(),
new Dictionary<string, string?>
{
{
"SQS:ServiceURL", "ServiceURL"
},
{
$"{Components.SettingSection}:{nameof(Components.QueueAdaptorSettings)}:{nameof(Components.QueueAdaptorSettings.ClassName)}",
"ArmoniK.Core.Adapters.SQS.QueueBuilder"
},
{
$"{Components.SettingSection}:{nameof(Components.QueueAdaptorSettings)}:{nameof(Components.QueueAdaptorSettings.AdapterAbsolutePath)}",
$"{SolutionRoot}{SqsPath}"
},
}).SetArgDisplayNames("SQS misses a method when loading");
}
}

[Test]
[TestCaseSource(nameof(ConfInvalidOperationException))]
public void InvalidConfShouldFail(Dictionary<string, string?> config)
=> Assert.Throws<InvalidOperationException>(() => BuildServiceProvider(config));
public void InvalidConfShouldFail<TEx>(TEx ex,
Dictionary<string, string?> config)
where TEx : Exception
=> Assert.Throws<TEx>(() => BuildServiceProvider(config));

public static IEnumerable ConfTypeLoadException
{
Expand Down
3 changes: 3 additions & 0 deletions Compute/PollingAgent/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using ArmoniK.Core.Adapters.MongoDB;
using ArmoniK.Core.Base;
using ArmoniK.Core.Base.DataStructures;
using ArmoniK.Core.Common.DynamicLoading;
using ArmoniK.Core.Common.gRPC.Services;
using ArmoniK.Core.Common.Injection;
using ArmoniK.Core.Common.Injection.Options;
Expand Down Expand Up @@ -78,6 +79,8 @@ public static async Task<int> Main(string[] args)

try
{
AppDomain.CurrentDomain.AssemblyResolve += new CollocatedAssemblyResolver(logger.GetLogger()).AssemblyResolve;

var pollsterOptions = builder.Configuration.GetSection(Pollster.SettingSection)
.Get<Pollster>() ?? new Pollster();

Expand Down
3 changes: 3 additions & 0 deletions Control/Submitter/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using ArmoniK.Core.Base;
using ArmoniK.Core.Base.DataStructures;
using ArmoniK.Core.Common.Auth.Authentication;
using ArmoniK.Core.Common.DynamicLoading;
using ArmoniK.Core.Common.gRPC;
using ArmoniK.Core.Common.gRPC.Services;
using ArmoniK.Core.Common.Injection;
Expand Down Expand Up @@ -80,6 +81,8 @@ public static async Task<int> Main(string[] args)

try
{
AppDomain.CurrentDomain.AssemblyResolve += new CollocatedAssemblyResolver(logger.GetLogger()).AssemblyResolve;

builder.Host.UseSerilog(logger.GetSerilogConf());

builder.Services.AddLogging(logger.Configure)
Expand Down
Loading

0 comments on commit 8f7a0f0

Please sign in to comment.