mirror of
https://github.com/eliasstepanik/SimpleFunctions.git
synced 2026-01-18 16:58:26 +00:00
f
This commit is contained in:
commit
cd23fbe4a9
25
.dockerignore
Normal file
25
.dockerignore
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/.idea
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/azds.yaml
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
||||||
12
.run/ClearDocker.xml
Normal file
12
.run/ClearDocker.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="ClearDocker" type="RunNativeExe" factoryName="Native Executable">
|
||||||
|
<option name="EXE_PATH" value="$PROJECT_DIR$/../../../../Windows/System32/bash.exe" />
|
||||||
|
<option name="PROGRAM_PARAMETERS" value="$PROJECT_DIR$/.scripts/clearDocker.sh" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Build Solution" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
24
.scripts/clearDocker.sh
Normal file
24
.scripts/clearDocker.sh
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# stop all running containers
|
||||||
|
echo '####################################################'
|
||||||
|
echo 'Stopping running containers (if available)...'
|
||||||
|
echo '####################################################'
|
||||||
|
docker stop $(docker ps -aq --filter "name=functions") || true
|
||||||
|
|
||||||
|
# remove all stopped containers
|
||||||
|
echo '####################################################'
|
||||||
|
echo 'Removing containers ..'
|
||||||
|
echo '####################################################'
|
||||||
|
docker rm $(docker ps -aq --filter "name=functions") || true
|
||||||
|
|
||||||
|
|
||||||
|
# remove all images
|
||||||
|
echo '####################################################'
|
||||||
|
echo 'Removing images ...'
|
||||||
|
echo '####################################################'
|
||||||
|
docker rmi $(docker images -q --filter "reference=*functions*") || true
|
||||||
|
|
||||||
|
# remove all stray volumes if any
|
||||||
|
#echo '####################################################'
|
||||||
|
#echo 'Revoming docker container volumes (if any)'
|
||||||
|
#echo '####################################################'
|
||||||
|
#docker volume rm $(docker volume ls -q --filter "name=*kassensystembbs2*")
|
||||||
16
.scripts/runDocker.sh
Normal file
16
.scripts/runDocker.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
echo '####################################################'
|
||||||
|
echo 'Starting Compose Containers ...'
|
||||||
|
echo '####################################################'
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
|
||||||
|
echo '####################################################'
|
||||||
|
echo 'Waiting for Webserver to Start ...'
|
||||||
|
echo '####################################################'
|
||||||
|
while ! curl --fail --silent --head http://172.29.111.95:8080; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo '####################################################'
|
||||||
|
echo 'Open your Browser at http://172.29.111.95:8080.'
|
||||||
|
echo '####################################################'
|
||||||
60
Functions/API/FunctionController.cs
Normal file
60
Functions/API/FunctionController.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using Docker.DotNet.Models;
|
||||||
|
using Functions.Services;
|
||||||
|
using Functions.Services.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Functions.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class FunctionController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<TestController> _logger;
|
||||||
|
private readonly FunctionManager _functionManager;
|
||||||
|
|
||||||
|
public FunctionController(ILogger<TestController> logger, FunctionManager functionManager)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_functionManager = functionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> CreateFunction(string functionName, string imageTag)
|
||||||
|
{
|
||||||
|
await _functionManager.CreateFunction(functionName, imageTag);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost("{functionName}")]
|
||||||
|
public async Task<string> RunFunctionPost(string functionName,[FromBody] string text)
|
||||||
|
{
|
||||||
|
var response = await _functionManager.RunInstance(functionName,HttpMethod.Post, text);
|
||||||
|
_logger.LogInformation(functionName);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
[HttpGet("{functionName}")]
|
||||||
|
public async Task<string> RunFunctionGet(string functionName)
|
||||||
|
{
|
||||||
|
var response = await _functionManager.RunInstance(functionName,HttpMethod.Get);
|
||||||
|
_logger.LogInformation(functionName);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPatch("{functionName}")]
|
||||||
|
public async Task<string> RunFunctionPatch(string functionName,[FromBody] string text)
|
||||||
|
{
|
||||||
|
var response = await _functionManager.RunInstance(functionName,HttpMethod.Patch, text);
|
||||||
|
_logger.LogInformation(functionName);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpDelete("{functionName}/delete")]
|
||||||
|
public async Task<IActionResult> DeleteFunction(string functionName)
|
||||||
|
{
|
||||||
|
await _functionManager.DeleteFunction(functionName);
|
||||||
|
_logger.LogInformation(functionName);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Functions/API/TestController.cs
Normal file
27
Functions/API/TestController.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using Docker.DotNet.Models;
|
||||||
|
using Functions.Services;
|
||||||
|
using Functions.Services.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Functions.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class TestController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<TestController> _logger;
|
||||||
|
private readonly IDockerManager _dockerManager;
|
||||||
|
|
||||||
|
public TestController(ILogger<TestController> logger, IDockerManager dockerManager)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_dockerManager = dockerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(Name = "Containers")]
|
||||||
|
public async Task<IEnumerable<ContainerListResponse>> Get()
|
||||||
|
{
|
||||||
|
return await _dockerManager.GetContainers();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Functions/Data/DB/FunctionsContext.cs
Normal file
37
Functions/Data/DB/FunctionsContext.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Functions.Data.DB;
|
||||||
|
|
||||||
|
public class FunctionsContext : DbContext
|
||||||
|
{
|
||||||
|
public FunctionsContext(DbContextOptions<FunctionsContext> options) : base(options) { }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Function>()
|
||||||
|
.HasMany(p => p.Instances)
|
||||||
|
.WithOne(s => s.Function)
|
||||||
|
.HasForeignKey(s => s.FunctionId);
|
||||||
|
modelBuilder.Entity<Function>()
|
||||||
|
.HasMany(p => p.EnvironmentVariables)
|
||||||
|
.WithOne(s => s.Function)
|
||||||
|
.HasForeignKey(s => s.FunctionId);
|
||||||
|
/*modelBuilder.Entity<Product>()
|
||||||
|
.HasMany(p => p.SellEntries)
|
||||||
|
.WithOne(s => s.Item);
|
||||||
|
|
||||||
|
modelBuilder.Entity<User>()
|
||||||
|
.HasMany(u => u.SellEntries)
|
||||||
|
.WithOne(e => e.SoldBy);
|
||||||
|
|
||||||
|
modelBuilder.Entity<User>()
|
||||||
|
.HasMany(u => u.Cart)
|
||||||
|
.WithOne(e => e.User);*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DbSet<Function> Functions { get; set; } = null!;
|
||||||
|
public DbSet<Instance> Instances { get; set; } = null!;
|
||||||
|
public DbSet<Environment> EnvironmentVariables { get; set; } = null!;
|
||||||
|
}
|
||||||
45
Functions/Data/DB/Migrations/20230528164833_Init.Designer.cs
generated
Normal file
45
Functions/Data/DB/Migrations/20230528164833_Init.Designer.cs
generated
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(FunctionsContext))]
|
||||||
|
[Migration("20230528164833_Init")]
|
||||||
|
partial class Init
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ImageTag")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Functions");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Functions/Data/DB/Migrations/20230528164833_Init.cs
Normal file
42
Functions/Data/DB/Migrations/20230528164833_Init.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Init : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterDatabase()
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Functions",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ImageTag = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Functions", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Functions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
81
Functions/Data/DB/Migrations/20230528180737_Function.Designer.cs
generated
Normal file
81
Functions/Data/DB/Migrations/20230528180737_Function.Designer.cs
generated
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(FunctionsContext))]
|
||||||
|
[Migration("20230528180737_Function")]
|
||||||
|
partial class Function
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ImageTag")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Functions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FunctionID")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FunctionID");
|
||||||
|
|
||||||
|
b.ToTable("Instances");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Functions.Data.Function", "Function")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("FunctionID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Function");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Instances");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Functions/Data/DB/Migrations/20230528180737_Function.cs
Normal file
49
Functions/Data/DB/Migrations/20230528180737_Function.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Function : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Instances",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
FunctionID = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Instances", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Instances_Functions_FunctionID",
|
||||||
|
column: x => x.FunctionID,
|
||||||
|
principalTable: "Functions",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Instances_FunctionID",
|
||||||
|
table: "Instances",
|
||||||
|
column: "FunctionID");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Instances");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
85
Functions/Data/DB/Migrations/20230528184618_Function2.Designer.cs
generated
Normal file
85
Functions/Data/DB/Migrations/20230528184618_Function2.Designer.cs
generated
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(FunctionsContext))]
|
||||||
|
[Migration("20230528184618_Function2")]
|
||||||
|
partial class Function2
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ImageTag")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Functions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FunctionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("InstanceId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FunctionId");
|
||||||
|
|
||||||
|
b.ToTable("Instances");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Functions.Data.Function", "Function")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("FunctionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Function");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Instances");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
Functions/Data/DB/Migrations/20230528184618_Function2.cs
Normal file
73
Functions/Data/DB/Migrations/20230528184618_Function2.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Function2 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Instances_Functions_FunctionID",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "FunctionID",
|
||||||
|
table: "Instances",
|
||||||
|
newName: "FunctionId");
|
||||||
|
|
||||||
|
migrationBuilder.RenameIndex(
|
||||||
|
name: "IX_Instances_FunctionID",
|
||||||
|
table: "Instances",
|
||||||
|
newName: "IX_Instances_FunctionId");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "InstanceId",
|
||||||
|
table: "Instances",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Instances_Functions_FunctionId",
|
||||||
|
table: "Instances",
|
||||||
|
column: "FunctionId",
|
||||||
|
principalTable: "Functions",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Instances_Functions_FunctionId",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "InstanceId",
|
||||||
|
table: "Instances");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "FunctionId",
|
||||||
|
table: "Instances",
|
||||||
|
newName: "FunctionID");
|
||||||
|
|
||||||
|
migrationBuilder.RenameIndex(
|
||||||
|
name: "IX_Instances_FunctionId",
|
||||||
|
table: "Instances",
|
||||||
|
newName: "IX_Instances_FunctionID");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Instances_Functions_FunctionID",
|
||||||
|
table: "Instances",
|
||||||
|
column: "FunctionID",
|
||||||
|
principalTable: "Functions",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
122
Functions/Data/DB/Migrations/20230529102304_Function3.Designer.cs
generated
Normal file
122
Functions/Data/DB/Migrations/20230529102304_Function3.Designer.cs
generated
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(FunctionsContext))]
|
||||||
|
[Migration("20230529102304_Function3")]
|
||||||
|
partial class Function3
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Environment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FunctionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FunctionId");
|
||||||
|
|
||||||
|
b.ToTable("EnvironmentVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ImageTag")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Functions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FunctionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("InstanceId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FunctionId");
|
||||||
|
|
||||||
|
b.ToTable("Instances");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Environment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Functions.Data.Function", "Function")
|
||||||
|
.WithMany("EnvironmentVariables")
|
||||||
|
.HasForeignKey("FunctionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Function");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Functions.Data.Function", "Function")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("FunctionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Function");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("EnvironmentVariables");
|
||||||
|
|
||||||
|
b.Navigation("Instances");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Functions/Data/DB/Migrations/20230529102304_Function3.cs
Normal file
51
Functions/Data/DB/Migrations/20230529102304_Function3.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Function3 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "EnvironmentVariables",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Key = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Value = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
FunctionId = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_EnvironmentVariables", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_EnvironmentVariables_Functions_FunctionId",
|
||||||
|
column: x => x.FunctionId,
|
||||||
|
principalTable: "Functions",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EnvironmentVariables_FunctionId",
|
||||||
|
table: "EnvironmentVariables",
|
||||||
|
column: "FunctionId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "EnvironmentVariables");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
119
Functions/Data/DB/Migrations/FunctionsContextModelSnapshot.cs
Normal file
119
Functions/Data/DB/Migrations/FunctionsContextModelSnapshot.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Functions.Data.DB.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(FunctionsContext))]
|
||||||
|
partial class FunctionsContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Environment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FunctionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FunctionId");
|
||||||
|
|
||||||
|
b.ToTable("EnvironmentVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ImageTag")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Functions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FunctionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("InstanceId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FunctionId");
|
||||||
|
|
||||||
|
b.ToTable("Instances");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Environment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Functions.Data.Function", "Function")
|
||||||
|
.WithMany("EnvironmentVariables")
|
||||||
|
.HasForeignKey("FunctionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Function");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Instance", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Functions.Data.Function", "Function")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("FunctionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Function");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Functions.Data.Function", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("EnvironmentVariables");
|
||||||
|
|
||||||
|
b.Navigation("Instances");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Functions/Data/Environment.cs
Normal file
25
Functions/Data/Environment.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Functions.Data;
|
||||||
|
|
||||||
|
public class Environment
|
||||||
|
{
|
||||||
|
public Environment(string key, string value)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Key { get; set; }
|
||||||
|
[Required]
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
public int FunctionId { get; set; }
|
||||||
|
public Function Function { get; set; } = null!;
|
||||||
|
}
|
||||||
27
Functions/Data/Function.cs
Normal file
27
Functions/Data/Function.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Functions.Data;
|
||||||
|
|
||||||
|
public class Function
|
||||||
|
{
|
||||||
|
public Function(string name, string imageTag)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
ImageTag = imageTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ImageTag { get; set; }
|
||||||
|
|
||||||
|
public List<Environment> EnvironmentVariables { get; set; }
|
||||||
|
|
||||||
|
public List<Instance> Instances { get; set; } = null!;
|
||||||
|
}
|
||||||
26
Functions/Data/Instance.cs
Normal file
26
Functions/Data/Instance.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Functions.Data;
|
||||||
|
|
||||||
|
public class Instance
|
||||||
|
{
|
||||||
|
public Instance(string name, string instanceId)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
InstanceId = instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string InstanceId { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public int FunctionId { get; set; }
|
||||||
|
public Function Function { get; set; }
|
||||||
|
}
|
||||||
20
Functions/Dockerfile
Normal file
20
Functions/Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["Functions/Functions.csproj", "Functions/"]
|
||||||
|
RUN dotnet restore "Functions/Functions.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/Functions"
|
||||||
|
RUN dotnet build "Functions.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "Functions.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "Functions.dll"]
|
||||||
30
Functions/Functions.csproj
Normal file
30
Functions/Functions.csproj
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Docker.DotNet" Version="3.125.15" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\.dockerignore">
|
||||||
|
<Link>.dockerignore</Link>
|
||||||
|
</Content>
|
||||||
|
<Content Update="appsettings.Development.json">
|
||||||
|
<DependentUpon>appsettings.json</DependentUpon>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
59
Functions/Program.cs
Normal file
59
Functions/Program.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Functions.Services;
|
||||||
|
using Functions.Services.Interfaces;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
//ASPNETCORE_AppConfig__TwilioSecret=my-secret
|
||||||
|
builder.Configuration.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var connectionString = new StringBuilder();
|
||||||
|
connectionString.Append($"server={builder.Configuration["AppConfig:DB:Server"]};");
|
||||||
|
connectionString.Append($"port={builder.Configuration["AppConfig:DB:Port"]};");
|
||||||
|
connectionString.Append($"user={builder.Configuration["AppConfig:DB:User"]};");
|
||||||
|
connectionString.Append($"password={builder.Configuration["AppConfig:DB:Password"]};");
|
||||||
|
connectionString.Append($"database={builder.Configuration["AppConfig:DB:Database"]};");
|
||||||
|
Console.WriteLine(connectionString.ToString());
|
||||||
|
|
||||||
|
var serverVersion = new MySqlServerVersion(new Version(8, 0, 31));
|
||||||
|
builder.Services.AddDbContextFactory<FunctionsContext>(
|
||||||
|
dbContextOptions => dbContextOptions
|
||||||
|
.UseMySql(connectionString.ToString(), serverVersion)
|
||||||
|
.LogTo(Console.WriteLine, LogLevel.Debug)
|
||||||
|
.EnableSensitiveDataLogging()
|
||||||
|
.EnableDetailedErrors());
|
||||||
|
|
||||||
|
|
||||||
|
builder.Services.AddTransient<IDockerManager,DockerManager>();
|
||||||
|
builder.Services.AddSingleton<FunctionManager>();
|
||||||
|
builder.Services.AddHttpClient<IExternalEndpointManager, ExternalEndpointManager>()
|
||||||
|
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
var dbFactory = app.Services.GetRequiredService<IDbContextFactory<FunctionsContext>>();
|
||||||
|
var db = await dbFactory.CreateDbContextAsync();
|
||||||
|
await db.Database.MigrateAsync();
|
||||||
|
|
||||||
|
|
||||||
|
app.Run();
|
||||||
25
Functions/Properties/launchSettings.json
Normal file
25
Functions/Properties/launchSettings.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5051",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7122;http://localhost:5051",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
122
Functions/Services/DockerManager.cs
Normal file
122
Functions/Services/DockerManager.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Docker.DotNet;
|
||||||
|
using Docker.DotNet.Models;
|
||||||
|
using Functions.Services.Interfaces;
|
||||||
|
using Environment = Functions.Data.Environment;
|
||||||
|
|
||||||
|
namespace Functions.Services;
|
||||||
|
|
||||||
|
public class DockerManager : IDockerManager
|
||||||
|
{
|
||||||
|
private readonly ILogger<DockerManager> _logger;
|
||||||
|
private readonly DockerClient _docker;
|
||||||
|
public DockerManager(ILogger<DockerManager> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
_docker = new DockerClientConfiguration(new Uri("npipe://./pipe/docker_engine")).CreateClient();
|
||||||
|
}
|
||||||
|
else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
_docker = new DockerClientConfiguration(new Uri("unix:///var/run/dockerManager.sock")).CreateClient();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("This Platform is not Supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IList<ContainerListResponse>> GetContainers()
|
||||||
|
{
|
||||||
|
//TODO: Add Log Message
|
||||||
|
IList<ContainerListResponse> containers = await _docker.Containers.ListContainersAsync(
|
||||||
|
new ContainersListParameters(){
|
||||||
|
Limit = 10,
|
||||||
|
});
|
||||||
|
return containers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ContainerResponse> CreateContainer(string image, List<Environment> envList)
|
||||||
|
{
|
||||||
|
var createContainerParameters = new CreateContainerParameters()
|
||||||
|
{
|
||||||
|
Image = image,
|
||||||
|
Name = "FN-" + new Random().Next(10000, 99999),
|
||||||
|
/*Env = envList,*/ //TODO: Parse the envs
|
||||||
|
NetworkingConfig = new NetworkingConfig()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var container = await _docker.Containers.CreateContainerAsync(createContainerParameters);
|
||||||
|
|
||||||
|
return new ContainerResponse(createContainerParameters.Name, container.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void ConnectNetwork(string name, string containerId)
|
||||||
|
{
|
||||||
|
var networkConnectParameters = new NetworkConnectParameters()
|
||||||
|
{
|
||||||
|
Container = containerId
|
||||||
|
};
|
||||||
|
await _docker.Networks.ConnectNetworkAsync(await GetNetworkId(name), networkConnectParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void StartContainer(string containerId)
|
||||||
|
{
|
||||||
|
|
||||||
|
var containerStartParameters = new ContainerStartParameters();
|
||||||
|
await _docker.Containers.StartContainerAsync(containerId, containerStartParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string?> GetNetworkId(string name)
|
||||||
|
{
|
||||||
|
var response = await _docker.Networks.ListNetworksAsync();
|
||||||
|
|
||||||
|
foreach (var networkResponse in response)
|
||||||
|
{
|
||||||
|
if (networkResponse.Name.Equals(name))
|
||||||
|
{
|
||||||
|
return networkResponse.ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void DeleteContainer(string containerId)
|
||||||
|
{
|
||||||
|
var parameters = new ContainerRemoveParameters()
|
||||||
|
{
|
||||||
|
Force = true
|
||||||
|
};
|
||||||
|
await _docker.Containers.RemoveContainerAsync(containerId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsRunning(string containerId)
|
||||||
|
{
|
||||||
|
var containers = await GetContainers();
|
||||||
|
foreach (var containerListResponse in containers)
|
||||||
|
{
|
||||||
|
if (containerListResponse.ID.Equals(containerId))
|
||||||
|
{
|
||||||
|
return containerListResponse.State.Equals("Running");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ContainerResponse
|
||||||
|
{
|
||||||
|
public ContainerResponse(string name, string id)
|
||||||
|
{
|
||||||
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
|
Id = id ?? throw new ArgumentNullException(nameof(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
118
Functions/Services/ExternalEndpointManager.cs
Normal file
118
Functions/Services/ExternalEndpointManager.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Functions.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace Functions.Services;
|
||||||
|
|
||||||
|
public class ExternalEndpointManager : IExternalEndpointManager
|
||||||
|
{
|
||||||
|
private readonly ILogger<ExternalEndpointManager> _logger;
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
|
||||||
|
public ExternalEndpointManager(ILogger<ExternalEndpointManager> logger, HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Get(string hostname)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Send GET request to the API
|
||||||
|
HttpResponseMessage response = await _httpClient.GetAsync($"http://{hostname}");
|
||||||
|
|
||||||
|
// Ensure the response was successful
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
// Read the response content as a string
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Display the response content
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
// Handle any errors that occurred during the request
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Post(string hostname, string body)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var content = new StringContent(body, Encoding.UTF8, "application/json");
|
||||||
|
// Send GET request to the API
|
||||||
|
HttpResponseMessage response = await _httpClient.PostAsync($"http://{hostname}",content);
|
||||||
|
|
||||||
|
// Ensure the response was successful
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
// Read the response content as a string
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Display the response content
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
// Handle any errors that occurred during the request
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Delete(string hostname)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Send GET request to the API
|
||||||
|
HttpResponseMessage response = await _httpClient.DeleteAsync($"http://{hostname}");
|
||||||
|
|
||||||
|
// Ensure the response was successful
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
// Read the response content as a string
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Display the response content
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
// Handle any errors that occurred during the request
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Patch(string hostname, string body)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var content = new StringContent(body, Encoding.UTF8, "application/json");
|
||||||
|
// Send GET request to the API
|
||||||
|
HttpResponseMessage response = await _httpClient.PatchAsync($"http://{hostname}",content);
|
||||||
|
|
||||||
|
// Ensure the response was successful
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
// Read the response content as a string
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Display the response content
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
// Handle any errors that occurred during the request
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
99
Functions/Services/FunctionManager.cs
Normal file
99
Functions/Services/FunctionManager.cs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
using Functions.Data;
|
||||||
|
using Functions.Data.DB;
|
||||||
|
using Functions.Services.Interfaces;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Functions.Services;
|
||||||
|
|
||||||
|
public class FunctionManager
|
||||||
|
{
|
||||||
|
//TODO: Add Logging
|
||||||
|
private readonly ILogger<FunctionManager> _logger;
|
||||||
|
private readonly IDockerManager _dockerManager;
|
||||||
|
private readonly IDbContextFactory<FunctionsContext> _dbContextFactory;
|
||||||
|
private readonly IExternalEndpointManager _externalEndpointManager;
|
||||||
|
|
||||||
|
public FunctionManager(ILogger<FunctionManager> logger, IDockerManager dockerManager, IDbContextFactory<FunctionsContext> dbContextFactory, IExternalEndpointManager externalEndpointManager)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_dockerManager = dockerManager;
|
||||||
|
_dbContextFactory = dbContextFactory;
|
||||||
|
_externalEndpointManager = externalEndpointManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task CreateFunction(string functionName, string imageTag)
|
||||||
|
{
|
||||||
|
var db = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
await db.Functions.AddAsync(new Function(functionName, imageTag));
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
public async Task DeleteFunction(string functionName)
|
||||||
|
{
|
||||||
|
var db = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
var function = db.Functions.Include(s => s.Instances).Include(s => s.EnvironmentVariables).First(s => s.Name.Equals(functionName));
|
||||||
|
foreach (var functionInstance in function.Instances)
|
||||||
|
{
|
||||||
|
_dockerManager.DeleteContainer(functionInstance.InstanceId);
|
||||||
|
}
|
||||||
|
db.Functions.Remove(function);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> RunInstance(string functionName, HttpMethod method, string body = "")
|
||||||
|
{
|
||||||
|
var db = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
var function = db.Functions.Include(s => s.Instances).Include(s => s.EnvironmentVariables).First(s => s.Name.Equals(functionName));
|
||||||
|
|
||||||
|
var container = await _dockerManager.CreateContainer(function.ImageTag,function.EnvironmentVariables);
|
||||||
|
var instance = new Instance(container.Name,container.Id);
|
||||||
|
function.Instances.Add(instance);
|
||||||
|
db.Functions.Update(function);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
_dockerManager.ConnectNetwork("simplefunctions_functions", instance.InstanceId);
|
||||||
|
_dockerManager.StartContainer(instance.InstanceId);
|
||||||
|
|
||||||
|
//TODO: If not started delete instance
|
||||||
|
//Send Request to Container
|
||||||
|
|
||||||
|
if (method.Equals(HttpMethod.Post))
|
||||||
|
{
|
||||||
|
var message = await _externalEndpointManager.Post(instance.Name, body);
|
||||||
|
if (message.Equals("error"))
|
||||||
|
{
|
||||||
|
_dockerManager.DeleteContainer(instance.InstanceId);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
if (method.Equals(HttpMethod.Get))
|
||||||
|
{
|
||||||
|
var message = await _externalEndpointManager.Get(instance.Name);
|
||||||
|
if (message.Equals("error"))
|
||||||
|
{
|
||||||
|
_dockerManager.DeleteContainer(instance.InstanceId);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
if (method.Equals(HttpMethod.Patch))
|
||||||
|
{
|
||||||
|
var message = await _externalEndpointManager.Patch(instance.Name, body);
|
||||||
|
if (message.Equals("error"))
|
||||||
|
{
|
||||||
|
_dockerManager.DeleteContainer(instance.InstanceId);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
15
Functions/Services/Interfaces/IDockerManager.cs
Normal file
15
Functions/Services/Interfaces/IDockerManager.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Docker.DotNet.Models;
|
||||||
|
using Functions.Data;
|
||||||
|
using Environment = Functions.Data.Environment;
|
||||||
|
|
||||||
|
namespace Functions.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface IDockerManager
|
||||||
|
{
|
||||||
|
public Task<IList<ContainerListResponse>> GetContainers();
|
||||||
|
public Task<ContainerResponse> CreateContainer(string image, List<Environment> envList);
|
||||||
|
public void ConnectNetwork(string name, string containerId);
|
||||||
|
public void StartContainer(string containerId);
|
||||||
|
public void DeleteContainer(string containerId);
|
||||||
|
public Task<bool> IsRunning(string containerId);
|
||||||
|
}
|
||||||
11
Functions/Services/Interfaces/IExternalEndpointManager.cs
Normal file
11
Functions/Services/Interfaces/IExternalEndpointManager.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Functions.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface IExternalEndpointManager
|
||||||
|
{
|
||||||
|
public Task<string> Get(string hostname);
|
||||||
|
public Task<string> Post(string hostname, string body);
|
||||||
|
public Task<string> Delete(string hostname);
|
||||||
|
public Task<string> Patch(string hostname, string body);
|
||||||
|
}
|
||||||
18
Functions/appsettings.Development.json
Normal file
18
Functions/appsettings.Development.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"AppConfig": {
|
||||||
|
"DB": {
|
||||||
|
"Server": "localhost",
|
||||||
|
"Port": "8082",
|
||||||
|
"User": "root",
|
||||||
|
"Password": "testPW",
|
||||||
|
"Database": "Functions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Functions/appsettings.Production.json
Normal file
18
Functions/appsettings.Production.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"AppConfig": {
|
||||||
|
"DB": {
|
||||||
|
"Server": "db",
|
||||||
|
"Port": "3306",
|
||||||
|
"User": "root",
|
||||||
|
"Password": "testPW",
|
||||||
|
"Database": "Functions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Functions/appsettings.json
Normal file
9
Functions/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
27
SimpleFunctions.sln
Normal file
27
SimpleFunctions.sln
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Functions", "Functions\Functions.csproj", "{F2CFCA0F-C615-4B7B-89D5-EB6C8EC3ACD1}"
|
||||||
|
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
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFunction", "TestFunction\TestFunction.csproj", "{BC3C484C-EFD0-45E5-BE6E-9212916489E4}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{F2CFCA0F-C615-4B7B-89D5-EB6C8EC3ACD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F2CFCA0F-C615-4B7B-89D5-EB6C8EC3ACD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F2CFCA0F-C615-4B7B-89D5-EB6C8EC3ACD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F2CFCA0F-C615-4B7B-89D5-EB6C8EC3ACD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BC3C484C-EFD0-45E5-BE6E-9212916489E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BC3C484C-EFD0-45E5-BE6E-9212916489E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BC3C484C-EFD0-45E5-BE6E-9212916489E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BC3C484C-EFD0-45E5-BE6E-9212916489E4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
32
TestFunction/Controllers/WeatherForecastController.cs
Normal file
32
TestFunction/Controllers/WeatherForecastController.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace TestFunction.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("")]
|
||||||
|
public class WeatherForecastController : ControllerBase
|
||||||
|
{
|
||||||
|
private static readonly string[] Summaries = new[]
|
||||||
|
{
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ILogger<WeatherForecastController> _logger;
|
||||||
|
|
||||||
|
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(Name = "GetWeatherForecast")]
|
||||||
|
public IEnumerable<WeatherForecast> Get()
|
||||||
|
{
|
||||||
|
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||||
|
{
|
||||||
|
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||||
|
TemperatureC = Random.Shared.Next(-20, 55),
|
||||||
|
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
20
TestFunction/Dockerfile
Normal file
20
TestFunction/Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["TestFunction/TestFunction.csproj", "TestFunction/"]
|
||||||
|
RUN dotnet restore "TestFunction/TestFunction.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/TestFunction"
|
||||||
|
RUN dotnet build "TestFunction.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "TestFunction.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "TestFunction.dll"]
|
||||||
25
TestFunction/Program.cs
Normal file
25
TestFunction/Program.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
25
TestFunction/Properties/launchSettings.json
Normal file
25
TestFunction/Properties/launchSettings.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5060",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7090;http://localhost:5060",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
TestFunction/TestFunction.csproj
Normal file
22
TestFunction/TestFunction.csproj
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<UserSecretsId>78de8317-ca29-42e4-8505-95b369d5f64b</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\.dockerignore">
|
||||||
|
<Link>.dockerignore</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
12
TestFunction/WeatherForecast.cs
Normal file
12
TestFunction/WeatherForecast.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace TestFunction;
|
||||||
|
|
||||||
|
public class WeatherForecast
|
||||||
|
{
|
||||||
|
public DateOnly Date { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureC { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
}
|
||||||
17
TestFunction/appsettings.Development.json
Normal file
17
TestFunction/appsettings.Development.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AppConfig": {
|
||||||
|
"DB": {
|
||||||
|
"Server": "localhost",
|
||||||
|
"Port": "8082",
|
||||||
|
"User": "root",
|
||||||
|
"Password": "testPW",
|
||||||
|
"Database": "Functions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
TestFunction/appsettings.json
Normal file
9
TestFunction/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
42
docker-compose.yml
Normal file
42
docker-compose.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
functions:
|
||||||
|
|
||||||
|
services:
|
||||||
|
functions:
|
||||||
|
build: ./Functions
|
||||||
|
environment:
|
||||||
|
ASPNETCORE_AppConfig__DB__Server: "db"
|
||||||
|
ASPNETCORE_AppConfig__DB__User: "root"
|
||||||
|
ASPNETCORE_AppConfig__DB__Password: "testPW"
|
||||||
|
ASPNETCORE_AppConfig__DB__Database: "Functions"
|
||||||
|
ASPNETCORE_ENVIRONMENT: "Production"
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
- "8081:443"
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
networks:
|
||||||
|
- functions
|
||||||
|
db:
|
||||||
|
image: mysql:8.0.31-debian
|
||||||
|
cap_add:
|
||||||
|
- SYS_NICE
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: 'db'
|
||||||
|
MYSQL_ROOT_PASSWORD: 'testPW'
|
||||||
|
volumes:
|
||||||
|
- db:/var/lib/mysql
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- functions
|
||||||
|
ports:
|
||||||
|
- "8082:3306"
|
||||||
7
global.json
Normal file
7
global.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"rollForward": "latestMinor",
|
||||||
|
"allowPrerelease": false
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user