github.com/mweagle/Sparta@v1.15.0/docs_source/content/example_service/step1.md (about) 1 --- 2 date: 2017-10-03 07:15:40 3 title: Overview 4 weight: 10 5 --- 6 7 Sparta is a framework for developing and deploying **go** based AWS Lambda-backed microservices. To help understand what that means we'll begin with a "Hello World" lambda function and eventually deploy that to AWS. Note that we're not going to handle all error cases to keep the example code to a minimum. 8 9 {{% notice warning %}} 10 Please be aware that running Lambda functions may incur [costs](https://aws.amazon.com/lambda/pricing"). Be sure to decommission Sparta stacks after you are finished using them (via the `delete` command line option) to avoid unwanted charges. It's likely that you'll be well under the free tier, but secondary AWS resources provisioned during development (eg, Kinesis streams) are not pay-per-invocation. 11 {{% /notice %}} 12 13 # Preconditions 14 15 Sparta uses the [AWS SDK for Go](http://aws.amazon.com/sdk-for-go/) to interact with AWS APIs. Before you get started, ensure that you've properly configured the [SDK credentials](https://github.com/aws/aws-sdk-go/wiki/configuring-sdk). 16 17 Note that you must use an AWS region that supports Lambda. Consult the [Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) page for the most up to date release information. 18 19 # Lambda Definition 20 21 The first place to start is with the lambda function definition. 22 23 ```go 24 // Standard AWS λ function 25 func helloWorld(ctx context.Context) (string, error) { 26 return "Hello World!", nil 27 } 28 ``` 29 30 The `ctx` parameter includes the following entries: 31 32 - The [AWS LambdaContext](https://godoc.org/github.com/aws/aws-lambda-go/lambdacontext#FromContext) 33 - A [\*logrus.Logger](https://github.com/sirupsen/logrus) instance (`sparta.ContextKeyLogger`) 34 - A per-request annotated [\*logrus.Entry](https://godoc.org/github.com/sirupsen/logrus#Entry) instance (`sparta.ContextKeyRequestLogger`) 35 36 # Creation 37 38 The next step is to create a Sparta-wrapped version of the `helloWorld` function. 39 40 ```go 41 var lambdaFunctions []*sparta.LambdaAWSInfo 42 helloWorldFn, _ := sparta.NewAWSLambda("Hello World", 43 helloWorld, 44 sparta.IAMRoleDefinition{}) 45 ``` 46 47 We first declare an empty slice `lambdaFunctions` to which all our service's lambda functions will be appended. The next step is to register a new lambda target via [NewAWSLambda](https://godoc.org/github.com/mweagle/Sparta#NewAWSLambda). `NewAWSLambda` accepts three parameters: 48 49 - `string`: The function name. A sanitized version of this value is used as the [FunctionName](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-functionname). 50 - `func(...)`: The **go** function to execute. 51 - `string|IAMRoleDefinition` : _Either_ a string literal that refers to a pre-existing IAM Role under which the lambda function will be executed, _OR_ a `sparta.IAMRoleDefinition` value that will be provisioned as part of this deployment and used as the execution role for the lambda function. 52 - In this example, we're defining a new `IAMRoleDefinition` as part of the stack. This role definition will automatically include privileges for actions such as CloudWatch logging, and since our function doesn't access any additional AWS services that's all we need. 53 54 # Delegation 55 56 The final step is to define a Sparta service under your application's `main` package and provide the non-empty slice of lambda functions: 57 58 ```go 59 sparta.Main("MyHelloWorldStack", 60 "Simple Sparta application that demonstrates core functionality", 61 lambdaFunctions, 62 nil, 63 nil) 64 ``` 65 66 `sparta.Main` accepts five parameters: 67 68 - `serviceName` : The string to use as the CloudFormation stackName. Note that there can be only a single stack with this name within a given AWS account, region pair. 69 - The `serviceName` is used as the stable identifier to determine when updates should be applied rather than new stacks provisioned, as well as the target of a `delete` command line request. 70 - Consider using [UserScopedStackName](https://godoc.org/github.com/mweagle/Sparta/aws/cloudformation#UserScopedStackName) to generate unique, stable names across a team. 71 - `serviceDescription`: An optional string used to describe the stack. 72 - `[]*LambdaAWSInfo` : Slice of `sparta.lambdaAWSInfo` that define a service 73 - `*API` : Optional pointer to data if you would like to provision and associate an API Gateway with the set of lambda functions. 74 - We'll walk through how to do that in [another section](/reference/apigateway/apigateway/), but for now our lambda function will only be accessible via the AWS SDK or Console. 75 - `*S3Site` : Optional pointer to data if you would like to provision an [static website on S3](http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html), initialized with local resources. 76 - We'll walk through how to do that in [another section](/reference/s3site), but for now our lambda function will only be accessible via the AWS SDK or Console. 77 78 Delegating `main()` to `Sparta.Main()` transforms the set of lambda functions into a standalone executable with several command line options. Run `go run main.go --help` to see the available options. 79 80 # Putting It Together 81 82 Putting everything together, and including the necessary imports, we have: 83 84 ```go 85 // File: main.go 86 package main 87 88 import ( 89 "context" 90 91 sparta "github.com/mweagle/Sparta" 92 ) 93 94 // Standard AWS λ function 95 func helloWorld(ctx context.Context) (string, error) { 96 return "Hello World!", nil 97 } 98 99 func main() { 100 var lambdaFunctions []*sparta.LambdaAWSInfo 101 helloWorldFn, _ := sparta.NewAWSLambda("Hello World", 102 helloWorld, 103 sparta.IAMRoleDefinition{}) 104 lambdaFunctions = append(lambdaFunctions, helloWorldFn) 105 sparta.Main("MyHelloWorldStack", 106 "Simple Sparta application that demonstrates core functionality", 107 lambdaFunctions, 108 nil, 109 nil) 110 } 111 ``` 112 113 # Running It 114 115 Next download the Sparta dependencies via: 116 117 - `go get ./...` 118 119 in the directory that you saved _main.go_. Once the packages are downloaded, first get a view of what's going on by the `describe` command (replacing `$S3_BUCKET` with an S3 bucket you own): 120 121 ```nohighlight 122 $ go run main.go --level info describe --out ./graph.html --s3Bucket $S3_BUCKET 123 INFO[0000] ════════════════════════════════════════════════ 124 INFO[0000] ╔═╗╔═╗╔═╗╦═╗╔╦╗╔═╗ Version : 1.13.0 125 INFO[0000] ╚═╗╠═╝╠═╣╠╦╝ ║ ╠═╣ SHA : 03cdb90 126 INFO[0000] ╚═╝╩ ╩ ╩╩╚═ ╩ ╩ ╩ Go : go1.13.3 127 INFO[0000] ════════════════════════════════════════════════ 128 INFO[0000] Service: MyHelloWorldStack-123412341234 LinkFlags= Option=describe UTC="2019-12-07T20:01:48Z" 129 INFO[0000] ════════════════════════════════════════════════ 130 INFO[0000] Provisioning service BuildID=none CodePipelineTrigger= InPlaceUpdates=false NOOP=true Tags= 131 INFO[0000] Verifying IAM Lambda execution roles 132 INFO[0000] IAM roles verified Count=1 133 INFO[0000] Skipping S3 preconditions check due to -n/-noop flag Bucket=weagle Region=us-west-2 VersioningEnabled=false 134 INFO[0000] Running `go generate` 135 INFO[0000] Compiling binary Name=Sparta.lambda.amd64 136 INFO[0001] Creating code ZIP archive for upload TempName=./.sparta/MyHelloWorldStack_123412341234-code.zip 137 INFO[0001] Lambda code archive size Size="24 MB" 138 INFO[0001] Skipping S3 upload due to -n/-noop flag Bucket=weagle File=MyHelloWorldStack_123412341234-code.zip Key=MyHelloWorldStack-123412341234/MyHelloWorldStack_123412341234-code-ec0d6f8bae7b6a7abaa77db394c96265e213d20d.zip Size="24 MB" 139 INFO[0001] Skipping Stack creation due to -n/-noop flag Bucket=weagle TemplateName=MyHelloWorldStack_123412341234-cftemplate.json 140 INFO[0001] ════════════════════════════════════════════════ 141 INFO[0001] MyHelloWorldStack-123412341234 Summary 142 INFO[0001] ════════════════════════════════════════════════ 143 INFO[0001] Verifying IAM roles Duration (s)=0 144 INFO[0001] Verifying AWS preconditions Duration (s)=0 145 INFO[0001] Creating code bundle Duration (s)=1 146 INFO[0001] Uploading code Duration (s)=0 147 INFO[0001] Ensuring CloudFormation stack Duration (s)=0 148 INFO[0001] Total elapsed time Duration (s)=1 149 ``` 150 151 Then open _graph.html_ in your browser (also linked [here](/images/overview/graph.html) ) to see what will be provisioned. 152 153 Since everything looks good, we'll provision the stack via `provision` and verify the lambda function. Note that the `$S3_BUCKET` value must be an S3 bucket to which you have write access since Sparta uploads the lambda package and CloudFormation template to that bucket as part of provisioning. 154 155 ```nohighlight 156 INFO[0000] ════════════════════════════════════════════════ 157 INFO[0000] ╔═╗╔═╗╔═╗╦═╗╔╦╗╔═╗ Version : 1.13.0 158 INFO[0000] ╚═╗╠═╝╠═╣╠╦╝ ║ ╠═╣ SHA : 03cdb90 159 INFO[0000] ╚═╝╩ ╩ ╩╩╚═ ╩ ╩ ╩ Go : go1.13.3 160 INFO[0000] ════════════════════════════════════════════════ 161 INFO[0000] Service: MyHelloWorldStack-123412341234 LinkFlags= Option=provision UTC="2019-12-07T19:53:24Z" 162 INFO[0000] ════════════════════════════════════════════════ 163 INFO[0000] Using `git` SHA for StampedBuildID Command="git rev-parse HEAD" SHA=b114e329ed37b532e1f7d2e727aa8211d9d5889c 164 INFO[0000] Provisioning service BuildID=b114e329ed37b532e1f7d2e727aa8211d9d5889c CodePipelineTrigger= InPlaceUpdates=false NOOP=false Tags= 165 INFO[0000] Verifying IAM Lambda execution roles 166 INFO[0000] IAM roles verified Count=1 167 INFO[0000] Checking S3 versioning Bucket=weagle VersioningEnabled=true 168 INFO[0000] Checking S3 region Bucket=weagle Region=us-west-2 169 INFO[0000] Running `go generate` 170 INFO[0001] Compiling binary Name=Sparta.lambda.amd64 171 INFO[0002] Creating code ZIP archive for upload TempName=./.sparta/MyHelloWorldStack_123412341234-code.zip 172 INFO[0002] Lambda code archive size Size="24 MB" 173 INFO[0002] Uploading local file to S3 Bucket=weagle Key=MyHelloWorldStack-123412341234/MyHelloWorldStack_123412341234-code.zip Path=./.sparta/MyHelloWorldStack_123412341234-code.zip Size="24 MB" 174 INFO[0011] Uploading local file to S3 Bucket=weagle Key=MyHelloWorldStack-123412341234/MyHelloWorldStack_123412341234-cftemplate.json Path=./.sparta/MyHelloWorldStack_123412341234-cftemplate.json Size="2.2 kB" 175 INFO[0011] Issued CreateChangeSet request StackName=MyHelloWorldStack-123412341234 176 INFO[0016] Issued ExecuteChangeSet request StackName=MyHelloWorldStack-123412341234 177 INFO[0033] CloudFormation Metrics ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬ 178 INFO[0033] Operation duration Duration=8.26s Resource=MyHelloWorldStack-123412341234 Type="AWS::CloudFormation::Stack" 179 INFO[0033] Operation duration Duration=1.35s Resource=HelloWorldLambda80576f7b21690b0cb485a6b69c927aac972cd693 Type="AWS::Lambda::Function" 180 INFO[0033] Stack provisioned CreationTime="2019-11-28 00:05:04.508 +0000 UTC" StackId="arn:aws:cloudformation:us-west-2:123412341234:stack/MyHelloWorldStack-123412341234/bab01fb0-1172-11ea-84a9-0ab88639bbc6" StackName=MyHelloWorldStack-123412341234 181 INFO[0033] ════════════════════════════════════════════════ 182 INFO[0033] MyHelloWorldStack-123412341234 Summary 183 INFO[0033] ════════════════════════════════════════════════ 184 INFO[0033] Verifying IAM roles Duration (s)=0 185 INFO[0033] Verifying AWS preconditions Duration (s)=0 186 INFO[0033] Creating code bundle Duration (s)=1 187 INFO[0033] Uploading code Duration (s)=9 188 INFO[0033] Ensuring CloudFormation stack Duration (s)=22 189 INFO[0033] Total elapsed time Duration (s)=33 190 ``` 191 192 Once the stack has been provisioned (`CREATE_COMPLETE`), login to the AWS console and navigate to the Lambda section. 193 194 # Testing 195 196 Find your Lambda function in the list of AWS Lambda functions and click the hyperlink. The display name will be prefixed by the name of your stack (_MyHelloWorldStack_ in our example): 197 198  199 200 On the Lambda details page, click the _Test_ button: 201 202  203 204 Accept the and name the _Hello World_ event template sample (our Lambda function doesn't consume the event data) and click _Save and test_. The execution result pane should display something similar to: 205 206  207 208 # Cleaning Up 209 210 To prevent unauthorized usage and potential charges, make sure to `delete` your stack before moving on: 211 212 ```nohighlight 213 $ go run main.go delete 214 215 INFO[0000] ════════════════════════════════════════════════ 216 INFO[0000] ╔═╗┌─┐┌─┐┬─┐┌┬┐┌─┐ Version : 1.0.2 217 INFO[0000] ╚═╗├─┘├─┤├┬┘ │ ├─┤ SHA : b37b93e 218 INFO[0000] ╚═╝┴ ┴ ┴┴└─ ┴ ┴ ┴ Go : go1.9.2 219 INFO[0000] ════════════════════════════════════════════════ 220 INFO[0000] Service: MyHelloWorldStack LinkFlags= Option=delete UTC="2018-01-27T22:01:59Z" 221 INFO[0000] ════════════════════════════════════════════════ 222 INFO[0000] Stack existence check Exists=true Name=MyHelloWorldStack 223 INFO[0000] Delete request submitted Response="{\n\n}" 224 ``` 225 226 # Conclusion 227 228 Congratulations! You've just deployed your first "serverless" service. The following sections will dive 229 deeper into what's going on under the hood as well as how to integrate your lambda function(s) into the broader AWS landscape. 230 231 # Next Steps 232 233 Walkthrough what Sparta actually does to deploy your application in the [next section](/reference/intro_example/step2/).