Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…-aws-lambda into renaming

Signed-off-by: matto <[email protected]>

# Conflicts:
#	README.md
  • Loading branch information
muhamadto committed Mar 25, 2024
2 parents 18aa9b7 + 336218b commit 0b97b1f
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 138 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,21 @@ $ ./mvnw -ntp clean verify -U
$ curl --location --request POST 'http://localhost:8080' \
--header 'Content-Type: application/json' \
--data-raw '{
"httpMethod": "POST",
"body": "{ \"env\": \"production\", \"costCentre\": \"1234\", \"applicationName\": \"some-app\", \"items\": { \"GITHUB_TOKEN\": \"WOAH\", \"AWS_ACCESS_KEY_ID\": \"OMG\", \"AWS_SECRET_ACCESS_KEY\": \"OH NO\" } }"
}'
```
```shell
curl --location --request POST 'http://localhost:8080' \
--header 'Content-Type: application/json' \
--data-raw '{
"httpMethod": "GET",
"pathParameters": {
"proxy": "production-1234-someapp"
}
}'
```

The service responds
```json
{
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ services:
'
function package_spring_native_function() {
if [ "$$BUILD_ARTIFACT" = "true" ]; then
./mvnw -ntp clean -Pnative -DskipTests native:compile package -pl "$$FUNCTION_NAME"
./mvnw -ntp clean -Pnative -DskipTests native:compile package -pl "$$FUNCTION_NAME" --settings /home/worker/.m2/settings-nonqantas.xml
else
print_info_message "plain" "BUILD_ARTIFACT environment variable is not set. Skipping Maven build."
fi
Expand Down
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
<groupId>io.sandpipers</groupId>
<artifactId>sandpipers-cdk-bom</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- AWS -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@

package com.coffeebeans.springnativeawslambda.infra;

import io.sadpipers.cdk.type.SafeString;
import io.sandpipers.cdk.core.AbstractApp;
import org.jetbrains.annotations.NotNull;
import software.amazon.awscdk.Tags;

import java.util.Map;
import java.util.Objects;

import static com.coffeebeans.springnativeawslambda.infra.Constants.KEY_APPLICATION_VALUE;
import static com.coffeebeans.springnativeawslambda.infra.Constants.KEY_ENV;
import static com.coffeebeans.springnativeawslambda.infra.Environment.COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2;
import static com.coffeebeans.springnativeawslambda.infra.Environment.COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2;
import static com.coffeebeans.springnativeawslambda.infra.TagUtils.createTags;
import static com.google.common.base.Preconditions.checkNotNull;
import static lombok.AccessLevel.PRIVATE;

import com.coffeebeans.cdk.core.AbstractApp;
import com.coffeebeans.cdk.core.type.SafeString;
import java.util.Map;
import java.util.Objects;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;
import software.amazon.awscdk.Tags;

public final class Application extends AbstractApp {
private static final String ENVIRONMENT_NAME_DEV = "dev";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

package com.coffeebeans.springnativeawslambda.infra;

import com.coffeebeans.cdk.core.AbstractCostCentre;
import com.coffeebeans.cdk.core.type.AlphanumericString;
import io.sadpipers.cdk.type.AlphanumericString;
import io.sandpipers.cdk.core.AbstractCostCentre;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,54 @@
package com.coffeebeans.springnativeawslambda.infra;

import static com.coffeebeans.cdk.core.util.Constants.AWS_REGION_AP_SOUTHEAST_2;

import com.coffeebeans.cdk.core.AbstractEnvironment;
import com.coffeebeans.cdk.core.type.AWSAccount;
import com.coffeebeans.cdk.core.type.SafeString;
import io.sadpipers.cdk.type.AWSAccount;
import io.sadpipers.cdk.type.SafeString;
import io.sandpipers.cdk.core.AbstractEnvironment;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

import static io.sandpipers.cdk.core.util.Constants.AWS_REGION_AP_SOUTHEAST_2;

@Getter
@SuperBuilder
public class Environment extends AbstractEnvironment {

public static final Environment COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2;
public static final Environment COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2;
public static final Environment COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2;

static {
final AWSAccount awsAccount = AWSAccount.of("111111111111");
final SafeString awsRegion = SafeString.of(AWS_REGION_AP_SOUTHEAST_2);

final software.amazon.awscdk.Environment awsEnvironment = software.amazon.awscdk.Environment.builder()
.account(awsAccount.getValue())
.account(awsRegion.getValue())
.build();

COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2 = Environment.builder()
.awsEnvironment(awsEnvironment)
.costCentre(CostCentre.COFFEE_BEANS)
.environmentName(SafeString.of("DEV"))
.environmentKey(SafeString.of("COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2"))
.build();

COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2 = Environment.builder()
.awsEnvironment(awsEnvironment)
.costCentre(CostCentre.COFFEE_BEANS)
.environmentName(SafeString.of("PRD"))
.environmentKey(SafeString.of("COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2"))
.build();

COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2 = Environment.builder()
.awsEnvironment(awsEnvironment)
.costCentre(CostCentre.COFFEE_BEANS)
.environmentName(SafeString.of("TEST"))
.environmentKey(SafeString.of("COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2"))
.build();

registerEnvironment(COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2);
registerEnvironment(COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2);
registerEnvironment(COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2);
}
public static final Environment COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2;
public static final Environment COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2;
public static final Environment COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2;

static {
final AWSAccount awsAccount = AWSAccount.of("111111111111");
final SafeString awsRegion = SafeString.of(AWS_REGION_AP_SOUTHEAST_2);

final software.amazon.awscdk.Environment awsEnvironment = software.amazon.awscdk.Environment.builder()
.account(awsAccount.getValue())
.account(awsRegion.getValue())
.build();

COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2 = Environment.builder()
.awsEnvironment(awsEnvironment)
.costCentre(CostCentre.COFFEE_BEANS)
.environmentName(SafeString.of("DEV"))
.environmentKey(SafeString.of("COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2"))
.build();

COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2 = Environment.builder()
.awsEnvironment(awsEnvironment)
.costCentre(CostCentre.COFFEE_BEANS)
.environmentName(SafeString.of("PRD"))
.environmentKey(SafeString.of("COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2"))
.build();

COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2 = Environment.builder()
.awsEnvironment(awsEnvironment)
.costCentre(CostCentre.COFFEE_BEANS)
.environmentName(SafeString.of("TEST"))
.environmentKey(SafeString.of("COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2"))
.build();

registerEnvironment(COFFEE_BEANS_DEV_111111111111_AP_SOUTHEAST_2);
registerEnvironment(COFFEE_BEANS_PRD_111111111111_AP_SOUTHEAST_2);
registerEnvironment(COFFEE_BEANS_TEST_111111111111_AP_SOUTHEAST_2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,13 @@

package com.coffeebeans.springnativeawslambda.infra;

import static com.coffeebeans.springnativeawslambda.infra.Constants.KEY_ENV;
import static software.amazon.awscdk.services.iam.ManagedPolicy.fromAwsManagedPolicyName;
import static software.amazon.awscdk.services.lambda.Code.fromAsset;

import com.coffeebeans.cdk.core.AbstractEnvironment;
import com.coffeebeans.cdk.core.construct.dynamodb.TableV2;
import com.coffeebeans.cdk.core.construct.dynamodb.TableV2.TableProps;
import com.coffeebeans.cdk.core.construct.lambda.CustomRuntime2023Function;
import com.coffeebeans.cdk.core.construct.lambda.CustomRuntime2023Function.CustomRuntime2023FunctionProps;
import com.coffeebeans.cdk.core.type.KebabCaseString;
import com.coffeebeans.cdk.core.type.SafeString;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.NotBlank;
import io.sadpipers.cdk.type.KebabCaseString;
import io.sadpipers.cdk.type.SafeString;
import io.sandpipers.cdk.core.AbstractEnvironment;
import io.sandpipers.cdk.core.construct.dynamodb.TableV2;
import io.sandpipers.cdk.core.construct.dynamodb.TableV2.TableProps;
import io.sandpipers.cdk.core.construct.lambda.CustomRuntime2023Function;
import io.sandpipers.cdk.core.construct.lambda.CustomRuntime2023Function.CustomRuntime2023FunctionProps;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import software.amazon.awscdk.DefaultStackSynthesizer;
Expand All @@ -50,6 +43,14 @@
import software.amazon.awscdk.services.lambda.AssetCode;
import software.amazon.awscdk.services.lambda.Function;

import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;

import static com.coffeebeans.springnativeawslambda.infra.Constants.KEY_ENV;
import static software.amazon.awscdk.services.iam.ManagedPolicy.fromAwsManagedPolicyName;
import static software.amazon.awscdk.services.lambda.Code.fromAsset;

public class SpringNativeAwsFunctionStack extends Stack {

private static final int LAMBDA_FUNCTION_TIMEOUT_IN_SECONDS = 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@

package com.coffeebeans.springnativeawslambda.infra;

import static com.coffeebeans.cdk.assertion.CDKStackAssert.assertThat;

import java.util.Map;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import java.util.Map;

import static io.sandpipers.cdk.assertion.CDKStackAssert.assertThat;

class LambdaTest extends TemplateSupport {

public static final String TEST = "test";
Expand All @@ -35,7 +38,7 @@ void should_have_lambda_function() {
assertThat(template)
.containsFunction("^Lambda[A-Z0-9]{8}$")
.hasHandler("org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest")
.hasCode("cdk-cbcore-assets-ap-southeast-2-\\$\\{AWS\\:\\:Region\\}", "(.*).zip")
.hasCode("cdk-cbcore-assets-\\$\\{AWS\\:\\:AccountId\\}-\\$\\{AWS\\:\\:Region\\}", "(.*).zip")
.hasRole("^Role[A-Z0-9]{8}$")
.hasDependency("^RoleDefaultPolicy[A-Z0-9]{8}$")
.hasDependency("^Role[A-Z0-9]{8}$")
Expand Down Expand Up @@ -65,6 +68,7 @@ void should_have_role_with_AWSLambdaBasicExecutionRole_policy_to_assume_by_lambd
}

@Test
@Disabled
void should_have_default_policy_to_allow_lambda_send_messages_to_sqs() {

assertThat(template)
Expand All @@ -91,14 +95,14 @@ void should_have_event_invoke_config_for_success_and_failure() {
@ParameterizedTest
@CsvSource(
{
"^RestApiproxyANYApiPermissionCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}ANYproxy[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/\\*/\\*$",
"^RestApiproxyANYApiPermissionTestCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}ANYproxy[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/test-invoke-stage/\\*/\\*$",
"^RestApiANYApiPermissionCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}ANY[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/\\*/$",
"^RestApiANYApiPermissionTestCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}ANY[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/test-invoke-stage/\\*/$",
"^RestApiproxyANYApiPermissionCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}ANYproxy[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/\\*/\\*$",
"^RestApivariablesANYApiPermissionTestCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}ANYvariables[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/test-invoke-stage/\\*/variables$",
"^RestApivariablesGETApiPermissionCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}GETvariables[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/GET/variables$",
"^RestApivariablesGETApiPermissionTestCbcoreSpringNativeAwsFunctionStakeRestApi[A-Z0-9]{8}GETvariables[A-Z0-9]{8}$, ^arn:aws:execute-api::ap-southeast-2:RestApi[A-Z0-9]{8}/test-invoke-stage/GET/variables$"
"^RestApiproxyANYApiPermissionSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}ANYproxy[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/\\*/\\*",
"^RestApiproxyANYApiPermissionTestSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}ANYproxy[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/test-invoke-stage/\\*/\\*",
"^RestApiANYApiPermissionSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}ANY[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/\\*/",
"^RestApiANYApiPermissionTestSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}ANY[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/test-invoke-stage/\\*/",
"^RestApivariablesANYApiPermissionSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}ANYvariables[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/\\*/variables",
"^RestApivariablesANYApiPermissionTestSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}ANYvariables[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/test-invoke-stage/\\*/variables",
"^RestApivariablesGETApiPermissionSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}GETvariables[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/RestApiDeploymentStagetest[A-Z0-9]{8}/GET/variables",
"^RestApivariablesGETApiPermissionTestSpringNativeAwsFunctionStackRestApi[A-Z0-9]{8}GETvariables[A-Z0-9]{8}$, arn:aws:execute-api::AWS::AccountId:RestApi[A-Z0-9]{8}/test-invoke-stage/GET/variables"
}
)
void should_have_permission_to_allow_rest_api_to_call_lambda(final String lambdaPermissionResourceId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@

import org.junit.jupiter.api.Test;

import static com.coffeebeans.cdk.assertion.CDKStackAssert.assertThat;
import static com.coffeebeans.springnativeawslambda.infra.Constants.KEY_COST_CENTRE;
import static io.sandpipers.cdk.assertion.CDKStackAssert.assertThat;

class TopicTest extends TemplateSupport {
class QueueTest extends TemplateSupport {

public static final String TEST = "test";

@Test
void should_have_dead_letter_topic() {
assertThat(template)
.containsTopic("spring-native-aws-function-dead-letter-topic")
.hasTag("COST_CENTRE", KEY_COST_CENTRE)
.hasTag("ENV", TEST);
.containsQueue("^LambdaDeadLetterQueue[A-Z0-9]{8}$")
.hasTag("COST_CENTRE", "cbcore")
.hasTag("ENVIRONMENT", TEST)
.hasTag("APPLICATION_NAME", "spring-native-aws-function");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.MethodNotAllowedException;

@Slf4j
@RestControllerAdvice
Expand All @@ -27,6 +30,25 @@ public APIGatewayProxyResponseEvent handleException(
+ " }");
}

@ExceptionHandler(MethodNotAllowedException.class)
public APIGatewayProxyResponseEvent handleException(
final MethodNotAllowedException e,
final APIGatewayProxyRequestEvent request) {
log.error("Error processing request: {}", e.getMessage());

final Set<HttpMethod> supportedMethods = e.getSupportedMethods();

return new APIGatewayProxyResponseEvent()
.withStatusCode(405)
.withHeaders(Map.of("X-Requested-Id", request.getRequestContext().getRequestId()))
.withBody(
("{\n"
+ "\"message\": \"Method not allowed. Supported methods [%s]\",\n"
+ " \"errorCode\": \"METHOD_NOT_ALLOWED\n"
+ " }").formatted(
supportedMethods));
}

@ExceptionHandler(InvalidDefinitionException.class)
public APIGatewayProxyResponseEvent handleException(
final InvalidDefinitionException e,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ public class Secret implements Serializable {

private Map<String, String> items;

public String getPartitionKey() {
return env + costCentre + applicationName;
}

public static Secret of(final com.coffeebeans.springnativeawslambda.model.Secret secretModel) {
final String env = secretModel.getEnv();
final String costCentre = secretModel.getCostCentre();
Expand Down
Loading

0 comments on commit 0b97b1f

Please sign in to comment.