-
Notifications
You must be signed in to change notification settings - Fork 575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
k8s first pass #8260
k8s first pass #8260
Conversation
no ingress support directly yet
/// <summary> | ||
/// Gets or sets the name of the Helm chart to be generated. | ||
/// </summary> | ||
public string HelmChartName { get; set; } = "aspire"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be the name of the application instead of aspire?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah! I just defaulted it to aspire, I thought the cli would probably pass it through
Gonna have to rework the unit tests - they work in xunit in my ide (Rider), but fail through dotnet test ran from cli. Strange... |
This is looking really promising @prom3theu5 ! |
@davidfowl you ok with the dual context? (One for publisher, one for the state of a processed resource) There were so many cross cutting concerns in the single context felt better to split them into two and isolate responsibilities |
Yep! it looks much cleaner. |
Still this strange case with tests failing from dotnet run, but not in the ide.
tests/Aspire.Hosting.Kubernetes.Tests/KubernetesPublisherTests.cs
Outdated
Show resolved
Hide resolved
"http" => 8080, | ||
"https" => 8443, | ||
_ => 9000, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What port is this supposed to be? The internal port? I think you can only choose a default for project resources. Otherwise, this has to throw right? The container needs to be configured to listen on this port.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The target port is returned, if something like sqlServer for example was configured, it should have its target port set as 1433 shouldn't it?
This was just the fall back for something that doesn't have a target port set, which probably means endpoint annotations on the resource are wrong
We can choose to only apply this for project resources, or else "explode" with an exception and end publishing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something like
foreach (var endpoint in endpoints)
{
var internalPort = endpoint.TargetPort;
if (resource is ProjectResource _)
{
internalPort ??= endpoint.UriScheme switch
{
"http" => 8080,
"https" => 8443,
_ => throw new NotSupportedException($"Unsupported scheme: {endpoint.UriScheme}"),
};
}
if (internalPort is null)
{
throw new InvalidOperationException("TargetPort for endpoint must be set");
}
EndpointMappings[endpoint.Name] = new(endpoint.UriScheme, resource.Name, internalPort.Value, internalPort.Value, endpoint.Name);
}
```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, either this or it becomes a parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's also "TargetPortEnvironmentVariable" to take into account, It's internal atm - but we'd probably want to make it public here so we can see if a value has been set too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That shouldn't be required. When it is set the correct data is expressed in the model as an environment variable:
aspire/src/Aspire.Hosting/ResourceBuilderExtensions.cs
Lines 566 to 569 in e5014c7
builder.WithAnnotation(new EnvironmentCallbackAnnotation(context => | |
{ | |
context.EnvironmentVariables[env] = endpointReference.Property(EndpointProperty.TargetPort); | |
})); |
All we need to do is model endpoints appropriately and it should all hang together.
The answer here might be to avoid doing anything clever and using a parameter if the value is not set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just done something along those lines in this: ce22f8a
However - if you see the message in the commit, I'm having a little issue with separation of env vars.
As you linked above, if we set WithEndpoint(env: "Port"), this forces an EV callback to populate an EnvVar called Port.
But i don't see a way without having access to
to know that this env var value that has been specified in the AppHost is meant to be referenced by the endpoint. When its populated back into the ev - this "link" is lost if you are just interrogating the annotations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might just be tired and missing something obvious lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, you shouldn't need to do anything special to make it work. If you do:
builder.AddNpmApp("fe", "../app").WithHttpEndpoint(env: "PORT");
The "PORT" environment variable slot will have a reference expression to the target endpoint value.
I realize now that in the docker compose case we use the port allocator:
var internalPort = endpoint.TargetPort ?? composePublishingContext.PortAllocator.AllocatePort(); |
We could do the same here, or we could decide to both use the port allocator and to parameterize to set a default value.
aspire/src/Aspire.Hosting/Publishing/ManifestPublishingContext.cs
Lines 415 to 429 in e5014c7
int? targetPort = (resource, endpoint.UriScheme, endpoint.TargetPort, endpoint.Port) switch | |
{ | |
// The port was specified so use it | |
(_, _, int target, _) => target, | |
// Container resources get their default listening port from the exposed port. | |
(ContainerResource, _, null, int port) => port, | |
// Check whether the project view this endpoint as Default (for its scheme). | |
// If so, we don't specify the target port, as it will get one from the deployment tool. | |
(ProjectResource project, string uriScheme, null, _) when IsHttpScheme(uriScheme) && !httpSchemesEncountered.Contains(uriScheme) => null, | |
// Allocate a dynamic port | |
_ => PortAllocator.AllocatePort() | |
}; |
We might need to revisit this logic in multiple places but lets treat this like a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realise the EnvVar had a reference expression, missed that yesterday ^^
Definitely will be a follow up on this some time this week
I opted to not use port allocator here purely because ClusterIP this wouldn't be an issue - its only if we had a specific NodePort binding to the same port we'd run into an issue, but two pods in two separate deployments can use the same port no problem
And fix niggles to do with formatting (editorconfig sets them to no space ^^)
…o add project defaults endpoint - Still not sure how best to handle WithEndpoint where the assigned TargetPort comes from an Env var - how to ensure we dont get duplicate env vars when there is no publically accessible reference to the fact that the env var is actually an endpoint annotation value? Getting at the actual value seems to require access to TargetPortEnvironmentVariable which is populated by ```csharp if (env is not null && builder.Resource is IResourceWithEndpoints resourceWithEndpoints and IResourceWithEnvironment) { annotation.TargetPortEnvironmentVariable = env; var endpointReference = new EndpointReference(resourceWithEndpoints, annotation); builder.WithAnnotation(new EnvironmentCallbackAnnotation(context => { context.EnvironmentVariables[env] = endpointReference.Property(EndpointProperty.TargetPort); })); } return builder.WithAnnotation(annotation); ``` But thats just expanded back into a regular env var? There's no concept of that being tired to the endpoint annotation at that point??
/// an integer or a string. It supports implicit and explicit conversions, | ||
/// equality comparisons, and YAML serialization/deserialization handling. | ||
/// </remarks> | ||
public sealed record Int32OrStringV1(int? Number = null, string? Text = null) : IEquatable<int>, IEquatable<string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DU! 😄 As a follow up I would just use object if this was internal storage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of follow ups but great start!
no ingress support directly yet
Checklist
<remarks />
and<code />
elements on your triple slash comments?breaking-change
template):doc-idea
template):