Skip to content

Commit

Permalink
aspire: Fix panic when a project has no endpoints (#4065)
Browse files Browse the repository at this point in the history
* aspire: Fix panic when a project has no endpoints

Worker projects do not expose endpoints and hence do not need ingress
configured on their container apps. We had a bug in constructing the
template context in the case where a project did not have and
endpoints.

To address this, we only set `TargetPortExpression` in the case where
we have Ingress configured. `TargetPortExpression` is only used in the
template when the service has ingress, so the empty value will cause
no harm in cases where the service has not configured ingress.

Fixes #4064
  • Loading branch information
ellismg authored Jul 4, 2024
1 parent 384941e commit 9290610
Show file tree
Hide file tree
Showing 17 changed files with 2,313 additions and 929 deletions.
12 changes: 8 additions & 4 deletions cli/azd/pkg/apphost/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,15 @@ func ContainerAppManifestTemplateForProject(
tCtx := generator.containerAppTemplateContexts[projectName]
tmplCtx := yamlTemplateCtx{
genContainerAppManifestTemplateContext: tCtx,
TargetPortExpression: fmt.Sprintf("{{ targetPortOrDefault %d }}", tCtx.Ingress.TargetPort),
}
if tCtx.Ingress.TargetPort != 0 && !tCtx.Ingress.UsingDefaultPort {
// not using default port makes this to be a non-changing value
tmplCtx.TargetPortExpression = fmt.Sprintf("%d", tCtx.Ingress.TargetPort)

if tCtx.Ingress != nil {
if tCtx.Ingress.TargetPort != 0 && !tCtx.Ingress.UsingDefaultPort {
// not using default port makes this to be a non-changing value
tmplCtx.TargetPortExpression = fmt.Sprintf("%d", tCtx.Ingress.TargetPort)
} else {
tmplCtx.TargetPortExpression = fmt.Sprintf("{{ targetPortOrDefault %d }}", tCtx.Ingress.TargetPort)
}
}

err := genTemplates.ExecuteTemplate(&buf, "containerApp.tmpl.yaml", tmplCtx)
Expand Down
2 changes: 1 addition & 1 deletion cli/azd/pkg/apphost/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func TestAspireEscaping(t *testing.T) {

m, err := ManifestFromAppHost(ctx, filepath.Join("testdata", "AspireDocker.AppHost.csproj"), mockCli, "")
require.NoError(t, err)
for _, name := range []string{"api"} {
for _, name := range []string{"api", "worker"} {
t.Run(name, func(t *testing.T) {
tmpl, err := ContainerAppManifestTemplateForProject(m, name, AppHostOptions{})
require.NoError(t, err)
Expand Down
34 changes: 34 additions & 0 deletions cli/azd/pkg/apphost/testdata/TestAspireEscaping-worker.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
api-version: 2024-02-02-preview
location: {{ .Env.AZURE_LOCATION }}
identity:
type: UserAssigned
userAssignedIdentities:
? "{{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}"
: {}
properties:
environmentId: {{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_ID }}
configuration:
activeRevisionsMode: single
runtime:
dotnet:
autoConfigureDataProtection: true
registries:
- server: {{ .Env.AZURE_CONTAINER_REGISTRY_ENDPOINT }}
identity: {{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}
template:
containers:
- image: {{ .Image }}
name: worker
env:
- name: AZURE_CLIENT_ID
value: {{ .Env.MANAGED_IDENTITY_CLIENT_ID }}
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES
value: "true"
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES
value: "true"
scale:
minReplicas: 1
tags:
azd-service-name: worker
aspire-resource-name: worker

8 changes: 8 additions & 0 deletions cli/azd/pkg/apphost/testdata/aspire-escaping.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
"type": "postgres.database.v0",
"parent": "pg"
},
"worker": {
"type": "project.v0",
"path": "../Test1.Worker/Test1.Worker.csproj",
"env": {
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true"
}
},
"api": {
"type": "project.v0",
"path": "..\\MyBlog.Api\\MyBlog.Api.csproj",
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ItemGroup>
<ProjectReference Include="..\AspireAzdTests.ApiService\AspireAzdTests.ApiService.csproj" />
<ProjectReference Include="..\AspireAzdTests.Web\AspireAzdTests.Web.csproj" />
<ProjectReference Include="..\AspireAzdTests.Worker\AspireAzdTests.Worker.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
var cosmos = builder.AddAzureCosmosDB("cosmos");
var cosmosDb = cosmos.AddDatabase("db3");

// worker with no bindings
var workerProj = builder.AddProject<Projects.AspireAzdTests_Worker>("worker");

// the front end app
_ = builder
.AddProject<Projects.AspireAzdTests_Web>("webfrontend")
Expand All @@ -34,6 +37,7 @@
.WithReference(markdownBlobs)
.WithReference(messageQueue)
.WithReference(apiservice)
.WithReference(cosmosDb);
.WithReference(cosmosDb)
.WithReference(workerProj);

builder.Build().Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-AspireAzdTests.Worker-7ae08e90-5023-4396-8dd7-b0b52bf65c9a</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AspireAzdTests.ServiceDefaults\AspireAzdTests.ServiceDefaults.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using AspireAzdTests.Worker;

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"AspireAzdTests.Worker": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace AspireAzdTests.Worker;

public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;

public Worker(ILogger<Worker> logger)
{
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
}
await Task.Delay(1000, stoppingToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
api-version: 2024-02-02-preview
location: {{ .Env.AZURE_LOCATION }}
identity:
type: UserAssigned
userAssignedIdentities:
? "{{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}"
: {}
properties:
environmentId: {{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_ID }}
configuration:
activeRevisionsMode: single
runtime:
dotnet:
autoConfigureDataProtection: true
registries:
- server: {{ .Env.AZURE_CONTAINER_REGISTRY_ENDPOINT }}
identity: {{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}
template:
containers:
- image: {{ .Image }}
name: worker
env:
- name: AZURE_CLIENT_ID
value: {{ .Env.MANAGED_IDENTITY_CLIENT_ID }}
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES
value: "true"
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES
value: "true"
- name: OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY
value: in_memory
scale:
minReplicas: 1
tags:
azd-service-name: worker
aspire-resource-name: worker

Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
"keyVaultName": ""
}
},
"worker": {
"type": "project.v0",
"path": "../AspireAzdTests.Worker/AspireAzdTests.Worker.csproj",
"env": {
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory"
}
},
"webfrontend": {
"type": "project.v0",
"path": "../AspireAzdTests.Web/AspireAzdTests.Web.csproj",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ public async Task ManageEnvironments()

var loadEnv = await esSvc.LoadEnvironmentAsync(context, e2.Name, observer, CancellationToken.None);
loadEnv.Name.ShouldEqual(e2.Name);
loadEnv.Services.Length.ShouldEqual(2);
loadEnv.Services.Length.ShouldEqual(3);
File.Exists(loadEnv.Services[0].Path).ShouldBeTrue();
File.Exists(loadEnv.Services[1].Path).ShouldBeTrue();
File.Exists(loadEnv.Services[2].Path).ShouldBeTrue();

// Delete environments
var deleted1 = await esSvc.DeleteEnvironmentAsync(context, e.Name, EnvironmentDeleteMode.Local, observer, CancellationToken.None);
Expand Down

0 comments on commit 9290610

Please sign in to comment.