Как вы увидите ниже, у меня есть интеграционные тесты, выполняемые с помощью LocalStack и TestContainers. Локально тесты выполняются успешно. В GitLab Pipelines они не проходят конфигурации, в которых таблица и очередь создаются при запуске приложения.
Ошибки: Ошибка создания очереди: Служба вернула код состояния HTTP 404 (Сервис : Sqs, код состояния: 404, идентификатор запроса: null), что указывает мне на то, что запрос каким-то образом искажен при работе в конвейере, но я не могу понять, как выглядит запрос. когда это терпит неудачу. Журналы LocalStack не фиксируют попытки вызова в случае сбоя конвейера, но они регистрируют успешные запуски локально.
Будем благодарны за любую информацию, которую кто-либо может предоставить.
Конфигурация Gitlab CICD:
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
image: maven:3.9.9-eclipse-temurin-21
integration-test-job:
stage: test
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
DOCKER_DRIVER: overlay2
script:
- ./mvnw -s mvn_ci_settings.xml integration-test
rules:
# Run only ONCE on every commit or merge request
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
artifacts:
reports:
junit: target/surefire-reports/TEST-*.xml
Эта тестовая конфигурация создает компонент localStackContainer
@TestConfiguration(proxyBeanMethods = false)
public class LocalStackConfig {
@Value("${amazon.region}")
private String awsRegion;
private static final DockerImageName LOCALSTACK_IMAGE_NAME = DockerImageName.parse("localstack/localstack:3.8.1");
private LocalStackContainer localStackContainer;
@Bean
public LocalStackContainer localStackContainer() {
// Setting defaults for LocalStackContainer. Access and Secret keys are fake.
// https://docs.localstack.cloud/references/credentials/
this.localStackContainer = new LocalStackContainer(LOCALSTACK_IMAGE_NAME)
.withEnv("LS_LOG", "trace-internal")
.withEnv("AWS_DEFAULT_REGION", awsRegion)
.withEnv("AWS_ACCESS_KEY_ID", "fake")
.withEnv("AWS_SECRET_ACCESS_KEY", "fake")
.withServices(DYNAMODB,SQS);
return this.localStackContainer;
}
@PreDestroy
public void closeLocalStackContainer() {
if (this.localStackContainer != null) {
this.localStackContainer.close();
}
}
}
Эта тестовая конфигурация создает клиенты SQS и DynamoDB, создает таблицу и очередь при запуске приложения, а также регистрирует проверки работоспособности LocalStack.
@TestConfiguration(proxyBeanMethods = false)
public class XadsIntegrationTestConfig {
@Autowired
private LocalStackContainer localStackContainer;
@Value("${amazon.sqs.name}")
private String queueName;
@Value("${amazon.region}")
private String awsRegion;
private static final Logger LOG = System.getLogger(ConsentRepositoryImpl.class.getName());
@Bean
public SqsClient sqsClient() {
LOG.log(System.Logger.Level.INFO, "SQS endpoint: " + localStackContainer.getEndpointOverride(SQS));
return SqsClient.builder()
.region(Region.of(awsRegion))
.credentialsProvider(
StaticCredentialsProvider.create(
AwsBasicCredentials.create(localStackContainer.getAccessKey(), localStackContainer.getSecretKey())
)
)
.endpointOverride(localStackContainer.getEndpointOverride(SQS))
.build();
}
@Bean
public DynamoDbClient dynamoDbClient() {
LOG.log(System.Logger.Level.INFO, "DynamoDB endpoint: " + localStackContainer.getEndpointOverride(DYNAMODB));
return DynamoDbClient.builder()
.region(Region.of(awsRegion))
.credentialsProvider(
StaticCredentialsProvider.create(
AwsBasicCredentials.create(localStackContainer.getAccessKey(), localStackContainer.getSecretKey())
)
)
.endpointOverride(localStackContainer.getEndpointOverride(DYNAMODB))
.build();
}
@EventListener
public void onApplicationReady(ApplicationReadyEvent applicationReadyEvent) {
checkLSHealth();
ApplicationContext applicationContext = applicationReadyEvent.getApplicationContext();
LOG.log(System.Logger.Level.INFO, "Creating tables and sqsclient for integration tests");
// Create DynamoDB table for testing
LOG.log(System.Logger.Level.INFO, "Getting consentTable bean...");
DynamoDbTable consentTable = applicationContext.getBean("consentTable", DynamoDbTable.class);
try {
consentTable.createTable();
LOG.log(System.Logger.Level.INFO, "consentTable created...");
String logs = localStackContainer.getLogs();
LOG.log(System.Logger.Level.ERROR, logs);
} catch (Exception e) {
String logs = localStackContainer.getLogs();
LOG.log(System.Logger.Level.ERROR, "Error creating queue: " + e.getMessage());
LOG.log(System.Logger.Level.ERROR, logs);
}
// Create SQS queue for testing
LOG.log(System.Logger.Level.INFO, "Getting sqsclient bean...");
SqsClient sqsClient = applicationContext.getBean("sqsClient", SqsClient.class);
CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
.queueName(queueName)
.build();
try {
CreateQueueResponse createQueueResponse = sqsClient.createQueue(createQueueRequest);
LOG.log(System.Logger.Level.INFO, "Queue created: " + createQueueResponse.queueUrl());
String logs = localStackContainer.getLogs();
LOG.log(System.Logger.Level.ERROR, logs);
} catch (Exception e) {
String logs = localStackContainer.getLogs();
LOG.log(System.Logger.Level.ERROR, "Error creating queue: " + e.getMessage());
LOG.log(System.Logger.Level.ERROR, logs);
}
}
private void checkLSHealth() {
LOG.log(System.Logger.Level.INFO, "LocalStack isRunning check...");
LOG.log(System.Logger.Level.INFO, "LocalStack is running: " + localStackContainer.isRunning());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(localStackContainer.getEndpointOverride(DYNAMODB) + "/_localstack/health"))
.GET()
.build();
try {
// Send the request synchronously
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
LOG.log(System.Logger.Level.INFO, "LocalStack health check response: " + response.statusCode());
LOG.log(System.Logger.Level.INFO, "LocalStack health check response body: " + response.body());
} catch (IOException | InterruptedException e) {
LOG.log(System.Logger.Level.ERROR, "Error during LocalStack health check: " + e.getMessage());
Thread.currentThread().interrupt(); // Restore interrupted status
}
String endpoint = localStackContainer.getEndpoint().toString();
LOG.log(System.Logger.Level.INFO, "LocalStack endpoint: " + endpoint);
String endpointOverride = localStackContainer.getEndpointOverride(DYNAMODB).toString();
LOG.log(System.Logger.Level.INFO, "LocalStack endpointOverride: " + endpointOverride);
}
}
При локальном запуске мои тесты (здесь не показаны) выполняются успешно. Работая в GitLab Pipelines, я получаю ошибку 404 при вызове DynamoDB и SQS.
Вот логи запуска на локальном и в конвейере. Ниже для краткости я исключаю выходные данные журнала LocalStack.
Локальные журналы:
2025-01-07T00:57:19.728-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack isRunning check...
2025-01-07T00:57:19.740-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack is running: true
2025-01-07T00:57:21.952-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack health check response: 200
2025-01-07T00:57:21.952-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack health check response body: {"services": {"acm": "disabled", "apigateway": "disabled", "cloudformation": "disabled", "cloudwatch": "disabled", "config": "disabled", "dynamodb": "available", "dynamodbstreams": "available", "ec2": "disabled", "es": "disabled", "events": "disabled", "firehose": "disabled", "iam": "disabled", "kinesis": "available", "kms": "disabled", "lambda": "disabled", "logs": "disabled", "opensearch": "disabled", "redshift": "disabled", "resource-groups": "disabled", "resourcegroupstaggingapi": "disabled", "route53": "disabled", "route53resolver": "disabled", "s3": "disabled", "s3control": "disabled", "scheduler": "disabled", "secretsmanager": "disabled", "ses": "disabled", "sns": "disabled", "sqs": "available", "ssm": "disabled", "stepfunctions": "disabled", "sts": "disabled", "support": "disabled", "swf": "disabled", "transcribe": "disabled"}, "edition": "community", "version": "3.8.1"}
2025-01-07T00:57:21.952-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack endpoint: http://127.0.0.1:33121
2025-01-07T00:57:21.952-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack endpointOverride: http://127.0.0.1:33121
2025-01-07T00:57:21.952-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Creating tables and sqsclient for integration tests
2025-01-07T00:57:21.952-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Getting consentTable bean...
2025-01-07T00:57:25.114-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : consentTable created...
.
.
.
2025-01-07T00:57:25.144-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Getting sqsclient bean...
2025-01-07T00:57:25.243-05:00 INFO 9560 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Queue created: http://127.0.0.1:33121/queue/us-east-1/ ... ring-queue
Журналы конвейера GitLab:
2025-01-07T05:40:53.906Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : DynamoDB endpoint: http://172.17.0.1:32781
2025-01-07T05:40:54.782Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : SQS endpoint: http://172.17.0.1:32781
2025-01-07T05:40:55.488Z INFO 179 --- [ main] g.f.x.q.DataSharingQueueIntegrationTests : Started DataSharingQueueIntegrationTests in 22.396 seconds (process running for 23.721)
2025-01-07T05:40:55.493Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack isRunning check...
2025-01-07T05:40:55.510Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack is running: true
2025-01-07T05:40:58.925Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack health check response: 200
2025-01-07T05:40:58.926Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack health check response body: {"services": {"acm": "disabled", "apigateway": "disabled", "cloudformation": "disabled", "cloudwatch": "disabled", "config": "disabled", "dynamodb": "available", "dynamodbstreams": "available", "ec2": "disabled", "es": "disabled", "events": "disabled", "firehose": "disabled", "iam": "disabled", "kinesis": "available", "kms": "disabled", "lambda": "disabled", "logs": "disabled", "opensearch": "disabled", "redshift": "disabled", "resource-groups": "disabled", "resourcegroupstaggingapi": "disabled", "route53": "disabled", "route53resolver": "disabled", "s3": "disabled", "s3control": "disabled", "scheduler": "disabled", "secretsmanager": "disabled", "ses": "disabled", "sns": "disabled", "sqs": "available", "ssm": "disabled", "stepfunctions": "disabled", "sts": "disabled", "support": "disabled", "swf": "disabled", "transcribe": "disabled"}, "edition": "community", "version": "3.8.1"}
2025-01-07T05:40:58.927Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack endpoint: http://172.17.0.1:32781
2025-01-07T05:40:58.927Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : LocalStack endpointOverride: http://172.17.0.1:32781
2025-01-07T05:40:58.927Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Creating tables and sqsclient for integration tests
2025-01-07T05:40:58.927Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Getting consentTable bean...
2025-01-07T05:40:59.643Z ERROR 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Error creating queue: Service returned HTTP status code 404 (Service: DynamoDb, Status Code: 404, Request ID: null)
.
.
.
025-01-07T05:40:59.646Z INFO 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Getting sqsclient bean...
2025-01-07T05:41:13.994Z ERROR 179 --- [ main] g.f.x.p.r.impl.ConsentRepositoryImpl : Error creating queue: Service returned HTTP status code 404 (Service: Sqs, Status Code: 404, Request ID: null)
Подробнее здесь: https://stackoverflow.com/questions/793 ... iners-runs
Интеграционное тестирование SQS и DynamoDB с помощью LocalStack и TestContainers выполняется локально успешно, но возвра ⇐ JAVA
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение