Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws2-lambda: Added updateFunction and getFunction tests #2749 #3120

Merged
merged 1 commit into from
Sep 21, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
Expand All @@ -40,10 +41,15 @@
import org.apache.camel.component.aws2.lambda.Lambda2Constants;
import org.apache.camel.component.aws2.lambda.Lambda2Operations;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.lambda.model.FunctionConfiguration;
import software.amazon.awssdk.services.lambda.model.GetFunctionResponse;
import software.amazon.awssdk.services.lambda.model.InvalidParameterValueException;
import software.amazon.awssdk.services.lambda.model.LastUpdateStatus;
import software.amazon.awssdk.services.lambda.model.ListFunctionsResponse;
import software.amazon.awssdk.services.lambda.model.Runtime;
import software.amazon.awssdk.services.lambda.model.UpdateFunctionCodeRequest;
import software.amazon.awssdk.services.lambda.model.UpdateFunctionCodeResponse;

@Path("/aws2-lambda")
@ApplicationScoped
Expand All @@ -54,14 +60,14 @@ public class Aws2LambdaResource {
@Inject
ProducerTemplate producerTemplate;

@Path("/create/{functionName}")
@Path("/function/create/{functionName}")
@POST
@Consumes("application/zip")
@Produces(MediaType.TEXT_PLAIN)
public Response createFunction(byte[] message, @PathParam("functionName") String functionName) throws Exception {
public Response createFunction(byte[] zipFunctionBytes, @PathParam("functionName") String functionName) throws Exception {
final String response = producerTemplate.requestBodyAndHeaders(
componentUri(functionName, Lambda2Operations.createFunction),
message,
zipFunctionBytes,
new LinkedHashMap<String, Object>() {
{
put(Lambda2Constants.ROLE, roleArn);
Expand All @@ -76,10 +82,36 @@ public Response createFunction(byte[] message, @PathParam("functionName") String
.build();
}

@Path("/listFunctions")
@Path("/function/get/{functionName}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public String getFunction(@PathParam("functionName") String functionName) {
return producerTemplate
.requestBody(componentUri(functionName, Lambda2Operations.getFunction), null, GetFunctionResponse.class)
.configuration().functionName();
}

@Path("/function/update/{functionName}")
@PUT
@Consumes("application/zip")
@Produces(MediaType.TEXT_PLAIN)
public Response updateFunction(byte[] zipFunctionBytes, @PathParam("functionName") String functionName) {
String uri = componentUri(functionName, Lambda2Operations.updateFunction) + "&pojoRequest=true";
UpdateFunctionCodeRequest ufcRequest = UpdateFunctionCodeRequest.builder().functionName(functionName)
.zipFile(SdkBytes.fromByteArray(zipFunctionBytes)).build();
UpdateFunctionCodeResponse ufcResponse = producerTemplate.requestBody(uri, ufcRequest,
UpdateFunctionCodeResponse.class);
if (ufcResponse.lastUpdateStatus() == LastUpdateStatus.SUCCESSFUL) {
return Response.ok().build();
}
throw new IllegalStateException(
ufcResponse.lastUpdateStatusReasonCodeAsString() + ": " + ufcResponse.lastUpdateStatusReason());
}

@Path("/function/list")
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<String> listFunctions() throws Exception {
public List<String> listFunctions() {
return producerTemplate.requestBody(
componentUri("foo", Lambda2Operations.listFunctions),
null,
Expand All @@ -89,21 +121,21 @@ public List<String> listFunctions() throws Exception {
.collect(Collectors.toList());
}

@Path("/invoke/{functionName}")
@Path("/function/invoke/{functionName}")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String invoke(byte[] message, @PathParam("functionName") String functionName) throws Exception {
public String invokeFunction(byte[] message, @PathParam("functionName") String functionName) {
return producerTemplate.requestBody(
componentUri(functionName, Lambda2Operations.invokeFunction),
message,
String.class);
}

@Path("/delete/{functionName}")
@Path("/function/delete/{functionName}")
@DELETE
@Produces(MediaType.APPLICATION_JSON)
public void delete(@PathParam("functionName") String functionName) throws Exception {
public void delete(@PathParam("functionName") String functionName) {
producerTemplate.requestBody(
componentUri(functionName, Lambda2Operations.deleteFunction),
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Aws2LambdaTest {
private static final Logger LOG = Logger.getLogger(Aws2LambdaTest.class);

@Test
public void e2e() {
public void performingOperationsOnLambdaFunctionShouldSucceed() {
final String functionName = "cqFunction" + java.util.UUID.randomUUID().toString().replace("-", "");
final String name = "Joe " + java.util.UUID.randomUUID().toString().replace("-", "");

Expand All @@ -53,29 +53,43 @@ public void e2e() {
() -> {
ExtractableResponse<?> response = RestAssured.given()
.contentType("application/zip")
.body(createFunctionZip())
.post("/aws2-lambda/create/" + functionName)
.body(createInitialLambdaFunctionZip())
.post("/aws2-lambda/function/create/" + functionName)
.then()
.extract();
switch (response.statusCode()) {
case 201:
LOG.infof("Function %s created", functionName);
LOG.infof("Lambda function %s created", functionName);
return true;
case 400:
LOG.infof("Could not create function %s yet (will retry): %d %s", functionName,
LOG.infof("Could not create Lambda function %s yet (will retry): %d %s", functionName,
response.statusCode(),
response.body().asString());
return false;
default:
throw new RuntimeException(
"Unexpected status from /aws2-lambda/create " + response.statusCode() + " "
"Unexpected status from /aws2-lambda/function/create " + response.statusCode() + " "
+ response.body().asString());
}
});

RestAssured.given()
.accept(ContentType.JSON)
.get("/aws2-lambda/listFunctions")
.get("/aws2-lambda/function/get/" + functionName)
.then()
.statusCode(200)
.body(Matchers.is(functionName));

RestAssured.given()
.contentType("application/zip")
.body(createUpdatedLambdaFunctionZip())
.put("/aws2-lambda/function/update/" + functionName)
.then()
.statusCode(200);

RestAssured.given()
.accept(ContentType.JSON)
.get("/aws2-lambda/function/list")
.then()
.statusCode(200)
.body("$", Matchers.hasItem(functionName));
Expand All @@ -90,7 +104,7 @@ public void e2e() {
ExtractableResponse<?> response = RestAssured.given()
.contentType(ContentType.JSON)
.body("{ \"firstName\": \"" + name + "\"}")
.post("/aws2-lambda/invoke/" + functionName)
.post("/aws2-lambda/function/invoke/" + functionName)
.then()
.extract();
String format = "Execution of aws2-lambda/invoke/%s returned status %d and content %s";
Expand All @@ -103,30 +117,44 @@ public void e2e() {
return null;
}
},
Matchers.is("Hello " + name));
Matchers.is("Hello updated " + name));

RestAssured.given()
.delete("/aws2-lambda/delete/" + functionName)
.delete("/aws2-lambda/function/delete/" + functionName)
.then()
.statusCode(204);

}

static byte[] createFunctionZip() {
static byte[] createInitialLambdaFunctionZip() {
return createLambdaFunctionZip(INITIAL_FUNCTION_SOURCE);
}

static byte[] createUpdatedLambdaFunctionZip() {
return createLambdaFunctionZip(UPDATED_FUNCTION_SOURCE);
}

static byte[] createLambdaFunctionZip(String source) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream out = new ZipOutputStream(baos)) {
out.putNextEntry(new ZipEntry("index.py"));
out.write(FUNCTION_SOURCE.getBytes(StandardCharsets.UTF_8));
out.write(source.getBytes(StandardCharsets.UTF_8));
out.closeEntry();
} catch (IOException e) {
throw new RuntimeException("Could not create a zip file", e);
}
return baos.toByteArray();
}

private static final String FUNCTION_SOURCE = "def handler(event, context):\n" +
private static final String INITIAL_FUNCTION_SOURCE = "def handler(event, context):\n" +
" message = 'Hello {}'.format(event['firstName'])\n" +
" return {\n" +
" 'greetings' : message\n" +
" }\n";

private static final String UPDATED_FUNCTION_SOURCE = "def handler(event, context):\n" +
" message = 'Hello updated {}'.format(event['firstName'])\n" +
" return {\n" +
" 'greetings' : message\n" +
" }\n";
}