Skip to content

Add AWS CDK support#2225

Merged
davidfowl merged 57 commits intomicrosoft:mainfrom
vlesierse:vlesierse/aws-cdk
Sep 13, 2024
Merged

Add AWS CDK support#2225
davidfowl merged 57 commits intomicrosoft:mainfrom
vlesierse:vlesierse/aws-cdk

Conversation

@vlesierse
Copy link
Copy Markdown
Contributor

@vlesierse vlesierse commented Feb 14, 2024

This pull request is intended to gather feedback for supporting AWS CDK with Aspire. It is build upon the work @normj is doing for general AWS with CloudFormation support (#1905 Add AWS CloudFormation Provisioning and SDK Configuration).

AWS CDK helps developers to write Infrastructure as Code using imperative programming languages like (C#, JavaScript/TypeScript, Python, Java, Go). In contrast with using the AWS SDK, CDK synthesized the code to CloudFormation which describes the desired state of the infrastructure and uses CloudFormation to deploy the resources.

Building CDK Stacks

Building CDK stacks with resources in Aspire should feel very familiar.

var builder = DistributedApplication.CreateBuilder(args);

var awssdkConfig = builder.AddAWSSDKConfig().WithProfile("default").WithRegion(RegionEndpoint.EUWest1);

var stack = builder.AddAWSCDKStack("stack").WithReference(awssdkConfig);
var bucket = stack.AddS3Bucket("bucket");

builder.AddProject<Projects.WebApp>("webapp")
    .WithEnvironment("AWS__Resources__BucketName", bucket, b => b.BucketName);

builder.Build().Run();

This library comes with convenient methods for creating common resources like S3 Buckets, DynamoDB Tables, SQS Queues, SNS Topics, Kinesis Stream and Cognito User Pools. All these construct are reference to projects as environment variables or configuration sections. It is also possible to build custom resources in stacks.

var builder = DistributedApplication.CreateBuilder(args);

var awssdkConfig = builder.AddAWSSDKConfig().WithProfile("default").WithRegion(RegionEndpoint.EUWest1);

var stack = builder.AddAWSCDKStack("stack").WithReference(awssdkConfig);
var custom = stack.AddConstruct("custom", scope => new CustomConstruct(scope, "custom"))
    .AddOutput("MyOutput", c => c.OutputId);

builder.AddProject<Projects.WebApp>("webapp")
    .WithReference(custom);

builder.Build().Run();

Using existing CDK Stacks

This PR supports CDK stacks written with C#. A developer can still write their infrastructure using a CDK project and use the CDK CLI to deploy this to their AWS account. One of the challenges developers usually have if to leverage AWS services like SQS & DynamoDB in their local development environment. Tools to simulate these services locally exists, but are usually lacking features. Aspire allows the developer to deploy their CDK stacks and reference them to their application projects. Aspire will provision the resources and hookup the projects with the output values from the stack.

AWS CDK Project

Using CDK with .NET requires you to create a console application. This application contains Stacks which contains AWS resources from S3 Buckets, DynamoDB Tables, Lambda Functions to entire Kubernetes Clusters.

public class WebAppStackProps : StackProps;

public class WebAppStack : Stack
{
    public ITable Table { get; }

    public WebAppStack(Construct scope, string id, WebAppStackProps props)
        : base(scope, id, props)
    {
        Table = new Table(this, "Table", new TableProps
        {
            PartitionKey = new Attribute { Name = "id", Type = AttributeType.STRING },
            BillingMode = BillingMode.PAY_PER_REQUEST
        });
        var imageAsset = new DockerImageAsset(this, "ImageAssets", new DockerImageAssetProps {
            Directory = ".",
            File = "WebApp/Dockerfile"
        });
        var cluster = new Cluster(this, "Cluster");
        var service = new ApplicationLoadBalancedFargateService(this, "Service",
                new ApplicationLoadBalancedFargateServiceProps
                {
                    Cluster = cluster,
                    TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions
                    {
                        Image = ContainerImage.FromDockerImageAsset(imageAsset),
                        ContainerPort = 8080
                    },
                    RuntimePlatform = new RuntimePlatform { CpuArchitecture = CpuArchitecture.ARM64 }
                });
        Table.GrantReadWriteData(service.TaskDefinition.TaskRole);
    }
}

A stack can create CfnOutput output resources to expose attribute values of resources to the outside or expose them through an interface/property. This allows other stacks to reference resources for their configurations.

In the example below you can see the CDK project that allows you to deploy the stacks using the CDK cli (cdk deploy)

using Amazon.CDK;
using WebApp.CDK;

var app = new App();

var dependencies = new WebAppDependenciesStack(app, "WebAppDependenciesStack", new WebAppDependenciesStackProps());
_ = new WebAppApplicationStack(app, "WebAppApplicationStack", new WebAppApplicationStackProps(dependencies.Table));

app.Synth();

Aspire Stack Resource

In order to make Aspire to work with CDK we introduce a StackResource which allows you to create a stack using a StackBuilderDelegate. The reason to create the stack delayed through a delegate is because Aspire is going to take ownership of the stack and provisioning and needs to additional resources for the outputs. Outputs can be defined using a StackOutputAnnotation which will allows you to point to the resource attribute in stack. When the stack get referenced by the ProjectResource/IResourceWithEnviroment it will take the output values and inject them as environment variables, just like the CloudFormationResource does.

var builder = DistributedApplication.CreateBuilder(args);

var awssdkConfig = builder.AddAWSSDKConfig()
    .WithProfile("default")
    .WithRegion(RegionEndpoint.EUWest1);

var stack = builder.AddAWSCDKStack(
    "AspireWebAppStack",
    context => new WebAppStack(context.Application, context.Name, new WebAppStackProps()))
    .AddOutput("TableName", stack => stack.Table.TableName)
    .WithReference(awssdkConfig);

builder.AddProject<Projects.WebApp>("webapp").WithReference(stack);

builder.Build().Run();

Notes

  • Using Aspire, the developer doesn't need to install the AWS CDK CLI in order to provision and use CDK resources in their project. However CDK makes use of JSII which is a proxy to the TypeScript code which is used to create CDK. For this reason the Node runtime needs to be installed.
  • Currently Aspire isn't able to deploy asset resources like Container Images, custom resources or S3 objects. An error will be shown when stacks require asset deployments.
Microsoft Reviewers: Open in CodeFlow

@ghost ghost added the area-integrations Issues pertaining to Aspire Integrations packages label Feb 14, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Feb 14, 2024
@mitchdenny mitchdenny added this to the preview 5 (Apr) milestone Feb 26, 2024
@ReubenBond
Copy link
Copy Markdown
Member

I like where this is heading! Have you explored the idea of synthesizing the stack from pieces of the Aspire app model? I believe that would be the ideal user experience, since it unifies the two worlds (Aspire app model & CDK stack)

@vlesierse
Copy link
Copy Markdown
Contributor Author

@ReubenBond thank you for the feedback! Yes, I started with experimenting of building the stack within Aspire in this branch. My first focus will be to rebase this PR on top of what @normj is merging into the Aspire main branch and add the AddConstruct method to the StackResource builder. It is sort of already supported for the outputs. It basically adds a CfnOutput construct to the stack.

Currently I'm working on the asset deploying (S3, Docker Images) as it is needed to complete the functionality of CDK deployments.

I like the idea to provide some out-of-the-box resources like a Bucket, DynamoDB Table or SQS Queue it we can easily do this with a couple of extensions methods that add the constructs to the stack underneath.

@vlesierse
Copy link
Copy Markdown
Contributor Author

Ok, after some busy weeks, I have picked up this PR again. First step is a rebase onto the work of @normj with the CloudFormation support. I have a made a couple of changes their to improve re-usability of the CloudFormation provisioner.
Next step is to get the asset provisioning working and the ability to build stacks out of single constructs.

@vlesierse
Copy link
Copy Markdown
Contributor Author

Building a CDK Stack has been made easier by using Construct resources. I still need to annotate the resource states correctly, but in general it works like this...

var stack = builder.AddAWSCDKStack("Stack").WithReference(awsConfig);
var table = stack.AddConstruct("Table", scope => new Table(scope, "Table", new TableProps
{
    PartitionKey = new Attribute { Name = "id", Type = AttributeType.STRING },
    BillingMode = BillingMode.PAY_PER_REQUEST,
    RemovalPolicy = RemovalPolicy.DESTROY
})).WithOutput("TableName", c => c.TableName);

builder.AddProject<Projects.WebApp>("webapp")
    .WithReference(table)
    .WithReference(awsConfig);

@vlesierse
Copy link
Copy Markdown
Contributor Author

Next steps could be to compose list of most used resources and make convenient methods for these resources like;

var stack = builder.AddAWSCDKStack("Stack").WithReference(awsConfig);
var table = stack.AddDynamoDBTable("Table");
var queue = stack.AddSQSQueue("Queue");

builder.AddProject<Projects.WebApp>("webapp")
    .WithReference(table)
    .WithReference(queue)
    .WithReference(awsConfig);

@davidfowl
Copy link
Copy Markdown
Contributor

I suggest looking at the azure package layering as it should be very similar to what AWS needs to do.

@davidfowl
Copy link
Copy Markdown
Contributor

Seems redundant to pass the same config twice

cc @normj

@normj
Copy link
Copy Markdown
Contributor

normj commented Mar 28, 2024

Seems redundant to pass the same config twice

cc @normj

Are you suggesting that if a project is referencing a CloudFormation / CDK construct that the project should infer the AWS SDK Config from the CloudFormation / CDK construct and pass that configuration to the projects? There could be cases later on for AWS SDK config to have a different configuration when configuration is extended for things like retry settings and timeouts but I can see allowing that fallback mechanism if a project doesn't have an explicit SDK reference.

@davidfowl
Copy link
Copy Markdown
Contributor

davidfowl commented Mar 28, 2024

but I can see allowing that fallback mechanism if a project doesn't have an explicit SDK reference.

Yep. Exactly this.

The stack has the config in the fallback case.

@vlesierse
Copy link
Copy Markdown
Contributor Author

vlesierse commented Mar 31, 2024

Getting closer to building AWS CDK stacks.

// Create a Distributed Application builder and enable AWS CDK, needed to host the App construct and attach the stack(s)
var builder = DistributedApplication.CreateBuilder(args).WithAWSCDK();

// Setup a configuration for the AWS .NET SDK.
var awsConfig = builder.AddAWSSDKConfig()
    .WithProfile("default")
    .WithRegion(RegionEndpoint.EUWest1);
// Create Stack
var stack = builder.AddStack("Stack").WithReference(awsConfig);
// Add DynamoDB Table to stack
var table = stack
  .AddDynamoDBTable("Table", new TableProps
  {
      PartitionKey = new Attribute { Name = "id", Type = AttributeType.STRING },
      BillingMode = BillingMode.PAY_PER_REQUEST,
      RemovalPolicy = RemovalPolicy.DESTROY
  })
  .AddGlobalSecondaryIndex(new GlobalSecondaryIndexProps {
      IndexName = "OwnerIndex",
      PartitionKey = new Attribute { Name = "owner", Type = AttributeType.STRING },
      SortKey = new Attribute { Name = "ownerSK", Type = AttributeType.STRING },
      ProjectionType = ProjectionType.ALL
  });
// Create project
builder.AddProject<Projects.WebApp>("webapp")
    .WithReference(table); // Reference DynamoDB Table

@djonser
Copy link
Copy Markdown
Contributor

djonser commented Apr 10, 2024

First of all, I'm greatly looking forward to this. I've myself experimenting with Aspire and AWS CDK.

Separate Project

One thing that comes to mind after your most recent commit. Would it not be better to have the CDK parts remains as a separate project that references Aspire.Hosting.AWS? My thinking is that other first-party and third-party hosting packages can build upon Aspire.Hosting.AWS without having a dependency on CDK. While AWS CDK is my own preference there are other abstractions for CloudFormation.

Provisioning

I'm agree with @ReubenBond in that having the AppHost project both be a CDK Application and AppHost is the ideal user experience, at least for those of us who are already comfortable using the CLI. I currently don't see any issues with these two approaches living side-by-side.

My own implementation (fork of your fork) can be summarized as the following: I create a cdk.json pointing to AppHost.csproj and run cdk [command] like I would in any cdk project. When I debug, I check if cdk cli is running inside builder.AddStack(stack) and if the cli is not running I utilize this.AddAWSCloudFormationStack(stack.StackName). This loads all the stack outputs.

var builder = DistributedApplication.CreateBuilder(args)
    // AwsConfig is used to load outputs from the created stacks
    .WithAWSCDKCLI(awsConfig => awsConfig.WithProfile("default").WithRegion(RegionEndpoint.EUWest1));

var stack = new Stack(builder.App, "MyStack");
builder.AddStack(stack).SetDefaultStack(stack);

var bucket = new Bucket(stack, "Bucket");
var topic = new Topic(stack, "Topic");

builder.AddProject<Projects.MyApp>("app")
    .WithReference(builder.AddAWSSDKConfig().WithProfile("default").WithRegion(RegionEndpoint.EUWest1))
    // All ${Token[TOKEN.*]} are converted to a CfnOutput and uses the "default stack" as scope
    .WithEnvironment("BUCKET_NAME", bucket.BucketName)
    // Also possible to explicitly provide a scope for the CfnOutput
    .WithEnvironment(topic, "TOPIC_ARN", topic.TopicArn)
    // References previously created CfnOutput based on same TOKEN to prevent duplicate outputs
    .WithEnvironment(bucket, "BUCKET_NAME_AGAIN", bucket.BucketName);

// synthesis occurs when the CLI is executing and then returns before builder.Build() runs
builder.SynthOrBuildAndRun();

@vlesierse
Copy link
Copy Markdown
Contributor Author

@djonser thank you for your feedback and mentioning some important points.

One thing that comes to mind after your most recent commit. Would it not be better to have the CDK parts remains as a separate project that references Aspire.Hosting.AWS? My thinking is that other first-party and third-party hosting packages can build upon Aspire.Hosting.AWS without having a dependency on CDK. While AWS CDK is my own preference there are other abstractions for CloudFormation.

This is for me still up for debate. At on one hand we would like to have an easy/out-of-the-box experience when you want to use AWS with .NET Aspire which make it easy to discover the available functionalities and API's. The CloudFormation Stack support is foundational for CDK and distributing them over multiple packages might make it harder to pick what is needed for your application. Especially if we would like to introduce convenient resource extensions like builder.AddBucket. On the other hand, CDK comes with different references (JSII, Constructs, AWS.CDK.Lib) which you don't need if you only want to deploy or reference a CloudFormation stack.

I'm agree with @ReubenBond in that having the AppHost project both be a CDK Application and AppHost is the ideal user experience, at least for those of us who are already comfortable using the CLI. I currently don't see any issues with these two approaches living side-by-side.

The current implementation support both the Aspire local development provisioning as provisioning the stack using cdk deploy with the cdk.json as you decribe. In publish mode it will always Synthesize the stack and write the reference to the assets in the manifest, but it does not provision.
cdk.json

{
  "app": "dotnet run -- --publisher manifest --output-path ./aspire-manifest.json",
  ...
}

Unfortunately with this deployment option you only deploy a part of your stack. The Project resources aren't taken into account yet and needs to be deployed differently when you would to publish your project. We are considering to leverage the AWS .NET Deployment Tools for this as Azure uses azd and for Kubernetes aspirate

I love the WithEnvironment syntax as additional option to WithReference for mapping construct information explicitly. 👍

builder.AddProject<Projects.MyApp>("app")
    // All ${Token[TOKEN.*]} are converted to a CfnOutput and uses the "default stack" as scope
    .WithEnvironment(bucket, "BUCKET_NAME", bucket.BucketName)

@djonser
Copy link
Copy Markdown
Contributor

djonser commented Apr 11, 2024

The CloudFormation Stack support is foundational for CDK and distributing them over multiple packages might make it harder to pick what is needed for your application.

My thinking was if other CloudFormation abstractions that is not CDK-based wanted to provide an Aspire package they could use the Aspire.Hosting.AWS package as a base. Also, Aspire.Hosting.AWS contains IAWSSDKConfig which establishes a way to handle this type of configuration in Aspire. If another package that does not directly deal with provisioning wants to use IAWSSDKConfig that package now also has a reference to CDK.Lib, JSII and Constructs.

Maybe I'm in the minority here having created a bunch of extensions and auto-completion seemingly always wants to pick the wrong IResource (hello API Gateway 😃 ).

I love the WithEnvironment syntax as additional option to WithReference for mapping construct information explicitly.

It really is the convenience extensions and inference that can be created when AWS CDK and Aspire is used together that is exciting. So much that could be derived from the shared context and reduce the amount of explicitly required configuration.

I've been experimenting with a little bit of everything and most recently extensions for Cognito. One thing I'm starting to believe is that if I'm to create constructs via inference (and re-using Aspire resource name as either a construct name or a construct name-prefix) is that it would be good to have a way to manage/track constructs in a way that does not require creation of Aspire Resources.

Regardless of Aspire parent resource the resource name must be unique. CloudFormation have less constraints for the resource name than Aspire have for resource names and having to specify both an Aspire resource name and Construct Id is inconvenient.

var userPoolId = stack.Node.TryGetContext("@acme/userPoolId");
var userPool = builder.ImportUserPoolById(stack, "UserPool", userPoolId, new UserPoolDefaults(/**/));

var api = builder.AddProject<Projects.Api>("api")
    .AsResourceServer("https://localhost", ["read", "write"])
    // Or with explicit scope and prefix for created constructs
    .AsResourceServer(scope, "idPrefix", "https://localhost", ["read", "write"], name: "api");

builder.AddProject<Projects.Worker>("worker")
    .AuthorizeAccess(api, ["read"]);
// Component wires up the Api Project.
builder.AddCognitoUserPoolAuthentication();
// ServiceDefaults used by Worker implements HttpClient parts.
builder.AddServiceDefaults();

@danmoseley danmoseley removed this from the preview 5 (Apr) milestone Apr 15, 2024
@eerhardt eerhardt added area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication and removed area-integrations Issues pertaining to Aspire Integrations packages labels Apr 18, 2024
@vlesierse
Copy link
Copy Markdown
Contributor Author

@normj
Ok, the base of this PR is ready and I'll focus on the (code) documentation, unit tests and adding additional extensions for common AWS resources. (S3, SQS, SNS, Kinesis, etc). Some others to consider are OpenSearch, Elasticache, etc.
I think we also need to have SSM Parameters, Secrets Manager and AppConfig to support the application configuration patterns.

NuGet.config Outdated
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❗ We can't pull packages from nuget.org.
This will have to be removed before this PR can get merged.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

@radical Aspire.Hosting.AWS.Tests on both Windows and Linux.

It will be tough to duplicate exactly how these tests are run on helix. It is usually helpful to look at the logs to get an idea of why the tests are failing or timing out. Do you have a link to the build where they failed? We can wait for the next run too.

@vlesierse
Copy link
Copy Markdown
Contributor Author

vlesierse commented Sep 13, 2024

This is the exact location... Aborting test run: test run timeout of 600000 milliseconds exceeded. Looks like it went over 10 minutes and got aborted.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

is it possible to add the new version of Amazon.CDK.Lib (2.158.0) to the repository? It also have a couple of dependencies which needs to be added as well.

@vlesierse is quick! I mirrored 2.158.0, but the PR is referencing 2.157.0.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

@davidfowl
Copy link
Copy Markdown
Contributor

These are unit tests, should be super simple and not require any logging. They are asserting object structure.

@vlesierse
Copy link
Copy Markdown
Contributor Author

These are unit tests, should be super simple and not require any logging. They are asserting object structure.

Agree and that's how they run, but somehow they behave differently on the test infrastructure. I'll look how the timeout bump works out and add the additional logging if required to find the root cause.

@davidfowl
Copy link
Copy Markdown
Contributor

Which ones are failing?

@vlesierse
Copy link
Copy Markdown
Contributor Author

This is from the logs...

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Blame: Attaching crash dump utility to process dotnet (4697).
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.3+1b45f5407b (64-bit .NET 8.0.7)
[xUnit.net 00:00:08.41]   Discovering: Aspire.Hosting.AWS.Tests
[xUnit.net 00:00:08.44]   Discovered:  Aspire.Hosting.AWS.Tests
[xUnit.net 00:00:08.44]   Starting:    Aspire.Hosting.AWS.Tests
info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 9.0.0-ci
info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 9.0.0-ci
  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlCreated_RegionEndpoint [163 ms]
  Passed Aspire.Hosting.AWS.Tests.StackOutputReferenceTests.ValueExpressionTest [200 ms]
  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlCreated_ServiceUrl [137 ms]
  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlNotCreated_LocalStackServiceUrl [63 ms]
  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlNotCreated_UnknownRegion [< 1 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSSchemaTests.ValidateAddAWSCloudFormationStackManifest [493 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSSchemaTests.ValidateAddAWSCloudFormationTemplateManifest [12 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCloudFormationResourceTests.AddAWSCloudFormationTemplateResourceTest [15 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCloudFormationResourceTests.ManifestAWSCloudFormationTemplateResourceTest [21 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCloudFormationResourceTests.ManifestAWSCloudFormationStackResourceTest [18 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCloudFormationResourceTests.AddAWSCloudFormationStackResourceTest [11 ms]
  Passed Aspire.Hosting.AWS.Tests.StackOutputReferenceTests.GetValueAsyncTest [2 s]
  Passed Aspire.Hosting.AWS.Tests.StackOutputReferenceTests.InvalidOutputKey [5 ms]
Aborting test run: test run timeout of 600000 milliseconds exceeded.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

If it fails again then we can look at the .trx for the tests, which might show what it was executing.

Running these locally, they take ~6secs on my mac. Timing out after 10mins sounds really excessive.

Also, another difference in the CI run now is that the tests won't be running in parallel.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

These are the tests that didn't show up in the Passed list.

Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceTest
Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithAdditionalStackAndConfigTest
Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithAdditionalStackTest
Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithConstructTest
Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.ManifestAWSCDKResourceTest

@vlesierse
Copy link
Copy Markdown
Contributor Author

Locally the tests are passing fast enough...

  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlCreated_RegionEndpoint [58 ms]
  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlCreated_ServiceUrl [186 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCloudFormationResourceTests.AddAWSCloudFormationTemplateResourceTest [252 ms]
  Passed Aspire.Hosting.AWS.Tests.StackOutputReferenceTests.ValueExpressionTest [252 ms]
  Passed Aspire.Hosting.AWS.Tests.CloudFormationAWSConsoleUrlTests.ConsoleUrlNotCreated_LocalStackServiceUrl [49 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithAdditionalStackAndConfigTest [3 s]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithAdditionalStackTest [76 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.ManifestAWSCDKResourceTest [101 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithConstructTest [63 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceTest [62 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithAdditionalStackAndConfigTest [3 s]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithAdditionalStackTest [76 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.ManifestAWSCDKResourceTest [101 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceWithConstructTest [63 ms]
  Passed Aspire.Hosting.AWS.Tests.AWSCDKResourceTests.AddAWSCDKResourceTest [62 ms]

@vlesierse
Copy link
Copy Markdown
Contributor Author

vlesierse commented Sep 13, 2024

If it fails again then we can look at the .trx for the tests, which might show what it was executing.

Running these locally, they take ~6secs on my mac. Timing out after 10mins sounds really excessive.

Also, another difference in the CI run now is that the tests won't be running in parallel.

The error message in the trx file shows System.ComponentModel.Win32Exception : An error occurred trying to start process 'node' with working directory 'C:\h\w\A6F0095F\w\95AB0854\e'. The system cannot find the file specified.

Looks like node is missing in this test container?

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

If it fails again then we can look at the .trx for the tests, which might show what it was executing.
Running these locally, they take ~6secs on my mac. Timing out after 10mins sounds really excessive.
Also, another difference in the CI run now is that the tests won't be running in parallel.

The error message in the trx file shows System.ComponentModel.Win32Exception : An error occurred trying to start process 'node' with working directory 'C:\h\w\A6F0095F\w\95AB0854\e'. The system cannot find the file specified.

Looks like node is missing in this test container?

node isn't installed on windows right now. Add [RequiresTools(["node"])] to the tests that need node. It should work on linux.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

Oh fun:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!                                                                            !!
!!  Node 12 has reached end-of-life on 2022-04-30 and is not supported.       !!
!!  Please upgrade to a supported node version as soon as possible.           !!
!!                                                                            !!
!!  This software is currently running on node v12.22.9.                      !!
!!  As of the current release of this software, supported node releases are:  !!
!!  - ^22.0.0 (Planned end-of-life: 2027-04-30)                               !!
!!  - ^20.0.0 (Planned end-of-life: 2026-04-30)                               !!
!!  - ^18.0.0 (Planned end-of-life: 2025-04-30)                               !!
!!                                                                            !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/datadisks/disk1/work/B32309A7/t/sjpproaf.n5y/lib/program.js:11001
            return !!ref?.fqn;
                         ^
SyntaxError: Unexpected token '.'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

@vlesierse
Copy link
Copy Markdown
Contributor Author

Oh fun:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!                                                                            !!
!!  Node 12 has reached end-of-life on 2022-04-30 and is not supported.       !!
!!  Please upgrade to a supported node version as soon as possible.           !!
!!                                                                            !!
!!  This software is currently running on node v12.22.9.                      !!
!!  As of the current release of this software, supported node releases are:  !!
!!  - ^22.0.0 (Planned end-of-life: 2027-04-30)                               !!
!!  - ^20.0.0 (Planned end-of-life: 2026-04-30)                               !!
!!  - ^18.0.0 (Planned end-of-life: 2025-04-30)                               !!
!!                                                                            !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/datadisks/disk1/work/B32309A7/t/sjpproaf.n5y/lib/program.js:11001
            return !!ref?.fqn;
                         ^
SyntaxError: Unexpected token '.'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

Node 12... that is a while ago 😄

@davidfowl
Copy link
Copy Markdown
Contributor

Why do unit tests require node?

@vlesierse
Copy link
Copy Markdown
Contributor Author

vlesierse commented Sep 13, 2024

Why do unit tests require node?

This is how AWS CDK works. To support multiple languages it uses JSII which executes the Typescript code on the C#, Python, Java, etc Interfaces.

@vlesierse
Copy link
Copy Markdown
Contributor Author

vlesierse commented Sep 13, 2024

@radical build is green, but does it mean the tests have run? Doesn't look like it. Think we can only get a green build when the issue #4508 get resolved?

@davidfowl
Copy link
Copy Markdown
Contributor

The tests is executing the cdk logic? Shouldn’t that only happen when the application runs or when the manifest is written? It should be deferred no?

@vlesierse
Copy link
Copy Markdown
Contributor Author

The tests is executing the cdk logic? Shouldn’t that only happen when the application runs or when the manifest is written? It should be deferred no?

It does as it needs to resolve IDs. Once it news up the CDK Stack or App it executes JavaScript code underneath. I have tried to delay the creation of these constructs in the lifecycle, but at some point I need to go trough it, even for the tests.

@davidfowl
Copy link
Copy Markdown
Contributor

I'm fine merging this but the failure mode should be that the dashboard starts up and it shows failed resources with logs. Ideally it wouldn't explode on running the apphost.

@radical
Copy link
Copy Markdown
Member

radical commented Sep 13, 2024

@radical build is green, but does it mean the tests have run? Doesn't look like it. Think we can only get a green build when the issue #4508 get resolved?

They get skipped as expected because of [ActiveIssue("https://github.com/dotnet/aspire/issues/4508", typeof(PlatformDetection), nameof(PlatformDetection.IsRunningOnCI))].

@davidfowl davidfowl merged commit dad2369 into microsoft:main Sep 13, 2024
@vlesierse vlesierse deleted the vlesierse/aws-cdk branch September 14, 2024 06:03
@github-actions github-actions bot locked and limited conversation to collaborators Oct 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.