/
main.go
128 lines (112 loc) · 4.05 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package main
import (
"context"
"fmt"
"net/http"
"os"
sparta "github.com/mweagle/Sparta"
spartaAPIGateway "github.com/mweagle/Sparta/aws/apigateway"
spartaCF "github.com/mweagle/Sparta/aws/cloudformation"
spartaAWSEvents "github.com/mweagle/Sparta/aws/events"
spartaDecorators "github.com/mweagle/Sparta/decorator"
gocf "github.com/mweagle/go-cloudformation"
"github.com/sirupsen/logrus"
)
////////////////////////////////////////////////////////////////////////////////
// CloudFront settings
const subdomain = "sparta-site"
// The domain managed by Route53.
const domainName = "spartademo.net"
// The site will be available at
// https://sparta-site.spartademo.net
// The S3 bucketname must match the subdomain.domain
// name pattern to serve as a CloudFront Distribution target
var bucketName = fmt.Sprintf("%s.%s", subdomain, domainName)
type helloWorldResponse struct {
Message string
Request spartaAWSEvents.APIGatewayRequest
}
////////////////////////////////////////////////////////////////////////////////
// Hello world event handler
func helloWorld(ctx context.Context,
gatewayEvent spartaAWSEvents.APIGatewayRequest) (interface{}, error) {
logger, loggerOk := ctx.Value(sparta.ContextKeyLogger).(*logrus.Logger)
if loggerOk {
logger.Info("Hello world structured log message")
}
// Return a message, together with the incoming input...
return spartaAPIGateway.NewResponse(http.StatusOK, &helloWorldResponse{
Message: fmt.Sprintf("Hello world 🌏"),
Request: gatewayEvent,
}), nil
}
func spartaHTMLLambdaFunctions(api *sparta.API) []*sparta.LambdaAWSInfo {
var lambdaFunctions []*sparta.LambdaAWSInfo
lambdaFn := sparta.HandleAWSLambda(sparta.LambdaName(helloWorld),
helloWorld,
sparta.IAMRoleDefinition{})
if nil != api {
apiGatewayResource, _ := api.NewResource("/hello", lambdaFn)
// We only return http.StatusOK
apiMethod, apiMethodErr := apiGatewayResource.NewMethod("GET",
http.StatusOK,
http.StatusInternalServerError)
if nil != apiMethodErr {
panic("Failed to create /hello resource: " + apiMethodErr.Error())
}
// The lambda resource only supports application/json Unmarshallable
// requests.
apiMethod.SupportedRequestContentTypes = []string{"application/json"}
}
return append(lambdaFunctions, lambdaFn)
}
////////////////////////////////////////////////////////////////////////////////
// Decorator
func distroHooks(s3Site *sparta.S3Site) *sparta.WorkflowHooks {
// Commented out demonstration of how to front the site
// with a CloudFront distribution.
// Note that provisioning a distribution will incur additional
// costs
hooks := &sparta.WorkflowHooks{}
if os.Getenv("SPARTA_ACM_CLOUDFRONT_ARN") != "" {
siteHookDecorator := spartaDecorators.CloudFrontSiteDistributionDecorator(s3Site,
subdomain,
domainName,
gocf.String(os.Getenv("SPARTA_ACM_CLOUDFRONT_ARN")))
hooks.ServiceDecorators = []sparta.ServiceDecoratorHookHandler{
siteHookDecorator,
}
}
return hooks
}
////////////////////////////////////////////////////////////////////////////////
// Main
func main() {
// Provision an S3 site
s3Site, s3SiteErr := sparta.NewS3Site("./resources")
if s3SiteErr != nil {
panic("Failed to create S3 Site")
}
s3Site.BucketName = gocf.String(bucketName)
// Register the function with the API Gateway
apiStage := sparta.NewStage("v1")
apiGateway := sparta.NewAPIGateway("SpartaHTML", apiStage)
// Enable CORS s.t. the S3 site can access the resources
apiGateway.CORSOptions = &sparta.CORSOptions{
Headers: map[string]interface{}{
"Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Origin": gocf.GetAtt(s3Site.CloudFormationS3ResourceName(), "WebsiteURL"),
},
}
hooks := distroHooks(s3Site)
// Deploy it
stackName := spartaCF.UserScopedStackName("SpartaHTML")
sparta.MainEx(stackName,
fmt.Sprintf("SpartaHTML provisions a static S3 hosted website with an API Gateway resource backed by a custom Lambda function"),
spartaHTMLLambdaFunctions(apiGateway),
apiGateway,
s3Site,
hooks,
false)
}