This repository has been archived by the owner on Dec 1, 2022. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the skeleton of an AWS API Gateway + Lambda frontend service
This adds a Spring MVC/REST web service, running as a Lambda function, fronted by API Gateway. See `docs/frontend.md` for an overview of how this works The main moving parts are: - Spring controller from which Swagger model is derived: `com.amazonaws.blox.frontend.controllers.EnvironmentController` - Serverless Application Model template: `frontend-infrastructure/api/template.yml` - Generated Swagger model: `frontend-service/api/swagger.yml` There is some custom build logic in `buildSrc` that takes care of generating a Swagger model from the Spring controller, and to add all the necessary extensions to make it work with API Gateway. This commit does not include the client that gets generated from the API, for ease of reviewing.
- Loading branch information
Showing
35 changed files
with
1,578 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,103 @@ | ||
import groovy.json.JsonSlurper | ||
|
||
group 'com.amazonaws.blox' | ||
version '0.1-SNAPSHOT' | ||
description "Blox: Open Source schedulers for Amazon ECS" | ||
|
||
buildscript { | ||
repositories { | ||
maven { url 'https://plugins.gradle.org/m2/' } | ||
} | ||
|
||
dependencies { | ||
classpath 'com.diffplug.gradle.spotless:spotless:2.4.1' | ||
} | ||
} | ||
|
||
def unformattedProjects = [ | ||
'frontend-infrastructure', | ||
'frontend-service-client' | ||
] | ||
|
||
allprojects { | ||
apply plugin: 'com.diffplug.gradle.spotless' | ||
} | ||
|
||
configure(subprojects.findAll { !unformattedProjects.contains(it.name) }) { | ||
spotless { | ||
java { | ||
googleJavaFormat() | ||
licenseHeaderFile rootProject.file('licenses/license-header.java') | ||
} | ||
} | ||
} | ||
|
||
ext { | ||
// This can be overridden by specifying -PawsProfile=my-other-profile | ||
// on the Gradle command line: | ||
awsProfile = project.hasProperty("awsProfile") ? project.awsProfile : "default" | ||
println("Profile: ${awsProfile}") | ||
|
||
awsCli = "/usr/local/bin/aws" | ||
awsRegion = "us-west-2" | ||
awsPrefix = System.getenv("USER") | ||
|
||
stackName = "${awsPrefix}-blox-frontend-${awsRegion}" | ||
s3BucketName = "${stackName}-${awsProfile}" | ||
stageName = "Beta" | ||
|
||
sdkZip = file("${buildDir}/java-sdk-${version}.zip") | ||
} | ||
|
||
def aws(... args) { | ||
return [awsCli, "--profile", awsProfile, "--region", awsRegion, *args] | ||
} | ||
|
||
task downloadClient() { | ||
group "codegen" | ||
description "Download a new version of the SDK for the currently deployed stack." | ||
|
||
def deployTask = tasks.getByPath(":frontend-infrastructure:deploy") | ||
|
||
inputs.file deployTask | ||
outputs.file sdkZip | ||
|
||
doLast { | ||
sdkZip.parentFile.mkdirs() | ||
|
||
def stackOutputs = new JsonSlurper().parse(deployTask.outputs.files.singleFile) | ||
|
||
def parameters = [ | ||
"service.name=Blox", | ||
"java.package-name=com.amazonaws.blox", | ||
"java.build-system=gradle", | ||
"java.group-id=${project.group}", | ||
"java.artifact-id=frontend-service-client", | ||
"java.artifact-version=${project.version}", | ||
].join(",") | ||
|
||
exec { | ||
commandLine aws("apigateway", "get-sdk", | ||
"--rest-api-id", stackOutputs.ApiId, | ||
"--stage-name", stageName, | ||
"--sdk-type", "java", | ||
"--parameters", parameters, | ||
sdkZip) | ||
} | ||
} | ||
} | ||
|
||
task updateClient(type: Copy, dependsOn: downloadClient) { | ||
group "codegen" | ||
description "Unpack the client for the currently deployed stack into the blox-client subproject." | ||
|
||
ext.tmpDir = file("${buildDir}/tmp/sdk") | ||
|
||
from zipTree(sdkZip) | ||
into tmpDir | ||
|
||
doLast { | ||
file("frontend-service-client").deleteDir() | ||
file("${tmpDir}/generated-code").renameTo(file("frontend-service-client")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,20 @@ | ||
description "Custom build logic for building Blox" | ||
|
||
apply plugin: 'java' | ||
|
||
sourceCompatibility = 1.8 | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
compile gradleApi() | ||
compile localGroovy() | ||
|
||
compile 'com.github.kongchen:swagger-maven-plugin:+' | ||
|
||
compileOnly 'org.projectlombok:lombok:1.16.16' | ||
|
||
testCompile group: 'junit', name: 'junit', version: '4.12' | ||
} |
80 changes: 80 additions & 0 deletions
80
buildSrc/src/main/java/com/amazonaws/blox/swagger/ApiGatewayExtensionsFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). You may | ||
* not use this file except in compliance with the License. A copy of the | ||
* License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0/ | ||
* | ||
* or in the "LICENSE" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
package com.amazonaws.blox.swagger; | ||
|
||
import io.swagger.models.Operation; | ||
import io.swagger.models.Path; | ||
import io.swagger.models.Swagger; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import lombok.AllArgsConstructor; | ||
import org.gradle.api.tasks.Input; | ||
|
||
/** | ||
* Add API Gateway extensions to all operations of a swagger spec. | ||
* | ||
* <p>This will add the necessary x-amazon-apigateway-integration section to all operations in a | ||
* Swagger spec to correctly proxy all requests to a single lambda function. | ||
* | ||
* <p>TODO Move everything in com.amazonaws.blox.swagger to a separate project | ||
*/ | ||
@AllArgsConstructor | ||
public class ApiGatewayExtensionsFilter implements SwaggerFilter { | ||
/** | ||
* The template for the Lambda function name to proxy to, in Cloudformation's Fn::Sub syntax. | ||
* | ||
* <p>A typical format for this is: | ||
* | ||
* <p>arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambdaFunction.Arn}/invocations | ||
*/ | ||
@Input private final String lambdaFunctionArnTemplate; | ||
|
||
public Map<String, Object> defaultExtensions() { | ||
Map<String, Object> extensions = new HashMap<>(); | ||
|
||
extensions.put("passthroughBehavior", "when_no_match"); | ||
extensions.put("httpMethod", "POST"); | ||
extensions.put("type", "aws_proxy"); | ||
|
||
extensions.put("uri", sub(lambdaFunctionArnTemplate)); | ||
|
||
return extensions; | ||
} | ||
|
||
@Override | ||
public void apply(Swagger swagger) { | ||
Map<String, Object> extensions = defaultExtensions(); | ||
|
||
for (Path path : swagger.getPaths().values()) { | ||
for (Operation operation : path.getOperations()) { | ||
operation.setVendorExtension("x-amazon-apigateway-integration", extensions); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Create a Fn::Sub node with the given template as contents. | ||
* | ||
* <p>This is to support using the CloudFormation Fn::Sub intrinsic function in the swagger | ||
* definition. Using sub("foo${AWS::Region}") for example, would emit {"Fn::Sub": | ||
* "foo${AWS::Region}"} in the template. | ||
*/ | ||
Map<String, String> sub(String template) { | ||
Map<String, String> map = new HashMap<>(); | ||
map.put("Fn::Sub", template); | ||
|
||
return map; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
buildSrc/src/main/java/com/amazonaws/blox/swagger/GenerationTimestampFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). You may | ||
* not use this file except in compliance with the License. A copy of the | ||
* License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0/ | ||
* | ||
* or in the "LICENSE" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
package com.amazonaws.blox.swagger; | ||
|
||
import io.swagger.models.Swagger; | ||
import java.time.Instant; | ||
|
||
/** | ||
* Add a timestamp to a Swagger spec as an 'x-generated-at' extended property. | ||
* | ||
* <p>TODO Move everything in com.amazonaws.blox.swagger to a separate project | ||
*/ | ||
public class GenerationTimestampFilter implements SwaggerFilter { | ||
@Override | ||
public void apply(Swagger swagger) { | ||
swagger.setVendorExtension("x-generated-at", Instant.now().toString()); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
buildSrc/src/main/java/com/amazonaws/blox/swagger/SwaggerFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). You may | ||
* not use this file except in compliance with the License. A copy of the | ||
* License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0/ | ||
* | ||
* or in the "LICENSE" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
package com.amazonaws.blox.swagger; | ||
|
||
import io.swagger.models.Swagger; | ||
|
||
/** | ||
* A filter that can apply arbitrary changes to a Swagger model | ||
* | ||
* <p>Implementations of this interface are wired up into {@link | ||
* com.amazonaws.blox.tasks.GenerateSwaggerModel} to post-process the Swagger model it generates | ||
* from source code. | ||
* | ||
* <p>TODO Move everything in com.amazonaws.blox.swagger to a separate project | ||
*/ | ||
public interface SwaggerFilter { | ||
void apply(Swagger swagger); | ||
} |
Oops, something went wrong.