Skip to content
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
88 changes: 78 additions & 10 deletions .gitlab/templates/pipeline.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,49 @@ signed layer bundle:
- mkdir -p datadog_extension-signed-bundle-${CI_JOB_ID}
- cp .layers/datadog_extension-*.zip datadog_extension-signed-bundle-${CI_JOB_ID}

# Integration Tests - Build Java Lambda function
build java lambda:
stage: integration-tests
image: registry.ddbuild.io/images/docker:27.3.1
tags: ["docker-in-docker:arm64"]
rules:
- when: on_success
needs: []
artifacts:
expire_in: 1 hour
paths:
- integration-tests/lambda/base-java/target/
script:
- cd integration-tests/lambda/base-java
- docker run --rm --platform linux/arm64
-v "$(pwd)":/workspace
-w /workspace
maven:3.9-eclipse-temurin-21-alpine
mvn clean package

# Integration Tests - Build .NET Lambda function
build dotnet lambda:
stage: integration-tests
image: registry.ddbuild.io/images/docker:27.3.1
tags: ["docker-in-docker:arm64"]
rules:
- when: on_success
needs: []
artifacts:
expire_in: 1 hour
paths:
- integration-tests/lambda/base-dotnet/bin/
script:
- cd integration-tests/lambda/base-dotnet
- docker run --rm --platform linux/arm64
-v "$(pwd)":/workspace
-w /workspace
mcr.microsoft.com/dotnet/sdk:8.0-alpine
sh -c "apk add --no-cache zip &&
dotnet tool install -g Amazon.Lambda.Tools || true &&
export PATH=\"\$PATH:/root/.dotnet/tools\" &&
dotnet lambda package -o bin/function.zip --function-architecture arm64"

# Integration Tests - Publish arm64 layer with integration test prefix
publish integration layer (arm64):
stage: integration-tests
Expand Down Expand Up @@ -362,6 +405,11 @@ integration-deploy:
- when: on_success
needs:
- publish integration layer (arm64)
- build java lambda
- build dotnet lambda
dependencies:
- build java lambda
- build dotnet lambda
variables:
IDENTIFIER: ${CI_COMMIT_SHORT_SHA}
AWS_DEFAULT_REGION: us-east-1
Expand Down Expand Up @@ -418,35 +466,55 @@ integration-cleanup-stacks:
stage: integration-tests
tags: ["arch:amd64"]
image: ${CI_DOCKER_TARGET_IMAGE}:${CI_DOCKER_TARGET_VERSION}
when: always
rules:
- when: always
needs:
- integration-test
- job: integration-test
optional: false
variables:
IDENTIFIER: ${CI_COMMIT_SHORT_SHA}
{{ with $environment := (ds "environments").environments.sandbox }}
before_script:
- EXTERNAL_ID_NAME={{ $environment.external_id }} ROLE_TO_ASSUME={{ $environment.role_to_assume }} AWS_ACCOUNT={{ $environment.account }} source .gitlab/scripts/get_secrets.sh
- curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
- apt-get install -y nodejs
- cd integration-tests
- npm ci
{{ end }}
script:
- echo "Destroying CDK stacks with identifier ${IDENTIFIER}..."
- npx cdk destroy "integ-$IDENTIFIER-*" --force || echo "Failed to destroy some stacks, but continuing..."
- |
# Find all stacks matching the pattern using CloudFormation API
STACKS=$(aws cloudformation list-stacks \
--stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE UPDATE_ROLLBACK_COMPLETE \
--query "StackSummaries[?starts_with(StackName, 'integ-${IDENTIFIER}-')].StackName" \
--output text --region us-east-1)

if [ -z "$STACKS" ]; then
echo "No stacks found matching pattern integ-${IDENTIFIER}-*"
else
echo "Found stacks to delete: ${STACKS}"
for STACK in $STACKS; do
echo "Deleting stack ${STACK}..."
aws cloudformation delete-stack --stack-name "${STACK}" --region us-east-1 || echo "Failed to delete ${STACK}, continuing..."
done

# Wait for all deletions to complete
echo "Waiting for stack deletions to complete..."
for STACK in $STACKS; do
echo "Waiting for ${STACK}..."
aws cloudformation wait stack-delete-complete --stack-name "${STACK}" --region us-east-1 || echo "Stack ${STACK} deletion did not complete cleanly, continuing..."
done

echo "All stacks deleted successfully"
fi

# Integration Tests - Cleanup layer
integration-cleanup-layer:
stage: integration-tests
tags: ["arch:amd64"]
image: ${CI_DOCKER_TARGET_IMAGE}:${CI_DOCKER_TARGET_VERSION}
when: always
rules:
- when: always
needs:
- integration-cleanup-stacks
- job: integration-cleanup-stacks
optional: false
variables:
IDENTIFIER: ${CI_COMMIT_SHORT_SHA}
{{ with $environment := (ds "environments").environments.sandbox }}
Expand All @@ -456,7 +524,7 @@ integration-cleanup-layer:
script:
- echo "Deleting integration test layer with identifier ${IDENTIFIER}..."
- |
LAYER_NAME="Datadog-Extension-${IDENTIFIER}"
LAYER_NAME="Datadog-Extension-ARM-${IDENTIFIER}"
echo "Looking for layer: ${LAYER_NAME}"

# Get all versions of the layer
Expand Down
35 changes: 34 additions & 1 deletion integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,40 @@ The general flow is:
3. Wait for data to propagate to Datadog.
4. Call Datadog to get telemetry data and check the data based on test requirements.

For simplicity, integraiton tests are setup to only test against ARM runtimes.
For simplicity, integration tests are setup to only test against ARM runtimes.

## Test Suites

### Base Tests

The base test suite provides basic functionality tests across all supported Lambda runtimes. Also serves as an example for other tests.

The base tests verify the extension can:
- Collect and forward logs to Datadog
- Generate and send traces with proper span structure
- Detect cold starts

**Test Coverage:**
- Lambda invocation succeeds (200 status code)
- "Hello world!" log message is sent to Datadog
- One trace is sent to Datadog
- `aws.lambda` span exists with correct properties including `cold_start: 'true'`
- `aws.lambda.cold_start` span is created
- `aws.lambda.load` spand is created for python and node.

**Build Requirements:**

For Java and .NET tests, Lambda functions must be built before deployment:

```bash
# Build Java Lambda (uses Docker)
cd lambda/base-java && ./build.sh

# Build .NET Lambda (uses Docker)
cd lambda/base-dotnet && ./build.sh
```

These builds use Docker to ensure cross-platform compatibility and do not require local Maven or .NET SDK installation.

## Guidelines

Expand Down
34 changes: 23 additions & 11 deletions integration-tests/bin/app.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { BaseNodeStack } from '../lib/stacks/base-node-stack';
import { BasePythonStack } from '../lib/stacks/base-python-stack';
import { getIdentifier } from '../tests/utils/config';
import {BaseNodeStack} from '../lib/stacks/base-node-stack';
import {BasePythonStack} from '../lib/stacks/base-python-stack';
import {BaseJavaStack} from '../lib/stacks/base-java-stack';
import {BaseDotnetStack} from '../lib/stacks/base-dotnet-stack';
import {getIdentifier} from '../tests/utils/config';

const app = new cdk.App();

const env = {
account: process.env.CDK_DEFAULT_ACCOUNT || process.env.AWS_ACCOUNT_ID,
region: process.env.CDK_DEFAULT_REGION || process.env.AWS_REGION || 'us-east-1',
account: process.env.CDK_DEFAULT_ACCOUNT || process.env.AWS_ACCOUNT_ID,
region: process.env.CDK_DEFAULT_REGION || process.env.AWS_REGION || 'us-east-1',
};

const identifier = getIdentifier();

new BaseNodeStack(app, `integ-${identifier}-base-node`, {
env,
});
const stacks = [
new BaseNodeStack(app, `integ-${identifier}-base-node`, {
env,
}),
new BasePythonStack(app, `integ-${identifier}-base-python`, {
env,
}),
new BaseJavaStack(app, `integ-${identifier}-base-java`, {
env,
}),
new BaseDotnetStack(app, `integ-${identifier}-base-dotnet`, {
env,
}),
]

new BasePythonStack(app, `integ-${identifier}-base-python`, {
env,
});
// Tag all stacks so we can easily clean them up
stacks.forEach(stack => stack.addStackTag("extension_integration_test", "true"))

app.synth();
4 changes: 4 additions & 0 deletions integration-tests/lambda/base-dotnet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bin/
obj/
*.user
*.suo
19 changes: 19 additions & 0 deletions integration-tests/lambda/base-dotnet/Function.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Amazon.Lambda.Core;
using System.Collections.Generic;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace Function
{
public class Handler
{
public Dictionary<string, object> FunctionHandler(Dictionary<string, object> input, ILambdaContext context)
{
context.Logger.LogLine("Hello world!");
return new Dictionary<string, object>
{
{ "statusCode", 200 }
};
}
}
}
14 changes: 14 additions & 0 deletions integration-tests/lambda/base-dotnet/Function.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AWSProjectType>Lambda</AWSProjectType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="2.2.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.0" />
</ItemGroup>
</Project>
35 changes: 35 additions & 0 deletions integration-tests/lambda/base-dotnet/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash
set -e

echo "Building .NET Lambda with Docker (ARM64)..."

# Check if Docker is available
if ! command -v docker &> /dev/null; then
echo "Error: Docker is not installed or not in PATH"
echo "Please install Docker: https://docs.docker.com/get-docker/"
exit 1
fi

# Get the directory of this script
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Clean previous build
rm -rf "$SCRIPT_DIR/bin" "$SCRIPT_DIR/obj"

# Build and package with Docker using ARM64 platform
docker run --rm --platform linux/arm64 \
-v "$SCRIPT_DIR":/workspace \
-w /workspace \
mcr.microsoft.com/dotnet/sdk:8.0-alpine \
sh -c "apk add --no-cache zip && \
dotnet tool install -g Amazon.Lambda.Tools || true && \
export PATH=\"\$PATH:/root/.dotnet/tools\" && \
dotnet lambda package -o bin/function.zip --function-architecture arm64"

if [ -f "$SCRIPT_DIR/bin/function.zip" ]; then
echo "✓ Build complete: bin/function.zip"
ls -lh "$SCRIPT_DIR/bin/function.zip"
else
echo "✗ Build failed: bin/function.zip not found"
exit 1
fi
5 changes: 5 additions & 0 deletions integration-tests/lambda/base-java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target/
*.class
.classpath
.project
.settings/
32 changes: 32 additions & 0 deletions integration-tests/lambda/base-java/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash
set -e

echo "Building Java Lambda with Docker (ARM64)..."

# Check if Docker is available
if ! command -v docker &> /dev/null; then
echo "Error: Docker is not installed or not in PATH"
echo "Please install Docker: https://docs.docker.com/get-docker/"
exit 1
fi

# Get the directory of this script
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Clean previous build
rm -rf "$SCRIPT_DIR/target"

# Build with Docker using ARM64 platform
docker run --rm --platform linux/arm64 \
-v "$SCRIPT_DIR":/workspace \
-w /workspace \
maven:3.9-eclipse-temurin-21-alpine \
mvn clean package

if [ -f "$SCRIPT_DIR/target/function.jar" ]; then
echo "✓ Build complete: target/function.jar"
ls -lh "$SCRIPT_DIR/target/function.jar"
else
echo "✗ Build failed: target/function.jar not found"
exit 1
fi
50 changes: 50 additions & 0 deletions integration-tests/lambda/base-java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>example</groupId>
<artifactId>base-java-lambda</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>Base Java Lambda</name>
<description>Base Java Lambda function for Datadog Extension integration testing</description>

<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>function</finalName>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading
Loading