diff --git a/README.md b/README.md
index ef87294..72d94d3 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,7 @@ make build
## Change Log
+* v0.2.2: Addition of CloudWatch Logs endpoint configuration
* v0.2.1: Move Java sources into separate project; mark non-Docker Java `LocalstackExtension` as deprecated; update paths for Python code lookup in Docker container
## License
diff --git a/pom.xml b/pom.xml
index e67c962..4b82de2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
cloud.localstack
localstack-utils
jar
- 0.2.1
+ 0.2.2
localstack-utils
Java utilities for the LocalStack platform.
diff --git a/src/main/java/cloud/localstack/Localstack.java b/src/main/java/cloud/localstack/Localstack.java
index c9d7723..2e694a7 100644
--- a/src/main/java/cloud/localstack/Localstack.java
+++ b/src/main/java/cloud/localstack/Localstack.java
@@ -169,6 +169,10 @@ public String getEndpointCloudWatch() {
return endpointForService(ServiceName.CLOUDWATCH);
}
+ public String getEndpointCloudWatchLogs() {
+ return endpointForService(ServiceName.CLOUDWATCH_LOGS);
+ }
+
public String getEndpointSES() {
return endpointForService(ServiceName.SES);
}
diff --git a/src/main/java/cloud/localstack/ServiceName.java b/src/main/java/cloud/localstack/ServiceName.java
index 934701f..a10154c 100644
--- a/src/main/java/cloud/localstack/ServiceName.java
+++ b/src/main/java/cloud/localstack/ServiceName.java
@@ -17,6 +17,7 @@ public class ServiceName {
public static final String ROUTE53 = "route53";
public static final String CLOUDFORMATION = "cloudformation";
public static final String CLOUDWATCH = "cloudwatch";
+ public static final String CLOUDWATCH_LOGS = "logs";
public static final String SSM = "ssm";
public static final String SECRETSMANAGER = "secretsmanager";
public static final String STEPFUNCTIONS = "stepfunctions";
diff --git a/src/main/java/cloud/localstack/awssdkv1/TestUtils.java b/src/main/java/cloud/localstack/awssdkv1/TestUtils.java
index 2ccf388..e7936e1 100644
--- a/src/main/java/cloud/localstack/awssdkv1/TestUtils.java
+++ b/src/main/java/cloud/localstack/awssdkv1/TestUtils.java
@@ -22,6 +22,8 @@
import com.amazonaws.services.lambda.AWSLambdaAsync;
import com.amazonaws.services.lambda.AWSLambdaAsyncClientBuilder;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
+import com.amazonaws.services.logs.AWSLogs;
+import com.amazonaws.services.logs.AWSLogsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.sns.AmazonSNS;
@@ -156,6 +158,12 @@ public static AmazonCloudWatch getClientCloudWatch() {
withEndpointConfiguration(getEndpointConfigurationCloudWatch()).
withCredentials(getCredentialsProvider()).build();
}
+
+ public static AWSLogs getClientCloudWatchLogs() {
+ return AWSLogsClientBuilder.standard().
+ withEndpointConfiguration(getEndpointConfigurationCloudWatchLogs()).
+ withCredentials(getCredentialsProvider()).build();
+ }
public static AmazonIdentityManagement getClientIAM() {
return AmazonIdentityManagementClientBuilder.standard().
@@ -198,6 +206,10 @@ protected static AwsClientBuilder.EndpointConfiguration getEndpointConfiguration
protected static AwsClientBuilder.EndpointConfiguration getEndpointConfigurationCloudWatch() {
return getEndpointConfiguration(Localstack.INSTANCE.getEndpointCloudWatch());
}
+
+ private static AwsClientBuilder.EndpointConfiguration getEndpointConfigurationCloudWatchLogs() {
+ return getEndpointConfiguration(Localstack.INSTANCE.getEndpointCloudWatchLogs());
+ }
protected static AwsClientBuilder.EndpointConfiguration getEndpointConfigurationSecretsManager() {
return getEndpointConfiguration(Localstack.INSTANCE.getEndpointSecretsmanager());
diff --git a/src/test/java/cloud/localstack/CloudWatchLogsTest.java b/src/test/java/cloud/localstack/CloudWatchLogsTest.java
new file mode 100644
index 0000000..29396b6
--- /dev/null
+++ b/src/test/java/cloud/localstack/CloudWatchLogsTest.java
@@ -0,0 +1,118 @@
+package cloud.localstack;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.runner.RunWith;
+
+import com.amazonaws.services.logs.AWSLogs;
+import com.amazonaws.services.logs.model.CreateLogGroupRequest;
+import com.amazonaws.services.logs.model.CreateLogStreamRequest;
+import com.amazonaws.services.logs.model.DescribeLogGroupsResult;
+import com.amazonaws.services.logs.model.GetLogEventsRequest;
+import com.amazonaws.services.logs.model.GetLogEventsResult;
+import com.amazonaws.services.logs.model.InputLogEvent;
+import com.amazonaws.services.logs.model.LogGroup;
+import com.amazonaws.services.logs.model.OutputLogEvent;
+import com.amazonaws.services.logs.model.PutLogEventsRequest;
+
+import cloud.localstack.awssdkv1.TestUtils;
+import cloud.localstack.docker.LocalstackDockerExtension;
+import cloud.localstack.docker.annotation.LocalstackDockerProperties;
+
+/**
+ * Test service usage of CloudWatchLogs with example connection, creation of log group stream
+ * and manual publication of sample events and their basic retrieval
+ *
+ * Issue: https://github.com/localstack/localstack-java-utils/issues/11
+ *
+ * @author Andrew Duffy
+ *
+ */
+@RunWith(LocalstackTestRunner.class)
+@ExtendWith(LocalstackDockerExtension.class)
+@LocalstackDockerProperties(services = {"logs"}, ignoreDockerRunErrors=true)
+class CloudWatchLogsTest {
+
+ @org.junit.Test
+ @org.junit.jupiter.api.Test
+ void testLogGroupSetupAndPublish() {
+ AWSLogs cloudWatchLogs = TestUtils.getClientCloudWatchLogs();
+ DescribeLogGroupsResult groups = cloudWatchLogs.describeLogGroups();
+ Assertions.assertTrue(groups.getLogGroups().isEmpty());
+
+ String logGroupName = createLogGroup();
+
+ DescribeLogGroupsResult groupsAfterCreation = cloudWatchLogs.describeLogGroups();
+ Assertions.assertFalse(groupsAfterCreation.getLogGroups().isEmpty());
+ Assertions.assertEquals(1, groupsAfterCreation.getLogGroups().size());
+
+ LogGroup newGroup = groupsAfterCreation.getLogGroups().get(0);
+ Assertions.assertEquals(logGroupName, newGroup.getLogGroupName());
+ Assertions.assertNotNull(newGroup.getArn());
+ Assertions.assertEquals(0, newGroup.getStoredBytes());
+
+ String logStream = createLogStream(logGroupName);
+
+ List events = publishLogEvents(logGroupName, logStream);
+
+ GetLogEventsResult publishedEvents = fetchEvents(logGroupName, logStream);
+ Assertions.assertEquals(events.size(), publishedEvents.getEvents().size());
+
+ List messagesSent = events.stream().map(InputLogEvent::getMessage).collect(Collectors.toList());
+ for (OutputLogEvent publishedOutputEvent: publishedEvents.getEvents()) {
+ Assertions.assertTrue(messagesSent.contains(publishedOutputEvent.getMessage()));
+ }
+ }
+
+ public String createLogGroup() {
+ CreateLogGroupRequest createLogGroupRequest = new CreateLogGroupRequest();
+ createLogGroupRequest.setLogGroupName("testLogGroupName-" + UUID.randomUUID().toString());
+
+ TestUtils.getClientCloudWatchLogs().createLogGroup(createLogGroupRequest);
+ return createLogGroupRequest.getLogGroupName();
+ }
+
+ public String createLogStream(String newGroup) {
+ CreateLogStreamRequest newStreamRequest = new CreateLogStreamRequest();
+ newStreamRequest.setLogGroupName(newGroup);
+ newStreamRequest.setLogStreamName("stream-" + UUID.randomUUID().toString());
+
+ TestUtils.getClientCloudWatchLogs().createLogStream(newStreamRequest);
+ return newStreamRequest.getLogStreamName();
+ }
+
+ public List publishLogEvents(String groupName, String logStream) {
+ InputLogEvent event1 = new InputLogEvent();
+ event1.setMessage("Event1-" + UUID.randomUUID().toString());
+ event1.setTimestamp(System.currentTimeMillis());
+
+ InputLogEvent event2 = new InputLogEvent();
+ event2.setMessage("Event2-" + UUID.randomUUID().toString());
+ event2.setTimestamp(System.currentTimeMillis());
+ List events = new ArrayList<>();
+ events.add(event1);
+ events.add(event2);
+
+ PutLogEventsRequest putLogEventsRequest = new PutLogEventsRequest();
+ putLogEventsRequest.setLogGroupName(groupName);
+ putLogEventsRequest.setLogStreamName(logStream);
+ putLogEventsRequest.setLogEvents(events);
+
+ TestUtils.getClientCloudWatchLogs().putLogEvents(putLogEventsRequest);
+ return events;
+ }
+
+ public GetLogEventsResult fetchEvents(String groupName, String logStream) {
+ GetLogEventsRequest getLogEventsRequest = new GetLogEventsRequest();
+ getLogEventsRequest.setLogStreamName(logStream);
+ getLogEventsRequest.setLogGroupName(groupName);
+
+ return TestUtils.getClientCloudWatchLogs().getLogEvents(getLogEventsRequest);
+ }
+
+}