This commit is contained in:
Elias Stepanik 2023-05-31 22:22:03 +02:00
parent 66acf4c34e
commit f0e056f207
14 changed files with 98 additions and 14 deletions

View File

@ -15,7 +15,13 @@ docker rm $(docker ps -aq --filter "name=functions") || true
echo '####################################################'
echo 'Removing images ...'
echo '####################################################'
docker rmi $(docker images -q --filter "reference=*functions*") || true
docker rmi -f $(docker images -q --filter "reference=*functions*") || true
# remove all networks
echo '####################################################'
echo 'Removing networks ...'
echo '####################################################'
docker network rm $(docker network ls -q --filter "name=FunctionsProxy") || true
# remove all stray volumes if any
#echo '####################################################'

View File

@ -21,7 +21,7 @@ public class Function
[Required]
public string ImageTag { get; set; }
public List<Environment> EnvironmentVariables { get; set; }
public List<Environment> EnvironmentVariables { get; set; } = null!;
public List<Instance> Instances { get; set; } = null!;
}

View File

@ -22,5 +22,5 @@ public class Instance
public string Name { get; set; }
public int FunctionId { get; set; }
public Function Function { get; set; }
public Function Function { get; set; } = null!;
}

View File

@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Text;
using Functions.Data.DB;
using Functions.Services;
@ -8,6 +9,12 @@ var builder = WebApplication.CreateBuilder(args);
//ASPNETCORE_AppConfig__TwilioSecret=my-secret
builder.Configuration.AddEnvironmentVariables();
builder.Configuration["AppConfig:FuctionNetworkName"] = Environment.GetEnvironmentVariable("FUNCTION_NETWORK") ?? "simplefunctions_functions";
builder.Configuration["AppConfig:DB:Server"] = Environment.GetEnvironmentVariable("DB_SERVER") ?? "localhost";
builder.Configuration["AppConfig:DB:Port"] = Environment.GetEnvironmentVariable("DB_PORT") ?? "3306";
builder.Configuration["AppConfig:DB:User"] = Environment.GetEnvironmentVariable("DB_USER") ?? "root";
builder.Configuration["AppConfig:DB:Password"] = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? "password";
builder.Configuration["AppConfig:DB:Database"] = Environment.GetEnvironmentVariable("DB_DATABASE") ?? "db";
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
@ -31,6 +38,7 @@ builder.Services.AddDbContextFactory<FunctionsContext>(
builder.Services.AddTransient<IDockerManager,DockerManager>();
builder.Services.AddSingleton<INativeCommandWrapper,NativeCommandWrapper>();
builder.Services.AddSingleton<FunctionManager>();
builder.Services.AddHttpClient<IExternalEndpointManager, ExternalEndpointManager>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
@ -55,5 +63,4 @@ var dbFactory = app.Services.GetRequiredService<IDbContextFactory<FunctionsConte
var db = await dbFactory.CreateDbContextAsync();
await db.Database.MigrateAsync();
app.Run();

View File

@ -43,6 +43,25 @@ public class DockerManager : IDockerManager
return new ContainerResponse(createContainerParameters.Name, container.ID);
}
public async void CreateNetwork(string name)
{
var networks = await _docker.Networks.ListNetworksAsync();
foreach (var networkResponse in networks)
{
if (networkResponse.Name.Equals(name))
{
return;
}
}
var networkCreateParameters = new NetworksCreateParameters()
{
Name = name,
Attachable = true
};
await _docker.Networks.CreateNetworkAsync(networkCreateParameters);
}
public async void ConnectNetwork(string name, string containerId)
{
var networkConnectParameters = new NetworkConnectParameters()

View File

@ -30,6 +30,7 @@ public class ExternalEndpointManager : IExternalEndpointManager
}
catch (HttpRequestException ex)
{
_logger.LogError(ex.Message);
// Handle any errors that occurred during the request
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
@ -51,6 +52,7 @@ public class ExternalEndpointManager : IExternalEndpointManager
}
catch (HttpRequestException ex)
{
_logger.LogError(ex.Message);
// Handle any errors that occurred during the request
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
@ -71,6 +73,7 @@ public class ExternalEndpointManager : IExternalEndpointManager
}
catch (HttpRequestException ex)
{
_logger.LogError(ex.Message);
// Handle any errors that occurred during the request
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
@ -92,6 +95,7 @@ public class ExternalEndpointManager : IExternalEndpointManager
}
catch (HttpRequestException ex)
{
_logger.LogError(ex.Message);
// Handle any errors that occurred during the request
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
@ -113,6 +117,7 @@ public class ExternalEndpointManager : IExternalEndpointManager
}
catch (HttpRequestException ex)
{
_logger.LogError(ex.Message);
// Handle any errors that occurred during the request
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}

View File

@ -13,13 +13,17 @@ public class FunctionManager
private readonly IDockerManager _dockerManager;
private readonly IDbContextFactory<FunctionsContext> _dbContextFactory;
private readonly IExternalEndpointManager _externalEndpointManager;
private readonly IConfiguration _configuration;
private readonly INativeCommandWrapper _nativeCommandWrapper;
public FunctionManager(ILogger<FunctionManager> logger, IDockerManager dockerManager, IDbContextFactory<FunctionsContext> dbContextFactory, IExternalEndpointManager externalEndpointManager)
public FunctionManager(ILogger<FunctionManager> logger, IDockerManager dockerManager, IDbContextFactory<FunctionsContext> dbContextFactory, IExternalEndpointManager externalEndpointManager, IConfiguration configuration, INativeCommandWrapper nativeCommandWrapper)
{
_logger = logger;
_dockerManager = dockerManager;
_dbContextFactory = dbContextFactory;
_externalEndpointManager = externalEndpointManager;
_configuration = configuration;
_nativeCommandWrapper = nativeCommandWrapper;
}
@ -28,6 +32,7 @@ public class FunctionManager
var db = await _dbContextFactory.CreateDbContextAsync();
await db.Functions.AddAsync(new Function(functionName, imageTag));
await db.SaveChangesAsync();
await db.DisposeAsync();
}
public async Task DeleteFunction(string functionName)
{
@ -39,6 +44,7 @@ public class FunctionManager
}
db.Functions.Remove(function);
await db.SaveChangesAsync();
await db.DisposeAsync();
}
public async Task<HttpResponseMessage> RunInstance(string functionName, HttpMethod method, string body = "")
@ -51,8 +57,9 @@ public class FunctionManager
function.Instances.Add(instance);
db.Functions.Update(function);
await db.SaveChangesAsync();
await db.DisposeAsync();
_dockerManager.ConnectNetwork("simplefunctions_functions", instance.InstanceId);
_dockerManager.ConnectNetwork(_configuration["AppConfig:FuctionNetworkName"] ?? throw new InvalidOperationException(), instance.InstanceId);
_dockerManager.StartContainer(instance.InstanceId);
//TODO: If not started delete instance

View File

@ -11,5 +11,6 @@ public interface IDockerManager
public void ConnectNetwork(string name, string containerId);
public void StartContainer(string containerId);
public void DeleteContainer(string containerId);
public void CreateNetwork(string name);
public Task<bool> IsRunning(string containerId);
}

View File

@ -0,0 +1,6 @@
namespace Functions.Services.Interfaces;
public interface INativeCommandWrapper
{
public Task<string> GetContainerIdSelf();
}

View File

@ -0,0 +1,28 @@
using System.Diagnostics;
using Functions.Services.Interfaces;
namespace Functions.Services;
public class NativeCommandWrapper : INativeCommandWrapper
{
private readonly ILogger<NativeCommandWrapper> _logger;
public NativeCommandWrapper(ILogger<NativeCommandWrapper> logger)
{
_logger = logger;
}
public async Task<string> GetContainerIdSelf()
{
Process proc = new();
proc.StartInfo.FileName = "head";
proc.StartInfo.Arguments = "-1 /proc/self/cgroup";
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
ArgumentNullException.ThrowIfNull(proc);
string output = await proc.StandardOutput.ReadToEndAsync();
_logger.LogDebug(output.Substring(24));
await proc.WaitForExitAsync();
return (output.Substring(24));
}
}

View File

@ -13,6 +13,7 @@
"User": "root",
"Password": "testPW",
"Database": "Functions"
}
},
"FuctionNetworkName": "FunctionsProxy"
}
}

View File

@ -13,6 +13,7 @@
"User": "root",
"Password": "testPW",
"Database": "Functions"
}
},
"FuctionNetworkName": "FunctionsProxy"
}
}

View File

@ -5,6 +5,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A7EF8833-F6BE-4EBD-8DB1-5AA8EDB5A16F}"
ProjectSection(SolutionItems) = preProject
docker-compose.yml = docker-compose.yml
.scripts\clearDocker.sh = .scripts\clearDocker.sh
.scripts\runDocker.sh = .scripts\runDocker.sh
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFunction", "TestFunction\TestFunction.csproj", "{BC3C484C-EFD0-45E5-BE6E-9212916489E4}"

View File

@ -7,14 +7,15 @@ networks:
functions:
services:
functions:
functions: #Name can not be changed
build: ./Functions
environment:
ASPNETCORE_AppConfig__DB__Server: "db"
ASPNETCORE_AppConfig__DB__User: "root"
ASPNETCORE_AppConfig__DB__Password: "testPW"
ASPNETCORE_AppConfig__DB__Database: "Functions"
DB_SERVER: "db"
DB_USER: "root"
DB_PASSWORD: "testPW"
DB_DATABASE: "Functions"
ASPNETCORE_ENVIRONMENT: "Production"
FUNCTION_NETWORK: "simplefunctions_functions"
ports:
- "8080:80"
- "8081:443"