diff --git a/amplify/backend.ts b/amplify/backend.ts deleted file mode 100644 index 86e3136a6..000000000 --- a/amplify/backend.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineBackend } from '@aws-amplify/backend' -import { goFunction } from './functions/go/resource.ts' -import { pythonFunction } from './functions/python/resource.ts' -import { rustFunction } from './functions/rust/resource.ts' - -defineBackend({ - goFunction, - pythonFunction, - rustFunction -}) - - - diff --git a/amplify/functions/go/resource.ts b/amplify/functions/go/resource.ts deleted file mode 100644 index 6cab69fd9..000000000 --- a/amplify/functions/go/resource.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineFunction } from '@aws-amplify/backend' - -export const goFunction = defineFunction({ - name: 'go-functions', - entry: '../../../functions/go-functions/main.go', // ← Points to your Go file - runtime: 'provided.al2023' // ← Custom runtime for Go -}) - - diff --git a/amplify/functions/python/resource.ts b/amplify/functions/python/resource.ts deleted file mode 100644 index e57a6065e..000000000 --- a/amplify/functions/python/resource.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineFunction } from '@aws-amplify/backend' - -export const pythonFunction = defineFunction({ - name: 'python-function', - entry: '../../../functions/python-function/handler.py', // ← Points to external folder - runtime: 'python3.12' -}) - diff --git a/amplify/functions/rust/resource.ts b/amplify/functions/rust/resource.ts deleted file mode 100644 index 785ce2421..000000000 --- a/amplify/functions/rust/resource.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineFunction } from '@aws-amplify/backend' - -export const rustFunction = defineFunction({ - name: 'rust-function', - entry: '../../../functions/rust-function/src/main.rs', // ← Points to external folder - runtime: 'provided.al2' -}) - diff --git a/infrastructure/api-gateway-stack.ts b/infrastructure/api-gateway-stack.ts new file mode 100644 index 000000000..4026b03ec --- /dev/null +++ b/infrastructure/api-gateway-stack.ts @@ -0,0 +1,190 @@ +// infrastructure/api-gateway-stack.ts +import { Stack, StackProps, CfnOutput } from 'aws-cdk-lib' +import { Construct } from 'constructs' +import * as apigateway from 'aws-cdk-lib/aws-apigateway' +import * as lambda from 'aws-cdk-lib/aws-lambda' +import * as logs from 'aws-cdk-lib/aws-logs' +import * as iam from 'aws-cdk-lib/aws-iam' + +export interface ApiGatewayStackProps extends StackProps { + // Reference to your Lambda functions from another stack + goFunction: lambda.Function + pythonFunction: lambda.Function + rustFunction: lambda.Function +} + +export class ApiGatewayStack extends Stack { + public readonly api: apigateway.RestApi + public readonly apiUrl: string + + constructor(scope: Construct, id: string, props: ApiGatewayStackProps) { + super(scope, id, props) + + // Create CloudWatch Log Group for API Gateway + const logGroup = new logs.LogGroup(this, 'ApiGatewayLogGroup', { + logGroupName: `/aws/apigateway/${id}`, + retention: logs.RetentionDays.ONE_WEEK, + }) + + // Create API Gateway + this.api = new apigateway.RestApi(this, 'MyApi', { + restApiName: 'My Multi-Language API', + description: 'API Gateway for Go, Python, and Rust Lambda functions', + + // Enable CORS for frontend integration + defaultCorsPreflightOptions: { + allowOrigins: [ + 'http://localhost:3000', // Local development + 'https://your-amplify-domain.amplifyapp.com', // Your Amplify domain + ], + allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + allowHeaders: [ + 'Content-Type', + 'X-Amz-Date', + 'Authorization', + 'X-Api-Key', + 'X-Amz-Security-Token', + ], + }, + + // Deploy automatically + deploy: true, + deployOptions: { + stageName: 'prod', + loggingLevel: apigateway.MethodLoggingLevel.INFO, + dataTraceEnabled: true, + metricsEnabled: true, + accessLogDestination: new apigateway.LogGroupLogDestination(logGroup), + accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields(), + }, + + // Enable endpoint configuration + endpointConfiguration: { + types: [apigateway.EndpointType.REGIONAL], + }, + }) + + // Create API resources and methods + this.createGoEndpoints(props.goFunction) + this.createPythonEndpoints(props.pythonFunction) + this.createRustEndpoints(props.rustFunction) + + // Add a health check endpoint + this.createHealthEndpoint() + + // Store API URL for output + this.apiUrl = this.api.url + + // Output the API URL + new CfnOutput(this, 'ApiUrl', { + value: this.apiUrl, + description: 'API Gateway URL', + exportName: `${this.stackName}-ApiUrl`, + }) + + // Output individual endpoint URLs + new CfnOutput(this, 'GoEndpoint', { + value: `${this.apiUrl}go`, + description: 'Go Lambda endpoint', + }) + + new CfnOutput(this, 'PythonEndpoint', { + value: `${this.apiUrl}python`, + description: 'Python Lambda endpoint', + }) + + new CfnOutput(this, 'RustEndpoint', { + value: `${this.apiUrl}rust`, + description: 'Rust Lambda endpoint', + }) + } + + private createGoEndpoints(goFunction: lambda.Function) { + // Create /go resource + const goResource = this.api.root.addResource('go') + + // Create Lambda integration + const goIntegration = new apigateway.LambdaIntegration(goFunction, { + requestTemplates: { 'application/json': '{ "statusCode": "200" }' }, + proxy: true, // Enable Lambda proxy integration + }) + + // Add methods + goResource.addMethod('GET', goIntegration) + goResource.addMethod('POST', goIntegration) + + // Add sub-resources if needed + const goHealthResource = goResource.addResource('health') + goHealthResource.addMethod('GET', goIntegration) + } + + private createPythonEndpoints(pythonFunction: lambda.Function) { + // Create /python resource + const pythonResource = this.api.root.addResource('python') + + // Create Lambda integration + const pythonIntegration = new apigateway.LambdaIntegration(pythonFunction, { + proxy: true, + }) + + // Add methods + pythonResource.addMethod('GET', pythonIntegration) + pythonResource.addMethod('POST', pythonIntegration) + pythonResource.addMethod('PUT', pythonIntegration) + + // Add sub-resources + const pythonDataResource = pythonResource.addResource('data') + pythonDataResource.addMethod('GET', pythonIntegration) + pythonDataResource.addMethod('POST', pythonIntegration) + } + + private createRustEndpoints(rustFunction: lambda.Function) { + // Create /rust resource + const rustResource = this.api.root.addResource('rust') + + // Create Lambda integration + const rustIntegration = new apigateway.LambdaIntegration(rustFunction, { + proxy: true, + }) + + // Add methods + rustResource.addMethod('GET', rustIntegration) + rustResource.addMethod('POST', rustIntegration) + rustResource.addMethod('DELETE', rustIntegration) + + // Add sub-resources + const rustProcessResource = rustResource.addResource('process') + rustProcessResource.addMethod('POST', rustIntegration) + } + + private createHealthEndpoint() { + // Create a simple health check endpoint + const healthResource = this.api.root.addResource('health') + + // Mock integration for health check (no Lambda needed) + const healthIntegration = new apigateway.MockIntegration({ + integrationResponses: [{ + statusCode: '200', + responseTemplates: { + 'application/json': JSON.stringify({ + status: 'healthy', + timestamp: '$context.requestTime', + requestId: '$context.requestId' + }) + }, + }], + requestTemplates: { + 'application/json': '{ "statusCode": 200 }' + }, + }) + + healthResource.addMethod('GET', healthIntegration, { + methodResponses: [{ + statusCode: '200', + responseModels: { + 'application/json': apigateway.Model.EMPTY_MODEL, + }, + }], + }) + } +} diff --git a/infrastructure/app.ts b/infrastructure/app.ts new file mode 100644 index 000000000..28ae6302a --- /dev/null +++ b/infrastructure/app.ts @@ -0,0 +1,28 @@ +// infrastructure/app.ts +import * as cdk from 'aws-cdk-lib' +import { LambdaStack } from './lambda-stack' +import { ApiGatewayStack } from './api-gateway-stack' + +const app = new cdk.App() + +// Create Lambda functions first +const lambdaStack = new LambdaStack(app, 'LambdaStack', { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + }, +}) + +// Create API Gateway and connect to Lambda functions +const apiStack = new ApiGatewayStack(app, 'ApiGatewayStack', { + goFunction: lambdaStack.goFunction, + pythonFunction: lambdaStack.pythonFunction, + rustFunction: lambdaStack.rustFunction, + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + }, +}) + +// Ensure Lambda stack is deployed before API Gateway +apiStack.addDependency(lambdaStack) diff --git a/infrastructure/lambda-stack.ts b/infrastructure/lambda-stack.ts new file mode 100644 index 000000000..6152e6c09 --- /dev/null +++ b/infrastructure/lambda-stack.ts @@ -0,0 +1,42 @@ +// infrastructure/lambda-stack.ts +import { Stack, StackProps, Duration } from 'aws-cdk-lib' +import { Construct } from 'constructs' +import * as lambda from 'aws-cdk-lib/aws-lambda' + +export class LambdaStack extends Stack { + public readonly goFunction: lambda.Function + public readonly pythonFunction: lambda.Function + public readonly rustFunction: lambda.Function + + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props) + + // Go function + this.goFunction = new lambda.Function(this, 'GoFunction', { + runtime: lambda.Runtime.PROVIDED_AL2023, + handler: 'bootstrap', + code: lambda.Code.fromAsset('../functions/go-functions'), + timeout: Duration.minutes(15), + memorySize: 1024, + }) + + // Python function + this.pythonFunction = new lambda.Function(this, 'PythonFunction', { + runtime: lambda.Runtime.PYTHON_3_12, + handler: 'handler.handler', + code: lambda.Code.fromAsset('../functions/python-function'), + timeout: Duration.minutes(5), + memorySize: 512, + }) + + // Rust function + this.rustFunction = new lambda.Function(this, 'RustFunction', { + runtime: lambda.Runtime.PROVIDED_AL2023, + handler: 'bootstrap', + code: lambda.Code.fromAsset('../functions/rust-function'), + timeout: Duration.minutes(10), + memorySize: 2048, + }) + } +} + diff --git a/src/Next.js b/src/Next.js new file mode 100644 index 000000000..2b7dd901c --- /dev/null +++ b/src/Next.js @@ -0,0 +1,17 @@ +// In your frontend +const API_BASE_URL = 'https://your-api-id.execute-api.region.amazonaws.com/prod' + +// Call Go function +const goResponse = await fetch(`${API_BASE_URL}/go/health`) + +// Call Python function +const pythonResponse = await fetch(`${API_BASE_URL}/python/data`, { + method: 'POST', + body: JSON.stringify({ data: 'example' }) +}) + +// Call Rust function +const rustResponse = await fetch(`${API_BASE_URL}/rust/process`, { + method: 'POST', + body: JSON.stringify({ input: 'process this' }) +}) diff --git a/tests/integration/integration_tests/test_placeholder.py b/tests/integration/integration_tests/test_placeholder.py deleted file mode 100644 index 3ada1ee4e..000000000 --- a/tests/integration/integration_tests/test_placeholder.py +++ /dev/null @@ -1,2 +0,0 @@ -def test_placeholder(): - assert True diff --git a/tests/integration/requirements-test.txt b/tests/integration/requirements-test.txt deleted file mode 100644 index 084df2bb1..000000000 --- a/tests/integration/requirements-test.txt +++ /dev/null @@ -1,3 +0,0 @@ -pytest>=8.0.0 -requests>=2.31.0 -httpx>=0.27.0