This repository was archived by the owner on May 20, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 17
add terratest guide #605
Closed
Closed
add terratest guide #605
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 |
---|---|---|
|
@@ -201,6 +201,7 @@ monorepos | |
decrypts | ||
deploytf | ||
href | ||
init | ||
|
||
^.+[-:_]\w+$ | ||
[a-z]+([A-Z0-9]|[A-Z0-9]\w+) | ||
|
This file contains hidden or 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 hidden or 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 hidden or 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,260 @@ | ||
export const description = | ||
'Use Terratest to validate the infrastructure of a Nitric GO project deployed with Terraform' | ||
|
||
# Testing AWS resources with Terratest | ||
|
||
This guide will walk you through adding Terratest to a Nitric project. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
## How Terratest works | ||
|
||
Terratest is designed to automate the entire process of testing your Terraform code with the following steps: | ||
|
||
- Initialize: Terratest will automatically run terraform init to initialize the Terraform working directory. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
- Apply: It will then run terraform apply to deploy the infrastructure as defined in your Terraform code. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
- Assert: The test script will then run assertions to check that the infrastructure was created as expected. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
- Teardown: Finally, it will run terraform destroy to tear down the infrastructure after the test completes. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
## What we'll be doing | ||
|
||
1. Create and set up your application. | ||
2. Deploying to AWS with a Terraform provider. | ||
3. Add and execute Terratest | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
## Create and set up your application. | ||
|
||
Our sample project creates a real-time communication service using websockets and a key-value store for connections. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
We intend to deploy to AWS and will use Terratest to ensure that the following: | ||
|
||
- **API Gateway WebSocket**: Confirm that the webSocket endpoint is correctly configured for real-time communication. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
- **DynamoDB Table**: Verify that the key-value store for connections is created and operational. | ||
- **IAM Roles**: Ensure that permissions for interacting with AWS services are correctly set up. | ||
|
||
Let's start by creating a new project for our application. | ||
|
||
```bash | ||
nitric new my-websocket-app go-starter | ||
``` | ||
|
||
### Application code | ||
|
||
Replace the contents of `services\hello.go` with our websockets application. | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/nitrictech/go-sdk/handler" | ||
"github.com/nitrictech/go-sdk/nitric" | ||
) | ||
|
||
func main() { | ||
// Create a WebSocket endpoint named "public". | ||
ws, err := nitric.NewWebsocket("public") | ||
if err != nil { | ||
fmt.Println("Error creating WebSocket:", err) | ||
return | ||
} | ||
|
||
// Initialize a KV store named "connections" with Get, Set, and Delete permissions. | ||
connections, err := nitric.NewKv("connections").Allow(nitric.KvStoreGet, nitric.KvStoreSet, nitric.KvStoreDelete) | ||
if err != nil { | ||
fmt.Println("Error creating KV store:", err) | ||
return | ||
} | ||
|
||
// Handle new WebSocket connections by storing the connection ID in the KV store. | ||
ws.On(handler.WebsocketConnect, func(ctx *handler.WebsocketContext, next handler.WebsocketHandler) (*handler.WebsocketContext, error) { | ||
err := connections.Set(context.TODO(), ctx.Request.ConnectionID(), map[string]interface{}{ | ||
"connectionId": ctx.Request.ConnectionID(), | ||
}) | ||
if err != nil { | ||
return ctx, err | ||
} | ||
|
||
return next(ctx) | ||
}) | ||
|
||
// Handle WebSocket disconnections by removing the connection ID from the KV store. | ||
ws.On(handler.WebsocketDisconnect, func(ctx *handler.WebsocketContext, next handler.WebsocketHandler) (*handler.WebsocketContext, error) { | ||
err := connections.Delete(context.TODO(), ctx.Request.ConnectionID()) | ||
if err != nil { | ||
return ctx, err | ||
} | ||
|
||
return next(ctx) | ||
}) | ||
|
||
// Handle incoming messages by broadcasting them to all other connections. | ||
ws.On(handler.WebsocketMessage, func(ctx *handler.WebsocketContext, next handler.WebsocketHandler) (*handler.WebsocketContext, error) { | ||
connectionStream, err := connections.Keys(context.TODO()) | ||
if err != nil { | ||
return ctx, err | ||
} | ||
|
||
senderId := ctx.Request.ConnectionID() | ||
|
||
for { | ||
connectionId, err := connectionStream.Recv() | ||
if err != nil { | ||
break | ||
} | ||
|
||
if connectionId == senderId { | ||
continue | ||
} | ||
|
||
message := fmt.Sprintf("%s: %s", senderId, ctx.Request.Message()) | ||
err = ws.Send(context.TODO(), connectionId, []byte(message)) | ||
if err != nil { | ||
return ctx, err | ||
} | ||
} | ||
|
||
return next(ctx) | ||
}) | ||
|
||
// Start the Nitric service to handle WebSocket events. | ||
if err := nitric.Run(); err != nil { | ||
fmt.Println("Error running Nitric service:", err) | ||
} | ||
} | ||
``` | ||
|
||
## Deploying to AWS with a Terraform provider | ||
|
||
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). | ||
|
||
``` | ||
nitric stack new dev aws-tf | ||
``` | ||
|
||
Update this newly created stack file to include your target region: | ||
|
||
```yaml | ||
# The nitric provider to use | ||
provider: nitric/[email protected] | ||
|
||
# The target aws region to deploy to | ||
region: us-east-2 | ||
``` | ||
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: | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
``` | ||
preview: | ||
- beta-providers | ||
``` | ||
Once you've created your Nitric stack, you can generate the Terraform code by running the following command: | ||
``` | ||
nitric up | ||
``` | ||
|
||
This will generate the Terraform code for your Nitric application into a folder named cdktf.out by default. | ||
raksiv marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
## Add and execute Terratest | ||
|
||
Add the necessary dependencies for Terratest: | ||
|
||
```bash | ||
go get github.com/gruntwork-io/terratest/modules/terraform | ||
go get github.com/stretchr/testify/assert | ||
go get github.com/aws/aws-sdk-go/aws | ||
go get github.com/aws/aws-sdk-go/aws/session | ||
go get github.com/aws/aws-sdk-go/service/apigatewayv2 | ||
go get github.com/aws/aws-sdk-go/service/dynamodb | ||
go get github.com/aws/aws-sdk-go/service/iam | ||
``` | ||
|
||
### Create the Test File | ||
|
||
Create a new file named `test_terraform_resources.go` in your project’s test directory: | ||
|
||
```bash | ||
mkdir -p test | ||
touch test/test_terraform_resources.go | ||
``` | ||
|
||
Add the following code to `test_terraform_resources.go`: | ||
|
||
```go | ||
package test | ||
|
||
import ( | ||
"testing" | ||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/session" | ||
"github.com/aws/aws-sdk-go/service/apigatewayv2" | ||
"github.com/aws/aws-sdk-go/service/dynamodb" | ||
"github.com/aws/aws-sdk-go/service/iam" | ||
"github.com/gruntwork-io/terratest/modules/terraform" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestTerraformResources(t *testing.T) { | ||
// Set Terraform options, specifying the directory with your Terraform configuration | ||
terraformOptions := &terraform.Options{ | ||
TerraformDir: "../cdktf.out/stacks/go-realtime-dev", | ||
} | ||
|
||
// Ensure resources are destroyed after test completion | ||
defer terraform.Destroy(t, terraformOptions) | ||
|
||
// Initialize and apply the Terraform configuration | ||
terraform.InitAndApply(t, terraformOptions) | ||
|
||
// Initialize AWS session for interacting with AWS services | ||
sess := session.Must(session.NewSession(&aws.Config{Region: aws.String("us-east-2")})) | ||
|
||
// Test DynamoDB table creation (key-value store) | ||
dynamoClient := dynamodb.New(sess) | ||
tableName := "connections" // Name of the DynamoDB table to check | ||
_, err := dynamoClient.DescribeTable(&dynamodb.DescribeTableInput{ | ||
TableName: aws.String(tableName), | ||
}) | ||
assert.NoError(t, err, "Expected DynamoDB table 'connections' to be created") | ||
|
||
// Test IAM role creation | ||
iamClient := iam.New(sess) | ||
roleName := "go-realtime_services-hello" // Name of the IAM role to check | ||
_, err = iamClient.GetRole(&iam.GetRoleInput{ | ||
RoleName: aws.String(roleName), | ||
}) | ||
assert.NoError(t, err, "Expected IAM role 'go-realtime_services-hello' to be created") | ||
|
||
// Test API gateway webSocket creation | ||
apiClient := apigatewayv2.New(sess) | ||
apiName := "public" // Name of the API Gateway WebSocket to check | ||
result, err := apiClient.GetApis(&apigatewayv2.GetApisInput{}) | ||
assert.NoError(t, err) | ||
found := false | ||
for _, api := range result.Items { | ||
if *api.Name == apiName { | ||
found = true | ||
break | ||
} | ||
} | ||
assert.True(t, found, "Expected API Gateway WebSocket 'public' to be created") | ||
} | ||
``` | ||
|
||
### Run the tests | ||
|
||
To run the tests, navigate to your project’s root directory and execute the Go test command: | ||
|
||
```bash | ||
go test -v ./test | ||
``` | ||
|
||
This will: | ||
|
||
1. Deploy the infrastructure using Terraform. | ||
2. Validate the creation of the DynamoDB table, IAM role, and API Gateway WebSocket. | ||
3. Clean up the infrastructure after testing. | ||
|
||
The output should confirm the successful creation and validation of each resource. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.