From b795458461486b579e6d512e2a0e7ec4872832ec Mon Sep 17 00:00:00 2001 From: msivasubramaniaan Date: Fri, 19 Jul 2024 18:37:47 +0530 Subject: [PATCH] added dotnet80 stack support Signed-off-by: msivasubramaniaan --- .../recognizer/devfile_recognizer_test.go | 13 ++ .../dotnet8.0/app/Data/AppConfiguration.cs | 6 + .../dotnet8.0/app/Data/AppDbContext.cs | 13 ++ .../projects/dotnet8.0/app/Data/Customer.cs | 11 ++ .../20191107110533_Initial.Designer.cs | 42 +++++ .../app/Migrations/20191107110533_Initial.cs | 30 ++++ .../Migrations/AppDbContextModelSnapshot.cs | 40 +++++ .../dotnet8.0/app/Pages/Create.cshtml | 16 ++ .../dotnet8.0/app/Pages/Create.cshtml.cs | 30 ++++ .../projects/dotnet8.0/app/Pages/Edit.cshtml | 24 +++ .../dotnet8.0/app/Pages/Edit.cshtml.cs | 52 ++++++ .../projects/dotnet8.0/app/Pages/Index.cshtml | 31 ++++ .../dotnet8.0/app/Pages/Index.cshtml.cs | 39 +++++ resources/projects/dotnet8.0/app/Program.cs | 8 + .../dotnet8.0/app/RazorPagesContacts.csproj | 22 +++ resources/projects/dotnet8.0/app/Startup.cs | 165 ++++++++++++++++++ .../app/app.csproj | 2 +- .../projects/s2i-dotnetcore-ex/app/app.csproj | 2 +- test/apis/language_recognizer_test.go | 2 +- 19 files changed, 545 insertions(+), 3 deletions(-) create mode 100644 resources/projects/dotnet8.0/app/Data/AppConfiguration.cs create mode 100644 resources/projects/dotnet8.0/app/Data/AppDbContext.cs create mode 100644 resources/projects/dotnet8.0/app/Data/Customer.cs create mode 100644 resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.Designer.cs create mode 100644 resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.cs create mode 100644 resources/projects/dotnet8.0/app/Migrations/AppDbContextModelSnapshot.cs create mode 100644 resources/projects/dotnet8.0/app/Pages/Create.cshtml create mode 100644 resources/projects/dotnet8.0/app/Pages/Create.cshtml.cs create mode 100644 resources/projects/dotnet8.0/app/Pages/Edit.cshtml create mode 100644 resources/projects/dotnet8.0/app/Pages/Edit.cshtml.cs create mode 100644 resources/projects/dotnet8.0/app/Pages/Index.cshtml create mode 100644 resources/projects/dotnet8.0/app/Pages/Index.cshtml.cs create mode 100644 resources/projects/dotnet8.0/app/Program.cs create mode 100644 resources/projects/dotnet8.0/app/RazorPagesContacts.csproj create mode 100644 resources/projects/dotnet8.0/app/Startup.cs diff --git a/pkg/apis/recognizer/devfile_recognizer_test.go b/pkg/apis/recognizer/devfile_recognizer_test.go index fed8e5be..87dacf6f 100644 --- a/pkg/apis/recognizer/devfile_recognizer_test.go +++ b/pkg/apis/recognizer/devfile_recognizer_test.go @@ -44,6 +44,10 @@ func TestDetectDotNet60Devfile(t *testing.T) { detectDevfile(t, "dotnet6.0", []string{"dotnet60"}) } +func TestDetectDotNet60Devfile(t *testing.T) { + detectDevfile(t, "dotnet8.0", []string{"dotnet80"}) +} + func TestDetectDotNetCore31Devfile(t *testing.T) { detectDevfile(t, "dotnetcore3.1", []string{"dotnetcore31"}) } @@ -686,6 +690,15 @@ func getDevfileTypes() []model.DevfileType { ".Net 6.0", }, }, + { + Name: "dotnet80", + Language: ".NET", + ProjectType: "dotnet", + Tags: []string{ + ".Net", + ".Net 8.0", + }, + }, { Name: "dotnetcore31", Language: ".NET", diff --git a/resources/projects/dotnet8.0/app/Data/AppConfiguration.cs b/resources/projects/dotnet8.0/app/Data/AppConfiguration.cs new file mode 100644 index 00000000..d41e8323 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Data/AppConfiguration.cs @@ -0,0 +1,6 @@ +namespace RazorPagesContacts.Data; + +public class AppConfiguration +{ + public string DatabaseProvider { get; set; } +} diff --git a/resources/projects/dotnet8.0/app/Data/AppDbContext.cs b/resources/projects/dotnet8.0/app/Data/AppDbContext.cs new file mode 100644 index 00000000..d62e330a --- /dev/null +++ b/resources/projects/dotnet8.0/app/Data/AppDbContext.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; + +namespace RazorPagesContacts.Data; + +public class AppDbContext : DbContext +{ + public AppDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Customers { get; set; } +} \ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Data/Customer.cs b/resources/projects/dotnet8.0/app/Data/Customer.cs new file mode 100644 index 00000000..3b31d072 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Data/Customer.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace RazorPagesContacts.Data; + +public class Customer +{ + public int Id { get; set; } + + [Required, StringLength(100)] + public string Name { get; set; } +} \ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.Designer.cs b/resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.Designer.cs new file mode 100644 index 00000000..1f021851 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.Designer.cs @@ -0,0 +1,42 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using RazorPagesContacts.Data; + +namespace RazorPagesContacts.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20191107110533_Initial")] + partial class Initial + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("RazorPagesContacts.Data.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(100)") + .HasMaxLength(100); + + b.HasKey("Id"); + + b.ToTable("Customers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.cs b/resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.cs new file mode 100644 index 00000000..53129a66 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Migrations/20191107110533_Initial.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace RazorPagesContacts.Migrations +{ + public partial class Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Customers", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(maxLength: 100, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Customers", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Customers"); + } + } +} diff --git a/resources/projects/dotnet8.0/app/Migrations/AppDbContextModelSnapshot.cs b/resources/projects/dotnet8.0/app/Migrations/AppDbContextModelSnapshot.cs new file mode 100644 index 00000000..3f02405b --- /dev/null +++ b/resources/projects/dotnet8.0/app/Migrations/AppDbContextModelSnapshot.cs @@ -0,0 +1,40 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using RazorPagesContacts.Data; + +namespace RazorPagesContacts.Migrations +{ + [DbContext(typeof(AppDbContext))] + partial class AppDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("RazorPagesContacts.Data.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(100)") + .HasMaxLength(100); + + b.HasKey("Id"); + + b.ToTable("Customers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/resources/projects/dotnet8.0/app/Pages/Create.cshtml b/resources/projects/dotnet8.0/app/Pages/Create.cshtml new file mode 100644 index 00000000..3c7be190 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Pages/Create.cshtml @@ -0,0 +1,16 @@ +@page +@model RazorPagesContacts.Pages.CreateModel +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + + + +

+ Enter your name. +

+
+
+
Name:
+ +
+ + \ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Pages/Create.cshtml.cs b/resources/projects/dotnet8.0/app/Pages/Create.cshtml.cs new file mode 100644 index 00000000..fb065c0c --- /dev/null +++ b/resources/projects/dotnet8.0/app/Pages/Create.cshtml.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using RazorPagesContacts.Data; + +namespace RazorPagesContacts.Pages; + +public class CreateModel : PageModel +{ + private readonly AppDbContext _db; + + public CreateModel(AppDbContext db) + { + _db = db; + } + + [BindProperty] + public Customer Customer { get; set; } + + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { + return Page(); + } + + _db.Customers.Add(Customer); + await _db.SaveChangesAsync(); + return RedirectToPage("/Index"); + } +} diff --git a/resources/projects/dotnet8.0/app/Pages/Edit.cshtml b/resources/projects/dotnet8.0/app/Pages/Edit.cshtml new file mode 100644 index 00000000..249d67e4 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Pages/Edit.cshtml @@ -0,0 +1,24 @@ +@page "{id:int}" +@model RazorPagesContacts.Pages.EditModel +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + +@{ + ViewData["Title"] = "Edit Customer"; +} + +

Edit Customer - @Model.Customer.Id

+
+
+ +
+ +
+ + +
+
+ +
+ +
+
\ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Pages/Edit.cshtml.cs b/resources/projects/dotnet8.0/app/Pages/Edit.cshtml.cs new file mode 100644 index 00000000..ef0deecd --- /dev/null +++ b/resources/projects/dotnet8.0/app/Pages/Edit.cshtml.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.EntityFrameworkCore; +using RazorPagesContacts.Data; + +namespace RazorPagesContacts.Pages; + +public class EditModel : PageModel +{ + private readonly AppDbContext _db; + + public EditModel(AppDbContext db) + { + _db = db; + } + + [BindProperty] + public Customer Customer { get; set; } + + public async Task OnGetAsync(int id) + { + Customer = await _db.Customers.FindAsync(id); + + if (Customer == null) + { + return RedirectToPage("/Index"); + } + + return Page(); + } + + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { + return Page(); + } + + _db.Attach(Customer).State = EntityState.Modified; + + try + { + await _db.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + throw new Exception($"Customer {Customer.Id} not found!"); + } + + return RedirectToPage("/Index"); + } +} \ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Pages/Index.cshtml b/resources/projects/dotnet8.0/app/Pages/Index.cshtml new file mode 100644 index 00000000..8a6fc086 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Pages/Index.cshtml @@ -0,0 +1,31 @@ +@page +@model RazorPagesContacts.Pages.IndexModel +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + +

Contacts from @Model.AppConfiguration.DatabaseProvider database

+
+ + + + + + + + + @foreach (var contact in Model.Customers) + { + + + + + + } + +
IDName
@contact.Id@contact.Name + edit + +
+ + Create +
\ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Pages/Index.cshtml.cs b/resources/projects/dotnet8.0/app/Pages/Index.cshtml.cs new file mode 100644 index 00000000..529a4ee5 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Pages/Index.cshtml.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using RazorPagesContacts.Data; +using Microsoft.EntityFrameworkCore; + +namespace RazorPagesContacts.Pages; + +public class IndexModel : PageModel +{ + private readonly AppDbContext _db; + + public IndexModel(AppDbContext db, AppConfiguration appConfig) + { + _db = db; + AppConfiguration = appConfig; + } + + public IList Customers { get; private set; } + + public AppConfiguration AppConfiguration { get; } + + public async Task OnGetAsync() + { + Customers = await _db.Customers.AsNoTracking().ToListAsync(); + } + + public async Task OnPostDeleteAsync(int id) + { + var contact = await _db.Customers.FindAsync(id); + + if (contact != null) + { + _db.Customers.Remove(contact); + await _db.SaveChangesAsync(); + } + + return RedirectToPage(); + } +} \ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/Program.cs b/resources/projects/dotnet8.0/app/Program.cs new file mode 100644 index 00000000..47db29a8 --- /dev/null +++ b/resources/projects/dotnet8.0/app/Program.cs @@ -0,0 +1,8 @@ +using RazorPagesContacts; + +var builder = Microsoft.AspNetCore.WebHost.CreateDefaultBuilder(args) + .UseStartup(); + +var app = builder.Build(); + +app.Run(); \ No newline at end of file diff --git a/resources/projects/dotnet8.0/app/RazorPagesContacts.csproj b/resources/projects/dotnet8.0/app/RazorPagesContacts.csproj new file mode 100644 index 00000000..aaeb4bf9 --- /dev/null +++ b/resources/projects/dotnet8.0/app/RazorPagesContacts.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/resources/projects/dotnet8.0/app/Startup.cs b/resources/projects/dotnet8.0/app/Startup.cs new file mode 100644 index 00000000..ac2f37fd --- /dev/null +++ b/resources/projects/dotnet8.0/app/Startup.cs @@ -0,0 +1,165 @@ +using Microsoft.EntityFrameworkCore; +using RazorPagesContacts.Data; + +namespace RazorPagesContacts; + +enum DbProvider +{ + InMemory, + PostgreSQL +} + +public class Startup +{ + public IConfiguration Configuration { get; } + public ILogger Logger { get; } + private bool _migrateDatabase = true; + + public Startup(IConfiguration configuration, ILogger logger) + { + Configuration = configuration; + Logger = logger; + } + + public void ConfigureServices(IServiceCollection services) + { + (DbProvider dbProvider, string connectionString) = DetermineDatabaseConfiguration(); + switch (dbProvider) + { + case DbProvider.PostgreSQL: + Logger.LogInformation($"Using PostgreSQL database"); + services.AddDbContext(options => + options.UseNpgsql(connectionString)); + _migrateDatabase = true; + break; + case DbProvider.InMemory: + Logger.LogInformation("Using InMemory database"); + services.AddDbContext(options => + options.UseInMemoryDatabase("name")); + _migrateDatabase = false; + break; + default: + throw new ArgumentException($"Unknown db provider: {dbProvider}"); + } + + services.AddSingleton(new AppConfiguration + { + DatabaseProvider = dbProvider.ToString() + }); + + services.AddRazorPages(); + + } + + public void Configure(IApplicationBuilder app) + { + if (_migrateDatabase) + { + MigrateDatabase(app); + } + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + }); + } + + private (DbProvider dbProvider, string connectionString) DetermineDatabaseConfiguration() + { + DbProvider? dbProvider = Configuration.GetValue("DB_PROVIDER"); + string connectionString = Configuration.GetConnectionString("Database"); + + // Explicit configuration. + if (dbProvider != null && connectionString != null) + { + return (dbProvider.Value, connectionString); + } + + // If there is no explicit configuration, try to pick an appropriate one by inspecting environment variables. + // We support a PostgreSQL database that was created and linked with odo (https://github.com/openshift/odo). + // And a secret from 'oc new-app postgresql-ephemeral' augmented with a 'database-service' envvar. + + if (dbProvider == null) + { + // 'odo' PostgreSQL has a 'uri' envvar that starts with 'postgres://'. + string uri = Configuration.GetValue("uri"); + string database_service = GetOcSetConfigurationValue("database-service"); + // 'oc' PostgreSQL has a 'database-service' envvar. + if ((uri != null && uri.StartsWith("postgres://")) || + (database_service != null)) + { + dbProvider = DbProvider.PostgreSQL; + } + else + { + dbProvider = DbProvider.InMemory; + } + } + + switch (dbProvider) + { + case DbProvider.PostgreSQL: + string database_name = null; + string host = null; + int port = -1; + string password = null; + string username = null; + + // 'odo' environment variables for PostgreSQL. + Uri uri = Configuration.GetValue("uri"); + if (uri != null) + { + database_name = Configuration.GetValue("database_name"); + password = Configuration.GetValue("password"); + host = uri.Host; + port = uri.Port == -1 ? 5432 : uri.Port; + username = Configuration.GetValue("username"); + } + else + { + host = GetOcSetConfigurationValue("database-service"); + // 'oc new-app postgresql-ephemeral' environment variables for PostgreSQL. + if (host != null) + { + database_name = GetOcSetConfigurationValue("database-name"); + username = GetOcSetConfigurationValue("database-user"); + password = GetOcSetConfigurationValue("database-password"); + port = 5432; + } + } + + connectionString = $"Host={host};Port={port};Database={database_name};Username={username};Password={password}"; + break; + case DbProvider.InMemory: + break; + default: + throw new ArgumentException($"Unknown db provider: {dbProvider}"); + } + + return (dbProvider.Value, connectionString); + } + + private T GetOcSetConfigurationValue(string name) + { + return Configuration.GetValue(name) ?? + Configuration.GetValue(name.Replace('-', '_').ToUpper()); // oc set-env --from-secret changes the names. + } + + private string GetOcSetConfigurationValue(string name) + => GetOcSetConfigurationValue(name); + + private static void MigrateDatabase(IApplicationBuilder app) + { + using (var serviceScope = app.ApplicationServices + .GetRequiredService() + .CreateScope()) + { + using (var context = serviceScope.ServiceProvider.GetService()) + { + context.Database.Migrate(); + } + } + } +} \ No newline at end of file diff --git a/resources/projects/multiple-dotnet-target-frameworks/app/app.csproj b/resources/projects/multiple-dotnet-target-frameworks/app/app.csproj index b56710e8..b4d35c78 100644 --- a/resources/projects/multiple-dotnet-target-frameworks/app/app.csproj +++ b/resources/projects/multiple-dotnet-target-frameworks/app/app.csproj @@ -1,7 +1,7 @@ - net6.0;netcoreapp3.1;net5.0 + net8.0;net6.0;netcoreapp3.1;net5.0 enable enable diff --git a/resources/projects/s2i-dotnetcore-ex/app/app.csproj b/resources/projects/s2i-dotnetcore-ex/app/app.csproj index c78c9c7e..1b28a01c 100644 --- a/resources/projects/s2i-dotnetcore-ex/app/app.csproj +++ b/resources/projects/s2i-dotnetcore-ex/app/app.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable enable diff --git a/test/apis/language_recognizer_test.go b/test/apis/language_recognizer_test.go index cf4bedca..209fa3e5 100644 --- a/test/apis/language_recognizer_test.go +++ b/test/apis/language_recognizer_test.go @@ -35,7 +35,7 @@ func TestAnalyzeOnDjango(t *testing.T) { } func TestAnalyzeOnCSharp(t *testing.T) { - isLanguageInProject(t, "s2i-dotnetcore-ex", "c#", []string{}, []string{"net6.0"}) + isLanguageInProject(t, "s2i-dotnetcore-ex", "c#", []string{}, []string{"net8.0"}) } func TestAnalyzeOnFSharp(t *testing.T) {