Skip to content
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

Add integration test and example for using CDK Nested Stacks with Pulumi #298

Merged
merged 3 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/eks/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: eks
runtime: nodejs
description: eks example for CDK
132 changes: 132 additions & 0 deletions examples/eks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import * as pulumicdk from '@pulumi/cdk';
import * as pulumi from '@pulumi/pulumi';
import * as awscc from '@pulumi/aws-native';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as eks from 'aws-cdk-lib/aws-eks';
import { KubectlV31Layer } from '@aws-cdk/lambda-layer-kubectl-v31';
import { ResourceMapping } from '@pulumi/cdk/lib/interop';
import { Duration } from 'aws-cdk-lib';

class EksStack extends pulumicdk.Stack {
public readonly clusterName: pulumi.Output<string>;
public readonly albAddress: pulumi.Output<string>;
constructor(app: pulumicdk.App, id: string) {
super(app, id);

const vpc = new ec2.Vpc(this, 'CdkEksVpc', {});

// Create the EKS cluster in the VPC and install the ALB controller
const cluster = new eks.Cluster(this, 'CdkEksCluster', {
version: eks.KubernetesVersion.V1_31,
authenticationMode: eks.AuthenticationMode.API,
endpointAccess: eks.EndpointAccess.PUBLIC,
kubectlLayer: new KubectlV31Layer(this, 'kubectl'),
vpc,
vpcSubnets: [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }],
albController: {
version: eks.AlbControllerVersion.V2_8_2,
},
});

this.clusterName = this.asOutput(cluster.clusterName);

const podInfo = cluster.addHelmChart('pod-info', {
chart: 'podinfo',
repository: 'https://stefanprodan.github.io/podinfo',
namespace: 'default',
version: '6.7.1',
values: {
fullnameOverride: 'podinfo',
replicaCount: 2,
resources: {
requests: {
cpu: '100m',
memory: '500Mi',
},
limits: {
cpu: '500m',
memory: '500Mi',
},
},
ingress: {
enabled: true,
className: 'alb',
annotations: {
'alb.ingress.kubernetes.io/scheme': 'internet-facing',
'alb.ingress.kubernetes.io/target-type': 'ip',
},
hosts: [
{
host: `*.${this.region}.elb.amazonaws.com`,
paths: [
{
path: '/',
pathType: 'Prefix',
},
],
},
],
},
},
});

// add the alb controller dependency to the pod info helm chart in order for the cleanup to work
// otherwise the alb controller will be deleted before the pod info helm chart is deleted and leave
// dangling Load Balancers
if (cluster.albController) {
podInfo.node.addDependency(cluster.albController);
}

const albAddress = new eks.KubernetesObjectValue(this, 'elbAddress', {
cluster,
objectType: 'Ingress',
objectName: 'podinfo',
jsonPath: '.status.loadBalancer.ingress[0].hostname',
timeout: Duration.minutes(15),
});

// fetch the alb address after the helm chart is deployed
albAddress.node.addDependency(podInfo);
this.albAddress = this.asOutput(albAddress.value);
}
}

class MyApp extends pulumicdk.App {
constructor() {
super(
'app',
(scope: pulumicdk.App): pulumicdk.AppOutputs => {
const stack = new EksStack(scope, 'eks');
return {
albAddress: stack.albAddress,
clusterName: stack.clusterName,
};
},
{
appOptions: {
// TODO[pulumi/pulumi-cdk#293]: 'AWS::IAM::Policy' is currently wrongly mapped to the classic aws.iam.Policy resource.
// The AWS::IAM::Policy resource creates an inline policy on the role whereas the Policy resources creates an actual
// policy and attaches it to the role. The standalone policy resource is plagued by eventual consistency issues.
remapCloudControlResource: (logicalId, typeName, props, options): ResourceMapping | undefined => {
if (typeName === 'AWS::IAM::Policy') {
return new awscc.iam.RolePolicy(
logicalId,
{
policyName: props.PolicyName,
policyDocument: props.PolicyDocument,
roleName: props.Roles[0],
},
options,
);
}
return undefined;
},
},
},
);
}
}

const app = new MyApp();
export const albAddress = app.outputs['albAddress'];
export const clusterName = app.outputs['clusterName'];
18 changes: 18 additions & 0 deletions examples/eks/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "pulumi-aws-cdk",
"devDependencies": {
"@types/node": "^10.0.0"
},
"dependencies": {
"@pulumi/aws": "6.65.0",
"@pulumi/aws-native": "1.15.0",
"@pulumi/cdk": "1.3.0",
"@pulumi/docker-build": "0.0.7",
"@pulumi/pulumi": "3.143.0",
"@types/express": "^5.0.0",
"aws-cdk-lib": "2.173.1",
"constructs": "10.3.0",
"esbuild": "^0.24.0",
"@aws-cdk/lambda-layer-kubectl-v31": "^2.0.0"
}
}
18 changes: 18 additions & 0 deletions examples/eks/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
Loading
Loading