Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 8ab986a

Browse files
committed
add terratest example
1 parent 701e40c commit 8ab986a

File tree

3 files changed

+270
-0
lines changed

3 files changed

+270
-0
lines changed

src/nav.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ const fullNav: FullNav = {
586586
title: 'AWS API Gateway Throttle',
587587
href: '/guides/terraform/api-gateway-throttle',
588588
},
589+
{
590+
title: 'Testing AWS resources with Terratest',
591+
href: '/guides/terraform/terratest',
592+
},
589593
],
590594
},
591595
],

src/pages/guides/terraform.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ export const description = 'How to work with the Terraform Providers'
2727
name="AWS API Gateway Throttle"
2828
description="Extend the Nitric AWS Terraform provider to set API Gateway throttling limits"
2929
/>
30+
<Guide
31+
customIcon={SiTerraform}
32+
href="/guides/terraform/terratest"
33+
name="Testing AWS resources with Terratest"
34+
description="Use Terratest to validate the infrastructure of a Nitric GO project deployed with Terraform"
35+
/>
3036
</GuidesGrid>
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
export const description =
2+
'Use Terratest to validate the infrastructure of a Nitric GO project deployed with Terraform'
3+
4+
# Testing AWS resources with Terratest
5+
6+
This guide will walk you through adding Terratest to a Nitric project.
7+
8+
## How Terratest works
9+
10+
Terratest is designed to automate the entire process of testing your Terraform code with the following steps:
11+
12+
- Initialize: Terratest will automatically run terraform init to initialize the Terraform working directory.
13+
- Apply: It will then run terraform apply to deploy the infrastructure as defined in your Terraform code.
14+
- Assert: The test script will then run assertions to check that the infrastructure was created as expected.
15+
- Teardown: Finally, it will run terraform destroy to tear down the infrastructure after the test completes.
16+
17+
## What we'll be doing
18+
19+
1. Create and set up your application.
20+
2. Deploying to AWS with a Terraform provider.
21+
3. Add and execute Terratest
22+
23+
## Create and set up your application.
24+
25+
Our sample project creates a real-time communication service using websockets and a key-value store for connections.
26+
27+
We intend to deploy to AWS and will use Terratest to ensure that the following:
28+
29+
- **API Gateway WebSocket**: Confirm that the webSocket endpoint is correctly configured for real-time communication.
30+
- **DynamoDB Table**: Verify that the key-value store for connections is created and operational.
31+
- **IAM Roles**: Ensure that permissions for interacting with AWS services are correctly set up.
32+
33+
Let's start by creating a new project for our application.
34+
35+
```bash
36+
nitric new my-websocket-app go-starter
37+
```
38+
39+
### Application code
40+
41+
Replace the contents of `services\hello.go` with our websockets application.
42+
43+
```go
44+
package main
45+
46+
import (
47+
"context"
48+
"fmt"
49+
50+
"github.com/nitrictech/go-sdk/handler"
51+
"github.com/nitrictech/go-sdk/nitric"
52+
)
53+
54+
func main() {
55+
// Create a WebSocket endpoint named "public".
56+
ws, err := nitric.NewWebsocket("public")
57+
if err != nil {
58+
fmt.Println("Error creating WebSocket:", err)
59+
return
60+
}
61+
62+
// Initialize a KV store named "connections" with Get, Set, and Delete permissions.
63+
connections, err := nitric.NewKv("connections").Allow(nitric.KvStoreGet, nitric.KvStoreSet, nitric.KvStoreDelete)
64+
if err != nil {
65+
fmt.Println("Error creating KV store:", err)
66+
return
67+
}
68+
69+
// Handle new WebSocket connections by storing the connection ID in the KV store.
70+
ws.On(handler.WebsocketConnect, func(ctx *handler.WebsocketContext, next handler.WebsocketHandler) (*handler.WebsocketContext, error) {
71+
err := connections.Set(context.TODO(), ctx.Request.ConnectionID(), map[string]interface{}{
72+
"connectionId": ctx.Request.ConnectionID(),
73+
})
74+
if err != nil {
75+
return ctx, err
76+
}
77+
78+
return next(ctx)
79+
})
80+
81+
// Handle WebSocket disconnections by removing the connection ID from the KV store.
82+
ws.On(handler.WebsocketDisconnect, func(ctx *handler.WebsocketContext, next handler.WebsocketHandler) (*handler.WebsocketContext, error) {
83+
err := connections.Delete(context.TODO(), ctx.Request.ConnectionID())
84+
if err != nil {
85+
return ctx, err
86+
}
87+
88+
return next(ctx)
89+
})
90+
91+
// Handle incoming messages by broadcasting them to all other connections.
92+
ws.On(handler.WebsocketMessage, func(ctx *handler.WebsocketContext, next handler.WebsocketHandler) (*handler.WebsocketContext, error) {
93+
connectionStream, err := connections.Keys(context.TODO())
94+
if err != nil {
95+
return ctx, err
96+
}
97+
98+
senderId := ctx.Request.ConnectionID()
99+
100+
for {
101+
connectionId, err := connectionStream.Recv()
102+
if err != nil {
103+
break
104+
}
105+
106+
if connectionId == senderId {
107+
continue
108+
}
109+
110+
message := fmt.Sprintf("%s: %s", senderId, ctx.Request.Message())
111+
err = ws.Send(context.TODO(), connectionId, []byte(message))
112+
if err != nil {
113+
return ctx, err
114+
}
115+
}
116+
117+
return next(ctx)
118+
})
119+
120+
// Start the Nitric service to handle WebSocket events.
121+
if err := nitric.Run(); err != nil {
122+
fmt.Println("Error running Nitric service:", err)
123+
}
124+
}
125+
```
126+
127+
## Deploying to AWS with a Terraform provider
128+
129+
To deploy your application with Terraform you'll need to use Nitric's Terraform providers. You can learn more about using Nitric with Terraform [here](/reference/providers/terraform).
130+
131+
```
132+
nitric stack new dev aws-tf
133+
```
134+
135+
Update this newly created stack file to include your target region:
136+
137+
```yaml
138+
# The nitric provider to use
139+
provider: nitric/[email protected]
140+
141+
# The target aws region to deploy to
142+
region: us-east-2
143+
```
144+
145+
The Nitric Terraform providers are currently in preview, to enable them you'll need to enable beta-providers in your Nitric project. You can do this by adding the following to your project's nitric.yaml file:
146+
147+
```
148+
preview:
149+
- beta-providers
150+
```
151+
152+
Once you've created your Nitric stack, you can generate the Terraform code by running the following command:
153+
154+
```
155+
nitric up
156+
```
157+
158+
This will generate the Terraform code for your Nitric application into a folder named cdktf.out by default. You can change this via the outdir property and inspect the code before deploying.
159+
160+
## Add and execute Terratest
161+
162+
Add the necessary dependencies for Terratest:
163+
164+
```bash
165+
go get github.com/gruntwork-io/terratest/modules/terraform
166+
go get github.com/stretchr/testify/assert
167+
go get github.com/aws/aws-sdk-go/aws
168+
go get github.com/aws/aws-sdk-go/aws/session
169+
go get github.com/aws/aws-sdk-go/service/apigatewayv2
170+
go get github.com/aws/aws-sdk-go/service/dynamodb
171+
go get github.com/aws/aws-sdk-go/service/iam
172+
```
173+
174+
### Create the Test File
175+
176+
Create a new file named `test_terraform_resources.go` in your project’s test directory:
177+
178+
```bash
179+
mkdir -p test
180+
touch test/test_terraform_resources.go
181+
```
182+
183+
Add the following code to `test_terraform_resources.go`:
184+
185+
```go
186+
package test
187+
188+
import (
189+
"testing"
190+
"github.com/aws/aws-sdk-go/aws"
191+
"github.com/aws/aws-sdk-go/aws/session"
192+
"github.com/aws/aws-sdk-go/service/apigatewayv2"
193+
"github.com/aws/aws-sdk-go/service/dynamodb"
194+
"github.com/aws/aws-sdk-go/service/iam"
195+
"github.com/gruntwork-io/terratest/modules/terraform"
196+
"github.com/stretchr/testify/assert"
197+
)
198+
199+
func TestTerraformResources(t *testing.T) {
200+
// Set Terraform options, specifying the directory with your Terraform configuration
201+
terraformOptions := &terraform.Options{
202+
TerraformDir: "../cdktf.out/stacks/go-realtime-dev",
203+
}
204+
205+
// Ensure resources are destroyed after test completion
206+
defer terraform.Destroy(t, terraformOptions)
207+
208+
// Initialize and apply the Terraform configuration
209+
terraform.InitAndApply(t, terraformOptions)
210+
211+
// Initialize AWS session for interacting with AWS services
212+
sess := session.Must(session.NewSession(&aws.Config{Region: aws.String("us-east-2")}))
213+
214+
// Test DynamoDB table creation (key-value store)
215+
dynamoClient := dynamodb.New(sess)
216+
tableName := "connections" // Name of the DynamoDB table to check
217+
_, err := dynamoClient.DescribeTable(&dynamodb.DescribeTableInput{
218+
TableName: aws.String(tableName),
219+
})
220+
assert.NoError(t, err, "Expected DynamoDB table 'connections' to be created")
221+
222+
// Test IAM role creation
223+
iamClient := iam.New(sess)
224+
roleName := "go-realtime_services-hello" // Name of the IAM role to check
225+
_, err = iamClient.GetRole(&iam.GetRoleInput{
226+
RoleName: aws.String(roleName),
227+
})
228+
assert.NoError(t, err, "Expected IAM role 'go-realtime_services-hello' to be created")
229+
230+
// Test API gateway webSocket creation
231+
apiClient := apigatewayv2.New(sess)
232+
apiName := "public" // Name of the API Gateway WebSocket to check
233+
result, err := apiClient.GetApis(&apigatewayv2.GetApisInput{})
234+
assert.NoError(t, err)
235+
found := false
236+
for _, api := range result.Items {
237+
if *api.Name == apiName {
238+
found = true
239+
break
240+
}
241+
}
242+
assert.True(t, found, "Expected API Gateway WebSocket 'public' to be created")
243+
}
244+
```
245+
246+
### Run the tests
247+
248+
To run the tests, navigate to your project’s root directory and execute the Go test command:
249+
250+
```bash
251+
go test -v ./test
252+
```
253+
254+
This will:
255+
256+
1. Deploy the infrastructure using Terraform.
257+
2. Validate the creation of the DynamoDB table, IAM role, and API Gateway WebSocket.
258+
3. Clean up the infrastructure after testing.
259+
260+
The output should confirm the successful creation and validation of each resource.

0 commit comments

Comments
 (0)