diff --git a/Azaion.Common/Services/AnnotationService.cs b/Azaion.Common/Services/AnnotationService.cs index a9859cd..af769fe 100644 --- a/Azaion.Common/Services/AnnotationService.cs +++ b/Azaion.Common/Services/AnnotationService.cs @@ -39,7 +39,6 @@ public class AnnotationService : INotificationHandler IOptions uiConfig, IGalleryService galleryService, IMediator mediator, - IHardwareService hardwareService, IAzaionApi api) { _dbFactory = dbFactory; diff --git a/Azaion.CommonSecurity/Services/AuthProvider.cs b/Azaion.CommonSecurity/Services/AuthProvider.cs index a729a6f..4baabf5 100644 --- a/Azaion.CommonSecurity/Services/AuthProvider.cs +++ b/Azaion.CommonSecurity/Services/AuthProvider.cs @@ -11,10 +11,10 @@ public interface IAzaionApi ApiCredentials Credentials { get; } User CurrentUser { get; } void UpdateOffsets(UserQueueOffsets offsets); - Stream GetResource(string filename, string folder); + //Stream GetResource(string filename, string folder); } -public class AzaionApi(HttpClient client, ICache cache, ApiCredentials credentials, IHardwareService hardwareService) : IAzaionApi +public class AzaionApi(HttpClient client, ICache cache, ApiCredentials credentials) : IAzaionApi { private string _jwtToken = null!; const string APP_JSON = "application/json"; @@ -32,17 +32,6 @@ public class AzaionApi(HttpClient client, ICache cache, ApiCredentials credentia } } - public Stream GetResource(string filename, string folder) - { - var hardware = cache.GetFromCache(SecurityConstants.HARDWARE_INFO_KEY, hardwareService.GetHardware); - - var response = Send(new HttpRequestMessage(HttpMethod.Post, $"/resources/get/{folder}") - { - Content = new StringContent(JsonConvert.SerializeObject(new { filename, credentials.Password, hardware }), Encoding.UTF8, APP_JSON) - }); - return response.Content.ReadAsStream(); - } - public void UpdateOffsets(UserQueueOffsets offsets) { Put($"/users/queue-offsets/{CurrentUser.Email}", offsets); diff --git a/Azaion.CommonSecurity/Services/HardwareService.cs b/Azaion.CommonSecurity/Services/HardwareService.cs index e61cadf..ec13a92 100644 --- a/Azaion.CommonSecurity/Services/HardwareService.cs +++ b/Azaion.CommonSecurity/Services/HardwareService.cs @@ -8,96 +8,96 @@ namespace Azaion.CommonSecurity.Services; public interface IHardwareService { - HardwareInfo GetHardware(); + //HardwareInfo GetHardware(); } public class HardwareService : IHardwareService { - private const string WIN32_GET_HARDWARE_COMMAND = - "powershell -Command \"" + - "Get-CimInstance -ClassName Win32_Processor | Select-Object -ExpandProperty Name | Write-Output; " + - "Get-CimInstance -ClassName Win32_VideoController | Select-Object -ExpandProperty Name | Write-Output; " + - "Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty TotalVisibleMemorySize | Write-Output" + - "\""; + // private const string WIN32_GET_HARDWARE_COMMAND = + // "powershell -Command \"" + + // "Get-CimInstance -ClassName Win32_Processor | Select-Object -ExpandProperty Name | Write-Output; " + + // "Get-CimInstance -ClassName Win32_VideoController | Select-Object -ExpandProperty Name | Write-Output; " + + // "Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty TotalVisibleMemorySize | Write-Output" + + // "\""; + // + // private const string UNIX_GET_HARDWARE_COMMAND = + // "/bin/bash -c \"free -g | grep Mem: | awk '{print $2}' && " + + // "lscpu | grep 'Model name:' | cut -d':' -f2 && " + + // "lspci | grep VGA | cut -d':' -f3\""; - private const string UNIX_GET_HARDWARE_COMMAND = - "/bin/bash -c \"free -g | grep Mem: | awk '{print $2}' && " + - "lscpu | grep 'Model name:' | cut -d':' -f2 && " + - "lspci | grep VGA | cut -d':' -f3\""; + // public HardwareInfo GetHardware() + // { + // try + // { + // var output = RunCommand(Environment.OSVersion.Platform == PlatformID.Win32NT + // ? WIN32_GET_HARDWARE_COMMAND + // : UNIX_GET_HARDWARE_COMMAND); + // + // var lines = output + // .Replace("TotalVisibleMemorySize=", "") + // .Replace("Name=", "") + // .Replace(" ", " ") + // .Trim() + // .Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries) + // .Select(x => x.Trim()) + // .ToArray(); + // + // if (lines.Length < 3) + // throw new Exception("Can't get hardware info"); + // + // var hardwareInfo = new HardwareInfo + // { + // CPU = lines[0], + // GPU = lines[1], + // Memory = lines[2], + // MacAddress = GetMacAddress() + // }; + // return hardwareInfo; + // } + // catch (Exception ex) + // { + // Console.WriteLine(ex.Message); + // throw; + // } + // } - public HardwareInfo GetHardware() - { - try - { - var output = RunCommand(Environment.OSVersion.Platform == PlatformID.Win32NT - ? WIN32_GET_HARDWARE_COMMAND - : UNIX_GET_HARDWARE_COMMAND); + // private string GetMacAddress() + // { + // var macAddress = NetworkInterface + // .GetAllNetworkInterfaces() + // .Where(nic => nic.OperationalStatus == OperationalStatus.Up) + // .Select(nic => nic.GetPhysicalAddress().ToString()) + // .FirstOrDefault(); + // + // return macAddress ?? string.Empty; + // } + // + // private string RunCommand(string command) + // { + // try + // { + // using var process = new Process(); + // process.StartInfo.FileName = Environment.OSVersion.Platform == PlatformID.Unix ? "/bin/bash" : "cmd.exe"; + // process.StartInfo.Arguments = Environment.OSVersion.Platform == PlatformID.Unix + // ? $"-c \"{command}\"" + // : $"/c {command}"; + // process.StartInfo.RedirectStandardOutput = true; + // process.StartInfo.UseShellExecute = false; + // process.StartInfo.CreateNoWindow = true; + // + // process.Start(); + // var result = process.StandardOutput.ReadToEnd(); + // process.WaitForExit(); + // + // return result.Trim(); + // } + // catch + // { + // return string.Empty; + // } + // } - var lines = output - .Replace("TotalVisibleMemorySize=", "") - .Replace("Name=", "") - .Replace(" ", " ") - .Trim() - .Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries) - .Select(x => x.Trim()) - .ToArray(); - - if (lines.Length < 3) - throw new Exception("Can't get hardware info"); - - var hardwareInfo = new HardwareInfo - { - CPU = lines[0], - GPU = lines[1], - Memory = lines[2], - MacAddress = GetMacAddress() - }; - return hardwareInfo; - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - throw; - } - } - - private string GetMacAddress() - { - var macAddress = NetworkInterface - .GetAllNetworkInterfaces() - .Where(nic => nic.OperationalStatus == OperationalStatus.Up) - .Select(nic => nic.GetPhysicalAddress().ToString()) - .FirstOrDefault(); - - return macAddress ?? string.Empty; - } - - private string RunCommand(string command) - { - try - { - using var process = new Process(); - process.StartInfo.FileName = Environment.OSVersion.Platform == PlatformID.Unix ? "/bin/bash" : "cmd.exe"; - process.StartInfo.Arguments = Environment.OSVersion.Platform == PlatformID.Unix - ? $"-c \"{command}\"" - : $"/c {command}"; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.UseShellExecute = false; - process.StartInfo.CreateNoWindow = true; - - process.Start(); - var result = process.StandardOutput.ReadToEnd(); - process.WaitForExit(); - - return result.Trim(); - } - catch - { - return string.Empty; - } - } - - private static string ToHash(string str) => - Convert.ToBase64String(SHA384.HashData(Encoding.UTF8.GetBytes(str))); + // private static string ToHash(string str) => + // Convert.ToBase64String(SHA384.HashData(Encoding.UTF8.GetBytes(str))); } diff --git a/Azaion.CommonSecurity/Services/InferenceClient.cs b/Azaion.CommonSecurity/Services/InferenceClient.cs index afbc0dd..cad5c98 100644 --- a/Azaion.CommonSecurity/Services/InferenceClient.cs +++ b/Azaion.CommonSecurity/Services/InferenceClient.cs @@ -60,7 +60,8 @@ public class InferenceClient : IInferenceClient private async Task ProcessClientCommands() { - + //TODO: implement always on ready to client's requests. Utilize RemoteCommand + await Task.CompletedTask; } public void Stop() diff --git a/Azaion.Inference/api_client.pyx b/Azaion.Inference/api_client.pyx index dffaf3f..5de25db 100644 --- a/Azaion.Inference/api_client.pyx +++ b/Azaion.Inference/api_client.pyx @@ -8,17 +8,18 @@ cimport constants import yaml from cdn_manager cimport CDNManager, CDNCredentials -from hardware_service cimport HardwareService, HardwareInfo +from hardware_service cimport HardwareService from security cimport Security from user cimport User, RoleEnum cdef class ApiClient: """Handles API authentication and downloading of the AI model.""" - def __init__(self): + def __init__(self, str api_url): self.credentials = None self.user = None self.token = None self.cdn_manager = None + self.api_url = api_url cdef set_credentials(self, Credentials credentials): self.credentials = credentials @@ -33,12 +34,13 @@ cdef class ApiClient: self.cdn_manager = CDNManager(creds) cdef login(self): - response = requests.post(f"{constants.API_URL}/login", - json={"email": self.credentials.email, "password": self.credentials.password}) + response = requests.post(f"{self.api_url}/login", + json={"email": self.credentials.email, "password": self.credentials.password}) response.raise_for_status() token = response.json()["token"] self.set_token(token) + cdef set_token(self, str token): self.token = token claims = jwt.decode(token, options={"verify_signature": False}) @@ -73,23 +75,22 @@ cdef class ApiClient: cdef upload_file(self, str filename, bytes resource, str folder): if self.token is None: self.login() - url = f"{constants.API_URL}/resources/{folder}" + url = f"{self.api_url}/resources/{folder}" headers = { "Authorization": f"Bearer {self.token}" } files = {'data': (filename, resource)} try: r = requests.post(url, headers=headers, files=files, allow_redirects=True) r.raise_for_status() - constants.log(f"Uploaded {filename} to {constants.API_URL}/{folder} successfully: {r.status_code}.") + constants.log(f"Uploaded {filename} to {self.api_url}/{folder} successfully: {r.status_code}.") except Exception as e: constants.log(f"Upload fail: {e}") cdef load_bytes(self, str filename, str folder): hardware_service = HardwareService() - cdef HardwareInfo hardware = hardware_service.get_hardware_info() - + cdef str hardware = hardware_service.get_hardware_info() if self.token is None: self.login() - url = f"{constants.API_URL}/resources/get/{folder}" + url = f"{self.api_url}/resources/get/{folder}" headers = { "Authorization": f"Bearer {self.token}", "Content-Type": "application/json" @@ -98,7 +99,7 @@ cdef class ApiClient: payload = json.dumps( { "password": self.credentials.password, - "hardware": hardware.to_json_object(), + "hardware": hardware, "fileName": filename }, indent=4) response = requests.post(url, data=payload, headers=headers, stream=True) diff --git a/Azaion.Inference/azaion-inference.spec b/Azaion.Inference/azaion-inference.spec index 5a83791..c71752a 100644 --- a/Azaion.Inference/azaion-inference.spec +++ b/Azaion.Inference/azaion-inference.spec @@ -28,8 +28,6 @@ tmp_ret = collect_all('pynvml') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] tmp_ret = collect_all('boto3') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] -tmp_ret = collect_all('re') -datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] tmp_ret = collect_all('jwt') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] diff --git a/Azaion.Inference/build.cmd b/Azaion.Inference/build.cmd index f21a7b9..5c70e65 100644 --- a/Azaion.Inference/build.cmd +++ b/Azaion.Inference/build.cmd @@ -31,7 +31,6 @@ venv\Scripts\pyinstaller --name=azaion-inference ^ --collect-all pycuda ^ --collect-all pynvml ^ --collect-all boto3 ^ ---collect-all re ^ --collect-all jwt ^ --hidden-import constants ^ --hidden-import annotation ^ diff --git a/Azaion.Inference/config.production.yaml b/Azaion.Inference/config.production.yaml index e575821..839b6fc 100644 --- a/Azaion.Inference/config.production.yaml +++ b/Azaion.Inference/config.production.yaml @@ -1 +1,2 @@ -zmq_port: 5131 \ No newline at end of file +zmq_port: 5131 +api_url: https://api.azaion.com \ No newline at end of file diff --git a/Azaion.Inference/config.yaml b/Azaion.Inference/config.yaml index 20a1884..3317558 100644 --- a/Azaion.Inference/config.yaml +++ b/Azaion.Inference/config.yaml @@ -1 +1,2 @@ -zmq_port: 5127 \ No newline at end of file +zmq_port: 5127 +api_url: http://localhost:5219 \ No newline at end of file diff --git a/Azaion.Inference/constants.pxd b/Azaion.Inference/constants.pxd index 660c97e..1e678c8 100644 --- a/Azaion.Inference/constants.pxd +++ b/Azaion.Inference/constants.pxd @@ -4,7 +4,6 @@ cdef int QUEUE_MAXSIZE # Maximum size of the command queue cdef str COMMANDS_QUEUE # Name of the commands queue in rabbit cdef str ANNOTATIONS_QUEUE # Name of the annotations queue in rabbit -cdef str API_URL # Base URL for the external API cdef str QUEUE_CONFIG_FILENAME # queue config filename to load from api cdef str AI_ONNX_MODEL_FILE diff --git a/Azaion.Inference/constants.pyx b/Azaion.Inference/constants.pyx index a8f384c..80f5f2c 100644 --- a/Azaion.Inference/constants.pyx +++ b/Azaion.Inference/constants.pyx @@ -6,7 +6,6 @@ cdef int QUEUE_MAXSIZE = 1000 # Maximum size of the command queue cdef str COMMANDS_QUEUE = "azaion-commands" cdef str ANNOTATIONS_QUEUE = "azaion-annotations" -cdef str API_URL = "https://api.azaion.com" # Base URL for the external API cdef str QUEUE_CONFIG_FILENAME = "secured-config.json" cdef str AI_ONNX_MODEL_FILE = "azaion.onnx" diff --git a/Azaion.Inference/hardware_service.pxd b/Azaion.Inference/hardware_service.pxd index 2a700a2..628e9e7 100644 --- a/Azaion.Inference/hardware_service.pxd +++ b/Azaion.Inference/hardware_service.pxd @@ -1,11 +1,6 @@ -cdef class HardwareInfo: - cdef str cpu, gpu, memory, mac_address - cdef to_json_object(self) - cdef class HardwareService: cdef bint is_windows - cdef get_mac_address(self, interface=*) @staticmethod cdef has_nvidia_gpu() - cdef HardwareInfo get_hardware_info(self) \ No newline at end of file + cdef str get_hardware_info(self) \ No newline at end of file diff --git a/Azaion.Inference/hardware_service.pyx b/Azaion.Inference/hardware_service.pyx index 9782b21..9501b77 100644 --- a/Azaion.Inference/hardware_service.pyx +++ b/Azaion.Inference/hardware_service.pyx @@ -1,25 +1,6 @@ -import re import subprocess -import psutil import pynvml -cdef class HardwareInfo: - def __init__(self, str cpu, str gpu, str memory, str mac_address): - self.cpu = cpu - self.gpu = gpu - self.memory = memory - self.mac_address = mac_address - - cdef to_json_object(self): - return { - "CPU": self.cpu, - "GPU": self.gpu, - "MacAddress": self.mac_address, - "Memory": self.memory - } - - def __str__(self): - return f'CPU: {self.cpu}. GPU: {self.gpu}. Memory: {self.memory}. MAC Address: {self.mac_address}' cdef class HardwareService: """Handles hardware information retrieval and hash generation.""" @@ -35,15 +16,6 @@ cdef class HardwareService: print('Error during os type checking') self.is_windows = False - cdef get_mac_address(self, interface="Ethernet"): - addresses = psutil.net_if_addrs() - for interface_name, interface_info in addresses.items(): - if interface_name == interface: - for addr in interface_info: - if addr.family == psutil.AF_LINK: - return addr.address.replace('-', '') - return None - @staticmethod cdef has_nvidia_gpu(): try: @@ -67,13 +39,14 @@ cdef class HardwareService: print('Failed to shutdown pynvml cause probably no NVidia GPU') pass - cdef HardwareInfo get_hardware_info(self): + cdef str get_hardware_info(self): if self.is_windows: os_command = ( "powershell -Command \"" "Get-CimInstance -ClassName Win32_Processor | Select-Object -ExpandProperty Name | Write-Output; " "Get-CimInstance -ClassName Win32_VideoController | Select-Object -ExpandProperty Name | Write-Output; " - "Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty TotalVisibleMemorySize | Write-Output" + "Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty TotalVisibleMemorySize | Write-Output; " + "(Get-Disk | Where-Object {$_.IsSystem -eq $true}).SerialNumber" "\"" ) else: @@ -81,16 +54,22 @@ cdef class HardwareService: "/bin/bash -c \" lscpu | grep 'Model name:' | cut -d':' -f2 && " "lspci | grep VGA | cut -d':' -f3 && " "free -g | grep Mem: | awk '{print $2}' && \"" + "udevadm info --query=property --name=\"/dev/$(lsblk -no pkname \"$(findmnt -n -o SOURCE --target /)\")\" | grep -E 'ID_SERIAL=|ID_SERIAL_SHORT=' | cut -d'=' -f2- | head -n1 && " ) # in case of subprocess error do: # cdef bytes os_command_bytes = os_command.encode('utf-8') # and use os_command_bytes + result = subprocess.check_output(os_command, shell=True).decode('utf-8') lines = [line.strip() for line in result.splitlines() if line.strip()] cdef str cpu = lines[0].replace("Name=", "").replace(" ", " ") cdef str gpu = lines[1].replace("Name=", "").replace(" ", " ") - cdef str memory = lines[2].replace("TotalVisibleMemorySize=", "").replace(" ", " ") - cdef str mac_address = self.get_mac_address() + # could be multiple gpus - return HardwareInfo(cpu, gpu, memory, mac_address) + len_lines = len(lines) + cdef str memory = lines[len_lines-2].replace("TotalVisibleMemorySize=", "").replace(" ", " ") + cdef str drive_serial = lines[len_lines-1] + + cdef str res = f'CPU: {cpu}. GPU: {gpu}. Memory: {memory}. DriveSerial: {drive_serial}' + return res diff --git a/Azaion.Inference/main.pyx b/Azaion.Inference/main.pyx index fcc484f..a29e512 100644 --- a/Azaion.Inference/main.pyx +++ b/Azaion.Inference/main.pyx @@ -23,8 +23,13 @@ cdef class CommandProcessor: cdef Inference inference def __init__(self): - self.api_client = ApiClient() - self.remote_handler = RemoteCommandHandler(self.on_command) + with open(constants.CONFIG_FILE, "r") as f: + config = yaml.safe_load(f) + zmq_port = config["zmq_port"] + api_url = config["api_url"] + + self.api_client = ApiClient(api_url) + self.remote_handler = RemoteCommandHandler(zmq_port, self.on_command) self.inference_queue = Queue(maxsize=constants.QUEUE_MAXSIZE) self.remote_handler.start() self.running = True diff --git a/Azaion.Inference/remote_command_handler.pyx b/Azaion.Inference/remote_command_handler.pyx index d380cc5..da34d5d 100644 --- a/Azaion.Inference/remote_command_handler.pyx +++ b/Azaion.Inference/remote_command_handler.pyx @@ -6,16 +6,13 @@ cimport constants import yaml cdef class RemoteCommandHandler: - def __init__(self, object on_command): + def __init__(self, int zmq_port, object on_command): self._on_command = on_command self._context = zmq.Context.instance() self._router = self._context.socket(zmq.ROUTER) self._router.setsockopt(zmq.LINGER, 0) - with open(constants.CONFIG_FILE, "r") as f: - config = yaml.safe_load(f) - port = config["zmq_port"] - self._router.bind(f'tcp://*:{port}') + self._router.bind(f'tcp://*:{zmq_port}') self._dealer = self._context.socket(zmq.DEALER) self._dealer.setsockopt(zmq.LINGER, 0) @@ -31,7 +28,7 @@ cdef class RemoteCommandHandler: for _ in range(4): # 4 worker threads worker = Thread(target=self._worker_loop, daemon=True) self._workers.append(worker) - print(f'Listening to commands on port {port}...') + print(f'Listening to commands on port {zmq_port}...') cdef start(self): self._proxy_thread.start() diff --git a/Azaion.Inference/security.pxd b/Azaion.Inference/security.pxd index ba6f4d8..ad1396f 100644 --- a/Azaion.Inference/security.pxd +++ b/Azaion.Inference/security.pxd @@ -1,5 +1,4 @@ from credentials cimport Credentials -from hardware_service cimport HardwareInfo cdef class Security: @staticmethod @@ -9,7 +8,7 @@ cdef class Security: cdef decrypt_to(input_bytes, key) @staticmethod - cdef get_hw_hash(HardwareInfo hardware) + cdef get_hw_hash(str hardware) @staticmethod cdef get_api_encryption_key(Credentials credentials, str hardware_hash) diff --git a/Azaion.Inference/security.pyx b/Azaion.Inference/security.pyx index aabc5e2..7bada8a 100644 --- a/Azaion.Inference/security.pyx +++ b/Azaion.Inference/security.pyx @@ -3,8 +3,6 @@ import hashlib import os from hashlib import sha384 from credentials cimport Credentials -from hardware_service cimport HardwareInfo - from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding @@ -48,8 +46,8 @@ cdef class Security: return bytes(plaintext_bytes) @staticmethod - cdef get_hw_hash(HardwareInfo hardware): - cdef str key = f'Azaion_{hardware.mac_address}_{hardware.cpu}_{hardware.gpu}' + cdef get_hw_hash(str hardware): + cdef str key = f'Azaion_{hardware}_%$$$)0_' return Security.calc_hash(key) @staticmethod diff --git a/Azaion.Inference/test/test_download_large_file.py b/Azaion.Inference/test/test_download_large_file.py index 0b17ecf..185f357 100644 --- a/Azaion.Inference/test/test_download_large_file.py +++ b/Azaion.Inference/test/test_download_large_file.py @@ -202,7 +202,7 @@ class Api: payload = json.dumps( { "password": self.credentials.password, - "hardware": hardware.to_json_object(), + "hardware": hardware, "fileName": filename }, indent=4) response = requests.post(url, data=payload, headers=headers, stream=True, timeout=20) diff --git a/Azaion.Suite/App.xaml.cs b/Azaion.Suite/App.xaml.cs index a397029..e2471e0 100644 --- a/Azaion.Suite/App.xaml.cs +++ b/Azaion.Suite/App.xaml.cs @@ -46,7 +46,6 @@ public partial class App private static readonly Guid KeyPressTaskId = Guid.NewGuid(); private readonly ICache _cache = new MemoryCache(); - private readonly IHardwareService _hardwareService = new HardwareService(); private IAzaionApi _azaionApi = null!; private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) @@ -97,7 +96,7 @@ public partial class App login.CredentialsEntered += (_, credentials) => { _inferenceClient.Send(RemoteCommand.Create(CommandType.Login, credentials)); - _azaionApi = new AzaionApi(new HttpClient { BaseAddress = new Uri(SecurityConstants.API_URL) }, _cache, credentials, _hardwareService); + _azaionApi = new AzaionApi(new HttpClient { BaseAddress = new Uri(SecurityConstants.API_URL) }, _cache, credentials); try { @@ -176,7 +175,6 @@ public partial class App .ConfigureServices((context, services) => { services.AddSingleton(); - services.AddSingleton(); services.Configure(context.Configuration); services.ConfigureSection(context.Configuration); diff --git a/Azaion.Test/HardwareServiceTest.cs b/Azaion.Test/HardwareServiceTest.cs deleted file mode 100644 index a7e5688..0000000 --- a/Azaion.Test/HardwareServiceTest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Azaion.Common.Services; -using Azaion.CommonSecurity.Services; -using Xunit; - -namespace Azaion.Annotator.Test; - -public class HardwareServiceTest -{ - [Fact] - public void GetHardware_Test() - { - var hardwareService = new HardwareService(); - var hw = hardwareService.GetHardware(); - Console.WriteLine(hw); - } -} \ No newline at end of file