-
Hi all! I'm trying to convert this Tye configuration to Aspire. I got most of it covered but I'm having some issues with converting a NetFX webapp hosted on IIS Express. Here is the Tye configuration name: mytd
services:
- name: web
executable: cmd
args: '/c npm run start --prefix Web'
bindings:
- protocol: http
env:
- name: BROWSER
value: none
- name: legacy
executable: '%PROGRAMFILES(x86)%\IIS Express\iisexpress.exe'
args: '/path:%MyTDLegacyPath% /systray:false /port:29213'
bindings:
- protocol: http
port: 29213
- name: api-v1
project: Backend/src/API/API.csproj
bindings:
- protocol: http
- name: database
image: mcr.microsoft.com/mssql/server:2022-latest
bindings:
- containerPort: 1433
port: 11400
connectionString: Server=${host},${port};Database=mytd;User Id=sa;Password=${env:MSSQL_SA_PASSWORD};TrustServerCertificate=True
env:
- name: ACCEPT_EULA
value: Y
- name: MSSQL_SA_PASSWORD
value: yourStrong!Password
volumes:
- target: /var/opt/mssql/data
source: data/database/data
- target: /var/opt/mssql/log
source: data/database/log
- target: /var/opt/mssql/secrets
source: data/database/secrets
tags:
- db
ingress:
- name: ingress
bindings:
- protocol: http
port: 11470
rules:
- path: /api/v1
service: api-v1
- path: /api
service: legacy
preservePath: true
- path: /services
service: legacy
preservePath: true
- path: /
service: web
preservePath: true This is what I got so far: using AppHost.Extensions;
using Aspirant.Hosting;
var builder = DistributedApplication.CreateBuilder(args);
var sqlServerPassword = builder.AddParameter("SqlServerPassword");
var db = builder.AddSqlServer("mssql", sqlServerPassword)
.WithDataVolume(name: "SqlServer-MyTD")
.WithHealthCheck()
.AddDatabase("Database");
var elasticsearchPassword = builder.AddParameter("ElasticsearchPassword");
var elasticsearch = builder.AddContainer("elasticsearch", "elasticsearch/elasticsearch", "8.13.4")
.WithVolume("ElasticSearch-MyTD", "/usr/share/elasticsearch/data")
.WithImageRegistry("docker.elastic.co")
.WithHttpsEndpoint(targetPort: 9200)
.WithEnvironment("ELASTIC_PASSWORD", elasticsearchPassword)
.WithEnvironment("DISCOVERY.TYPE", "SINGLE-NODE")
.WithEnvironment("XPACK.SECURITY.ENABLED", "TRUE");
var legacyPort = 29213;
var legacy = builder.AddExecutable("legacy", $@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)}\IIS Express\iisexpress.exe", ".")
.WithArgs($"/path:{Environment.GetEnvironmentVariable("MyTDLegacyPath")}", "/systray:false", $"/port:{legacyPort}")
.WithHttpEndpoint(port: legacyPort, targetPort: legacyPort, isProxied: false);
var backend = builder.AddProject<Projects.API>("backend")
.WithReference(db)
.WithEnvironment("Elasticsearch__Endpoint", elasticsearch.GetEndpoint("https"))
.WithEnvironment("Elasticsearch__Username", "elastic")
.WithEnvironment("Elasticsearch__Password", elasticsearchPassword)
.WithEnvironment("LegacyEndpoint", legacy.GetEndpoint("http"))
.WaitFor(db);
var frontend = builder.AddNpmApp("frontend", "../../web")
.WithHttpEndpoint(env: "PORT")
.RunWithEnvironment("BROWSER", "none");
var isHttps = builder.Configuration["DOTNET_LAUNCH_PROFILE"] == "https";
builder.AddYarp("ingress")
.WithEndpoint(scheme: isHttps ? "https" : "http", port: 11400)
.WithReference(backend)
.WithReference(frontend)
.WithReference(legacy.GetEndpoint("http"))
.LoadFromConfiguration("ReverseProxy");
builder.Build().Run(); Legacy is being terminated with a laconic I wish I could make the port of the legacy service randomly generated at startup. Thanks! EDIT: splitting the arguments in different strings solved the issue of starting IIS, but I can't reference it in any of the other services. EDIT2: I have no idea why it works, but EDIT3: updated Aspire snippet with working version before applying the solution from accepted answer. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Can you update the above with the working version?
When you use WithReference, it'll handle making the format correct to work with service discovery (which is what the YARP resource expects at runtime, much like any other resource).
Here's where you build a custom resource and use the extensibility of the app model! var builder = DistributedApplication.CreateBuilder(args);
builder.AddIISExpress("legacy", Environment.GetEnvironmentVariable("MyTDLegacyPath"));
builder.Build().Run();
class IISExpressResource(string name, string path, string workingDirectory) :
ExecutableResource(name, path, workingDirectory),
IResourceWithServiceDiscovery
{
}
static class IISExpressResourceExtensions
{
public static IResourceBuilder<IISExpressResource> AddIISExpress(this IDistributedApplicationBuilder builder, string name, string applicationPath)
{
var iisexpressPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "IIS Express", "iisexpress.exe");
var appPath = Path.GetFullPath(applicationPath, builder.AppHostDirectory);
var resource = new IISExpressResource(name, iisexpressPath, ".");
return builder.AddResource(resource)
.WithArgs($"/path:{appPath}", "/systray:false")
.WithArgs(context =>
{
var http = resource.GetEndpoint("http");
// This will resolve the port dynamically using the orchestrator
var portExpression = ReferenceExpression.Create($"/port:{http.Property(EndpointProperty.TargetPort)}");
context.Args.Add(portExpression);
})
.WithHttpEndpoint(name: "http"); // Random http endpoint
}
} Implementing IResourceWithServiceDiscovery means you can use |
Beta Was this translation helpful? Give feedback.
Can you update the above with the working version?
When you use WithReference, it'll handle making the format correct to work with service discovery (which is what the YARP resource expects at runtime, much like any other resource).
Here's where you build a custom resource and use the extensibility of the app model!