Implement Devices controller and service

This commit is contained in:
Andrii Tykhonov 2024-07-17 00:26:09 +03:00
parent 41ec149b79
commit b69d6d50c7
7 changed files with 249 additions and 9 deletions

View File

@ -37,7 +37,7 @@ public class ClustersController : ControllerBase
}
if (!_clusterConfigurationFile.DirectoryExists())
{
_logger.LogError($"Cluster not found: {clusterName}");
_logger.LogError($"Cluster not found: {_clusterConfigurationFile.GetDirectoryPath()}");
return new NotFound("Cluster not found");
}

View File

@ -0,0 +1,147 @@
namespace DevicesRestApi.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Diagnostics;
using DevicesRestApi.Helpers;
[ApiController]
[Route("[controller]")]
public class DevicesController : ControllerBase
{
private readonly ILogger<ClustersController> _logger;
private readonly AppSettings _appSettings;
public DevicesController(
ILogger<ClustersController> logger,
IOptions<AppSettings> appSettings
) {
_logger = logger;
_appSettings = appSettings.Value;
}
[HttpPost]
[Route("~/devices/{deviceName}")]
public IActionResult UpdateDeviceConfiguration(string deviceName, UpdateDeviceRequest request)
{
DeviceConfigurationFile configurationFile = null;
try {
configurationFile = GetConfigurationFile(deviceName);
}
catch (ConfigurationException e)
{
_logger.LogWarning(e.Message);
return BadRequest(new{
message = e.Message,
});
}
var command = createCommand(
configurationFile.GetFilePath(),
request.clusterName
);
executeCommand(command);
return new Ok("Device configuration updated");
}
[HttpDelete]
[Route("~/devices/{deviceName}")]
public IActionResult DeleteDeviceConfiguration(string deviceName)
{
DeviceConfigurationFile configurationFile = null;
try {
configurationFile = GetConfigurationFile(deviceName);
}
catch (ConfigurationException e)
{
_logger.LogWarning(e.Message);
return BadRequest(new{
message = e.Message,
});
}
var command = createCommand(
configurationFile.GetFilePath(),
"no-cluster"
);
executeCommand(command);
return new Ok("Device configuration updated");
}
private DeviceConfigurationFile GetConfigurationFile(string deviceName)
{
DeviceConfigurationFile configurationFile = null;
try {
configurationFile = new DeviceConfigurationFile(deviceName, _appSettings);
}
catch (ArgumentException e)
{
_logger.LogError($"Something went wrong: {e}");
throw new ConfigurationException($"Something went wrong: {e}");
}
if (!configurationFile.FileExists())
{
var message = "Configuration file doesn't exist";
_logger.LogError(message);
throw new ConfigurationException(message);
}
return configurationFile;
}
private string createCommand(string filePath, string clusterName)
{
return $"sed -i -E 's/^project\\s?=.*/project = {clusterName}/' {filePath}";
}
private void executeCommand(string command)
{
_logger.LogDebug($"Executing the command: {command}");
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = $"-c \"{command}\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
process.Start();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();
if (process.ExitCode > 0)
{
var message = error ?? "Unknown error";
message = $"An error occurred during the execution of the command: {message}";
_logger.LogError(message);
throw new Exception(message);
}
}
public class CommandRequest
{
public string ClusterName { get; set; }
public string DeviceName { get; set; }
}
public class ConfigurationException : Exception
{
public ConfigurationException() : base() { }
public ConfigurationException(string message) : base(message) { }
public ConfigurationException(string message, Exception inner) : base(message, inner) { }
}
}

View File

@ -4,5 +4,5 @@ public class AppSettings
{
public string ApiKey { get; set; } = string.Empty;
public string ClustersRootPath { get; set; } = string.Empty;
public string RootPath { get; set; } = string.Empty;
}

View File

@ -15,20 +15,26 @@ public class ClusterConfigurationFile
AppSettings appSettings
) {
_clusterName = clusterName;
_appSettings = appSettings;
_rootDirectory = _appSettings.ClustersRootPath;
if (string.IsNullOrEmpty(_clusterName))
{
throw new ArgumentException("The provided cluster name is null or empty.");
}
if (string.IsNullOrEmpty(_rootDirectory))
_appSettings = appSettings;
var rootPath = _appSettings.RootPath;
if (string.IsNullOrEmpty(rootPath))
{
throw new ArgumentException("Clusters root directory is not configured.");
throw new ArgumentException("Root path is not configured.");
}
_rootDirectory = Path.Combine(rootPath, "projects");
if (!Directory.Exists(_rootDirectory))
{
throw new ArgumentException($"Clusters directory doesn't exist: {_rootDirectory}.");
}
}
private string GetDirectoryPath()
public string GetDirectoryPath()
{
return Path.Combine(_rootDirectory, _clusterName);
}

View File

@ -0,0 +1,81 @@
namespace DevicesRestApi.Helpers;
public class DeviceConfigurationFile
{
private readonly string _rootDirectory;
private readonly string _deviceName;
private const string SettingsFilename = "settings.conf";
private readonly AppSettings _appSettings;
public DeviceConfigurationFile(
string deviceName,
AppSettings appSettings
) {
_deviceName = deviceName;
if (string.IsNullOrEmpty(_deviceName))
{
throw new ArgumentException("The provided device name is null or empty.");
}
_appSettings = appSettings;
var rootPath = _appSettings.RootPath;
if (string.IsNullOrEmpty(rootPath))
{
throw new ArgumentException("Root path is not configured.");
}
_rootDirectory = Path.Combine(rootPath, "devices");
if (!Directory.Exists(_rootDirectory))
{
throw new ArgumentException($"Devices directory doesn't exist: {_rootDirectory}.");
}
}
public string GetDirectoryPath()
{
return Path.Combine(_rootDirectory, _deviceName);
}
public string GetFilePath()
{
return Path.Combine(GetDirectoryPath(), SettingsFilename);
}
public bool FileExists()
{
return File.Exists(GetFilePath());
}
public bool DirectoryExists()
{
return Directory.Exists(GetDirectoryPath());
}
private void CreateDirectory()
{
Directory.CreateDirectory(GetDirectoryPath());
}
private void CreateFile()
{
using (FileStream fs = File.Create(GetFilePath()))
{
// The file is created and opened, we don't need to write anything to it
}
}
public void Create()
{
if (!DirectoryExists())
{
CreateDirectory();
}
if (!FileExists())
{
CreateFile();
}
}
}

View File

@ -0,0 +1,6 @@
namespace DevicesRestApi.Helpers;
public class UpdateDeviceRequest
{
public string clusterName { get; set; }
}

View File

@ -8,7 +8,7 @@
},
"AppSettings": {
"ApiKey": "api-key",
"ClustersRootPath": "/tmp/projects"
"RootPath": "/tmp"
},
"Urls": "http://0.0.0.0:8765",
"AllowedHosts": "*",