Code Examples Guide
AWS SDK for Go Code Examples
Copyright © 2024 Amazon Web Services, Inc. and/or its affiliates. All rights reserved.
AWS SDK for Go Code Examples Code Examples Guide
AWS SDK for Go Code Examples: Code Examples Guide
Copyright © 2024 Amazon Web Services, Inc. and/or its affiliates. All rights reserved.
Amazon's trademarks and trade dress may not be used in connection with any product or service
that is not Amazon's, in any manner that is likely to cause confusion among customers, or in any
manner that disparages or discredits Amazon. All other trademarks not owned by Amazon are
the property of their respective owners, who may or may not be affiliated with, connected to, or
sponsored by Amazon.
AWS SDK for Go Code Examples Code Examples Guide
Table of Contents
What is the AWS SDK for Go V2 Code Examples Guide? .............................................................. 1
Code examples ................................................................................................................................. 2
Aurora .............................................................................................................................................................. 2
Basics .......................................................................................................................................................... 4
Actions ..................................................................................................................................................... 22
Amazon Bedrock ......................................................................................................................................... 37
Actions ..................................................................................................................................................... 22
Amazon Bedrock Runtime ........................................................................................................................ 40
Scenarios ................................................................................................................................................. 44
AI21 Labs Jurassic-2 ............................................................................................................................. 47
Amazon Titan Image Generator ........................................................................................................ 49
Amazon Titan Text ............................................................................................................................... 51
Anthropic Claude .................................................................................................................................. 53
Meta Llama ............................................................................................................................................. 58
AWS CloudFormation ................................................................................................................................ 60
Actions ..................................................................................................................................................... 22
CloudWatch Logs ........................................................................................................................................ 62
Actions ..................................................................................................................................................... 22
Amazon Cognito Identity Provider ......................................................................................................... 64
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Amazon DocumentDB ............................................................................................................................. 138
Serverless examples ........................................................................................................................... 138
DynamoDB ................................................................................................................................................. 140
Basics .......................................................................................................................................................... 4
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Serverless examples ........................................................................................................................... 138
IAM .............................................................................................................................................................. 202
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Kinesis ......................................................................................................................................................... 253
Serverless examples ........................................................................................................................... 138
Lambda ....................................................................................................................................................... 256
iii
AWS SDK for Go Code Examples Code Examples Guide
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Serverless examples ........................................................................................................................... 138
Amazon RDS ............................................................................................................................................. 356
Basics .......................................................................................................................................................... 4
Actions ..................................................................................................................................................... 22
Serverless examples ........................................................................................................................... 138
Amazon S3 ................................................................................................................................................ 388
Basics .......................................................................................................................................................... 4
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Serverless examples ........................................................................................................................... 138
Amazon SNS ............................................................................................................................................. 457
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Serverless examples ........................................................................................................................... 138
Amazon SQS ............................................................................................................................................. 482
Actions ..................................................................................................................................................... 22
Scenarios ................................................................................................................................................. 44
Serverless examples ........................................................................................................................... 138
Document history ........................................................................................................................ 511
iv
AWS SDK for Go Code Examples Code Examples Guide
What is the AWS SDK for Go V2 Code Examples Guide?
The AWS SDK for Go V2 Code Examples Guide is a collection of code examples that show you how
to use AWS with the AWS SDK for Go V2.
The examples are organized by AWS service.
Within each section, the examples are divided into the following categories:
Actions are code excerpts that show you how to call individual service functions. See ???.
Scenarios are code examples that show you how to accomplish a specific task by calling multiple
functions within the same service. See ???.
The examples in this library can also be found in the following:
The gov2 folder in the AWS Code Examples GitHub repository.
This repository also contains instructions on how to set up, run, and test the examples stored in
it.
1
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2 code examples
The code examples in this topic show you how to use the AWS SDK for Go V2 with AWS.
Basics are code examples that show you how to perform the essential operations within a service.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Services
Aurora examples using SDK for Go V2
Amazon Bedrock examples using SDK for Go V2
Amazon Bedrock Runtime examples using SDK for Go V2
AWS CloudFormation examples using SDK for Go V2
CloudWatch Logs examples using SDK for Go V2
Amazon Cognito Identity Provider examples using SDK for Go V2
Amazon DocumentDB examples using SDK for Go V2
DynamoDB examples using SDK for Go V2
IAM examples using SDK for Go V2
Kinesis examples using SDK for Go V2
Lambda examples using SDK for Go V2
Amazon RDS examples using SDK for Go V2
Amazon S3 examples using SDK for Go V2
Amazon SNS examples using SDK for Go V2
Amazon SQS examples using SDK for Go V2
Aurora examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Aurora.
Basics are code examples that show you how to perform the essential operations within a service.
Aurora 2
AWS SDK for Go Code Examples Code Examples Guide
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Aurora
The following code examples show how to get started using Aurora.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/rds"
)
// main uses the AWS SDK for Go V2 to create an Amazon Aurora client and list up to
20
// DB clusters in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
Aurora 3
AWS SDK for Go Code Examples Code Examples Guide
fmt.Println(err)
return
}
auroraClient := rds.NewFromConfig(sdkConfig)
const maxClusters = 20
fmt.Printf("Let's list up to %v DB clusters.\n", maxClusters)
output, err := auroraClient.DescribeDBClusters(context.TODO(),
&rds.DescribeDBClustersInput{MaxRecords: aws.Int32(maxClusters)})
if err != nil {
fmt.Printf("Couldn't list DB clusters: %v\n", err)
return
}
if len(output.DBClusters) == 0 {
fmt.Println("No DB clusters found.")
} else {
for _, cluster := range output.DBClusters {
fmt.Printf("DB cluster %v has database %v.\n", *cluster.DBClusterIdentifier,
*cluster.DatabaseName)
}
}
}
For API details, see DescribeDBClusters in AWS SDK for Go API Reference.
Topics
Basics
Actions
Basics
Learn the basics
The following code example shows how to:
Create a custom Aurora DB cluster parameter group and set parameter values.
Create a DB cluster that uses the parameter group.
Create a DB instance that contains a database.
Take a snapshot of the DB cluster, then clean up resources.
Basics 4
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
// GetStartedClusters is an interactive example that shows you how to use the AWS
SDK for Go
// with Amazon Aurora to do the following:
//
// 1. Create a custom DB cluster parameter group and set parameter values.
// 2. Create an Aurora DB cluster that is configured to use the parameter group.
// 3. Create a DB instance in the DB cluster that contains a database.
// 4. Take a snapshot of the DB cluster.
// 5. Delete the DB instance, DB cluster, and parameter group.
type GetStartedClusters struct {
sdkConfig aws.Config
dbClusters actions.DbClusters
questioner demotools.IQuestioner
helper IScenarioHelper
isTestRun bool
}
// NewGetStartedClusters constructs a GetStartedClusters instance from a
configuration.
// It uses the specified config to get an Amazon Relational Database Service (Amazon
RDS)
// client and create wrappers for the actions used in the scenario.
func NewGetStartedClusters(sdkConfig aws.Config, questioner demotools.IQuestioner,
helper IScenarioHelper) GetStartedClusters {
auroraClient := rds.NewFromConfig(sdkConfig)
return GetStartedClusters{
sdkConfig: sdkConfig,
dbClusters: actions.DbClusters{AuroraClient: auroraClient},
questioner: questioner,
helper: helper,
}
}
Basics 5
AWS SDK for Go Code Examples Code Examples Guide
// Run runs the interactive scenario.
func (scenario GetStartedClusters) Run(dbEngine string, parameterGroupName string,
clusterName string, dbName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon Aurora DB Cluster demo.")
log.Println(strings.Repeat("-", 88))
parameterGroup := scenario.CreateParameterGroup(dbEngine, parameterGroupName)
scenario.SetUserParameters(parameterGroupName)
cluster := scenario.CreateCluster(clusterName, dbEngine, dbName, parameterGroup)
scenario.helper.Pause(5)
dbInstance := scenario.CreateInstance(cluster)
scenario.DisplayConnection(cluster)
scenario.CreateSnapshot(clusterName)
scenario.Cleanup(dbInstance, cluster, parameterGroup)
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
// CreateParameterGroup shows how to get available engine versions for a specified
// database engine and create a DB cluster parameter group that is compatible with a
// selected engine family.
func (scenario GetStartedClusters) CreateParameterGroup(dbEngine string,
parameterGroupName string) *types.DBClusterParameterGroup {
log.Printf("Checking for an existing DB cluster parameter group named %v.\n",
parameterGroupName)
parameterGroup, err := scenario.dbClusters.GetParameterGroup(parameterGroupName)
if err != nil {
panic(err)
}
if parameterGroup == nil {
log.Printf("Getting available database engine versions for %v.\n", dbEngine)
engineVersions, err := scenario.dbClusters.GetEngineVersions(dbEngine, "")
if err != nil {
Basics 6
AWS SDK for Go Code Examples Code Examples Guide
panic(err)
}
familySet := map[string]struct{}{}
for _, family := range engineVersions {
familySet[*family.DBParameterGroupFamily] = struct{}{}
}
var families []string
for family := range familySet {
families = append(families, family)
}
sort.Strings(families)
familyIndex := scenario.questioner.AskChoice("Which family do you want to use?\n",
families)
log.Println("Creating a DB cluster parameter group.")
_, err = scenario.dbClusters.CreateParameterGroup(
parameterGroupName, families[familyIndex], "Example parameter group.")
if err != nil {
panic(err)
}
parameterGroup, err = scenario.dbClusters.GetParameterGroup(parameterGroupName)
if err != nil {
panic(err)
}
}
log.Printf("Parameter group %v:\n", *parameterGroup.DBParameterGroupFamily)
log.Printf("\tName: %v\n", *parameterGroup.DBClusterParameterGroupName)
log.Printf("\tARN: %v\n", *parameterGroup.DBClusterParameterGroupArn)
log.Printf("\tFamily: %v\n", *parameterGroup.DBParameterGroupFamily)
log.Printf("\tDescription: %v\n", *parameterGroup.Description)
log.Println(strings.Repeat("-", 88))
return parameterGroup
}
// SetUserParameters shows how to get the parameters contained in a custom parameter
// group and update some of the parameter values in the group.
func (scenario GetStartedClusters) SetUserParameters(parameterGroupName string) {
log.Println("Let's set some parameter values in your parameter group.")
dbParameters, err := scenario.dbClusters.GetParameters(parameterGroupName, "")
if err != nil {
panic(err)
}
var updateParams []types.Parameter
Basics 7
AWS SDK for Go Code Examples Code Examples Guide
for _, dbParam := range dbParameters {
if strings.HasPrefix(*dbParam.ParameterName, "auto_increment") &&
dbParam.IsModifiable && *dbParam.DataType == "integer" {
log.Printf("The %v parameter is described as:\n\t%v",
*dbParam.ParameterName, *dbParam.Description)
rangeSplit := strings.Split(*dbParam.AllowedValues, "-")
lower, _ := strconv.Atoi(rangeSplit[0])
upper, _ := strconv.Atoi(rangeSplit[1])
newValue := scenario.questioner.AskInt(
fmt.Sprintf("Enter a value between %v and %v:", lower, upper),
demotools.InIntRange{Lower: lower, Upper: upper})
dbParam.ParameterValue = aws.String(strconv.Itoa(newValue))
updateParams = append(updateParams, dbParam)
}
}
err = scenario.dbClusters.UpdateParameters(parameterGroupName, updateParams)
if err != nil {
panic(err)
}
log.Println("You can get a list of parameters you've set by specifying a source of
'user'.")
userParameters, err := scenario.dbClusters.GetParameters(parameterGroupName,
"user")
if err != nil {
panic(err)
}
log.Println("Here are the parameters you've set:")
for _, param := range userParameters {
log.Printf("\t%v: %v\n", *param.ParameterName, *param.ParameterValue)
}
log.Println(strings.Repeat("-", 88))
}
// CreateCluster shows how to create an Aurora DB cluster that contains a database
// of a specified type. The database is also configured to use a custom DB cluster
// parameter group.
func (scenario GetStartedClusters) CreateCluster(clusterName string, dbEngine
string,
dbName string, parameterGroup *types.DBClusterParameterGroup) *types.DBCluster {
log.Println("Checking for an existing DB cluster.")
cluster, err := scenario.dbClusters.GetDbCluster(clusterName)
if err != nil {
panic(err)
Basics 8
AWS SDK for Go Code Examples Code Examples Guide
}
if cluster == nil {
adminUsername := scenario.questioner.Ask(
"Enter an administrator user name for the database: ", demotools.NotEmpty{})
adminPassword := scenario.questioner.Ask(
"Enter a password for the administrator (at least 8 characters): ",
demotools.NotEmpty{})
engineVersions, err := scenario.dbClusters.GetEngineVersions(dbEngine,
*parameterGroup.DBParameterGroupFamily)
if err != nil {
panic(err)
}
var engineChoices []string
for _, engine := range engineVersions {
engineChoices = append(engineChoices, *engine.EngineVersion)
}
log.Println("The available engines for your parameter group are:")
engineIndex := scenario.questioner.AskChoice("Which engine do you want to use?\n",
engineChoices)
log.Printf("Creating DB cluster %v and database %v.\n", clusterName, dbName)
log.Printf("The DB cluster is configured to use\nyour custom parameter group %v
\n",
*parameterGroup.DBClusterParameterGroupName)
log.Printf("and selected engine %v.\n", engineChoices[engineIndex])
log.Println("This typically takes several minutes.")
cluster, err = scenario.dbClusters.CreateDbCluster(
clusterName, *parameterGroup.DBClusterParameterGroupName, dbName, dbEngine,
engineChoices[engineIndex], adminUsername, adminPassword)
if err != nil {
panic(err)
}
for *cluster.Status != "available" {
scenario.helper.Pause(30)
cluster, err = scenario.dbClusters.GetDbCluster(clusterName)
if err != nil {
panic(err)
}
log.Println("Cluster created and available.")
}
}
log.Println("Cluster data:")
log.Printf("\tDBClusterIdentifier: %v\n", *cluster.DBClusterIdentifier)
log.Printf("\tARN: %v\n", *cluster.DBClusterArn)
log.Printf("\tStatus: %v\n", *cluster.Status)
Basics 9
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("\tEngine: %v\n", *cluster.Engine)
log.Printf("\tEngine version: %v\n", *cluster.EngineVersion)
log.Printf("\tDBClusterParameterGroup: %v\n", *cluster.DBClusterParameterGroup)
log.Printf("\tEngineMode: %v\n", *cluster.EngineMode)
log.Println(strings.Repeat("-", 88))
return cluster
}
// CreateInstance shows how to create a DB instance in an existing Aurora DB
cluster.
// A new DB cluster contains no DB instances, so you must add one. The first DB
instance
// that is added to a DB cluster defaults to a read-write DB instance.
func (scenario GetStartedClusters) CreateInstance(cluster *types.DBCluster)
*types.DBInstance {
log.Println("Checking for an existing database instance.")
dbInstance, err := scenario.dbClusters.GetInstance(*cluster.DBClusterIdentifier)
if err != nil {
panic(err)
}
if dbInstance == nil {
log.Println("Let's create a database instance in your DB cluster.")
log.Println("First, choose a DB instance type:")
instOpts, err := scenario.dbClusters.GetOrderableInstances(
*cluster.Engine, *cluster.EngineVersion)
if err != nil {
panic(err)
}
var instChoices []string
for _, opt := range instOpts {
instChoices = append(instChoices, *opt.DBInstanceClass)
}
instIndex := scenario.questioner.AskChoice(
"Which DB instance class do you want to use?\n", instChoices)
log.Println("Creating a database instance. This typically takes several minutes.")
dbInstance, err = scenario.dbClusters.CreateInstanceInCluster(
*cluster.DBClusterIdentifier, *cluster.DBClusterIdentifier, *cluster.Engine,
instChoices[instIndex])
if err != nil {
panic(err)
}
for *dbInstance.DBInstanceStatus != "available" {
scenario.helper.Pause(30)
dbInstance, err = scenario.dbClusters.GetInstance(*cluster.DBClusterIdentifier)
Basics 10
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
panic(err)
}
}
}
log.Println("Instance data:")
log.Printf("\tDBInstanceIdentifier: %v\n", *dbInstance.DBInstanceIdentifier)
log.Printf("\tARN: %v\n", *dbInstance.DBInstanceArn)
log.Printf("\tStatus: %v\n", *dbInstance.DBInstanceStatus)
log.Printf("\tEngine: %v\n", *dbInstance.Engine)
log.Printf("\tEngine version: %v\n", *dbInstance.EngineVersion)
log.Println(strings.Repeat("-", 88))
return dbInstance
}
// DisplayConnection displays connection information about an Aurora DB cluster and
tips
// on how to connect to it.
func (scenario GetStartedClusters) DisplayConnection(cluster *types.DBCluster) {
log.Println(
"You can now connect to your database using your favorite MySql client.\n" +
"One way to connect is by using the 'mysql' shell on an Amazon EC2 instance\n" +
"that is running in the same VPC as your database cluster. Pass the endpoint,\n"
+
"port, and administrator user name to 'mysql' and enter your password\n" +
"when prompted:")
log.Printf("\n\tmysql -h %v -P %v -u %v -p\n",
*cluster.Endpoint, *cluster.Port, *cluster.MasterUsername)
log.Println("For more information, see the User Guide for Aurora:\n" +
"\thttps://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/
CHAP_GettingStartedAurora.CreatingConnecting.Aurora.html#CHAP_GettingStartedAurora.Aurora.Connect")
log.Println(strings.Repeat("-", 88))
}
// CreateSnapshot shows how to create a DB cluster snapshot and wait until it's
available.
func (scenario GetStartedClusters) CreateSnapshot(clusterName string) {
if scenario.questioner.AskBool(
"Do you want to create a snapshot of your DB cluster (y/n)? ", "y") {
snapshotId := fmt.Sprintf("%v-%v", clusterName, scenario.helper.UniqueId())
log.Printf("Creating a snapshot named %v. This typically takes a few minutes.\n",
snapshotId)
snapshot, err := scenario.dbClusters.CreateClusterSnapshot(clusterName,
snapshotId)
Basics 11
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
panic(err)
}
for *snapshot.Status != "available" {
scenario.helper.Pause(30)
snapshot, err = scenario.dbClusters.GetClusterSnapshot(snapshotId)
if err != nil {
panic(err)
}
}
log.Println("Snapshot data:")
log.Printf("\tDBClusterSnapshotIdentifier: %v\n",
*snapshot.DBClusterSnapshotIdentifier)
log.Printf("\tARN: %v\n", *snapshot.DBClusterSnapshotArn)
log.Printf("\tStatus: %v\n", *snapshot.Status)
log.Printf("\tEngine: %v\n", *snapshot.Engine)
log.Printf("\tEngine version: %v\n", *snapshot.EngineVersion)
log.Printf("\tDBClusterIdentifier: %v\n", *snapshot.DBClusterIdentifier)
log.Printf("\tSnapshotCreateTime: %v\n", *snapshot.SnapshotCreateTime)
log.Println(strings.Repeat("-", 88))
}
}
// Cleanup shows how to clean up a DB instance, DB cluster, and DB cluster parameter
group.
// Before the DB cluster parameter group can be deleted, all associated DB instances
and
// DB clusters must first be deleted.
func (scenario GetStartedClusters) Cleanup(dbInstance *types.DBInstance, cluster
*types.DBCluster,
parameterGroup *types.DBClusterParameterGroup) {
if scenario.questioner.AskBool(
"\nDo you want to delete the database instance, DB cluster, and parameter group
(y/n)? ", "y") {
log.Printf("Deleting database instance %v.\n", *dbInstance.DBInstanceIdentifier)
err := scenario.dbClusters.DeleteInstance(*dbInstance.DBInstanceIdentifier)
if err != nil {
panic(err)
}
log.Printf("Deleting database cluster %v.\n", *cluster.DBClusterIdentifier)
err = scenario.dbClusters.DeleteDbCluster(*cluster.DBClusterIdentifier)
if err != nil {
panic(err)
Basics 12
AWS SDK for Go Code Examples Code Examples Guide
}
log.Println(
"Waiting for the DB instance and DB cluster to delete. This typically takes
several minutes.")
for dbInstance != nil || cluster != nil {
scenario.helper.Pause(30)
if dbInstance != nil {
dbInstance, err =
scenario.dbClusters.GetInstance(*dbInstance.DBInstanceIdentifier)
if err != nil {
panic(err)
}
}
if cluster != nil {
cluster, err = scenario.dbClusters.GetDbCluster(*cluster.DBClusterIdentifier)
if err != nil {
panic(err)
}
}
}
log.Printf("Deleting parameter group %v.",
*parameterGroup.DBClusterParameterGroupName)
err =
scenario.dbClusters.DeleteParameterGroup(*parameterGroup.DBClusterParameterGroupName)
if err != nil {
panic(err)
}
}
}
Define functions that are called by the scenario to manage Aurora actions.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetParameterGroup gets a DB cluster parameter group by name.
func (clusters *DbClusters) GetParameterGroup(parameterGroupName string) (
*types.DBClusterParameterGroup, error) {
Basics 13
AWS SDK for Go Code Examples Code Examples Guide
output, err := clusters.AuroraClient.DescribeDBClusterParameterGroups(
context.TODO(), &rds.DescribeDBClusterParameterGroupsInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
var notFoundError *types.DBParameterGroupNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("Parameter group %v does not exist.\n", parameterGroupName)
err = nil
} else {
log.Printf("Error getting parameter group %v: %v\n", parameterGroupName, err)
}
return nil, err
} else {
return &output.DBClusterParameterGroups[0], err
}
}
// CreateParameterGroup creates a DB cluster parameter group that is based on the
specified
// parameter group family.
func (clusters *DbClusters) CreateParameterGroup(
parameterGroupName string, parameterGroupFamily string, description string) (
*types.DBClusterParameterGroup, error) {
output, err := clusters.AuroraClient.CreateDBClusterParameterGroup(context.TODO(),
&rds.CreateDBClusterParameterGroupInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
Description: aws.String(description),
})
if err != nil {
log.Printf("Couldn't create parameter group %v: %v\n", parameterGroupName, err)
return nil, err
} else {
return output.DBClusterParameterGroup, err
}
}
// DeleteParameterGroup deletes the named DB cluster parameter group.
func (clusters *DbClusters) DeleteParameterGroup(parameterGroupName string) error {
Basics 14
AWS SDK for Go Code Examples Code Examples Guide
_, err := clusters.AuroraClient.DeleteDBClusterParameterGroup(context.TODO(),
&rds.DeleteDBClusterParameterGroupInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
log.Printf("Couldn't delete parameter group %v: %v\n", parameterGroupName, err)
return err
} else {
return nil
}
}
// GetParameters gets the parameters that are contained in a DB cluster parameter
group.
func (clusters *DbClusters) GetParameters(parameterGroupName string, source string)
(
[]types.Parameter, error) {
var output *rds.DescribeDBClusterParametersOutput
var params []types.Parameter
var err error
parameterPaginator :=
rds.NewDescribeDBClusterParametersPaginator(clusters.AuroraClient,
&rds.DescribeDBClusterParametersInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
Source: aws.String(source),
})
for parameterPaginator.HasMorePages() {
output, err = parameterPaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get paramaeters for %v: %v\n", parameterGroupName, err)
break
} else {
params = append(params, output.Parameters...)
}
}
return params, err
}
// UpdateParameters updates parameters in a named DB cluster parameter group.
Basics 15
AWS SDK for Go Code Examples Code Examples Guide
func (clusters *DbClusters) UpdateParameters(parameterGroupName string, params
[]types.Parameter) error {
_, err := clusters.AuroraClient.ModifyDBClusterParameterGroup(context.TODO(),
&rds.ModifyDBClusterParameterGroupInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't update parameters in %v: %v\n", parameterGroupName, err)
return err
} else {
return nil
}
}
// GetDbCluster gets data about an Aurora DB cluster.
func (clusters *DbClusters) GetDbCluster(clusterName string) (*types.DBCluster,
error) {
output, err := clusters.AuroraClient.DescribeDBClusters(context.TODO(),
&rds.DescribeDBClustersInput{
DBClusterIdentifier: aws.String(clusterName),
})
if err != nil {
var notFoundError *types.DBClusterNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("DB cluster %v does not exist.\n", clusterName)
err = nil
} else {
log.Printf("Couldn't get DB cluster %v: %v\n", clusterName, err)
}
return nil, err
} else {
return &output.DBClusters[0], err
}
}
// CreateDbCluster creates a DB cluster that is configured to use the specified
parameter group.
// The newly created DB cluster contains a database that uses the specified engine
and
Basics 16
AWS SDK for Go Code Examples Code Examples Guide
// engine version.
func (clusters *DbClusters) CreateDbCluster(clusterName string, parameterGroupName
string,
dbName string, dbEngine string, dbEngineVersion string, adminName string,
adminPassword string) (
*types.DBCluster, error) {
output, err := clusters.AuroraClient.CreateDBCluster(context.TODO(),
&rds.CreateDBClusterInput{
DBClusterIdentifier: aws.String(clusterName),
Engine: aws.String(dbEngine),
DBClusterParameterGroupName: aws.String(parameterGroupName),
DatabaseName: aws.String(dbName),
EngineVersion: aws.String(dbEngineVersion),
MasterUserPassword: aws.String(adminPassword),
MasterUsername: aws.String(adminName),
})
if err != nil {
log.Printf("Couldn't create DB cluster %v: %v\n", clusterName, err)
return nil, err
} else {
return output.DBCluster, err
}
}
// DeleteDbCluster deletes a DB cluster without keeping a final snapshot.
func (clusters *DbClusters) DeleteDbCluster(clusterName string) error {
_, err := clusters.AuroraClient.DeleteDBCluster(context.TODO(),
&rds.DeleteDBClusterInput{
DBClusterIdentifier: aws.String(clusterName),
SkipFinalSnapshot: true,
})
if err != nil {
log.Printf("Couldn't delete DB cluster %v: %v\n", clusterName, err)
return err
} else {
return nil
}
}
Basics 17
AWS SDK for Go Code Examples Code Examples Guide
// CreateClusterSnapshot creates a snapshot of a DB cluster.
func (clusters *DbClusters) CreateClusterSnapshot(clusterName string, snapshotName
string) (
*types.DBClusterSnapshot, error) {
output, err := clusters.AuroraClient.CreateDBClusterSnapshot(context.TODO(),
&rds.CreateDBClusterSnapshotInput{
DBClusterIdentifier: aws.String(clusterName),
DBClusterSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't create snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return output.DBClusterSnapshot, nil
}
}
// GetClusterSnapshot gets a DB cluster snapshot.
func (clusters *DbClusters) GetClusterSnapshot(snapshotName string)
(*types.DBClusterSnapshot, error) {
output, err := clusters.AuroraClient.DescribeDBClusterSnapshots(context.TODO(),
&rds.DescribeDBClusterSnapshotsInput{
DBClusterSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't get snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return &output.DBClusterSnapshots[0], nil
}
}
// CreateInstanceInCluster creates a database instance in an existing DB cluster.
The first database that is
// created defaults to a read-write DB instance.
func (clusters *DbClusters) CreateInstanceInCluster(clusterName string, instanceName
string,
dbEngine string, dbInstanceClass string) (*types.DBInstance, error) {
output, err := clusters.AuroraClient.CreateDBInstance(context.TODO(),
&rds.CreateDBInstanceInput{
Basics 18
AWS SDK for Go Code Examples Code Examples Guide
DBInstanceIdentifier: aws.String(instanceName),
DBClusterIdentifier: aws.String(clusterName),
Engine: aws.String(dbEngine),
DBInstanceClass: aws.String(dbInstanceClass),
})
if err != nil {
log.Printf("Couldn't create instance %v: %v\n", instanceName, err)
return nil, err
} else {
return output.DBInstance, nil
}
}
// GetInstance gets data about a DB instance.
func (clusters *DbClusters) GetInstance(instanceName string) (
*types.DBInstance, error) {
output, err := clusters.AuroraClient.DescribeDBInstances(context.TODO(),
&rds.DescribeDBInstancesInput{
DBInstanceIdentifier: aws.String(instanceName),
})
if err != nil {
var notFoundError *types.DBInstanceNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("DB instance %v does not exist.\n", instanceName)
err = nil
} else {
log.Printf("Couldn't get instance %v: %v\n", instanceName, err)
}
return nil, err
} else {
return &output.DBInstances[0], nil
}
}
// DeleteInstance deletes a DB instance.
func (clusters *DbClusters) DeleteInstance(instanceName string) error {
_, err := clusters.AuroraClient.DeleteDBInstance(context.TODO(),
&rds.DeleteDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
SkipFinalSnapshot: true,
Basics 19
AWS SDK for Go Code Examples Code Examples Guide
DeleteAutomatedBackups: aws.Bool(true),
})
if err != nil {
log.Printf("Couldn't delete instance %v: %v\n", instanceName, err)
return err
} else {
return nil
}
}
// GetEngineVersions gets database engine versions that are available for the
specified engine
// and parameter group family.
func (clusters *DbClusters) GetEngineVersions(engine string, parameterGroupFamily
string) (
[]types.DBEngineVersion, error) {
output, err := clusters.AuroraClient.DescribeDBEngineVersions(context.TODO(),
&rds.DescribeDBEngineVersionsInput{
Engine: aws.String(engine),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
})
if err != nil {
log.Printf("Couldn't get engine versions for %v: %v\n", engine, err)
return nil, err
} else {
return output.DBEngineVersions, nil
}
}
// GetOrderableInstances uses a paginator to get DB instance options that can be
used to create DB instances that are
// compatible with a set of specifications.
func (clusters *DbClusters) GetOrderableInstances(engine string, engineVersion
string) (
[]types.OrderableDBInstanceOption, error) {
var output *rds.DescribeOrderableDBInstanceOptionsOutput
var instances []types.OrderableDBInstanceOption
var err error
Basics 20
AWS SDK for Go Code Examples Code Examples Guide
orderablePaginator :=
rds.NewDescribeOrderableDBInstanceOptionsPaginator(clusters.AuroraClient,
&rds.DescribeOrderableDBInstanceOptionsInput{
Engine: aws.String(engine),
EngineVersion: aws.String(engineVersion),
})
for orderablePaginator.HasMorePages() {
output, err = orderablePaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get orderable DB instances: %v\n", err)
break
} else {
instances = append(instances, output.OrderableDBInstanceOptions...)
}
}
return instances, err
}
For API details, see the following topics in AWS SDK for Go API Reference.
CreateDBCluster
CreateDBClusterParameterGroup
CreateDBClusterSnapshot
CreateDBInstance
DeleteDBCluster
DeleteDBClusterParameterGroup
DeleteDBInstance
DescribeDBClusterParameterGroups
DescribeDBClusterParameters
DescribeDBClusterSnapshots
DescribeDBClusters
DescribeDBEngineVersions
DescribeDBInstances
DescribeOrderableDBInstanceOptions
ModifyDBClusterParameterGroup
Basics 21
AWS SDK for Go Code Examples Code Examples Guide
Actions
CreateDBCluster
The following code example shows how to use CreateDBCluster.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// CreateDbCluster creates a DB cluster that is configured to use the specified
parameter group.
// The newly created DB cluster contains a database that uses the specified engine
and
// engine version.
func (clusters *DbClusters) CreateDbCluster(clusterName string, parameterGroupName
string,
dbName string, dbEngine string, dbEngineVersion string, adminName string,
adminPassword string) (
*types.DBCluster, error) {
output, err := clusters.AuroraClient.CreateDBCluster(context.TODO(),
&rds.CreateDBClusterInput{
DBClusterIdentifier: aws.String(clusterName),
Engine: aws.String(dbEngine),
DBClusterParameterGroupName: aws.String(parameterGroupName),
DatabaseName: aws.String(dbName),
EngineVersion: aws.String(dbEngineVersion),
MasterUserPassword: aws.String(adminPassword),
MasterUsername: aws.String(adminName),
})
Actions 22
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't create DB cluster %v: %v\n", clusterName, err)
return nil, err
} else {
return output.DBCluster, err
}
}
For API details, see CreateDBCluster in AWS SDK for Go API Reference.
CreateDBClusterParameterGroup
The following code example shows how to use CreateDBClusterParameterGroup.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// CreateParameterGroup creates a DB cluster parameter group that is based on the
specified
// parameter group family.
func (clusters *DbClusters) CreateParameterGroup(
parameterGroupName string, parameterGroupFamily string, description string) (
*types.DBClusterParameterGroup, error) {
output, err := clusters.AuroraClient.CreateDBClusterParameterGroup(context.TODO(),
&rds.CreateDBClusterParameterGroupInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
Actions 23
AWS SDK for Go Code Examples Code Examples Guide
Description: aws.String(description),
})
if err != nil {
log.Printf("Couldn't create parameter group %v: %v\n", parameterGroupName, err)
return nil, err
} else {
return output.DBClusterParameterGroup, err
}
}
For API details, see CreateDBClusterParameterGroup in AWS SDK for Go API Reference.
CreateDBClusterSnapshot
The following code example shows how to use CreateDBClusterSnapshot.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// CreateClusterSnapshot creates a snapshot of a DB cluster.
func (clusters *DbClusters) CreateClusterSnapshot(clusterName string, snapshotName
string) (
*types.DBClusterSnapshot, error) {
output, err := clusters.AuroraClient.CreateDBClusterSnapshot(context.TODO(),
&rds.CreateDBClusterSnapshotInput{
DBClusterIdentifier: aws.String(clusterName),
DBClusterSnapshotIdentifier: aws.String(snapshotName),
})
Actions 24
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't create snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return output.DBClusterSnapshot, nil
}
}
For API details, see CreateDBClusterSnapshot in AWS SDK for Go API Reference.
CreateDBInstance
The following code example shows how to use CreateDBInstance.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// CreateInstanceInCluster creates a database instance in an existing DB cluster.
The first database that is
// created defaults to a read-write DB instance.
func (clusters *DbClusters) CreateInstanceInCluster(clusterName string, instanceName
string,
dbEngine string, dbInstanceClass string) (*types.DBInstance, error) {
output, err := clusters.AuroraClient.CreateDBInstance(context.TODO(),
&rds.CreateDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
DBClusterIdentifier: aws.String(clusterName),
Engine: aws.String(dbEngine),
Actions 25
AWS SDK for Go Code Examples Code Examples Guide
DBInstanceClass: aws.String(dbInstanceClass),
})
if err != nil {
log.Printf("Couldn't create instance %v: %v\n", instanceName, err)
return nil, err
} else {
return output.DBInstance, nil
}
}
For API details, see CreateDBInstance in AWS SDK for Go API Reference.
DeleteDBCluster
The following code example shows how to use DeleteDBCluster.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// DeleteDbCluster deletes a DB cluster without keeping a final snapshot.
func (clusters *DbClusters) DeleteDbCluster(clusterName string) error {
_, err := clusters.AuroraClient.DeleteDBCluster(context.TODO(),
&rds.DeleteDBClusterInput{
DBClusterIdentifier: aws.String(clusterName),
SkipFinalSnapshot: true,
})
if err != nil {
log.Printf("Couldn't delete DB cluster %v: %v\n", clusterName, err)
Actions 26
AWS SDK for Go Code Examples Code Examples Guide
return err
} else {
return nil
}
}
For API details, see DeleteDBCluster in AWS SDK for Go API Reference.
DeleteDBClusterParameterGroup
The following code example shows how to use DeleteDBClusterParameterGroup.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// DeleteParameterGroup deletes the named DB cluster parameter group.
func (clusters *DbClusters) DeleteParameterGroup(parameterGroupName string) error {
_, err := clusters.AuroraClient.DeleteDBClusterParameterGroup(context.TODO(),
&rds.DeleteDBClusterParameterGroupInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
log.Printf("Couldn't delete parameter group %v: %v\n", parameterGroupName, err)
return err
} else {
return nil
}
}
Actions 27
AWS SDK for Go Code Examples Code Examples Guide
For API details, see DeleteDBClusterParameterGroup in AWS SDK for Go API Reference.
DeleteDBInstance
The following code example shows how to use DeleteDBInstance.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// DeleteInstance deletes a DB instance.
func (clusters *DbClusters) DeleteInstance(instanceName string) error {
_, err := clusters.AuroraClient.DeleteDBInstance(context.TODO(),
&rds.DeleteDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
SkipFinalSnapshot: true,
DeleteAutomatedBackups: aws.Bool(true),
})
if err != nil {
log.Printf("Couldn't delete instance %v: %v\n", instanceName, err)
return err
} else {
return nil
}
}
Actions 28
AWS SDK for Go Code Examples Code Examples Guide
For API details, see DeleteDBInstance in AWS SDK for Go API Reference.
DescribeDBClusterParameterGroups
The following code example shows how to use DescribeDBClusterParameterGroups.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetParameterGroup gets a DB cluster parameter group by name.
func (clusters *DbClusters) GetParameterGroup(parameterGroupName string) (
*types.DBClusterParameterGroup, error) {
output, err := clusters.AuroraClient.DescribeDBClusterParameterGroups(
context.TODO(), &rds.DescribeDBClusterParameterGroupsInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
var notFoundError *types.DBParameterGroupNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("Parameter group %v does not exist.\n", parameterGroupName)
err = nil
} else {
log.Printf("Error getting parameter group %v: %v\n", parameterGroupName, err)
}
return nil, err
} else {
return &output.DBClusterParameterGroups[0], err
}
}
Actions 29
AWS SDK for Go Code Examples Code Examples Guide
For API details, see DescribeDBClusterParameterGroups in AWS SDK for Go API Reference.
DescribeDBClusterParameters
The following code example shows how to use DescribeDBClusterParameters.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetParameters gets the parameters that are contained in a DB cluster parameter
group.
func (clusters *DbClusters) GetParameters(parameterGroupName string, source string)
(
[]types.Parameter, error) {
var output *rds.DescribeDBClusterParametersOutput
var params []types.Parameter
var err error
parameterPaginator :=
rds.NewDescribeDBClusterParametersPaginator(clusters.AuroraClient,
&rds.DescribeDBClusterParametersInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
Source: aws.String(source),
})
for parameterPaginator.HasMorePages() {
output, err = parameterPaginator.NextPage(context.TODO())
if err != nil {
Actions 30
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't get paramaeters for %v: %v\n", parameterGroupName, err)
break
} else {
params = append(params, output.Parameters...)
}
}
return params, err
}
For API details, see DescribeDBClusterParameters in AWS SDK for Go API Reference.
DescribeDBClusterSnapshots
The following code example shows how to use DescribeDBClusterSnapshots.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetClusterSnapshot gets a DB cluster snapshot.
func (clusters *DbClusters) GetClusterSnapshot(snapshotName string)
(*types.DBClusterSnapshot, error) {
output, err := clusters.AuroraClient.DescribeDBClusterSnapshots(context.TODO(),
&rds.DescribeDBClusterSnapshotsInput{
DBClusterSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't get snapshot %v: %v\n", snapshotName, err)
Actions 31
AWS SDK for Go Code Examples Code Examples Guide
return nil, err
} else {
return &output.DBClusterSnapshots[0], nil
}
}
For API details, see DescribeDBClusterSnapshots in AWS SDK for Go API Reference.
DescribeDBClusters
The following code example shows how to use DescribeDBClusters.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetDbCluster gets data about an Aurora DB cluster.
func (clusters *DbClusters) GetDbCluster(clusterName string) (*types.DBCluster,
error) {
output, err := clusters.AuroraClient.DescribeDBClusters(context.TODO(),
&rds.DescribeDBClustersInput{
DBClusterIdentifier: aws.String(clusterName),
})
if err != nil {
var notFoundError *types.DBClusterNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("DB cluster %v does not exist.\n", clusterName)
err = nil
Actions 32
AWS SDK for Go Code Examples Code Examples Guide
} else {
log.Printf("Couldn't get DB cluster %v: %v\n", clusterName, err)
}
return nil, err
} else {
return &output.DBClusters[0], err
}
}
For API details, see DescribeDBClusters in AWS SDK for Go API Reference.
DescribeDBEngineVersions
The following code example shows how to use DescribeDBEngineVersions.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetEngineVersions gets database engine versions that are available for the
specified engine
// and parameter group family.
func (clusters *DbClusters) GetEngineVersions(engine string, parameterGroupFamily
string) (
[]types.DBEngineVersion, error) {
output, err := clusters.AuroraClient.DescribeDBEngineVersions(context.TODO(),
&rds.DescribeDBEngineVersionsInput{
Engine: aws.String(engine),
Actions 33
AWS SDK for Go Code Examples Code Examples Guide
DBParameterGroupFamily: aws.String(parameterGroupFamily),
})
if err != nil {
log.Printf("Couldn't get engine versions for %v: %v\n", engine, err)
return nil, err
} else {
return output.DBEngineVersions, nil
}
}
For API details, see DescribeDBEngineVersions in AWS SDK for Go API Reference.
DescribeDBInstances
The following code example shows how to use DescribeDBInstances.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetInstance gets data about a DB instance.
func (clusters *DbClusters) GetInstance(instanceName string) (
*types.DBInstance, error) {
output, err := clusters.AuroraClient.DescribeDBInstances(context.TODO(),
&rds.DescribeDBInstancesInput{
DBInstanceIdentifier: aws.String(instanceName),
})
if err != nil {
Actions 34
AWS SDK for Go Code Examples Code Examples Guide
var notFoundError *types.DBInstanceNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("DB instance %v does not exist.\n", instanceName)
err = nil
} else {
log.Printf("Couldn't get instance %v: %v\n", instanceName, err)
}
return nil, err
} else {
return &output.DBInstances[0], nil
}
}
For API details, see DescribeDBInstances in AWS SDK for Go API Reference.
DescribeOrderableDBInstanceOptions
The following code example shows how to use DescribeOrderableDBInstanceOptions.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
AuroraClient *rds.Client
}
// GetOrderableInstances uses a paginator to get DB instance options that can be
used to create DB instances that are
// compatible with a set of specifications.
func (clusters *DbClusters) GetOrderableInstances(engine string, engineVersion
string) (
Actions 35
AWS SDK for Go Code Examples Code Examples Guide
[]types.OrderableDBInstanceOption, error) {
var output *rds.DescribeOrderableDBInstanceOptionsOutput
var instances []types.OrderableDBInstanceOption
var err error
orderablePaginator :=
rds.NewDescribeOrderableDBInstanceOptionsPaginator(clusters.AuroraClient,
&rds.DescribeOrderableDBInstanceOptionsInput{
Engine: aws.String(engine),
EngineVersion: aws.String(engineVersion),
})
for orderablePaginator.HasMorePages() {
output, err = orderablePaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get orderable DB instances: %v\n", err)
break
} else {
instances = append(instances, output.OrderableDBInstanceOptions...)
}
}
return instances, err
}
For API details, see DescribeOrderableDBInstanceOptions in AWS SDK for Go API Reference.
ModifyDBClusterParameterGroup
The following code example shows how to use ModifyDBClusterParameterGroup.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbClusters struct {
Actions 36
AWS SDK for Go Code Examples Code Examples Guide
AuroraClient *rds.Client
}
// UpdateParameters updates parameters in a named DB cluster parameter group.
func (clusters *DbClusters) UpdateParameters(parameterGroupName string, params
[]types.Parameter) error {
_, err := clusters.AuroraClient.ModifyDBClusterParameterGroup(context.TODO(),
&rds.ModifyDBClusterParameterGroupInput{
DBClusterParameterGroupName: aws.String(parameterGroupName),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't update parameters in %v: %v\n", parameterGroupName, err)
return err
} else {
return nil
}
}
For API details, see ModifyDBClusterParameterGroup in AWS SDK for Go API Reference.
Amazon Bedrock examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon Bedrock.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Amazon Bedrock
The following code examples show how to get started using Amazon Bedrock.
Amazon Bedrock 37
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/bedrock"
)
const region = "us-east-1"
// main uses the AWS SDK for Go (v2) to create an Amazon Bedrock client and
// list the available foundation models in your account and the chosen region.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region))
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
bedrockClient := bedrock.NewFromConfig(sdkConfig)
result, err := bedrockClient.ListFoundationModels(context.TODO(),
&bedrock.ListFoundationModelsInput{})
if err != nil {
fmt.Printf("Couldn't list foundation models. Here's why: %v\n", err)
return
}
if len(result.ModelSummaries) == 0 {
Amazon Bedrock 38
AWS SDK for Go Code Examples Code Examples Guide
fmt.Println("There are no foundation models.")}
for _, modelSummary := range result.ModelSummaries {
fmt.Println(*modelSummary.ModelId)
}
}
For API details, see ListFoundationModels in AWS SDK for Go API Reference.
Topics
Actions
Actions
ListFoundationModels
The following code example shows how to use ListFoundationModels.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
List the available Bedrock foundation models.
// FoundationModelWrapper encapsulates Amazon Bedrock actions used in the examples.
// It contains a Bedrock service client that is used to perform foundation model
actions.
type FoundationModelWrapper struct {
BedrockClient *bedrock.Client
}
// ListPolicies lists Bedrock foundation models that you can use.
Actions 39
AWS SDK for Go Code Examples Code Examples Guide
func (wrapper FoundationModelWrapper) ListFoundationModels()
([]types.FoundationModelSummary, error) {
var models []types.FoundationModelSummary
result, err := wrapper.BedrockClient.ListFoundationModels(context.TODO(),
&bedrock.ListFoundationModelsInput{})
if err != nil {
log.Printf("Couldn't list foundation models. Here's why: %v\n", err)
} else {
models = result.ModelSummaries
}
return models, err
}
For API details, see ListFoundationModels in AWS SDK for Go API Reference.
Amazon Bedrock Runtime examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon Bedrock Runtime.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Amazon Bedrock
The following code examples show how to get started using Amazon Bedrock.
Amazon Bedrock Runtime 40
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/bedrockruntime"
)
// Each model provider defines their own individual request and response formats.
// For the format, ranges, and default values for the different models, refer to:
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html
type ClaudeRequest struct {
Prompt string `json:"prompt"`
MaxTokensToSample int `json:"max_tokens_to_sample"`
// Omitting optional request parameters
}
type ClaudeResponse struct {
Completion string `json:"completion"`
}
// main uses the AWS SDK for Go (v2) to create an Amazon Bedrock Runtime client
// and invokes Anthropic Claude 2 inside your account and the chosen region.
// This example uses the default settings specified in your shared credentials
Amazon Bedrock Runtime 41
AWS SDK for Go Code Examples Code Examples Guide
// and config files.
func main() {
region := flag.String("region", "us-east-1", "The AWS region")
flag.Parse()
fmt.Printf("Using AWS region: %s\n", *region)
sdkConfig, err := config.LoadDefaultConfig(context.Background(),
config.WithRegion(*region))
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
client := bedrockruntime.NewFromConfig(sdkConfig)
modelId := "anthropic.claude-v2"
prompt := "Hello, how are you today?"
// Anthropic Claude requires you to enclose the prompt as follows:
prefix := "Human: "
postfix := "\n\nAssistant:"
wrappedPrompt := prefix + prompt + postfix
request := ClaudeRequest{
Prompt: wrappedPrompt,
MaxTokensToSample: 200,
}
body, err := json.Marshal(request)
if err != nil {
log.Panicln("Couldn't marshal the request: ", err)
}
result, err := client.InvokeModel(context.Background(),
&bedrockruntime.InvokeModelInput{
ModelId: aws.String(modelId),
ContentType: aws.String("application/json"),
Body: body,
})
Amazon Bedrock Runtime 42
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
errMsg := err.Error()
if strings.Contains(errMsg, "no such host") {
fmt.Printf("Error: The Bedrock service is not available in the selected
region. Please double-check the service availability for your region at https://
aws.amazon.com/about-aws/global-infrastructure/regional-product-services/.\n")
} else if strings.Contains(errMsg, "Could not resolve the foundation model") {
fmt.Printf("Error: Could not resolve the foundation model from model identifier:
\"%v\". Please verify that the requested model exists and is accessible within the
specified region.\n", modelId)
} else {
fmt.Printf("Error: Couldn't invoke Anthropic Claude. Here's why: %v\n", err)
}
os.Exit(1)
}
var response ClaudeResponse
err = json.Unmarshal(result.Body, &response)
if err != nil {
log.Fatal("failed to unmarshal", err)
}
fmt.Println("Prompt:\n", prompt)
fmt.Println("Response from Anthropic Claude:\n", response.Completion)
}
For API details, see InvokeModel in AWS SDK for Go API Reference.
Topics
Scenarios
AI21 Labs Jurassic-2
Amazon Titan Image Generator
Amazon Titan Text
Anthropic Claude
Meta Llama
Amazon Bedrock Runtime 43
AWS SDK for Go Code Examples Code Examples Guide
Scenarios
Invoke multiple foundation models on Amazon Bedrock
The following code example shows how to prepare and send a prompt to a variety of large-
language models (LLMs) on Amazon Bedrock
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Invoke multiple foundation models on Amazon Bedrock.
// InvokeModelsScenario demonstrates how to use the Amazon Bedrock Runtime client
// to invoke various foundation models for text and image generation
//
// 1. Generate text with Anthropic Claude 2
// 2. Generate text with AI21 Labs Jurassic-2
// 3. Generate text with Meta Llama 2 Chat
// 4. Generate text and asynchronously process the response stream with Anthropic
Claude 2
// 5. Generate and image with the Amazon Titan image generation model
// 6. Generate text with Amazon Titan Text G1 Express model
type InvokeModelsScenario struct {
sdkConfig aws.Config
invokeModelWrapper actions.InvokeModelWrapper
responseStreamWrapper actions.InvokeModelWithResponseStreamWrapper
questioner demotools.IQuestioner
}
// NewInvokeModelsScenario constructs an InvokeModelsScenario instance from a
configuration.
// It uses the specified config to get a Bedrock Runtime client and create wrappers
for the
// actions used in the scenario.
func NewInvokeModelsScenario(sdkConfig aws.Config, questioner demotools.IQuestioner)
InvokeModelsScenario {
Scenarios 44
AWS SDK for Go Code Examples Code Examples Guide
client := bedrockruntime.NewFromConfig(sdkConfig)
return InvokeModelsScenario{
sdkConfig: sdkConfig,
invokeModelWrapper: actions.InvokeModelWrapper{BedrockRuntimeClient: client},
responseStreamWrapper:
actions.InvokeModelWithResponseStreamWrapper{BedrockRuntimeClient: client},
questioner: questioner,
}
}
// Runs the interactive scenario.
func (scenario InvokeModelsScenario) Run() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong with the demo: %v\n", r)
}
}()
log.Println(strings.Repeat("=", 77))
log.Println("Welcome to the Amazon Bedrock Runtime model invocation demo.")
log.Println(strings.Repeat("=", 77))
log.Printf("First, let's invoke a few large-language models using the synchronous
client:\n\n")
text2textPrompt := "In one paragraph, who are you?"
log.Println(strings.Repeat("-", 77))
log.Printf("Invoking Claude with prompt: %v\n", text2textPrompt)
scenario.InvokeClaude(text2textPrompt)
log.Println(strings.Repeat("-", 77))
log.Printf("Invoking Jurassic-2 with prompt: %v\n", text2textPrompt)
scenario.InvokeJurassic2(text2textPrompt)
log.Println(strings.Repeat("-", 77))
log.Printf("Invoking Llama2 with prompt: %v\n", text2textPrompt)
scenario.InvokeLlama2(text2textPrompt)
log.Println(strings.Repeat("=", 77))
log.Printf("Now, let's invoke Claude with the asynchronous client and process the
response stream:\n\n")
log.Println(strings.Repeat("-", 77))
Scenarios 45
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Invoking Claude with prompt: %v\n", text2textPrompt)
scenario.InvokeWithResponseStream(text2textPrompt)
log.Println(strings.Repeat("=", 77))
log.Printf("Now, let's create an image with the Amazon Titan image generation
model:\n\n")
text2ImagePrompt := "stylized picture of a cute old steampunk robot"
seed := rand.Int63n(2147483648)
log.Println(strings.Repeat("-", 77))
log.Printf("Invoking Amazon Titan with prompt: %v\n", text2ImagePrompt)
scenario.InvokeTitanImage(text2ImagePrompt, seed)
log.Println(strings.Repeat("-", 77))
log.Printf("Invoking Titan Text Express with prompt: %v\n", text2textPrompt)
scenario.InvokeTitanText(text2textPrompt)
log.Println(strings.Repeat("=", 77))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("=", 77))
}
func (scenario InvokeModelsScenario) InvokeClaude(prompt string) {
completion, err := scenario.invokeModelWrapper.InvokeClaude(prompt)
if err != nil {
panic(err)
}
log.Printf("\nClaude : %v\n", strings.TrimSpace(completion))
}
func (scenario InvokeModelsScenario) InvokeJurassic2(prompt string) {
completion, err := scenario.invokeModelWrapper.InvokeJurassic2(prompt)
if err != nil {
panic(err)
}
log.Printf("\nJurassic-2 : %v\n", strings.TrimSpace(completion))
}
func (scenario InvokeModelsScenario) InvokeLlama2(prompt string) {
completion, err := scenario.invokeModelWrapper.InvokeLlama2(prompt)
if err != nil {
panic(err)
}
Scenarios 46
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("\nLlama 2 : %v\n\n", strings.TrimSpace(completion))
}
func (scenario InvokeModelsScenario) InvokeWithResponseStream(prompt string) {
log.Println("\nClaude with response stream:")
_, err := scenario.responseStreamWrapper.InvokeModelWithResponseStream(prompt)
if err != nil {
panic(err)
}
log.Println()
}
func (scenario InvokeModelsScenario) InvokeTitanImage(prompt string, seed int64) {
base64ImageData, err := scenario.invokeModelWrapper.InvokeTitanImage(prompt, seed)
if err != nil {
panic(err)
}
imagePath := saveImage(base64ImageData, "amazon.titan-image-generator-v1")
fmt.Printf("The generated image has been saved to %s\n", imagePath)
}
func (scenario InvokeModelsScenario) InvokeTitanText(prompt string) {
completion, err := scenario.invokeModelWrapper.InvokeTitanText(prompt)
if err != nil {
panic(err)
}
log.Printf("\nTitan Text Express : %v\n\n", strings.TrimSpace(completion))
}
For API details, see the following topics in AWS SDK for Go API Reference.
InvokeModel
InvokeModelWithResponseStream
AI21 Labs Jurassic-2
InvokeModel
The following code example shows how to send a text message to AI21 Labs Jurassic-2, using the
Invoke Model API.
AI21 Labs Jurassic-2 47
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Use the Invoke Model API to send a text message.
// Each model provider has their own individual request and response formats.
// For the format, ranges, and default values for AI21 Labs Jurassic-2, refer to:
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-
jurassic2.html
type Jurassic2Request struct {
Prompt string `json:"prompt"`
MaxTokens int `json:"maxTokens,omitempty"`
Temperature float64 `json:"temperature,omitempty"`
}
type Jurassic2Response struct {
Completions []Completion `json:"completions"`
}
type Completion struct {
Data Data `json:"data"`
}
type Data struct {
Text string `json:"text"`
}
// Invokes AI21 Labs Jurassic-2 on Amazon Bedrock to run an inference using the
input
// provided in the request body.
func (wrapper InvokeModelWrapper) InvokeJurassic2(prompt string) (string, error) {
modelId := "ai21.j2-mid-v1"
body, err := json.Marshal(Jurassic2Request{
Prompt: prompt,
MaxTokens: 200,
Temperature: 0.5,
})
AI21 Labs Jurassic-2 48
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Fatal("failed to marshal", err)
}
output, err := wrapper.BedrockRuntimeClient.InvokeModel(context.TODO(),
&bedrockruntime.InvokeModelInput{
ModelId: aws.String(modelId),
ContentType: aws.String("application/json"),
Body: body,
})
if err != nil {
ProcessError(err, modelId)
}
var response Jurassic2Response
if err := json.Unmarshal(output.Body, &response); err != nil {
log.Fatal("failed to unmarshal", err)
}
return response.Completions[0].Data.Text, nil
}
For API details, see InvokeModel in AWS SDK for Go API Reference.
Amazon Titan Image Generator
InvokeModel
The following code example shows how to invoke Amazon Titan Image on Amazon Bedrock to
generate an image.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Amazon Titan Image Generator 49
AWS SDK for Go Code Examples Code Examples Guide
Create an image with the Amazon Titan Image Generator.
type TitanImageRequest struct {
TaskType string `json:"taskType"`
TextToImageParams TextToImageParams `json:"textToImageParams"`
ImageGenerationConfig ImageGenerationConfig `json:"imageGenerationConfig"`
}
type TextToImageParams struct {
Text string `json:"text"`
}
type ImageGenerationConfig struct {
NumberOfImages int `json:"numberOfImages"`
Quality string `json:"quality"`
CfgScale float64 `json:"cfgScale"`
Height int `json:"height"`
Width int `json:"width"`
Seed int64 `json:"seed"`
}
type TitanImageResponse struct {
Images []string `json:"images"`
}
// Invokes the Titan Image model to create an image using the input provided
// in the request body.
func (wrapper InvokeModelWrapper) InvokeTitanImage(prompt string, seed int64)
(string, error) {
modelId := "amazon.titan-image-generator-v1"
body, err := json.Marshal(TitanImageRequest{
TaskType: "TEXT_IMAGE",
TextToImageParams: TextToImageParams{
Text: prompt,
},
ImageGenerationConfig: ImageGenerationConfig{
NumberOfImages: 1,
Quality: "standard",
CfgScale: 8.0,
Height: 512,
Width: 512,
Seed: seed,
},
})
Amazon Titan Image Generator 50
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Fatal("failed to marshal", err)
}
output, err := wrapper.BedrockRuntimeClient.InvokeModel(context.TODO(),
&bedrockruntime.InvokeModelInput{
ModelId: aws.String(modelId),
ContentType: aws.String("application/json"),
Body: body,
})
if err != nil {
ProcessError(err, modelId)
}
var response TitanImageResponse
if err := json.Unmarshal(output.Body, &response); err != nil {
log.Fatal("failed to unmarshal", err)
}
base64ImageData := response.Images[0]
return base64ImageData, nil
}
For API details, see InvokeModel in AWS SDK for Go API Reference.
Amazon Titan Text
InvokeModel
The following code example shows how to send a text message to Amazon Titan Text, using the
Invoke Model API.
Amazon Titan Text 51
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Use the Invoke Model API to send a text message.
// Each model provider has their own individual request and response formats.
// For the format, ranges, and default values for Amazon Titan Text, refer to:
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-
text.html
type TitanTextRequest struct {
InputText string `json:"inputText"`
TextGenerationConfig TextGenerationConfig `json:"textGenerationConfig"`
}
type TextGenerationConfig struct {
Temperature float64 `json:"temperature"`
TopP float64 `json:"topP"`
MaxTokenCount int `json:"maxTokenCount"`
StopSequences []string `json:"stopSequences,omitempty"`
}
type TitanTextResponse struct {
InputTextTokenCount int `json:"inputTextTokenCount"`
Results []Result `json:"results"`
}
type Result struct {
TokenCount int `json:"tokenCount"`
OutputText string `json:"outputText"`
CompletionReason string `json:"completionReason"`
}
func (wrapper InvokeModelWrapper) InvokeTitanText(prompt string) (string, error) {
modelId := "amazon.titan-text-express-v1"
body, err := json.Marshal(TitanTextRequest{
InputText: prompt,
Amazon Titan Text 52
AWS SDK for Go Code Examples Code Examples Guide
TextGenerationConfig: TextGenerationConfig{
Temperature: 0,
TopP: 1,
MaxTokenCount: 4096,
},
})
if err != nil {
log.Fatal("failed to marshal", err)
}
output, err := wrapper.BedrockRuntimeClient.InvokeModel(context.Background(),
&bedrockruntime.InvokeModelInput{
ModelId: aws.String(modelId),
ContentType: aws.String("application/json"),
Body: body,
})
if err != nil {
ProcessError(err, modelId)
}
var response TitanTextResponse
if err := json.Unmarshal(output.Body, &response); err != nil {
log.Fatal("failed to unmarshal", err)
}
return response.Results[0].OutputText, nil
}
For API details, see InvokeModel in AWS SDK for Go API Reference.
Anthropic Claude
InvokeModel
The following code example shows how to send a text message to Anthropic Claude, using the
Invoke Model API.
Anthropic Claude 53
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Invoke the Anthropic Claude 2 foundation model to generate text.
// Each model provider has their own individual request and response formats.
// For the format, ranges, and default values for Anthropic Claude, refer to:
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-claude.html
type ClaudeRequest struct {
Prompt string `json:"prompt"`
MaxTokensToSample int `json:"max_tokens_to_sample"`
Temperature float64 `json:"temperature,omitempty"`
StopSequences []string `json:"stop_sequences,omitempty"`
}
type ClaudeResponse struct {
Completion string `json:"completion"`
}
// Invokes Anthropic Claude on Amazon Bedrock to run an inference using the input
// provided in the request body.
func (wrapper InvokeModelWrapper) InvokeClaude(prompt string) (string, error) {
modelId := "anthropic.claude-v2"
// Anthropic Claude requires enclosing the prompt as follows:
enclosedPrompt := "Human: " + prompt + "\n\nAssistant:"
body, err := json.Marshal(ClaudeRequest{
Prompt: enclosedPrompt,
MaxTokensToSample: 200,
Temperature: 0.5,
StopSequences: []string{"\n\nHuman:"},
})
if err != nil {
log.Fatal("failed to marshal", err)
Anthropic Claude 54
AWS SDK for Go Code Examples Code Examples Guide
}
output, err := wrapper.BedrockRuntimeClient.InvokeModel(context.TODO(),
&bedrockruntime.InvokeModelInput{
ModelId: aws.String(modelId),
ContentType: aws.String("application/json"),
Body: body,
})
if err != nil {
ProcessError(err, modelId)
}
var response ClaudeResponse
if err := json.Unmarshal(output.Body, &response); err != nil {
log.Fatal("failed to unmarshal", err)
}
return response.Completion, nil
}
For API details, see InvokeModel in AWS SDK for Go API Reference.
InvokeModelWithResponseStream
The following code example shows how to send a text message to Anthropic Claude models, using
the Invoke Model API, and print the response stream.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Use the Invoke Model API to send a text message and process the response stream in real-time.
// Each model provider defines their own individual request and response formats.
Anthropic Claude 55
AWS SDK for Go Code Examples Code Examples Guide
// For the format, ranges, and default values for the different models, refer to:
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html
type Request struct {
Prompt string `json:"prompt"`
MaxTokensToSample int `json:"max_tokens_to_sample"`
Temperature float64 `json:"temperature,omitempty"`
}
type Response struct {
Completion string `json:"completion"`
}
// Invokes Anthropic Claude on Amazon Bedrock to run an inference and asynchronously
// process the response stream.
func (wrapper InvokeModelWithResponseStreamWrapper)
InvokeModelWithResponseStream(prompt string) (string, error) {
modelId := "anthropic.claude-v2"
// Anthropic Claude requires you to enclose the prompt as follows:
prefix := "Human: "
postfix := "\n\nAssistant:"
prompt = prefix + prompt + postfix
request := ClaudeRequest{
Prompt: prompt,
MaxTokensToSample: 200,
Temperature: 0.5,
StopSequences: []string{"\n\nHuman:"},
}
body, err := json.Marshal(request)
if err != nil {
log.Panicln("Couldn't marshal the request: ", err)
}
output, err :=
wrapper.BedrockRuntimeClient.InvokeModelWithResponseStream(context.Background(),
&bedrockruntime.InvokeModelWithResponseStreamInput{
Body: body,
ModelId: aws.String(modelId),
ContentType: aws.String("application/json"),
Anthropic Claude 56
AWS SDK for Go Code Examples Code Examples Guide
})
if err != nil {
errMsg := err.Error()
if strings.Contains(errMsg, "no such host") {
log.Printf("The Bedrock service is not available in the selected region. Please
double-check the service availability for your region at https://aws.amazon.com/
about-aws/global-infrastructure/regional-product-services/.\n")
} else if strings.Contains(errMsg, "Could not resolve the foundation model") {
log.Printf("Could not resolve the foundation model from model identifier: \"%v
\". Please verify that the requested model exists and is accessible within the
specified region.\n", modelId)
} else {
log.Printf("Couldn't invoke Anthropic Claude. Here's why: %v\n", err)
}
}
resp, err := processStreamingOutput(output, func(ctx context.Context, part []byte)
error {
fmt.Print(string(part))
return nil
})
if err != nil {
log.Fatal("streaming output processing error: ", err)
}
return resp.Completion, nil
}
type StreamingOutputHandler func(ctx context.Context, part []byte) error
func processStreamingOutput(output
*bedrockruntime.InvokeModelWithResponseStreamOutput, handler
StreamingOutputHandler) (Response, error) {
var combinedResult string
resp := Response{}
for event := range output.GetStream().Events() {
switch v := event.(type) {
case *types.ResponseStreamMemberChunk:
Anthropic Claude 57
AWS SDK for Go Code Examples Code Examples Guide
//fmt.Println("payload", string(v.Value.Bytes))
var resp Response
err := json.NewDecoder(bytes.NewReader(v.Value.Bytes)).Decode(&resp)
if err != nil {
return resp, err
}
err = handler(context.Background(), []byte(resp.Completion))
if err != nil {
return resp, err
}
combinedResult += resp.Completion
case *types.UnknownUnionMember:
fmt.Println("unknown tag:", v.Tag)
default:
fmt.Println("union is nil or unknown type")
}
}
resp.Completion = combinedResult
return resp, nil
}
For API details, see InvokeModelWithResponseStream in AWS SDK for Go API Reference.
Meta Llama
InvokeModel: Llama 2
The following code example shows how to send a text message to Meta Llama 2, using the Invoke
Model API.
Meta Llama 58
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Use the Invoke Model API to send a text message.
// Each model provider has their own individual request and response formats.
// For the format, ranges, and default values for Meta Llama 2 Chat, refer to:
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-meta.html
type Llama2Request struct {
Prompt string `json:"prompt"`
MaxGenLength int `json:"max_gen_len,omitempty"`
Temperature float64 `json:"temperature,omitempty"`
}
type Llama2Response struct {
Generation string `json:"generation"`
}
// Invokes Meta Llama 2 Chat on Amazon Bedrock to run an inference using the input
// provided in the request body.
func (wrapper InvokeModelWrapper) InvokeLlama2(prompt string) (string, error) {
modelId := "meta.llama2-13b-chat-v1"
body, err := json.Marshal(Llama2Request{
Prompt: prompt,
MaxGenLength: 512,
Temperature: 0.5,
})
if err != nil {
log.Fatal("failed to marshal", err)
}
output, err := wrapper.BedrockRuntimeClient.InvokeModel(context.TODO(),
&bedrockruntime.InvokeModelInput{
ModelId: aws.String(modelId),
Meta Llama 59
AWS SDK for Go Code Examples Code Examples Guide
ContentType: aws.String("application/json"),
Body: body,
})
if err != nil {
ProcessError(err, modelId)
}
var response Llama2Response
if err := json.Unmarshal(output.Body, &response); err != nil {
log.Fatal("failed to unmarshal", err)
}
return response.Generation, nil
}
For API details, see InvokeModel in AWS SDK for Go API Reference.
AWS CloudFormation examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with AWS CloudFormation.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Topics
Actions
Actions
DescribeStacks
The following code example shows how to use DescribeStacks.
AWS CloudFormation 60
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
if err != nil || len(output.Stacks) == 0 {
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
For API details, see DescribeStacks in AWS SDK for Go API Reference.
Actions 61
AWS SDK for Go Code Examples Code Examples Guide
CloudWatch Logs examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with CloudWatch Logs.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Topics
Actions
Actions
StartLiveTail
The following code example shows how to use StartLiveTail.
SDK for Go V2
Include the required files.
import (
"context"
"log"
"time"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
)
Handle the events from the Live Tail session.
func handleEventStreamAsync(stream *cloudwatchlogs.StartLiveTailEventStream) {
eventsChan := stream.Events()
for {
CloudWatch Logs 62
AWS SDK for Go Code Examples Code Examples Guide
event := <-eventsChan
switch e := event.(type) {
case *types.StartLiveTailResponseStreamMemberSessionStart:
log.Println("Received SessionStart event")
case *types.StartLiveTailResponseStreamMemberSessionUpdate:
for _, logEvent := range e.Value.SessionResults {
log.Println(*logEvent.Message)
}
default:
// Handle on-stream exceptions
if err := stream.Err(); err != nil {
log.Fatalf("Error occured during streaming: %v", err)
} else if event == nil {
log.Println("Stream is Closed")
return
} else {
log.Fatalf("Unknown event type: %T", e)
}
}
}
}
Start the Live Tail session.
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic("configuration error, " + err.Error())
}
client := cloudwatchlogs.NewFromConfig(cfg)
request := &cloudwatchlogs.StartLiveTailInput{
LogGroupIdentifiers: logGroupIdentifiers,
LogStreamNames: logStreamNames,
LogEventFilterPattern: logEventFilterPattern,
}
response, err := client.StartLiveTail(context.TODO(), request)
// Handle pre-stream Exceptions
if err != nil {
log.Fatalf("Failed to start streaming: %v", err)
}
Actions 63
AWS SDK for Go Code Examples Code Examples Guide
// Start a Goroutine to handle events over stream
stream := response.GetStream()
go handleEventStreamAsync(stream)
Stop the Live Tail session after a period of time has elapsed.
// Close the stream (which ends the session) after a timeout
time.Sleep(10 * time.Second)
stream.Close()
log.Println("Event stream closed")
For API details, see StartLiveTail in AWS SDK for Go API Reference.
Amazon Cognito Identity Provider examples using SDK for Go
V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon Cognito Identity Provider.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Amazon Cognito
The following code examples show how to get started using Amazon Cognito.
Amazon Cognito Identity Provider 64
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
)
// main uses the AWS SDK for Go V2 to create an Amazon Simple Notification Service
// (Amazon SNS) client and list the topics in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
cognitoClient := cognitoidentityprovider.NewFromConfig(sdkConfig)
fmt.Println("Let's list the user pools for your account.")
var pools []types.UserPoolDescriptionType
paginator := cognitoidentityprovider.NewListUserPoolsPaginator(
cognitoClient, &cognitoidentityprovider.ListUserPoolsInput{MaxResults:
aws.Int32(10)})
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.TODO())
Amazon Cognito Identity Provider 65
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't get user pools. Here's why: %v\n", err)
} else {
pools = append(pools, output.UserPools...)
}
}
if len(pools) == 0 {
fmt.Println("You don't have any user pools!")
} else {
for _, pool := range pools {
fmt.Printf("\t%v: %v\n", *pool.Name, *pool.Id)
}
}
}
For API details, see ListUserPools in AWS SDK for Go API Reference.
Topics
Actions
Scenarios
Actions
AdminCreateUser
The following code example shows how to use AdminCreateUser.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
Actions 66
AWS SDK for Go Code Examples Code Examples Guide
CognitoClient *cognitoidentityprovider.Client
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
}
}
return err
}
For API details, see AdminCreateUser in AWS SDK for Go API Reference.
AdminSetUserPassword
The following code example shows how to use AdminSetUserPassword.
Actions 67
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
return err
}
For API details, see AdminSetUserPassword in AWS SDK for Go API Reference.
Actions 68
AWS SDK for Go Code Examples Code Examples Guide
ConfirmForgotPassword
The following code example shows how to use ConfirmForgotPassword.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
Actions 69
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ConfirmForgotPassword in AWS SDK for Go API Reference.
DeleteUser
The following code example shows how to use DeleteUser.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// DeleteUser removes a user from the user pool.
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
For API details, see DeleteUser in AWS SDK for Go API Reference.
ForgotPassword
The following code example shows how to use ForgotPassword.
Actions 70
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
For API details, see ForgotPassword in AWS SDK for Go API Reference.
InitiateAuth
The following code example shows how to use InitiateAuth.
Actions 71
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
For API details, see InitiateAuth in AWS SDK for Go API Reference.
Actions 72
AWS SDK for Go Code Examples Code Examples Guide
ListUserPools
The following code example shows how to use ListUserPools.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
)
// main uses the AWS SDK for Go V2 to create an Amazon Simple Notification Service
// (Amazon SNS) client and list the topics in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
cognitoClient := cognitoidentityprovider.NewFromConfig(sdkConfig)
fmt.Println("Let's list the user pools for your account.")
var pools []types.UserPoolDescriptionType
paginator := cognitoidentityprovider.NewListUserPoolsPaginator(
Actions 73
AWS SDK for Go Code Examples Code Examples Guide
cognitoClient, &cognitoidentityprovider.ListUserPoolsInput{MaxResults:
aws.Int32(10)})
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get user pools. Here's why: %v\n", err)
} else {
pools = append(pools, output.UserPools...)
}
}
if len(pools) == 0 {
fmt.Println("You don't have any user pools!")
} else {
for _, pool := range pools {
fmt.Printf("\t%v: %v\n", *pool.Name, *pool.Id)
}
}
}
For API details, see ListUserPools in AWS SDK for Go API Reference.
SignUp
The following code example shows how to use SignUp.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
Actions 74
AWS SDK for Go Code Examples Code Examples Guide
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
For API details, see SignUp in AWS SDK for Go API Reference.
UpdateUserPool
The following code example shows how to use UpdateUserPool.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Actions 75
AWS SDK for Go Code Examples Code Examples Guide
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
Actions 76
AWS SDK for Go Code Examples Code Examples Guide
lambdaConfig.PostAuthentication = trigger.HandlerArn
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
For API details, see UpdateUserPool in AWS SDK for Go API Reference.
Scenarios
Automatically confirm known users with a Lambda function
The following code example shows how to automatically confirm known Amazon Cognito users
with a Lambda function.
Configure a user pool to call a Lambda function for the PreSignUp trigger.
Sign up a user with Amazon Cognito.
The Lambda function scans a DynamoDB table and automatically confirms known users.
Sign in as the new user, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
Scenarios 77
AWS SDK for Go Code Examples Code Examples Guide
// AutoConfirm separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type AutoConfirm struct {
helper IScenarioHelper
questioner demotools.IQuestioner
resources Resources
cognitoActor *actions.CognitoActions
}
// NewAutoConfirm constructs a new auto confirm runner.
func NewAutoConfirm(sdkConfig aws.Config, questioner demotools.IQuestioner, helper
IScenarioHelper) AutoConfirm {
scenario := AutoConfirm{
helper: helper,
questioner: questioner,
resources: Resources{},
cognitoActor: &actions.CognitoActions{CognitoClient:
cognitoidentityprovider.NewFromConfig(sdkConfig)},
}
scenario.resources.init(scenario.cognitoActor, questioner)
return scenario
}
// AddPreSignUpTrigger adds a Lambda handler as an invocation target for the
PreSignUp trigger.
func (runner *AutoConfirm) AddPreSignUpTrigger(userPoolId string, functionArn
string) {
log.Printf("Let's add a Lambda function to handle the PreSignUp trigger from
Cognito.\n" +
"This trigger happens when a user signs up, and lets your function take action
before the main Cognito\n" +
"sign up processing occurs.\n")
err := runner.cognitoActor.UpdateTriggers(
userPoolId,
actions.TriggerInfo{Trigger: actions.PreSignUp, HandlerArn:
aws.String(functionArn)})
if err != nil {
panic(err)
}
log.Printf("Lambda function %v added to user pool %v to handle the PreSignUp
trigger.\n",
Scenarios 78
AWS SDK for Go Code Examples Code Examples Guide
functionArn, userPoolId)
}
// SignUpUser signs up a user from the known user table with a password you specify.
func (runner *AutoConfirm) SignUpUser(clientId string, usersTable string) (string,
string) {
log.Println("Let's sign up a user to your Cognito user pool. When the user's email
matches an email in the\n" +
"DynamoDB known users table, it is automatically verified and the user is
confirmed.")
knownUsers, err := runner.helper.GetKnownUsers(usersTable)
if err != nil {
panic(err)
}
userChoice := runner.questioner.AskChoice("Which user do you want to use?\n",
knownUsers.UserNameList())
user := knownUsers.Users[userChoice]
var signedUp bool
var userConfirmed bool
password := runner.questioner.AskPassword("Enter a password that has at least eight
characters, uppercase, lowercase, numbers and symbols.\n"+
"(the password will not display as you type):", 8)
for !signedUp {
log.Printf("Signing up user '%v' with email '%v' to Cognito.\n", user.UserName,
user.UserEmail)
userConfirmed, err = runner.cognitoActor.SignUp(clientId, user.UserName, password,
user.UserEmail)
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
password = runner.questioner.AskPassword("Enter another password:", 8)
} else {
panic(err)
}
} else {
signedUp = true
}
}
log.Printf("User %v signed up, confirmed = %v.\n", user.UserName, userConfirmed)
log.Println(strings.Repeat("-", 88))
Scenarios 79
AWS SDK for Go Code Examples Code Examples Guide
return user.UserName, password
}
// SignInUser signs in a user.
func (runner *AutoConfirm) SignInUser(clientId string, userName string, password
string) string {
runner.questioner.Ask("Press Enter when you're ready to continue.")
log.Printf("Let's sign in as %v...\n", userName)
authResult, err := runner.cognitoActor.SignIn(clientId, userName, password)
if err != nil {
panic(err)
}
log.Printf("Successfully signed in. Your access token starts with: %v...\n",
(*authResult.AccessToken)[:10])
log.Println(strings.Repeat("-", 88))
return *authResult.AccessToken
}
// Run runs the scenario.
func (runner *AutoConfirm) Run(stackName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
runner.resources.Cleanup()
}
}()
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome\n")
log.Println(strings.Repeat("-", 88))
stackOutputs, err := runner.helper.GetStackOutputs(stackName)
if err != nil {
panic(err)
}
runner.resources.userPoolId = stackOutputs["UserPoolId"]
runner.helper.PopulateUserTable(stackOutputs["TableName"])
runner.AddPreSignUpTrigger(stackOutputs["UserPoolId"],
stackOutputs["AutoConfirmFunctionArn"])
runner.resources.triggers = append(runner.resources.triggers, actions.PreSignUp)
userName, password := runner.SignUpUser(stackOutputs["UserPoolClientId"],
stackOutputs["TableName"])
Scenarios 80
AWS SDK for Go Code Examples Code Examples Guide
runner.helper.ListRecentLogEvents(stackOutputs["AutoConfirmFunction"])
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
runner.SignInUser(stackOutputs["UserPoolClientId"], userName, password))
runner.resources.Cleanup()
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Handle the PreSignUp trigger with a Lambda function.
const TABLE_NAME = "TABLE_NAME"
// UserInfo defines structured user data that can be marshalled to a DynamoDB
format.
type UserInfo struct {
UserName string `dynamodbav:"UserName"`
UserEmail string `dynamodbav:"UserEmail"`
}
// GetKey marshals the user email value to a DynamoDB key format.
func (user UserInfo) GetKey() map[string]dynamodbtypes.AttributeValue {
userEmail, err := attributevalue.Marshal(user.UserEmail)
if err != nil {
panic(err)
}
return map[string]dynamodbtypes.AttributeValue{"UserEmail": userEmail}
}
type handler struct {
dynamoClient *dynamodb.Client
}
// HandleRequest handles the PreSignUp event by looking up a user in an Amazon
DynamoDB table and
// specifying whether they should be confirmed and verified.
Scenarios 81
AWS SDK for Go Code Examples Code Examples Guide
func (h *handler) HandleRequest(ctx context.Context, event
events.CognitoEventUserPoolsPreSignup) (events.CognitoEventUserPoolsPreSignup,
error) {
log.Printf("Received presignup from %v for user '%v'", event.TriggerSource,
event.UserName)
if event.TriggerSource != "PreSignUp_SignUp" {
// Other trigger sources, such as PreSignUp_AdminInitiateAuth, ignore the response
from this handler.
return event, nil
}
tableName := os.Getenv(TABLE_NAME)
user := UserInfo{
UserEmail: event.Request.UserAttributes["email"],
}
log.Printf("Looking up email %v in table %v.\n", user.UserEmail, tableName)
output, err := h.dynamoClient.GetItem(ctx, &dynamodb.GetItemInput{
Key: user.GetKey(),
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Error looking up email %v.\n", user.UserEmail)
return event, err
}
if output.Item == nil {
log.Printf("Email %v not found. Email verification is required.\n",
user.UserEmail)
return event, err
}
err = attributevalue.UnmarshalMap(output.Item, &user)
if err != nil {
log.Printf("Couldn't unmarshal DynamoDB item. Here's why: %v\n", err)
return event, err
}
if user.UserName != event.UserName {
log.Printf("UserEmail %v found, but stored UserName '%v' does not match supplied
UserName '%v'. Verification is required.\n",
user.UserEmail, user.UserName, event.UserName)
} else {
log.Printf("UserEmail %v found with matching UserName %v. User is confirmed.\n",
user.UserEmail, user.UserName)
event.Response.AutoConfirmUser = true
event.Response.AutoVerifyEmail = true
Scenarios 82
AWS SDK for Go Code Examples Code Examples Guide
}
return event, err
}
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Panicln(err)
}
h := handler{
dynamoClient: dynamodb.NewFromConfig(sdkConfig),
}
lambda.Start(h.HandleRequest)
}
Create a struct that performs common tasks.
// IScenarioHelper defines common functions used by the workflows in this example.
type IScenarioHelper interface {
Pause(secs int)
GetStackOutputs(stackName string) (actions.StackOutputs, error)
PopulateUserTable(tableName string)
GetKnownUsers(tableName string) (actions.UserList, error)
AddKnownUser(tableName string, user actions.User)
ListRecentLogEvents(functionName string)
}
// ScenarioHelper contains AWS wrapper structs used by the workflows in this
example.
type ScenarioHelper struct {
questioner demotools.IQuestioner
dynamoActor *actions.DynamoActions
cfnActor *actions.CloudFormationActions
cwlActor *actions.CloudWatchLogsActions
isTestRun bool
}
// NewScenarioHelper constructs a new scenario helper.
Scenarios 83
AWS SDK for Go Code Examples Code Examples Guide
func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner)
ScenarioHelper {
scenario := ScenarioHelper{
questioner: questioner,
dynamoActor: &actions.DynamoActions{DynamoClient:
dynamodb.NewFromConfig(sdkConfig)},
cfnActor: &actions.CloudFormationActions{CfnClient:
cloudformation.NewFromConfig(sdkConfig)},
cwlActor: &actions.CloudWatchLogsActions{CwlClient:
cloudwatchlogs.NewFromConfig(sdkConfig)},
}
return scenario
}
// Pause waits for the specified number of seconds.
func (helper ScenarioHelper) Pause(secs int) {
if !helper.isTestRun {
time.Sleep(time.Duration(secs) * time.Second)
}
}
// GetStackOutputs gets the outputs from the specified CloudFormation stack in a
structured format.
func (helper ScenarioHelper) GetStackOutputs(stackName string)
(actions.StackOutputs, error) {
return helper.cfnActor.GetOutputs(stackName), nil
}
// PopulateUserTable fills the known user table with example data.
func (helper ScenarioHelper) PopulateUserTable(tableName string) {
log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this
example.\n", tableName)
err := helper.dynamoActor.PopulateTable(tableName)
if err != nil {
panic(err)
}
}
// GetKnownUsers gets the users from the known users table in a structured format.
func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList,
error) {
knownUsers, err := helper.dynamoActor.Scan(tableName)
if err != nil {
Scenarios 84
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName,
err)
}
return knownUsers, err
}
// AddKnownUser adds a user to the known users table.
func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) {
log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...
\n",
user.UserName, user.UserEmail)
err := helper.dynamoActor.AddUser(tableName, user)
if err != nil {
panic(err)
}
}
// ListRecentLogEvents gets the most recent log stream and events for the specified
Lambda function and displays them.
func (helper ScenarioHelper) ListRecentLogEvents(functionName string) {
log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...")
helper.Pause(10)
log.Println("Okay, let's check the logs to find what's happened recently with your
Lambda function.")
logStream, err := helper.cwlActor.GetLatestLogStream(functionName)
if err != nil {
panic(err)
}
log.Printf("Getting some recent events from log stream %v\n",
*logStream.LogStreamName)
events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName,
10)
if err != nil {
panic(err)
}
for _, event := range events {
log.Printf("\t%v", *event.Message)
}
log.Println(strings.Repeat("-", 88))
}
Scenarios 85
AWS SDK for Go Code Examples Code Examples Guide
Create a struct that wraps Amazon Cognito actions.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
Scenarios 86
AWS SDK for Go Code Examples Code Examples Guide
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
lambdaConfig.PostAuthentication = trigger.HandlerArn
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
Scenarios 87
AWS SDK for Go Code Examples Code Examples Guide
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
Scenarios 88
AWS SDK for Go Code Examples Code Examples Guide
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
// DeleteUser removes a user from the user pool.
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
Scenarios 89
AWS SDK for Go Code Examples Code Examples Guide
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
}
}
return err
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
Scenarios 90
AWS SDK for Go Code Examples Code Examples Guide
return err
}
Create a struct that wraps DynamoDB actions.
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type DynamoActions struct {
DynamoClient *dynamodb.Client
}
// User defines structured user data.
type User struct {
UserName string
UserEmail string
LastLogin *LoginInfo `dynamodbav:",omitempty"`
}
// LoginInfo defines structured custom login data.
type LoginInfo struct {
UserPoolId string
ClientId string
Time string
}
// UserList defines a list of users.
type UserList struct {
Users []User
}
// UserNameList returns the usernames contained in a UserList as a list of strings.
func (users *UserList) UserNameList() []string {
names := make([]string, len(users.Users))
for i := 0; i < len(users.Users); i++ {
names[i] = users.Users[i].UserName
}
return names
}
Scenarios 91
AWS SDK for Go Code Examples Code Examples Guide
// PopulateTable adds a set of test users to the table.
func (actor DynamoActions) PopulateTable(tableName string) error {
var err error
var item map[string]types.AttributeValue
var writeReqs []types.WriteRequest
for i := 1; i < 4; i++ {
item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v",
i), UserEmail: fmt.Sprintf("test_email_%[email protected]", i)})
if err != nil {
log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err)
return err
}
writeReqs = append(writeReqs, types.WriteRequest{PutRequest:
&types.PutRequest{Item: item}})
}
_, err = actor.DynamoClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{tableName: writeReqs},
})
if err != nil {
log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName,
err)
}
return err
}
// Scan scans the table for all items.
func (actor DynamoActions) Scan(tableName string) (UserList, error) {
var userList UserList
output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err)
} else {
err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users)
if err != nil {
log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err)
}
}
return userList, err
}
// AddUser adds a user item to a table.
Scenarios 92
AWS SDK for Go Code Examples Code Examples Guide
func (actor DynamoActions) AddUser(tableName string, user User) error {
userItem, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshall user to item. Here's why: %v\n", err)
}
_, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
Item: userItem,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err)
}
return err
}
Create a struct that wraps CloudWatch Logs actions.
type CloudWatchLogsActions struct {
CwlClient *cloudwatchlogs.Client
}
// GetLatestLogStream gets the most recent log stream for a Lambda function.
func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string)
(types.LogStream, error) {
var logStream types.LogStream
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.DescribeLogStreams(context.TODO(),
&cloudwatchlogs.DescribeLogStreamsInput{
Descending: aws.Bool(true),
Limit: aws.Int32(1),
LogGroupName: aws.String(logGroupName),
OrderBy: types.OrderByLastEventTime,
})
if err != nil {
log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n",
logGroupName, err)
} else {
logStream = output.LogStreams[0]
}
return logStream, err
Scenarios 93
AWS SDK for Go Code Examples Code Examples Guide
}
// GetLogEvents gets the most recent eventCount events from the specified log
stream.
func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName
string, eventCount int32) (
[]types.OutputLogEvent, error) {
var events []types.OutputLogEvent
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.GetLogEvents(context.TODO(),
&cloudwatchlogs.GetLogEventsInput{
LogStreamName: aws.String(logStreamName),
Limit: aws.Int32(eventCount),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n",
logStreamName, err)
} else {
events = output.Events
}
return events, err
}
Create a struct that wraps AWS CloudFormation actions.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
Scenarios 94
AWS SDK for Go Code Examples Code Examples Guide
if err != nil || len(output.Stacks) == 0 {
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
Clean up resources.
// Resources keeps track of AWS resources created during an example and handles
// cleanup when the example finishes.
type Resources struct {
userPoolId string
userAccessTokens []string
triggers []actions.Trigger
cognitoActor *actions.CognitoActions
questioner demotools.IQuestioner
}
func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner
demotools.IQuestioner) {
resources.userAccessTokens = []string{}
resources.triggers = []actions.Trigger{}
resources.cognitoActor = cognitoActor
resources.questioner = questioner
}
// Cleanup deletes all AWS resources created during an example.
func (resources *Resources) Cleanup() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources \n"
+
"that were created for this scenario.")
Scenarios 95
AWS SDK for Go Code Examples Code Examples Guide
}
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
if wantDelete {
for _, accessToken := range resources.userAccessTokens {
err := resources.cognitoActor.DeleteUser(accessToken)
if err != nil {
log.Println("Couldn't delete user during cleanup.")
panic(err)
}
log.Println("Deleted user.")
}
triggerList := make([]actions.TriggerInfo, len(resources.triggers))
for i := 0; i < len(resources.triggers); i++ {
triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn:
nil}
}
err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...)
if err != nil {
log.Println("Couldn't update Cognito triggers during cleanup.")
panic(err)
}
log.Println("Removed Cognito triggers from user pool.")
} else {
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
DeleteUser
InitiateAuth
SignUp
UpdateUserPool
Scenarios 96
AWS SDK for Go Code Examples Code Examples Guide
Automatically migrate known users with a Lambda function
The following code example shows how to automatically migrate known Amazon Cognito users
with a Lambda function.
Configure a user pool to call a Lambda function for the MigrateUser trigger.
Sign in to Amazon Cognito with a username and email that is not in the user pool.
The Lambda function scans a DynamoDB table and automatically migrates known users to the
user pool.
Perform the forgot password flow to reset the password for the migrated user.
Sign in as the new user, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
import (
"errors"
"fmt"
"log"
"strings"
"user_pools_and_lambda_triggers/actions"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
"github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools"
)
// MigrateUser separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type MigrateUser struct {
Scenarios 97
AWS SDK for Go Code Examples Code Examples Guide
helper IScenarioHelper
questioner demotools.IQuestioner
resources Resources
cognitoActor *actions.CognitoActions
}
// NewMigrateUser constructs a new migrate user runner.
func NewMigrateUser(sdkConfig aws.Config, questioner demotools.IQuestioner, helper
IScenarioHelper) MigrateUser {
scenario := MigrateUser{
helper: helper,
questioner: questioner,
resources: Resources{},
cognitoActor: &actions.CognitoActions{CognitoClient:
cognitoidentityprovider.NewFromConfig(sdkConfig)},
}
scenario.resources.init(scenario.cognitoActor, questioner)
return scenario
}
// AddMigrateUserTrigger adds a Lambda handler as an invocation target for the
MigrateUser trigger.
func (runner *MigrateUser) AddMigrateUserTrigger(userPoolId string, functionArn
string) {
log.Printf("Let's add a Lambda function to handle the MigrateUser trigger from
Cognito.\n" +
"This trigger happens when an unknown user signs in, and lets your function take
action before Cognito\n" +
"rejects the user.\n\n")
err := runner.cognitoActor.UpdateTriggers(
userPoolId,
actions.TriggerInfo{Trigger: actions.UserMigration, HandlerArn:
aws.String(functionArn)})
if err != nil {
panic(err)
}
log.Printf("Lambda function %v added to user pool %v to handle the MigrateUser
trigger.\n",
functionArn, userPoolId)
log.Println(strings.Repeat("-", 88))
}
Scenarios 98
AWS SDK for Go Code Examples Code Examples Guide
// SignInUser adds a new user to the known users table and signs that user in to
Amazon Cognito.
func (runner *MigrateUser) SignInUser(usersTable string, clientId string) (bool,
actions.User) {
log.Println("Let's sign in a user to your Cognito user pool. When the username and
email matches an entry in the\n" +
"DynamoDB known users table, the email is automatically verified and the user is
migrated to the Cognito user pool.")
user := actions.User{}
user.UserName = runner.questioner.Ask("\nEnter a username:")
user.UserEmail = runner.questioner.Ask("\nEnter an email that you own. This email
will be used to confirm user migration\n" +
"during this example:")
runner.helper.AddKnownUser(usersTable, user)
var err error
var resetRequired *types.PasswordResetRequiredException
var authResult *types.AuthenticationResultType
signedIn := false
for !signedIn && resetRequired == nil {
log.Printf("Signing in to Cognito as user '%v'. The expected result is a
PasswordResetRequiredException.\n\n", user.UserName)
authResult, err = runner.cognitoActor.SignIn(clientId, user.UserName, "_")
if err != nil {
if errors.As(err, &resetRequired) {
log.Printf("\nUser '%v' is not in the Cognito user pool but was found in the
DynamoDB known users table.\n"+
"User migration is started and a password reset is required.", user.UserName)
} else {
panic(err)
}
} else {
log.Printf("User '%v' successfully signed in. This is unexpected and probably
means you have not\n"+
"cleaned up a previous run of this scenario, so the user exist in the Cognito
user pool.\n"+
"You can continue this example and select to clean up resources, or manually
remove\n"+
"the user from your user pool and try again.", user.UserName)
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
*authResult.AccessToken)
signedIn = true
Scenarios 99
AWS SDK for Go Code Examples Code Examples Guide
}
}
log.Println(strings.Repeat("-", 88))
return resetRequired != nil, user
}
// ResetPassword starts a password recovery flow.
func (runner *MigrateUser) ResetPassword(clientId string, user actions.User) {
wantCode := runner.questioner.AskBool(fmt.Sprintf("In order to migrate the user to
Cognito, you must be able to receive a confirmation\n"+
"code by email at %v. Do you want to send a code (y/n)?", user.UserEmail), "y")
if !wantCode {
log.Println("To complete this example and successfully migrate a user to Cognito,
you must enter an email\n" +
"you own that can receive a confirmation code.")
return
}
codeDelivery, err := runner.cognitoActor.ForgotPassword(clientId, user.UserName)
if err != nil {
panic(err)
}
log.Printf("\nA confirmation code has been sent to %v.", *codeDelivery.Destination)
code := runner.questioner.Ask("Check your email and enter it here:")
confirmed := false
password := runner.questioner.AskPassword("\nEnter a password that has at least
eight characters, uppercase, lowercase, numbers and symbols.\n"+
"(the password will not display as you type):", 8)
for !confirmed {
log.Printf("\nConfirming password reset for user '%v'.\n", user.UserName)
err = runner.cognitoActor.ConfirmForgotPassword(clientId, code, user.UserName,
password)
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
password = runner.questioner.AskPassword("\nEnter another password:", 8)
} else {
panic(err)
}
} else {
confirmed = true
}
}
Scenarios 100
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("User '%v' successfully confirmed and migrated.\n", user.UserName)
log.Println("Signing in with your username and password...")
authResult, err := runner.cognitoActor.SignIn(clientId, user.UserName, password)
if err != nil {
panic(err)
}
log.Printf("Successfully signed in. Your access token starts with: %v...\n",
(*authResult.AccessToken)[:10])
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
*authResult.AccessToken)
log.Println(strings.Repeat("-", 88))
}
// Run runs the scenario.
func (runner *MigrateUser) Run(stackName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
runner.resources.Cleanup()
}
}()
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome\n")
log.Println(strings.Repeat("-", 88))
stackOutputs, err := runner.helper.GetStackOutputs(stackName)
if err != nil {
panic(err)
}
runner.resources.userPoolId = stackOutputs["UserPoolId"]
runner.AddMigrateUserTrigger(stackOutputs["UserPoolId"],
stackOutputs["MigrateUserFunctionArn"])
runner.resources.triggers = append(runner.resources.triggers,
actions.UserMigration)
resetNeeded, user := runner.SignInUser(stackOutputs["TableName"],
stackOutputs["UserPoolClientId"])
if resetNeeded {
runner.helper.ListRecentLogEvents(stackOutputs["MigrateUserFunction"])
runner.ResetPassword(stackOutputs["UserPoolClientId"], user)
}
Scenarios 101
AWS SDK for Go Code Examples Code Examples Guide
runner.resources.Cleanup()
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Handle the MigrateUser trigger with a Lambda function.
const TABLE_NAME = "TABLE_NAME"
// UserInfo defines structured user data that can be marshalled to a DynamoDB
format.
type UserInfo struct {
UserName string `dynamodbav:"UserName"`
UserEmail string `dynamodbav:"UserEmail"`
}
type handler struct {
dynamoClient *dynamodb.Client
}
// HandleRequest handles the MigrateUser event by looking up a user in an Amazon
DynamoDB table and
// specifying whether they should be migrated to the user pool.
func (h *handler) HandleRequest(ctx context.Context, event
events.CognitoEventUserPoolsMigrateUser) (events.CognitoEventUserPoolsMigrateUser,
error) {
log.Printf("Received migrate trigger from %v for user '%v'", event.TriggerSource,
event.UserName)
if event.TriggerSource != "UserMigration_Authentication" {
return event, nil
}
tableName := os.Getenv(TABLE_NAME)
user := UserInfo{
UserName: event.UserName,
}
log.Printf("Looking up user '%v' in table %v.\n", user.UserName, tableName)
filterEx := expression.Name("UserName").Equal(expression.Value(user.UserName))
Scenarios 102
AWS SDK for Go Code Examples Code Examples Guide
expr, err := expression.NewBuilder().WithFilter(filterEx).Build()
if err != nil {
log.Printf("Error building expression to query for user '%v'.\n", user.UserName)
return event, err
}
output, err := h.dynamoClient.Scan(ctx, &dynamodb.ScanInput{
TableName: aws.String(tableName),
FilterExpression: expr.Filter(),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
})
if err != nil {
log.Printf("Error looking up user '%v'.\n", user.UserName)
return event, err
}
if output.Items == nil || len(output.Items) == 0 {
log.Printf("User '%v' not found, not migrating user.\n", user.UserName)
return event, err
}
var users []UserInfo
err = attributevalue.UnmarshalListOfMaps(output.Items, &users)
if err != nil {
log.Printf("Couldn't unmarshal DynamoDB items. Here's why: %v\n", err)
return event, err
}
user = users[0]
log.Printf("UserName '%v' found with email %v. User is migrated and must reset
password.\n", user.UserName, user.UserEmail)
event.CognitoEventUserPoolsMigrateUserResponse.UserAttributes = map[string]string{
"email": user.UserEmail,
"email_verified": "true", // email_verified is required for the forgot password
flow.
}
event.CognitoEventUserPoolsMigrateUserResponse.FinalUserStatus = "RESET_REQUIRED"
event.CognitoEventUserPoolsMigrateUserResponse.MessageAction = "SUPPRESS"
return event, err
}
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
Scenarios 103
AWS SDK for Go Code Examples Code Examples Guide
log.Panicln(err)
}
h := handler{
dynamoClient: dynamodb.NewFromConfig(sdkConfig),
}
lambda.Start(h.HandleRequest)
}
Create a struct that performs common tasks.
// IScenarioHelper defines common functions used by the workflows in this example.
type IScenarioHelper interface {
Pause(secs int)
GetStackOutputs(stackName string) (actions.StackOutputs, error)
PopulateUserTable(tableName string)
GetKnownUsers(tableName string) (actions.UserList, error)
AddKnownUser(tableName string, user actions.User)
ListRecentLogEvents(functionName string)
}
// ScenarioHelper contains AWS wrapper structs used by the workflows in this
example.
type ScenarioHelper struct {
questioner demotools.IQuestioner
dynamoActor *actions.DynamoActions
cfnActor *actions.CloudFormationActions
cwlActor *actions.CloudWatchLogsActions
isTestRun bool
}
// NewScenarioHelper constructs a new scenario helper.
func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner)
ScenarioHelper {
scenario := ScenarioHelper{
questioner: questioner,
dynamoActor: &actions.DynamoActions{DynamoClient:
dynamodb.NewFromConfig(sdkConfig)},
cfnActor: &actions.CloudFormationActions{CfnClient:
cloudformation.NewFromConfig(sdkConfig)},
Scenarios 104
AWS SDK for Go Code Examples Code Examples Guide
cwlActor: &actions.CloudWatchLogsActions{CwlClient:
cloudwatchlogs.NewFromConfig(sdkConfig)},
}
return scenario
}
// Pause waits for the specified number of seconds.
func (helper ScenarioHelper) Pause(secs int) {
if !helper.isTestRun {
time.Sleep(time.Duration(secs) * time.Second)
}
}
// GetStackOutputs gets the outputs from the specified CloudFormation stack in a
structured format.
func (helper ScenarioHelper) GetStackOutputs(stackName string)
(actions.StackOutputs, error) {
return helper.cfnActor.GetOutputs(stackName), nil
}
// PopulateUserTable fills the known user table with example data.
func (helper ScenarioHelper) PopulateUserTable(tableName string) {
log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this
example.\n", tableName)
err := helper.dynamoActor.PopulateTable(tableName)
if err != nil {
panic(err)
}
}
// GetKnownUsers gets the users from the known users table in a structured format.
func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList,
error) {
knownUsers, err := helper.dynamoActor.Scan(tableName)
if err != nil {
log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName,
err)
}
return knownUsers, err
}
// AddKnownUser adds a user to the known users table.
func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) {
Scenarios 105
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...
\n",
user.UserName, user.UserEmail)
err := helper.dynamoActor.AddUser(tableName, user)
if err != nil {
panic(err)
}
}
// ListRecentLogEvents gets the most recent log stream and events for the specified
Lambda function and displays them.
func (helper ScenarioHelper) ListRecentLogEvents(functionName string) {
log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...")
helper.Pause(10)
log.Println("Okay, let's check the logs to find what's happened recently with your
Lambda function.")
logStream, err := helper.cwlActor.GetLatestLogStream(functionName)
if err != nil {
panic(err)
}
log.Printf("Getting some recent events from log stream %v\n",
*logStream.LogStreamName)
events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName,
10)
if err != nil {
panic(err)
}
for _, event := range events {
log.Printf("\t%v", *event.Message)
}
log.Println(strings.Repeat("-", 88))
}
Create a struct that wraps Amazon Cognito actions.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
Scenarios 106
AWS SDK for Go Code Examples Code Examples Guide
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
lambdaConfig.PostAuthentication = trigger.HandlerArn
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
Scenarios 107
AWS SDK for Go Code Examples Code Examples Guide
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
Scenarios 108
AWS SDK for Go Code Examples Code Examples Guide
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
Scenarios 109
AWS SDK for Go Code Examples Code Examples Guide
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
// DeleteUser removes a user from the user pool.
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
Scenarios 110
AWS SDK for Go Code Examples Code Examples Guide
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
}
}
return err
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
return err
}
Create a struct that wraps DynamoDB actions.
Scenarios 111
AWS SDK for Go Code Examples Code Examples Guide
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type DynamoActions struct {
DynamoClient *dynamodb.Client
}
// User defines structured user data.
type User struct {
UserName string
UserEmail string
LastLogin *LoginInfo `dynamodbav:",omitempty"`
}
// LoginInfo defines structured custom login data.
type LoginInfo struct {
UserPoolId string
ClientId string
Time string
}
// UserList defines a list of users.
type UserList struct {
Users []User
}
// UserNameList returns the usernames contained in a UserList as a list of strings.
func (users *UserList) UserNameList() []string {
names := make([]string, len(users.Users))
for i := 0; i < len(users.Users); i++ {
names[i] = users.Users[i].UserName
}
return names
}
// PopulateTable adds a set of test users to the table.
func (actor DynamoActions) PopulateTable(tableName string) error {
var err error
var item map[string]types.AttributeValue
var writeReqs []types.WriteRequest
for i := 1; i < 4; i++ {
Scenarios 112
AWS SDK for Go Code Examples Code Examples Guide
item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v",
i), UserEmail: fmt.Sprintf("test_email_%[email protected]", i)})
if err != nil {
log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err)
return err
}
writeReqs = append(writeReqs, types.WriteRequest{PutRequest:
&types.PutRequest{Item: item}})
}
_, err = actor.DynamoClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{tableName: writeReqs},
})
if err != nil {
log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName,
err)
}
return err
}
// Scan scans the table for all items.
func (actor DynamoActions) Scan(tableName string) (UserList, error) {
var userList UserList
output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err)
} else {
err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users)
if err != nil {
log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err)
}
}
return userList, err
}
// AddUser adds a user item to a table.
func (actor DynamoActions) AddUser(tableName string, user User) error {
userItem, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshall user to item. Here's why: %v\n", err)
}
_, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
Scenarios 113
AWS SDK for Go Code Examples Code Examples Guide
Item: userItem,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err)
}
return err
}
Create a struct that wraps CloudWatch Logs actions.
type CloudWatchLogsActions struct {
CwlClient *cloudwatchlogs.Client
}
// GetLatestLogStream gets the most recent log stream for a Lambda function.
func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string)
(types.LogStream, error) {
var logStream types.LogStream
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.DescribeLogStreams(context.TODO(),
&cloudwatchlogs.DescribeLogStreamsInput{
Descending: aws.Bool(true),
Limit: aws.Int32(1),
LogGroupName: aws.String(logGroupName),
OrderBy: types.OrderByLastEventTime,
})
if err != nil {
log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n",
logGroupName, err)
} else {
logStream = output.LogStreams[0]
}
return logStream, err
}
// GetLogEvents gets the most recent eventCount events from the specified log
stream.
func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName
string, eventCount int32) (
Scenarios 114
AWS SDK for Go Code Examples Code Examples Guide
[]types.OutputLogEvent, error) {
var events []types.OutputLogEvent
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.GetLogEvents(context.TODO(),
&cloudwatchlogs.GetLogEventsInput{
LogStreamName: aws.String(logStreamName),
Limit: aws.Int32(eventCount),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n",
logStreamName, err)
} else {
events = output.Events
}
return events, err
}
Create a struct that wraps AWS CloudFormation actions.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
if err != nil || len(output.Stacks) == 0 {
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
Scenarios 115
AWS SDK for Go Code Examples Code Examples Guide
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
Clean up resources.
// Resources keeps track of AWS resources created during an example and handles
// cleanup when the example finishes.
type Resources struct {
userPoolId string
userAccessTokens []string
triggers []actions.Trigger
cognitoActor *actions.CognitoActions
questioner demotools.IQuestioner
}
func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner
demotools.IQuestioner) {
resources.userAccessTokens = []string{}
resources.triggers = []actions.Trigger{}
resources.cognitoActor = cognitoActor
resources.questioner = questioner
}
// Cleanup deletes all AWS resources created during an example.
func (resources *Resources) Cleanup() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources \n"
+
"that were created for this scenario.")
}
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
Scenarios 116
AWS SDK for Go Code Examples Code Examples Guide
if wantDelete {
for _, accessToken := range resources.userAccessTokens {
err := resources.cognitoActor.DeleteUser(accessToken)
if err != nil {
log.Println("Couldn't delete user during cleanup.")
panic(err)
}
log.Println("Deleted user.")
}
triggerList := make([]actions.TriggerInfo, len(resources.triggers))
for i := 0; i < len(resources.triggers); i++ {
triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn:
nil}
}
err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...)
if err != nil {
log.Println("Couldn't update Cognito triggers during cleanup.")
panic(err)
}
log.Println("Removed Cognito triggers from user pool.")
} else {
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
ConfirmForgotPassword
DeleteUser
ForgotPassword
InitiateAuth
SignUp
UpdateUserPool
Write custom activity data with a Lambda function after Amazon Cognito user authentication
The following code example shows how to write custom activity data with a Lambda function after
Amazon Cognito user authentication.
Scenarios 117
AWS SDK for Go Code Examples Code Examples Guide
Use administrator functions to add a user to a user pool.
Configure a user pool to call a Lambda function for the PostAuthentication trigger.
Sign the new user in to Amazon Cognito.
The Lambda function writes custom information to CloudWatch Logs and to an DynamoDB
table.
Get and display custom data from the DynamoDB table, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
// ActivityLog separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type ActivityLog struct {
helper IScenarioHelper
questioner demotools.IQuestioner
resources Resources
cognitoActor *actions.CognitoActions
}
// NewActivityLog constructs a new activity log runner.
func NewActivityLog(sdkConfig aws.Config, questioner demotools.IQuestioner, helper
IScenarioHelper) ActivityLog {
scenario := ActivityLog{
helper: helper,
questioner: questioner,
resources: Resources{},
cognitoActor: &actions.CognitoActions{CognitoClient:
cognitoidentityprovider.NewFromConfig(sdkConfig)},
}
scenario.resources.init(scenario.cognitoActor, questioner)
return scenario
Scenarios 118
AWS SDK for Go Code Examples Code Examples Guide
}
// AddUserToPool selects a user from the known users table and uses administrator
credentials to add the user to the user pool.
func (runner *ActivityLog) AddUserToPool(userPoolId string, tableName string)
(string, string) {
log.Println("To facilitate this example, let's add a user to the user pool using
administrator privileges.")
users, err := runner.helper.GetKnownUsers(tableName)
if err != nil {
panic(err)
}
user := users.Users[0]
log.Printf("Adding known user %v to the user pool.\n", user.UserName)
err = runner.cognitoActor.AdminCreateUser(userPoolId, user.UserName,
user.UserEmail)
if err != nil {
panic(err)
}
pwSet := false
password := runner.questioner.AskPassword("\nEnter a password that has at least
eight characters, uppercase, lowercase, numbers and symbols.\n"+
"(the password will not display as you type):", 8)
for !pwSet {
log.Printf("\nSetting password for user '%v'.\n", user.UserName)
err = runner.cognitoActor.AdminSetUserPassword(userPoolId, user.UserName,
password)
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
password = runner.questioner.AskPassword("\nEnter another password:", 8)
} else {
panic(err)
}
} else {
pwSet = true
}
}
log.Println(strings.Repeat("-", 88))
return user.UserName, password
}
Scenarios 119
AWS SDK for Go Code Examples Code Examples Guide
// AddActivityLogTrigger adds a Lambda handler as an invocation target for the
PostAuthentication trigger.
func (runner *ActivityLog) AddActivityLogTrigger(userPoolId string, activityLogArn
string) {
log.Println("Let's add a Lambda function to handle the PostAuthentication trigger
from Cognito.\n" +
"This trigger happens after a user is authenticated, and lets your function take
action, such as logging\n" +
"the outcome.")
err := runner.cognitoActor.UpdateTriggers(
userPoolId,
actions.TriggerInfo{Trigger: actions.PostAuthentication, HandlerArn:
aws.String(activityLogArn)})
if err != nil {
panic(err)
}
runner.resources.triggers = append(runner.resources.triggers,
actions.PostAuthentication)
log.Printf("Lambda function %v added to user pool %v to handle PostAuthentication
Cognito trigger.\n",
activityLogArn, userPoolId)
log.Println(strings.Repeat("-", 88))
}
// SignInUser signs in as the specified user.
func (runner *ActivityLog) SignInUser(clientId string, userName string, password
string) {
log.Printf("Now we'll sign in user %v and check the results in the logs and the
DynamoDB table.", userName)
runner.questioner.Ask("Press Enter when you're ready.")
authResult, err := runner.cognitoActor.SignIn(clientId, userName, password)
if err != nil {
panic(err)
}
log.Println("Sign in successful.",
"The PostAuthentication Lambda handler writes custom information to CloudWatch
Logs.")
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
*authResult.AccessToken)
}
Scenarios 120
AWS SDK for Go Code Examples Code Examples Guide
// GetKnownUserLastLogin gets the login info for a user from the Amazon DynamoDB
table and displays it.
func (runner *ActivityLog) GetKnownUserLastLogin(tableName string, userName string)
{
log.Println("The PostAuthentication handler also writes login data to the DynamoDB
table.")
runner.questioner.Ask("Press Enter when you're ready to continue.")
users, err := runner.helper.GetKnownUsers(tableName)
if err != nil {
panic(err)
}
for _, user := range users.Users {
if user.UserName == userName {
log.Println("The last login info for the user in the known users table is:")
log.Printf("\t%+v", *user.LastLogin)
}
}
log.Println(strings.Repeat("-", 88))
}
// Run runs the scenario.
func (runner *ActivityLog) Run(stackName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
runner.resources.Cleanup()
}
}()
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome\n")
log.Println(strings.Repeat("-", 88))
stackOutputs, err := runner.helper.GetStackOutputs(stackName)
if err != nil {
panic(err)
}
runner.resources.userPoolId = stackOutputs["UserPoolId"]
runner.helper.PopulateUserTable(stackOutputs["TableName"])
userName, password := runner.AddUserToPool(stackOutputs["UserPoolId"],
stackOutputs["TableName"])
Scenarios 121
AWS SDK for Go Code Examples Code Examples Guide
runner.AddActivityLogTrigger(stackOutputs["UserPoolId"],
stackOutputs["ActivityLogFunctionArn"])
runner.SignInUser(stackOutputs["UserPoolClientId"], userName, password)
runner.helper.ListRecentLogEvents(stackOutputs["ActivityLogFunction"])
runner.GetKnownUserLastLogin(stackOutputs["TableName"], userName)
runner.resources.Cleanup()
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Handle the PostAuthentication trigger with a Lambda function.
const TABLE_NAME = "TABLE_NAME"
// LoginInfo defines structured login data that can be marshalled to a DynamoDB
format.
type LoginInfo struct {
UserPoolId string `dynamodbav:"UserPoolId"`
ClientId string `dynamodbav:"ClientId"`
Time string `dynamodbav:"Time"`
}
// UserInfo defines structured user data that can be marshalled to a DynamoDB
format.
type UserInfo struct {
UserName string `dynamodbav:"UserName"`
UserEmail string `dynamodbav:"UserEmail"`
LastLogin LoginInfo `dynamodbav:"LastLogin"`
}
// GetKey marshals the user email value to a DynamoDB key format.
func (user UserInfo) GetKey() map[string]dynamodbtypes.AttributeValue {
userEmail, err := attributevalue.Marshal(user.UserEmail)
if err != nil {
panic(err)
}
return map[string]dynamodbtypes.AttributeValue{"UserEmail": userEmail}
Scenarios 122
AWS SDK for Go Code Examples Code Examples Guide
}
type handler struct {
dynamoClient *dynamodb.Client
}
// HandleRequest handles the PostAuthentication event by writing custom data to the
logs and
// to an Amazon DynamoDB table.
func (h *handler) HandleRequest(ctx context.Context,
event events.CognitoEventUserPoolsPostAuthentication)
(events.CognitoEventUserPoolsPostAuthentication, error) {
log.Printf("Received post authentication trigger from %v for user '%v'",
event.TriggerSource, event.UserName)
tableName := os.Getenv(TABLE_NAME)
user := UserInfo{
UserName: event.UserName,
UserEmail: event.Request.UserAttributes["email"],
LastLogin: LoginInfo{
UserPoolId: event.UserPoolID,
ClientId: event.CallerContext.ClientID,
Time: time.Now().Format(time.UnixDate),
},
}
// Write to CloudWatch Logs.
fmt.Printf("%#v", user)
// Also write to an external system. This examples uses DynamoDB to demonstrate.
userMap, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshal to DynamoDB map. Here's why: %v\n", err)
} else if len(userMap) == 0 {
log.Printf("User info marshaled to an empty map.")
} else {
_, err := h.dynamoClient.PutItem(ctx, &dynamodb.PutItemInput{
Item: userMap,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't write to DynamoDB. Here's why: %v\n", err)
} else {
log.Printf("Wrote user info to DynamoDB table %v.\n", tableName)
}
}
Scenarios 123
AWS SDK for Go Code Examples Code Examples Guide
return event, nil
}
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Panicln(err)
}
h := handler{
dynamoClient: dynamodb.NewFromConfig(sdkConfig),
}
lambda.Start(h.HandleRequest)
}
Create a struct that performs common tasks.
// IScenarioHelper defines common functions used by the workflows in this example.
type IScenarioHelper interface {
Pause(secs int)
GetStackOutputs(stackName string) (actions.StackOutputs, error)
PopulateUserTable(tableName string)
GetKnownUsers(tableName string) (actions.UserList, error)
AddKnownUser(tableName string, user actions.User)
ListRecentLogEvents(functionName string)
}
// ScenarioHelper contains AWS wrapper structs used by the workflows in this
example.
type ScenarioHelper struct {
questioner demotools.IQuestioner
dynamoActor *actions.DynamoActions
cfnActor *actions.CloudFormationActions
cwlActor *actions.CloudWatchLogsActions
isTestRun bool
}
// NewScenarioHelper constructs a new scenario helper.
func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner)
ScenarioHelper {
Scenarios 124
AWS SDK for Go Code Examples Code Examples Guide
scenario := ScenarioHelper{
questioner: questioner,
dynamoActor: &actions.DynamoActions{DynamoClient:
dynamodb.NewFromConfig(sdkConfig)},
cfnActor: &actions.CloudFormationActions{CfnClient:
cloudformation.NewFromConfig(sdkConfig)},
cwlActor: &actions.CloudWatchLogsActions{CwlClient:
cloudwatchlogs.NewFromConfig(sdkConfig)},
}
return scenario
}
// Pause waits for the specified number of seconds.
func (helper ScenarioHelper) Pause(secs int) {
if !helper.isTestRun {
time.Sleep(time.Duration(secs) * time.Second)
}
}
// GetStackOutputs gets the outputs from the specified CloudFormation stack in a
structured format.
func (helper ScenarioHelper) GetStackOutputs(stackName string)
(actions.StackOutputs, error) {
return helper.cfnActor.GetOutputs(stackName), nil
}
// PopulateUserTable fills the known user table with example data.
func (helper ScenarioHelper) PopulateUserTable(tableName string) {
log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this
example.\n", tableName)
err := helper.dynamoActor.PopulateTable(tableName)
if err != nil {
panic(err)
}
}
// GetKnownUsers gets the users from the known users table in a structured format.
func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList,
error) {
knownUsers, err := helper.dynamoActor.Scan(tableName)
if err != nil {
log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName,
err)
}
Scenarios 125
AWS SDK for Go Code Examples Code Examples Guide
return knownUsers, err
}
// AddKnownUser adds a user to the known users table.
func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) {
log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...
\n",
user.UserName, user.UserEmail)
err := helper.dynamoActor.AddUser(tableName, user)
if err != nil {
panic(err)
}
}
// ListRecentLogEvents gets the most recent log stream and events for the specified
Lambda function and displays them.
func (helper ScenarioHelper) ListRecentLogEvents(functionName string) {
log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...")
helper.Pause(10)
log.Println("Okay, let's check the logs to find what's happened recently with your
Lambda function.")
logStream, err := helper.cwlActor.GetLatestLogStream(functionName)
if err != nil {
panic(err)
}
log.Printf("Getting some recent events from log stream %v\n",
*logStream.LogStreamName)
events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName,
10)
if err != nil {
panic(err)
}
for _, event := range events {
log.Printf("\t%v", *event.Message)
}
log.Println(strings.Repeat("-", 88))
}
Create a struct that wraps Amazon Cognito actions.
Scenarios 126
AWS SDK for Go Code Examples Code Examples Guide
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
lambdaConfig.PostAuthentication = trigger.HandlerArn
Scenarios 127
AWS SDK for Go Code Examples Code Examples Guide
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
Scenarios 128
AWS SDK for Go Code Examples Code Examples Guide
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
Scenarios 129
AWS SDK for Go Code Examples Code Examples Guide
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
// DeleteUser removes a user from the user pool.
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
Scenarios 130
AWS SDK for Go Code Examples Code Examples Guide
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
}
}
return err
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
return err
}
Scenarios 131
AWS SDK for Go Code Examples Code Examples Guide
Create a struct that wraps DynamoDB actions.
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type DynamoActions struct {
DynamoClient *dynamodb.Client
}
// User defines structured user data.
type User struct {
UserName string
UserEmail string
LastLogin *LoginInfo `dynamodbav:",omitempty"`
}
// LoginInfo defines structured custom login data.
type LoginInfo struct {
UserPoolId string
ClientId string
Time string
}
// UserList defines a list of users.
type UserList struct {
Users []User
}
// UserNameList returns the usernames contained in a UserList as a list of strings.
func (users *UserList) UserNameList() []string {
names := make([]string, len(users.Users))
for i := 0; i < len(users.Users); i++ {
names[i] = users.Users[i].UserName
}
return names
}
// PopulateTable adds a set of test users to the table.
func (actor DynamoActions) PopulateTable(tableName string) error {
Scenarios 132
AWS SDK for Go Code Examples Code Examples Guide
var err error
var item map[string]types.AttributeValue
var writeReqs []types.WriteRequest
for i := 1; i < 4; i++ {
item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v",
i), UserEmail: fmt.Sprintf("test_email_%[email protected]", i)})
if err != nil {
log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err)
return err
}
writeReqs = append(writeReqs, types.WriteRequest{PutRequest:
&types.PutRequest{Item: item}})
}
_, err = actor.DynamoClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{tableName: writeReqs},
})
if err != nil {
log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName,
err)
}
return err
}
// Scan scans the table for all items.
func (actor DynamoActions) Scan(tableName string) (UserList, error) {
var userList UserList
output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err)
} else {
err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users)
if err != nil {
log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err)
}
}
return userList, err
}
// AddUser adds a user item to a table.
func (actor DynamoActions) AddUser(tableName string, user User) error {
userItem, err := attributevalue.MarshalMap(user)
Scenarios 133
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't marshall user to item. Here's why: %v\n", err)
}
_, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
Item: userItem,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err)
}
return err
}
Create a struct that wraps CloudWatch Logs actions.
type CloudWatchLogsActions struct {
CwlClient *cloudwatchlogs.Client
}
// GetLatestLogStream gets the most recent log stream for a Lambda function.
func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string)
(types.LogStream, error) {
var logStream types.LogStream
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.DescribeLogStreams(context.TODO(),
&cloudwatchlogs.DescribeLogStreamsInput{
Descending: aws.Bool(true),
Limit: aws.Int32(1),
LogGroupName: aws.String(logGroupName),
OrderBy: types.OrderByLastEventTime,
})
if err != nil {
log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n",
logGroupName, err)
} else {
logStream = output.LogStreams[0]
}
return logStream, err
}
Scenarios 134
AWS SDK for Go Code Examples Code Examples Guide
// GetLogEvents gets the most recent eventCount events from the specified log
stream.
func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName
string, eventCount int32) (
[]types.OutputLogEvent, error) {
var events []types.OutputLogEvent
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.GetLogEvents(context.TODO(),
&cloudwatchlogs.GetLogEventsInput{
LogStreamName: aws.String(logStreamName),
Limit: aws.Int32(eventCount),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n",
logStreamName, err)
} else {
events = output.Events
}
return events, err
}
Create a struct that wraps AWS CloudFormation actions.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
if err != nil || len(output.Stacks) == 0 {
Scenarios 135
AWS SDK for Go Code Examples Code Examples Guide
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
Clean up resources.
// Resources keeps track of AWS resources created during an example and handles
// cleanup when the example finishes.
type Resources struct {
userPoolId string
userAccessTokens []string
triggers []actions.Trigger
cognitoActor *actions.CognitoActions
questioner demotools.IQuestioner
}
func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner
demotools.IQuestioner) {
resources.userAccessTokens = []string{}
resources.triggers = []actions.Trigger{}
resources.cognitoActor = cognitoActor
resources.questioner = questioner
}
// Cleanup deletes all AWS resources created during an example.
func (resources *Resources) Cleanup() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources \n"
+
"that were created for this scenario.")
}
Scenarios 136
AWS SDK for Go Code Examples Code Examples Guide
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
if wantDelete {
for _, accessToken := range resources.userAccessTokens {
err := resources.cognitoActor.DeleteUser(accessToken)
if err != nil {
log.Println("Couldn't delete user during cleanup.")
panic(err)
}
log.Println("Deleted user.")
}
triggerList := make([]actions.TriggerInfo, len(resources.triggers))
for i := 0; i < len(resources.triggers); i++ {
triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn:
nil}
}
err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...)
if err != nil {
log.Println("Couldn't update Cognito triggers during cleanup.")
panic(err)
}
log.Println("Removed Cognito triggers from user pool.")
} else {
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
AdminCreateUser
AdminSetUserPassword
DeleteUser
InitiateAuth
UpdateUserPool
Scenarios 137
AWS SDK for Go Code Examples Code Examples Guide
Amazon DocumentDB examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon DocumentDB.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Topics
Serverless examples
Serverless examples
Invoke a Lambda function from a Amazon DocumentDB trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving records from a DocumentDB change stream. The function retrieves the
DocumentDB payload and logs the record contents.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming a Amazon DocumentDB event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/lambda"
Amazon DocumentDB 138
AWS SDK for Go Code Examples Code Examples Guide
)
type Event struct {
Events []Record `json:"events"`
}
type Record struct {
Event struct {
OperationType string `json:"operationType"`
NS struct {
DB string `json:"db"`
Coll string `json:"coll"`
} `json:"ns"`
FullDocument interface{} `json:"fullDocument"`
} `json:"event"`
}
func main() {
lambda.Start(handler)
}
func handler(ctx context.Context, event Event) (string, error) {
fmt.Println("Loading function")
for _, record := range event.Events {
logDocumentDBEvent(record)
}
return "OK", nil
}
func logDocumentDBEvent(record Record) {
fmt.Printf("Operation type: %s\n", record.Event.OperationType)
fmt.Printf("db: %s\n", record.Event.NS.DB)
fmt.Printf("collection: %s\n", record.Event.NS.Coll)
docBytes, _ := json.MarshalIndent(record.Event.FullDocument, "", " ")
fmt.Printf("Full document: %s\n", string(docBytes))
}
Serverless examples 139
AWS SDK for Go Code Examples Code Examples Guide
DynamoDB examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with DynamoDB.
Basics are code examples that show you how to perform the essential operations within a service.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Topics
Basics
Actions
Scenarios
Serverless examples
Basics
Learn the basics
The following code example shows how to:
Create a table that can hold movie data.
Put, get, and update a single movie in the table.
Write movie data to the table from a sample JSON file.
Query for movies that were released in a given year.
Scan for movies that were released in a range of years.
Delete a movie from the table, then delete the table.
DynamoDB 140
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario to create the table and perform actions on it.
// RunMovieScenario is an interactive example that shows you how to use the AWS SDK
for Go
// to create and use an Amazon DynamoDB table that stores data about movies.
//
// 1. Create a table that can hold movie data.
// 2. Put, get, and update a single movie in the table.
// 3. Write movie data to the table from a sample JSON file.
// 4. Query for movies that were released in a given year.
// 5. Scan for movies that were released in a range of years.
// 6. Delete a movie from the table.
// 7. Delete the table.
//
// This example creates a DynamoDB service client from the specified sdkConfig so
that
// you can replace it with a mocked or stubbed config for unit testing.
//
// It uses a questioner from the `demotools` package to get input during the
example.
// This package can be found in the ..\..\demotools folder of this repo.
//
// The specified movie sampler is used to get sample data from a URL that is loaded
// into the named table.
func RunMovieScenario(
sdkConfig aws.Config, questioner demotools.IQuestioner, tableName string,
movieSampler actions.IMovieSampler) {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Something went wrong with the demo.")
}
}()
log.Println(strings.Repeat("-", 88))
Basics 141
AWS SDK for Go Code Examples Code Examples Guide
log.Println("Welcome to the Amazon DynamoDB getting started demo.")
log.Println(strings.Repeat("-", 88))
tableBasics := actions.TableBasics{TableName: tableName,
DynamoDbClient: dynamodb.NewFromConfig(sdkConfig)}
exists, err := tableBasics.TableExists()
if err != nil {
panic(err)
}
if !exists {
log.Printf("Creating table %v...\n", tableName)
_, err = tableBasics.CreateMovieTable()
if err != nil {
panic(err)
} else {
log.Printf("Created table %v.\n", tableName)
}
} else {
log.Printf("Table %v already exists.\n", tableName)
}
var customMovie actions.Movie
customMovie.Title = questioner.Ask("Enter a movie title to add to the table:",
[]demotools.IAnswerValidator{demotools.NotEmpty{}})
customMovie.Year = questioner.AskInt("What year was it released?",
[]demotools.IAnswerValidator{demotools.NotEmpty{}, demotools.InIntRange{
Lower: 1900, Upper: 2030}})
customMovie.Info = map[string]interface{}{}
customMovie.Info["rating"] = questioner.AskFloat64(
"Enter a rating between 1 and 10:", []demotools.IAnswerValidator{
demotools.NotEmpty{}, demotools.InFloatRange{Lower: 1, Upper: 10}})
customMovie.Info["plot"] = questioner.Ask("What's the plot? ",
[]demotools.IAnswerValidator{demotools.NotEmpty{}})
err = tableBasics.AddMovie(customMovie)
if err == nil {
log.Printf("Added %v to the movie table.\n", customMovie.Title)
}
log.Println(strings.Repeat("-", 88))
log.Printf("Let's update your movie. You previously rated it %v.\n",
customMovie.Info["rating"])
customMovie.Info["rating"] = questioner.AskFloat64(
"What new rating would you give it?", []demotools.IAnswerValidator{
Basics 142
AWS SDK for Go Code Examples Code Examples Guide
demotools.NotEmpty{}, demotools.InFloatRange{Lower: 1, Upper: 10}})
log.Printf("You summarized the plot as '%v'.\n", customMovie.Info["plot"])
customMovie.Info["plot"] = questioner.Ask("What would you say now?",
[]demotools.IAnswerValidator{demotools.NotEmpty{}})
attributes, err := tableBasics.UpdateMovie(customMovie)
if err == nil {
log.Printf("Updated %v with new values.\n", customMovie.Title)
for _, attVal := range attributes {
for valKey, val := range attVal {
log.Printf("\t%v: %v\n", valKey, val)
}
}
}
log.Println(strings.Repeat("-", 88))
log.Printf("Getting movie data from %v and adding 250 movies to the table...\n",
movieSampler.GetURL())
movies := movieSampler.GetSampleMovies()
written, err := tableBasics.AddMovieBatch(movies, 250)
if err != nil {
panic(err)
} else {
log.Printf("Added %v movies to the table.\n", written)
}
show := 10
if show > written {
show = written
}
log.Printf("The first %v movies in the table are:", show)
for index, movie := range movies[:show] {
log.Printf("\t%v. %v\n", index+1, movie.Title)
}
movieIndex := questioner.AskInt(
"Enter the number of a movie to get info about it: ",
[]demotools.IAnswerValidator{
demotools.InIntRange{Lower: 1, Upper: show}},
)
movie, err := tableBasics.GetMovie(movies[movieIndex-1].Title,
movies[movieIndex-1].Year)
if err == nil {
log.Println(movie)
}
log.Println(strings.Repeat("-", 88))
Basics 143
AWS SDK for Go Code Examples Code Examples Guide
log.Println("Let's get a list of movies released in a given year.")
releaseYear := questioner.AskInt("Enter a year between 1972 and 2018: ",
[]demotools.IAnswerValidator{demotools.InIntRange{Lower: 1972, Upper: 2018}},
)
releases, err := tableBasics.Query(releaseYear)
if err == nil {
if len(releases) == 0 {
log.Printf("I couldn't find any movies released in %v!\n", releaseYear)
} else {
for _, movie = range releases {
log.Println(movie)
}
}
}
log.Println(strings.Repeat("-", 88))
log.Println("Now let's scan for movies released in a range of years.")
startYear := questioner.AskInt("Enter a year: ", []demotools.IAnswerValidator{
demotools.InIntRange{Lower: 1972, Upper: 2018}})
endYear := questioner.AskInt("Enter another year: ", []demotools.IAnswerValidator{
demotools.InIntRange{Lower: 1972, Upper: 2018}})
releases, err = tableBasics.Scan(startYear, endYear)
if err == nil {
if len(releases) == 0 {
log.Printf("I couldn't find any movies released between %v and %v!\n", startYear,
endYear)
} else {
log.Printf("Found %v movies. In this list, the plot is <nil> because "+
"we used a projection expression when scanning for items to return only "+
"the title, year, and rating.\n", len(releases))
for _, movie = range releases {
log.Println(movie)
}
}
}
log.Println(strings.Repeat("-", 88))
var tables []string
if questioner.AskBool("Do you want to list all of your tables? (y/n) ", "y") {
tables, err = tableBasics.ListTables()
if err == nil {
log.Printf("Found %v tables:", len(tables))
for _, table := range tables {
Basics 144
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("\t%v", table)
}
}
}
log.Println(strings.Repeat("-", 88))
log.Printf("Let's remove your movie '%v'.\n", customMovie.Title)
if questioner.AskBool("Do you want to delete it from the table? (y/n) ", "y") {
err = tableBasics.DeleteMovie(customMovie)
}
if err == nil {
log.Printf("Deleted %v.\n", customMovie.Title)
}
if questioner.AskBool("Delete the table, too? (y/n)", "y") {
err = tableBasics.DeleteTable()
} else {
log.Println("Don't forget to delete the table when you're done or you might " +
"incur charges on your account.")
}
if err == nil {
log.Printf("Deleted table %v.\n", tableBasics.TableName)
}
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define a Movie struct that is used in this example.
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
Basics 145
AWS SDK for Go Code Examples Code Examples Guide
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
Create a struct and methods that call DynamoDB actions.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// TableExists determines whether a DynamoDB table exists.
func (basics TableBasics) TableExists() (bool, error) {
exists := true
_, err := basics.DynamoDbClient.DescribeTable(
Basics 146
AWS SDK for Go Code Examples Code Examples Guide
context.TODO(), &dynamodb.DescribeTableInput{TableName:
aws.String(basics.TableName)},
)
if err != nil {
var notFoundEx *types.ResourceNotFoundException
if errors.As(err, &notFoundEx) {
log.Printf("Table %v does not exist.\n", basics.TableName)
err = nil
} else {
log.Printf("Couldn't determine existence of table %v. Here's why: %v\n",
basics.TableName, err)
}
exists = false
}
return exists, err
}
// CreateMovieTable creates a DynamoDB table with a composite primary key defined as
// a string sort key named `title`, and a numeric partition key named `year`.
// This function uses NewTableExistsWaiter to wait for the table to be created by
// DynamoDB before it returns.
func (basics TableBasics) CreateMovieTable() (*types.TableDescription, error) {
var tableDesc *types.TableDescription
table, err := basics.DynamoDbClient.CreateTable(context.TODO(),
&dynamodb.CreateTableInput{
AttributeDefinitions: []types.AttributeDefinition{{
AttributeName: aws.String("year"),
AttributeType: types.ScalarAttributeTypeN,
}, {
AttributeName: aws.String("title"),
AttributeType: types.ScalarAttributeTypeS,
}},
KeySchema: []types.KeySchemaElement{{
AttributeName: aws.String("year"),
KeyType: types.KeyTypeHash,
}, {
AttributeName: aws.String("title"),
KeyType: types.KeyTypeRange,
}},
TableName: aws.String(basics.TableName),
ProvisionedThroughput: &types.ProvisionedThroughput{
ReadCapacityUnits: aws.Int64(10),
Basics 147
AWS SDK for Go Code Examples Code Examples Guide
WriteCapacityUnits: aws.Int64(10),
},
})
if err != nil {
log.Printf("Couldn't create table %v. Here's why: %v\n", basics.TableName, err)
} else {
waiter := dynamodb.NewTableExistsWaiter(basics.DynamoDbClient)
err = waiter.Wait(context.TODO(), &dynamodb.DescribeTableInput{
TableName: aws.String(basics.TableName)}, 5*time.Minute)
if err != nil {
log.Printf("Wait for table exists failed. Here's why: %v\n", err)
}
tableDesc = table.TableDescription
}
return tableDesc, err
}
// ListTables lists the DynamoDB table names for the current account.
func (basics TableBasics) ListTables() ([]string, error) {
var tableNames []string
var output *dynamodb.ListTablesOutput
var err error
tablePaginator := dynamodb.NewListTablesPaginator(basics.DynamoDbClient,
&dynamodb.ListTablesInput{})
for tablePaginator.HasMorePages() {
output, err = tablePaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't list tables. Here's why: %v\n", err)
break
} else {
tableNames = append(tableNames, output.TableNames...)
}
}
return tableNames, err
}
// AddMovie adds a movie the DynamoDB table.
func (basics TableBasics) AddMovie(movie Movie) error {
item, err := attributevalue.MarshalMap(movie)
if err != nil {
Basics 148
AWS SDK for Go Code Examples Code Examples Guide
panic(err)
}
_, err = basics.DynamoDbClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
TableName: aws.String(basics.TableName), Item: item,
})
if err != nil {
log.Printf("Couldn't add item to table. Here's why: %v\n", err)
}
return err
}
// UpdateMovie updates the rating and plot of a movie that already exists in the
// DynamoDB table. This function uses the `expression` package to build the update
// expression.
func (basics TableBasics) UpdateMovie(movie Movie)
(map[string]map[string]interface{}, error) {
var err error
var response *dynamodb.UpdateItemOutput
var attributeMap map[string]map[string]interface{}
update := expression.Set(expression.Name("info.rating"),
expression.Value(movie.Info["rating"]))
update.Set(expression.Name("info.plot"), expression.Value(movie.Info["plot"]))
expr, err := expression.NewBuilder().WithUpdate(update).Build()
if err != nil {
log.Printf("Couldn't build expression for update. Here's why: %v\n", err)
} else {
response, err = basics.DynamoDbClient.UpdateItem(context.TODO(),
&dynamodb.UpdateItemInput{
TableName: aws.String(basics.TableName),
Key: movie.GetKey(),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
UpdateExpression: expr.Update(),
ReturnValues: types.ReturnValueUpdatedNew,
})
if err != nil {
log.Printf("Couldn't update movie %v. Here's why: %v\n", movie.Title, err)
} else {
err = attributevalue.UnmarshalMap(response.Attributes, &attributeMap)
if err != nil {
log.Printf("Couldn't unmarshall update response. Here's why: %v\n", err)
}
Basics 149
AWS SDK for Go Code Examples Code Examples Guide
}
}
return attributeMap, err
}
// AddMovieBatch adds a slice of movies to the DynamoDB table. The function sends
// batches of 25 movies to DynamoDB until all movies are added or it reaches the
// specified maximum.
func (basics TableBasics) AddMovieBatch(movies []Movie, maxMovies int) (int, error)
{
var err error
var item map[string]types.AttributeValue
written := 0
batchSize := 25 // DynamoDB allows a maximum batch size of 25 items.
start := 0
end := start + batchSize
for start < maxMovies && start < len(movies) {
var writeReqs []types.WriteRequest
if end > len(movies) {
end = len(movies)
}
for _, movie := range movies[start:end] {
item, err = attributevalue.MarshalMap(movie)
if err != nil {
log.Printf("Couldn't marshal movie %v for batch writing. Here's why: %v\n",
movie.Title, err)
} else {
writeReqs = append(
writeReqs,
types.WriteRequest{PutRequest: &types.PutRequest{Item: item}},
)
}
}
_, err = basics.DynamoDbClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{basics.TableName: writeReqs}})
if err != nil {
log.Printf("Couldn't add a batch of movies to %v. Here's why: %v\n",
basics.TableName, err)
} else {
written += len(writeReqs)
}
Basics 150
AWS SDK for Go Code Examples Code Examples Guide
start = end
end += batchSize
}
return written, err
}
// GetMovie gets movie data from the DynamoDB table by using the primary composite
key
// made of title and year.
func (basics TableBasics) GetMovie(title string, year int) (Movie, error) {
movie := Movie{Title: title, Year: year}
response, err := basics.DynamoDbClient.GetItem(context.TODO(),
&dynamodb.GetItemInput{
Key: movie.GetKey(), TableName: aws.String(basics.TableName),
})
if err != nil {
log.Printf("Couldn't get info about %v. Here's why: %v\n", title, err)
} else {
err = attributevalue.UnmarshalMap(response.Item, &movie)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
}
}
return movie, err
}
// Query gets all movies in the DynamoDB table that were released in the specified
year.
// The function uses the `expression` package to build the key condition expression
// that is used in the query.
func (basics TableBasics) Query(releaseYear int) ([]Movie, error) {
var err error
var response *dynamodb.QueryOutput
var movies []Movie
keyEx := expression.Key("year").Equal(expression.Value(releaseYear))
expr, err := expression.NewBuilder().WithKeyCondition(keyEx).Build()
if err != nil {
log.Printf("Couldn't build expression for query. Here's why: %v\n", err)
} else {
Basics 151
AWS SDK for Go Code Examples Code Examples Guide
queryPaginator := dynamodb.NewQueryPaginator(basics.DynamoDbClient,
&dynamodb.QueryInput{
TableName: aws.String(basics.TableName),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
KeyConditionExpression: expr.KeyCondition(),
})
for queryPaginator.HasMorePages() {
response, err = queryPaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't query for movies released in %v. Here's why: %v\n",
releaseYear, err)
break
} else {
var moviePage []Movie
err = attributevalue.UnmarshalListOfMaps(response.Items, &moviePage)
if err != nil {
log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
break
} else {
movies = append(movies, moviePage...)
}
}
}
}
return movies, err
}
// Scan gets all movies in the DynamoDB table that were released in a range of years
// and projects them to return a reduced set of fields.
// The function uses the `expression` package to build the filter and projection
// expressions.
func (basics TableBasics) Scan(startYear int, endYear int) ([]Movie, error) {
var movies []Movie
var err error
var response *dynamodb.ScanOutput
filtEx := expression.Name("year").Between(expression.Value(startYear),
expression.Value(endYear))
projEx := expression.NamesList(
expression.Name("year"), expression.Name("title"), expression.Name("info.rating"))
expr, err :=
expression.NewBuilder().WithFilter(filtEx).WithProjection(projEx).Build()
Basics 152
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't build expressions for scan. Here's why: %v\n", err)
} else {
scanPaginator := dynamodb.NewScanPaginator(basics.DynamoDbClient,
&dynamodb.ScanInput{
TableName: aws.String(basics.TableName),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
FilterExpression: expr.Filter(),
ProjectionExpression: expr.Projection(),
})
for scanPaginator.HasMorePages() {
response, err = scanPaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't scan for movies released between %v and %v. Here's why: %v
\n",
startYear, endYear, err)
break
} else {
var moviePage []Movie
err = attributevalue.UnmarshalListOfMaps(response.Items, &moviePage)
if err != nil {
log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
break
} else {
movies = append(movies, moviePage...)
}
}
}
}
return movies, err
}
// DeleteMovie removes a movie from the DynamoDB table.
func (basics TableBasics) DeleteMovie(movie Movie) error {
_, err := basics.DynamoDbClient.DeleteItem(context.TODO(),
&dynamodb.DeleteItemInput{
TableName: aws.String(basics.TableName), Key: movie.GetKey(),
})
if err != nil {
log.Printf("Couldn't delete %v from the table. Here's why: %v\n", movie.Title,
err)
Basics 153
AWS SDK for Go Code Examples Code Examples Guide
}
return err
}
// DeleteTable deletes the DynamoDB table and all of its data.
func (basics TableBasics) DeleteTable() error {
_, err := basics.DynamoDbClient.DeleteTable(context.TODO(),
&dynamodb.DeleteTableInput{
TableName: aws.String(basics.TableName)})
if err != nil {
log.Printf("Couldn't delete table %v. Here's why: %v\n", basics.TableName, err)
}
return err
}
For API details, see the following topics in AWS SDK for Go API Reference.
BatchWriteItem
CreateTable
DeleteItem
DeleteTable
DescribeTable
GetItem
PutItem
Query
Scan
UpdateItem
Actions
BatchExecuteStatement
The following code example shows how to use BatchExecuteStatement.
Actions 154
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Use batches of INSERT statements to add items.
// AddMovieBatch runs a batch of PartiQL INSERT statements to add multiple movies to
the
// DynamoDB table.
func (runner PartiQLRunner) AddMovieBatch(movies []Movie) error {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year,
movie.Info})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(fmt.Sprintf(
"INSERT INTO \"%v\" VALUE {'title': ?, 'year': ?, 'info': ?}",
runner.TableName)),
Parameters: params,
}
}
_, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
if err != nil {
log.Printf("Couldn't insert a batch of items with PartiQL. Here's why: %v\n", err)
}
return err
}
Actions 155
AWS SDK for Go Code Examples Code Examples Guide
Use batches of SELECT statements to get items.
// GetMovieBatch runs a batch of PartiQL SELECT statements to get multiple movies
from
// the DynamoDB table by title and year.
func (runner PartiQLRunner) GetMovieBatch(movies []Movie) ([]Movie, error) {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(
fmt.Sprintf("SELECT * FROM \"%v\" WHERE title=? AND year=?", runner.TableName)),
Parameters: params,
}
}
output, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
var outMovies []Movie
if err != nil {
log.Printf("Couldn't get a batch of items with PartiQL. Here's why: %v\n", err)
} else {
for _, response := range output.Responses {
var movie Movie
err = attributevalue.UnmarshalMap(response.Item, &movie)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
} else {
outMovies = append(outMovies, movie)
}
}
}
return outMovies, err
}
Actions 156
AWS SDK for Go Code Examples Code Examples Guide
Use batches of UPDATE statements to update items.
// UpdateMovieBatch runs a batch of PartiQL UPDATE statements to update the rating
of
// multiple movies that already exist in the DynamoDB table.
func (runner PartiQLRunner) UpdateMovieBatch(movies []Movie, ratings []float64)
error {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{ratings[index],
movie.Title, movie.Year})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(
fmt.Sprintf("UPDATE \"%v\" SET info.rating=? WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
}
}
_, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
if err != nil {
log.Printf("Couldn't update the batch of movies. Here's why: %v\n", err)
}
return err
}
Use batches of DELETE statements to delete items.
// DeleteMovieBatch runs a batch of PartiQL DELETE statements to remove multiple
movies
// from the DynamoDB table.
func (runner PartiQLRunner) DeleteMovieBatch(movies []Movie) error {
statementRequests := make([]types.BatchStatementRequest, len(movies))
Actions 157
AWS SDK for Go Code Examples Code Examples Guide
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(
fmt.Sprintf("DELETE FROM \"%v\" WHERE title=? AND year=?", runner.TableName)),
Parameters: params,
}
}
_, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
if err != nil {
log.Printf("Couldn't delete the batch of movies. Here's why: %v\n", err)
}
return err
}
Define a Movie struct that is used in this example.
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
Actions 158
AWS SDK for Go Code Examples Code Examples Guide
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see BatchExecuteStatement in AWS SDK for Go API Reference.
BatchWriteItem
The following code example shows how to use BatchWriteItem.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
Actions 159
AWS SDK for Go Code Examples Code Examples Guide
// AddMovieBatch adds a slice of movies to the DynamoDB table. The function sends
// batches of 25 movies to DynamoDB until all movies are added or it reaches the
// specified maximum.
func (basics TableBasics) AddMovieBatch(movies []Movie, maxMovies int) (int, error)
{
var err error
var item map[string]types.AttributeValue
written := 0
batchSize := 25 // DynamoDB allows a maximum batch size of 25 items.
start := 0
end := start + batchSize
for start < maxMovies && start < len(movies) {
var writeReqs []types.WriteRequest
if end > len(movies) {
end = len(movies)
}
for _, movie := range movies[start:end] {
item, err = attributevalue.MarshalMap(movie)
if err != nil {
log.Printf("Couldn't marshal movie %v for batch writing. Here's why: %v\n",
movie.Title, err)
} else {
writeReqs = append(
writeReqs,
types.WriteRequest{PutRequest: &types.PutRequest{Item: item}},
)
}
}
_, err = basics.DynamoDbClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{basics.TableName: writeReqs}})
if err != nil {
log.Printf("Couldn't add a batch of movies to %v. Here's why: %v\n",
basics.TableName, err)
} else {
written += len(writeReqs)
}
start = end
end += batchSize
}
return written, err
}
Actions 160
AWS SDK for Go Code Examples Code Examples Guide
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see BatchWriteItem in AWS SDK for Go API Reference.
CreateTable
The following code example shows how to use CreateTable.
Actions 161
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// CreateMovieTable creates a DynamoDB table with a composite primary key defined as
// a string sort key named `title`, and a numeric partition key named `year`.
// This function uses NewTableExistsWaiter to wait for the table to be created by
// DynamoDB before it returns.
func (basics TableBasics) CreateMovieTable() (*types.TableDescription, error) {
var tableDesc *types.TableDescription
table, err := basics.DynamoDbClient.CreateTable(context.TODO(),
&dynamodb.CreateTableInput{
AttributeDefinitions: []types.AttributeDefinition{{
AttributeName: aws.String("year"),
AttributeType: types.ScalarAttributeTypeN,
}, {
AttributeName: aws.String("title"),
AttributeType: types.ScalarAttributeTypeS,
}},
KeySchema: []types.KeySchemaElement{{
AttributeName: aws.String("year"),
KeyType: types.KeyTypeHash,
}, {
AttributeName: aws.String("title"),
KeyType: types.KeyTypeRange,
}},
TableName: aws.String(basics.TableName),
Actions 162
AWS SDK for Go Code Examples Code Examples Guide
ProvisionedThroughput: &types.ProvisionedThroughput{
ReadCapacityUnits: aws.Int64(10),
WriteCapacityUnits: aws.Int64(10),
},
})
if err != nil {
log.Printf("Couldn't create table %v. Here's why: %v\n", basics.TableName, err)
} else {
waiter := dynamodb.NewTableExistsWaiter(basics.DynamoDbClient)
err = waiter.Wait(context.TODO(), &dynamodb.DescribeTableInput{
TableName: aws.String(basics.TableName)}, 5*time.Minute)
if err != nil {
log.Printf("Wait for table exists failed. Here's why: %v\n", err)
}
tableDesc = table.TableDescription
}
return tableDesc, err
}
For API details, see CreateTable in AWS SDK for Go API Reference.
DeleteItem
The following code example shows how to use DeleteItem.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
Actions 163
AWS SDK for Go Code Examples Code Examples Guide
}
// DeleteMovie removes a movie from the DynamoDB table.
func (basics TableBasics) DeleteMovie(movie Movie) error {
_, err := basics.DynamoDbClient.DeleteItem(context.TODO(),
&dynamodb.DeleteItemInput{
TableName: aws.String(basics.TableName), Key: movie.GetKey(),
})
if err != nil {
log.Printf("Couldn't delete %v from the table. Here's why: %v\n", movie.Title,
err)
}
return err
}
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
Actions 164
AWS SDK for Go Code Examples Code Examples Guide
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see DeleteItem in AWS SDK for Go API Reference.
DeleteTable
The following code example shows how to use DeleteTable.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// DeleteTable deletes the DynamoDB table and all of its data.
func (basics TableBasics) DeleteTable() error {
_, err := basics.DynamoDbClient.DeleteTable(context.TODO(),
&dynamodb.DeleteTableInput{
TableName: aws.String(basics.TableName)})
if err != nil {
log.Printf("Couldn't delete table %v. Here's why: %v\n", basics.TableName, err)
}
Actions 165
AWS SDK for Go Code Examples Code Examples Guide
return err
}
For API details, see DeleteTable in AWS SDK for Go API Reference.
DescribeTable
The following code example shows how to use DescribeTable.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// TableExists determines whether a DynamoDB table exists.
func (basics TableBasics) TableExists() (bool, error) {
exists := true
_, err := basics.DynamoDbClient.DescribeTable(
context.TODO(), &dynamodb.DescribeTableInput{TableName:
aws.String(basics.TableName)},
)
if err != nil {
var notFoundEx *types.ResourceNotFoundException
if errors.As(err, &notFoundEx) {
log.Printf("Table %v does not exist.\n", basics.TableName)
err = nil
Actions 166
AWS SDK for Go Code Examples Code Examples Guide
} else {
log.Printf("Couldn't determine existence of table %v. Here's why: %v\n",
basics.TableName, err)
}
exists = false
}
return exists, err
}
For API details, see DescribeTable in AWS SDK for Go API Reference.
ExecuteStatement
The following code example shows how to use ExecuteStatement.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Use an INSERT statement to add an item.
// AddMovie runs a PartiQL INSERT statement to add a movie to the DynamoDB table.
func (runner PartiQLRunner) AddMovie(movie Movie) error {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year,
movie.Info})
if err != nil {
panic(err)
}
_, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("INSERT INTO \"%v\" VALUE {'title': ?, 'year': ?, 'info': ?}",
runner.TableName)),
Parameters: params,
})
Actions 167
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't insert an item with PartiQL. Here's why: %v\n", err)
}
return err
}
Use a SELECT statement to get an item.
// GetMovie runs a PartiQL SELECT statement to get a movie from the DynamoDB table
by
// title and year.
func (runner PartiQLRunner) GetMovie(title string, year int) (Movie, error) {
var movie Movie
params, err := attributevalue.MarshalList([]interface{}{title, year})
if err != nil {
panic(err)
}
response, err := runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("SELECT * FROM \"%v\" WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't get info about %v. Here's why: %v\n", title, err)
} else {
err = attributevalue.UnmarshalMap(response.Items[0], &movie)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
}
}
return movie, err
}
Use a SELECT statement to get a list of items and project the results.
Actions 168
AWS SDK for Go Code Examples Code Examples Guide
// GetAllMovies runs a PartiQL SELECT statement to get all movies from the DynamoDB
table.
// pageSize is not typically required and is used to show how to paginate the
results.
// The results are projected to return only the title and rating of each movie.
func (runner PartiQLRunner) GetAllMovies(pageSize int32) ([]map[string]interface{},
error) {
var output []map[string]interface{}
var response *dynamodb.ExecuteStatementOutput
var err error
var nextToken *string
for moreData := true; moreData; {
response, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("SELECT title, info.rating FROM \"%v\"", runner.TableName)),
Limit: aws.Int32(pageSize),
NextToken: nextToken,
})
if err != nil {
log.Printf("Couldn't get movies. Here's why: %v\n", err)
moreData = false
} else {
var pageOutput []map[string]interface{}
err = attributevalue.UnmarshalListOfMaps(response.Items, &pageOutput)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
} else {
log.Printf("Got a page of length %v.\n", len(response.Items))
output = append(output, pageOutput...)
}
nextToken = response.NextToken
moreData = nextToken != nil
}
}
return output, err
}
Use an UPDATE statement to update an item.
Actions 169
AWS SDK for Go Code Examples Code Examples Guide
// UpdateMovie runs a PartiQL UPDATE statement to update the rating of a movie that
// already exists in the DynamoDB table.
func (runner PartiQLRunner) UpdateMovie(movie Movie, rating float64) error {
params, err := attributevalue.MarshalList([]interface{}{rating, movie.Title,
movie.Year})
if err != nil {
panic(err)
}
_, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("UPDATE \"%v\" SET info.rating=? WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't update movie %v. Here's why: %v\n", movie.Title, err)
}
return err
}
Use a DELETE statement to delete an item.
// DeleteMovie runs a PartiQL DELETE statement to remove a movie from the DynamoDB
table.
func (runner PartiQLRunner) DeleteMovie(movie Movie) error {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year})
if err != nil {
panic(err)
}
_, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("DELETE FROM \"%v\" WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't delete %v from the table. Here's why: %v\n", movie.Title,
err)
Actions 170
AWS SDK for Go Code Examples Code Examples Guide
}
return err
}
Define a Movie struct that is used in this example.
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
Actions 171
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ExecuteStatement in AWS SDK for Go API Reference.
GetItem
The following code example shows how to use GetItem.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// GetMovie gets movie data from the DynamoDB table by using the primary composite
key
// made of title and year.
func (basics TableBasics) GetMovie(title string, year int) (Movie, error) {
movie := Movie{Title: title, Year: year}
response, err := basics.DynamoDbClient.GetItem(context.TODO(),
&dynamodb.GetItemInput{
Key: movie.GetKey(), TableName: aws.String(basics.TableName),
})
if err != nil {
log.Printf("Couldn't get info about %v. Here's why: %v\n", title, err)
} else {
err = attributevalue.UnmarshalMap(response.Item, &movie)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
}
}
Actions 172
AWS SDK for Go Code Examples Code Examples Guide
return movie, err
}
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see GetItem in AWS SDK for Go API Reference.
Actions 173
AWS SDK for Go Code Examples Code Examples Guide
ListTables
The following code example shows how to use ListTables.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// ListTables lists the DynamoDB table names for the current account.
func (basics TableBasics) ListTables() ([]string, error) {
var tableNames []string
var output *dynamodb.ListTablesOutput
var err error
tablePaginator := dynamodb.NewListTablesPaginator(basics.DynamoDbClient,
&dynamodb.ListTablesInput{})
for tablePaginator.HasMorePages() {
output, err = tablePaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't list tables. Here's why: %v\n", err)
break
} else {
tableNames = append(tableNames, output.TableNames...)
}
}
return tableNames, err
}
Actions 174
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListTables in AWS SDK for Go API Reference.
PutItem
The following code example shows how to use PutItem.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// AddMovie adds a movie the DynamoDB table.
func (basics TableBasics) AddMovie(movie Movie) error {
item, err := attributevalue.MarshalMap(movie)
if err != nil {
panic(err)
}
_, err = basics.DynamoDbClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
TableName: aws.String(basics.TableName), Item: item,
})
if err != nil {
log.Printf("Couldn't add item to table. Here's why: %v\n", err)
}
return err
}
Actions 175
AWS SDK for Go Code Examples Code Examples Guide
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see PutItem in AWS SDK for Go API Reference.
Query
The following code example shows how to use Query.
Actions 176
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// Query gets all movies in the DynamoDB table that were released in the specified
year.
// The function uses the `expression` package to build the key condition expression
// that is used in the query.
func (basics TableBasics) Query(releaseYear int) ([]Movie, error) {
var err error
var response *dynamodb.QueryOutput
var movies []Movie
keyEx := expression.Key("year").Equal(expression.Value(releaseYear))
expr, err := expression.NewBuilder().WithKeyCondition(keyEx).Build()
if err != nil {
log.Printf("Couldn't build expression for query. Here's why: %v\n", err)
} else {
queryPaginator := dynamodb.NewQueryPaginator(basics.DynamoDbClient,
&dynamodb.QueryInput{
TableName: aws.String(basics.TableName),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
KeyConditionExpression: expr.KeyCondition(),
})
for queryPaginator.HasMorePages() {
response, err = queryPaginator.NextPage(context.TODO())
if err != nil {
Actions 177
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't query for movies released in %v. Here's why: %v\n",
releaseYear, err)
break
} else {
var moviePage []Movie
err = attributevalue.UnmarshalListOfMaps(response.Items, &moviePage)
if err != nil {
log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
break
} else {
movies = append(movies, moviePage...)
}
}
}
}
return movies, err
}
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
Actions 178
AWS SDK for Go Code Examples Code Examples Guide
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see Query in AWS SDK for Go API Reference.
Scan
The following code example shows how to use Scan.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// Scan gets all movies in the DynamoDB table that were released in a range of years
// and projects them to return a reduced set of fields.
// The function uses the `expression` package to build the filter and projection
// expressions.
func (basics TableBasics) Scan(startYear int, endYear int) ([]Movie, error) {
var movies []Movie
var err error
Actions 179
AWS SDK for Go Code Examples Code Examples Guide
var response *dynamodb.ScanOutput
filtEx := expression.Name("year").Between(expression.Value(startYear),
expression.Value(endYear))
projEx := expression.NamesList(
expression.Name("year"), expression.Name("title"), expression.Name("info.rating"))
expr, err :=
expression.NewBuilder().WithFilter(filtEx).WithProjection(projEx).Build()
if err != nil {
log.Printf("Couldn't build expressions for scan. Here's why: %v\n", err)
} else {
scanPaginator := dynamodb.NewScanPaginator(basics.DynamoDbClient,
&dynamodb.ScanInput{
TableName: aws.String(basics.TableName),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
FilterExpression: expr.Filter(),
ProjectionExpression: expr.Projection(),
})
for scanPaginator.HasMorePages() {
response, err = scanPaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't scan for movies released between %v and %v. Here's why: %v
\n",
startYear, endYear, err)
break
} else {
var moviePage []Movie
err = attributevalue.UnmarshalListOfMaps(response.Items, &moviePage)
if err != nil {
log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
break
} else {
movies = append(movies, moviePage...)
}
}
}
}
return movies, err
}
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
Actions 180
AWS SDK for Go Code Examples Code Examples Guide
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see Scan in AWS SDK for Go API Reference.
UpdateItem
The following code example shows how to use UpdateItem.
Actions 181
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// TableBasics encapsulates the Amazon DynamoDB service actions used in the
examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// UpdateMovie updates the rating and plot of a movie that already exists in the
// DynamoDB table. This function uses the `expression` package to build the update
// expression.
func (basics TableBasics) UpdateMovie(movie Movie)
(map[string]map[string]interface{}, error) {
var err error
var response *dynamodb.UpdateItemOutput
var attributeMap map[string]map[string]interface{}
update := expression.Set(expression.Name("info.rating"),
expression.Value(movie.Info["rating"]))
update.Set(expression.Name("info.plot"), expression.Value(movie.Info["plot"]))
expr, err := expression.NewBuilder().WithUpdate(update).Build()
if err != nil {
log.Printf("Couldn't build expression for update. Here's why: %v\n", err)
} else {
response, err = basics.DynamoDbClient.UpdateItem(context.TODO(),
&dynamodb.UpdateItemInput{
TableName: aws.String(basics.TableName),
Key: movie.GetKey(),
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
UpdateExpression: expr.Update(),
ReturnValues: types.ReturnValueUpdatedNew,
Actions 182
AWS SDK for Go Code Examples Code Examples Guide
})
if err != nil {
log.Printf("Couldn't update movie %v. Here's why: %v\n", movie.Title, err)
} else {
err = attributevalue.UnmarshalMap(response.Attributes, &attributeMap)
if err != nil {
log.Printf("Couldn't unmarshall update response. Here's why: %v\n", err)
}
}
}
return attributeMap, err
}
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
Actions 183
AWS SDK for Go Code Examples Code Examples Guide
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
For API details, see UpdateItem in AWS SDK for Go API Reference.
Scenarios
Query a table by using batches of PartiQL statements
The following code example shows how to:
Get a batch of items by running multiple SELECT statements.
Add a batch of items by running multiple INSERT statements.
Update a batch of items by running multiple UPDATE statements.
Delete a batch of items by running multiple DELETE statements.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run a scenario that creates a table and runs batches of PartiQL queries.
// RunPartiQLBatchScenario shows you how to use the AWS SDK for Go
// to run batches of PartiQL statements to query a table that stores data about
movies.
//
// - Use batches of PartiQL statements to add, get, update, and delete data for
// individual movies.
//
// This example creates an Amazon DynamoDB service client from the specified
sdkConfig so that
// you can replace it with a mocked or stubbed config for unit testing.
//
Scenarios 184
AWS SDK for Go Code Examples Code Examples Guide
// This example creates and deletes a DynamoDB table to use during the scenario.
func RunPartiQLBatchScenario(sdkConfig aws.Config, tableName string) {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Something went wrong with the demo.")
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon DynamoDB PartiQL batch demo.")
log.Println(strings.Repeat("-", 88))
tableBasics := actions.TableBasics{
DynamoDbClient: dynamodb.NewFromConfig(sdkConfig),
TableName: tableName,
}
runner := actions.PartiQLRunner{
DynamoDbClient: dynamodb.NewFromConfig(sdkConfig),
TableName: tableName,
}
exists, err := tableBasics.TableExists()
if err != nil {
panic(err)
}
if !exists {
log.Printf("Creating table %v...\n", tableName)
_, err = tableBasics.CreateMovieTable()
if err != nil {
panic(err)
} else {
log.Printf("Created table %v.\n", tableName)
}
} else {
log.Printf("Table %v already exists.\n", tableName)
}
log.Println(strings.Repeat("-", 88))
currentYear, _, _ := time.Now().Date()
customMovies := []actions.Movie{{
Title: "House PartiQL",
Year: currentYear - 5,
Info: map[string]interface{}{
"plot": "Wacky high jinks result from querying a mysterious database.",
Scenarios 185
AWS SDK for Go Code Examples Code Examples Guide
"rating": 8.5}}, {
Title: "House PartiQL 2",
Year: currentYear - 3,
Info: map[string]interface{}{
"plot": "Moderate high jinks result from querying another mysterious
database.",
"rating": 6.5}}, {
Title: "House PartiQL 3",
Year: currentYear - 1,
Info: map[string]interface{}{
"plot": "Tepid high jinks result from querying yet another mysterious
database.",
"rating": 2.5},
},
}
log.Printf("Inserting a batch of movies into table '%v'.\n", tableName)
err = runner.AddMovieBatch(customMovies)
if err == nil {
log.Printf("Added %v movies to the table.\n", len(customMovies))
}
log.Println(strings.Repeat("-", 88))
log.Println("Getting data for a batch of movies.")
movies, err := runner.GetMovieBatch(customMovies)
if err == nil {
for _, movie := range movies {
log.Println(movie)
}
}
log.Println(strings.Repeat("-", 88))
newRatings := []float64{7.7, 4.4, 1.1}
log.Println("Updating a batch of movies with new ratings.")
err = runner.UpdateMovieBatch(customMovies, newRatings)
if err == nil {
log.Printf("Updated %v movies with new ratings.\n", len(customMovies))
}
log.Println(strings.Repeat("-", 88))
log.Println("Getting projected data from the table to verify our update.")
log.Println("Using a page size of 2 to demonstrate paging.")
projections, err := runner.GetAllMovies(2)
if err == nil {
Scenarios 186
AWS SDK for Go Code Examples Code Examples Guide
log.Println("All movies:")
for _, projection := range projections {
log.Println(projection)
}
}
log.Println(strings.Repeat("-", 88))
log.Println("Deleting a batch of movies.")
err = runner.DeleteMovieBatch(customMovies)
if err == nil {
log.Printf("Deleted %v movies.\n", len(customMovies))
}
err = tableBasics.DeleteTable()
if err == nil {
log.Printf("Deleted table %v.\n", tableBasics.TableName)
}
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define a Movie struct that is used in this example.
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
Scenarios 187
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
Create a struct and methods that run PartiQL statements.
// PartiQLRunner encapsulates the Amazon DynamoDB service actions used in the
// PartiQL examples. It contains a DynamoDB service client that is used to act on
the
// specified table.
type PartiQLRunner struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// AddMovieBatch runs a batch of PartiQL INSERT statements to add multiple movies to
the
// DynamoDB table.
func (runner PartiQLRunner) AddMovieBatch(movies []Movie) error {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year,
movie.Info})
if err != nil {
panic(err)
Scenarios 188
AWS SDK for Go Code Examples Code Examples Guide
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(fmt.Sprintf(
"INSERT INTO \"%v\" VALUE {'title': ?, 'year': ?, 'info': ?}",
runner.TableName)),
Parameters: params,
}
}
_, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
if err != nil {
log.Printf("Couldn't insert a batch of items with PartiQL. Here's why: %v\n", err)
}
return err
}
// GetMovieBatch runs a batch of PartiQL SELECT statements to get multiple movies
from
// the DynamoDB table by title and year.
func (runner PartiQLRunner) GetMovieBatch(movies []Movie) ([]Movie, error) {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(
fmt.Sprintf("SELECT * FROM \"%v\" WHERE title=? AND year=?", runner.TableName)),
Parameters: params,
}
}
output, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
var outMovies []Movie
if err != nil {
Scenarios 189
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't get a batch of items with PartiQL. Here's why: %v\n", err)
} else {
for _, response := range output.Responses {
var movie Movie
err = attributevalue.UnmarshalMap(response.Item, &movie)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
} else {
outMovies = append(outMovies, movie)
}
}
}
return outMovies, err
}
// GetAllMovies runs a PartiQL SELECT statement to get all movies from the DynamoDB
table.
// pageSize is not typically required and is used to show how to paginate the
results.
// The results are projected to return only the title and rating of each movie.
func (runner PartiQLRunner) GetAllMovies(pageSize int32) ([]map[string]interface{},
error) {
var output []map[string]interface{}
var response *dynamodb.ExecuteStatementOutput
var err error
var nextToken *string
for moreData := true; moreData; {
response, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("SELECT title, info.rating FROM \"%v\"", runner.TableName)),
Limit: aws.Int32(pageSize),
NextToken: nextToken,
})
if err != nil {
log.Printf("Couldn't get movies. Here's why: %v\n", err)
moreData = false
} else {
var pageOutput []map[string]interface{}
err = attributevalue.UnmarshalListOfMaps(response.Items, &pageOutput)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
Scenarios 190
AWS SDK for Go Code Examples Code Examples Guide
} else {
log.Printf("Got a page of length %v.\n", len(response.Items))
output = append(output, pageOutput...)
}
nextToken = response.NextToken
moreData = nextToken != nil
}
}
return output, err
}
// UpdateMovieBatch runs a batch of PartiQL UPDATE statements to update the rating
of
// multiple movies that already exist in the DynamoDB table.
func (runner PartiQLRunner) UpdateMovieBatch(movies []Movie, ratings []float64)
error {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{ratings[index],
movie.Title, movie.Year})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(
fmt.Sprintf("UPDATE \"%v\" SET info.rating=? WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
}
}
_, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
if err != nil {
log.Printf("Couldn't update the batch of movies. Here's why: %v\n", err)
}
return err
}
Scenarios 191
AWS SDK for Go Code Examples Code Examples Guide
// DeleteMovieBatch runs a batch of PartiQL DELETE statements to remove multiple
movies
// from the DynamoDB table.
func (runner PartiQLRunner) DeleteMovieBatch(movies []Movie) error {
statementRequests := make([]types.BatchStatementRequest, len(movies))
for index, movie := range movies {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year})
if err != nil {
panic(err)
}
statementRequests[index] = types.BatchStatementRequest{
Statement: aws.String(
fmt.Sprintf("DELETE FROM \"%v\" WHERE title=? AND year=?", runner.TableName)),
Parameters: params,
}
}
_, err := runner.DynamoDbClient.BatchExecuteStatement(context.TODO(),
&dynamodb.BatchExecuteStatementInput{
Statements: statementRequests,
})
if err != nil {
log.Printf("Couldn't delete the batch of movies. Here's why: %v\n", err)
}
return err
}
For API details, see BatchExecuteStatement in AWS SDK for Go API Reference.
Query a table using PartiQL
The following code example shows how to:
Get an item by running a SELECT statement.
Add an item by running an INSERT statement.
Update an item by running an UPDATE statement.
Delete an item by running a DELETE statement.
Scenarios 192
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run a scenario that creates a table and runs PartiQL queries.
// RunPartiQLSingleScenario shows you how to use the AWS SDK for Go
// to use PartiQL to query a table that stores data about movies.
//
// * Use PartiQL statements to add, get, update, and delete data for individual
movies.
//
// This example creates an Amazon DynamoDB service client from the specified
sdkConfig so that
// you can replace it with a mocked or stubbed config for unit testing.
//
// This example creates and deletes a DynamoDB table to use during the scenario.
func RunPartiQLSingleScenario(sdkConfig aws.Config, tableName string) {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Something went wrong with the demo.")
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon DynamoDB PartiQL single action demo.")
log.Println(strings.Repeat("-", 88))
tableBasics := actions.TableBasics{
DynamoDbClient: dynamodb.NewFromConfig(sdkConfig),
TableName: tableName,
}
runner := actions.PartiQLRunner{
DynamoDbClient: dynamodb.NewFromConfig(sdkConfig),
TableName: tableName,
}
exists, err := tableBasics.TableExists()
Scenarios 193
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
panic(err)
}
if !exists {
log.Printf("Creating table %v...\n", tableName)
_, err = tableBasics.CreateMovieTable()
if err != nil {
panic(err)
} else {
log.Printf("Created table %v.\n", tableName)
}
} else {
log.Printf("Table %v already exists.\n", tableName)
}
log.Println(strings.Repeat("-", 88))
currentYear, _, _ := time.Now().Date()
customMovie := actions.Movie{
Title: "24 Hour PartiQL People",
Year: currentYear,
Info: map[string]interface{}{
"plot": "A group of data developers discover a new query language they can't
stop using.",
"rating": 9.9,
},
}
log.Printf("Inserting movie '%v' released in %v.", customMovie.Title,
customMovie.Year)
err = runner.AddMovie(customMovie)
if err == nil {
log.Printf("Added %v to the movie table.\n", customMovie.Title)
}
log.Println(strings.Repeat("-", 88))
log.Printf("Getting data for movie '%v' released in %v.", customMovie.Title,
customMovie.Year)
movie, err := runner.GetMovie(customMovie.Title, customMovie.Year)
if err == nil {
log.Println(movie)
}
log.Println(strings.Repeat("-", 88))
newRating := 6.6
Scenarios 194
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Updating movie '%v' with a rating of %v.", customMovie.Title,
newRating)
err = runner.UpdateMovie(customMovie, newRating)
if err == nil {
log.Printf("Updated %v with a new rating.\n", customMovie.Title)
}
log.Println(strings.Repeat("-", 88))
log.Printf("Getting data again to verify the update.")
movie, err = runner.GetMovie(customMovie.Title, customMovie.Year)
if err == nil {
log.Println(movie)
}
log.Println(strings.Repeat("-", 88))
log.Printf("Deleting movie '%v'.\n", customMovie.Title)
err = runner.DeleteMovie(customMovie)
if err == nil {
log.Printf("Deleted %v.\n", customMovie.Title)
}
err = tableBasics.DeleteTable()
if err == nil {
log.Printf("Deleted table %v.\n", tableBasics.TableName)
}
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define a Movie struct that is used in this example.
// Movie encapsulates data about a movie. Title and Year are the composite primary
key
// of the movie in Amazon DynamoDB. Title is the sort key, Year is the partition
key,
// and Info is additional data.
type Movie struct {
Title string `dynamodbav:"title"`
Scenarios 195
AWS SDK for Go Code Examples Code Examples Guide
Year int `dynamodbav:"year"`
Info map[string]interface{} `dynamodbav:"info"`
}
// GetKey returns the composite primary key of the movie in a format that can be
// sent to DynamoDB.
func (movie Movie) GetKey() map[string]types.AttributeValue {
title, err := attributevalue.Marshal(movie.Title)
if err != nil {
panic(err)
}
year, err := attributevalue.Marshal(movie.Year)
if err != nil {
panic(err)
}
return map[string]types.AttributeValue{"title": title, "year": year}
}
// String returns the title, year, rating, and plot of a movie, formatted for the
example.
func (movie Movie) String() string {
return fmt.Sprintf("%v\n\tReleased: %v\n\tRating: %v\n\tPlot: %v\n",
movie.Title, movie.Year, movie.Info["rating"], movie.Info["plot"])
}
Create a struct and methods that run PartiQL statements.
// PartiQLRunner encapsulates the Amazon DynamoDB service actions used in the
// PartiQL examples. It contains a DynamoDB service client that is used to act on
the
// specified table.
type PartiQLRunner struct {
DynamoDbClient *dynamodb.Client
TableName string
}
// AddMovie runs a PartiQL INSERT statement to add a movie to the DynamoDB table.
func (runner PartiQLRunner) AddMovie(movie Movie) error {
Scenarios 196
AWS SDK for Go Code Examples Code Examples Guide
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year,
movie.Info})
if err != nil {
panic(err)
}
_, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("INSERT INTO \"%v\" VALUE {'title': ?, 'year': ?, 'info': ?}",
runner.TableName)),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't insert an item with PartiQL. Here's why: %v\n", err)
}
return err
}
// GetMovie runs a PartiQL SELECT statement to get a movie from the DynamoDB table
by
// title and year.
func (runner PartiQLRunner) GetMovie(title string, year int) (Movie, error) {
var movie Movie
params, err := attributevalue.MarshalList([]interface{}{title, year})
if err != nil {
panic(err)
}
response, err := runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("SELECT * FROM \"%v\" WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't get info about %v. Here's why: %v\n", title, err)
} else {
err = attributevalue.UnmarshalMap(response.Items[0], &movie)
if err != nil {
log.Printf("Couldn't unmarshal response. Here's why: %v\n", err)
}
}
Scenarios 197
AWS SDK for Go Code Examples Code Examples Guide
return movie, err
}
// UpdateMovie runs a PartiQL UPDATE statement to update the rating of a movie that
// already exists in the DynamoDB table.
func (runner PartiQLRunner) UpdateMovie(movie Movie, rating float64) error {
params, err := attributevalue.MarshalList([]interface{}{rating, movie.Title,
movie.Year})
if err != nil {
panic(err)
}
_, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("UPDATE \"%v\" SET info.rating=? WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't update movie %v. Here's why: %v\n", movie.Title, err)
}
return err
}
// DeleteMovie runs a PartiQL DELETE statement to remove a movie from the DynamoDB
table.
func (runner PartiQLRunner) DeleteMovie(movie Movie) error {
params, err := attributevalue.MarshalList([]interface{}{movie.Title, movie.Year})
if err != nil {
panic(err)
}
_, err = runner.DynamoDbClient.ExecuteStatement(context.TODO(),
&dynamodb.ExecuteStatementInput{
Statement: aws.String(
fmt.Sprintf("DELETE FROM \"%v\" WHERE title=? AND year=?",
runner.TableName)),
Parameters: params,
})
if err != nil {
Scenarios 198
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't delete %v from the table. Here's why: %v\n", movie.Title,
err)
}
return err
}
For API details, see ExecuteStatement in AWS SDK for Go API Reference.
Serverless examples
Invoke a Lambda function from a DynamoDB trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving records from a DynamoDB stream. The function retrieves the DynamoDB
payload and logs the record contents.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming a DynamoDB event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-lambda-go/events"
"fmt"
)
func HandleRequest(ctx context.Context, event events.DynamoDBEvent) (*string, error)
{
Serverless examples 199
AWS SDK for Go Code Examples Code Examples Guide
if len(event.Records) == 0 {
return nil, fmt.Errorf("received empty event")
}
for _, record := range event.Records {
LogDynamoDBRecord(record)
}
message := fmt.Sprintf("Records processed: %d", len(event.Records))
return &message, nil
}
func main() {
lambda.Start(HandleRequest)
}
func LogDynamoDBRecord(record events.DynamoDBEventRecord){
fmt.Println(record.EventID)
fmt.Println(record.EventName)
fmt.Printf("%+v\n", record.Change)
}
Reporting batch item failures for Lambda functions with a DynamoDB trigger
The following code example shows how to implement partial batch response for Lambda functions
that receive events from a DynamoDB stream. The function reports the batch item failures in the
response, signaling to Lambda to retry those messages later.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Reporting DynamoDB batch item failures with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
Serverless examples 200
AWS SDK for Go Code Examples Code Examples Guide
import (
"context"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
type BatchItemFailure struct {
ItemIdentifier string `json:"ItemIdentifier"`
}
type BatchResult struct {
BatchItemFailures []BatchItemFailure `json:"BatchItemFailures"`
}
func HandleRequest(ctx context.Context, event events.DynamoDBEvent) (*BatchResult,
error) {
var batchItemFailures []BatchItemFailure
curRecordSequenceNumber := ""
for _, record := range event.Records {
// Process your record
curRecordSequenceNumber = record.Change.SequenceNumber
}
if curRecordSequenceNumber != "" {
batchItemFailures = append(batchItemFailures, BatchItemFailure{ItemIdentifier:
curRecordSequenceNumber})
}
batchResult := BatchResult{
BatchItemFailures: batchItemFailures,
}
return &batchResult, nil
}
func main() {
lambda.Start(HandleRequest)
}
Serverless examples 201
AWS SDK for Go Code Examples Code Examples Guide
IAM examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with IAM.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello IAM
The following code examples show how to get started using IAM.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/iam"
)
IAM 202
AWS SDK for Go Code Examples Code Examples Guide
// main uses the AWS SDK for Go (v2) to create an AWS Identity and Access Management
(IAM)
// client and list up to 10 policies in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
iamClient := iam.NewFromConfig(sdkConfig)
const maxPols = 10
fmt.Printf("Let's list up to %v policies for your account.\n", maxPols)
result, err := iamClient.ListPolicies(context.TODO(), &iam.ListPoliciesInput{
MaxItems: aws.Int32(maxPols),
})
if err != nil {
fmt.Printf("Couldn't list policies for your account. Here's why: %v\n", err)
return
}
if len(result.Policies) == 0 {
fmt.Println("You don't have any policies!")
} else {
for _, policy := range result.Policies {
fmt.Printf("\t%v\n", *policy.PolicyName)
}
}
}
For API details, see ListPolicies in AWS SDK for Go API Reference.
Topics
Actions
Scenarios
IAM 203
AWS SDK for Go Code Examples Code Examples Guide
Actions
AttachRolePolicy
The following code example shows how to use AttachRolePolicy.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// AttachRolePolicy attaches a policy to a role.
func (wrapper RoleWrapper) AttachRolePolicy(policyArn string, roleName string) error
{
_, err := wrapper.IamClient.AttachRolePolicy(context.TODO(),
&iam.AttachRolePolicyInput{
PolicyArn: aws.String(policyArn),
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't attach policy %v to role %v. Here's why: %v\n", policyArn,
roleName, err)
}
return err
}
For API details, see AttachRolePolicy in AWS SDK for Go API Reference.
Actions 204
AWS SDK for Go Code Examples Code Examples Guide
CreateAccessKey
The following code example shows how to use CreateAccessKey.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// CreateAccessKeyPair creates an access key for a user. The returned access key
contains
// the ID and secret credentials needed to use the key.
func (wrapper UserWrapper) CreateAccessKeyPair(userName string) (*types.AccessKey,
error) {
var key *types.AccessKey
result, err := wrapper.IamClient.CreateAccessKey(context.TODO(),
&iam.CreateAccessKeyInput{
UserName: aws.String(userName)})
if err != nil {
log.Printf("Couldn't create access key pair for user %v. Here's why: %v\n",
userName, err)
} else {
key = result.AccessKey
}
return key, err
}
For API details, see CreateAccessKey in AWS SDK for Go API Reference.
Actions 205
AWS SDK for Go Code Examples Code Examples Guide
CreatePolicy
The following code example shows how to use CreatePolicy.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// PolicyWrapper encapsulates AWS Identity and Access Management (IAM) policy
actions
// used in the examples.
// It contains an IAM service client that is used to perform policy actions.
type PolicyWrapper struct {
IamClient *iam.Client
}
// CreatePolicy creates a policy that grants a list of actions to the specified
resource.
// PolicyDocument shows how to work with a policy document as a data structure and
// serialize it to JSON by using Go's JSON marshaler.
func (wrapper PolicyWrapper) CreatePolicy(policyName string, actions []string,
resourceArn string) (*types.Policy, error) {
var policy *types.Policy
policyDoc := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: actions,
Resource: aws.String(resourceArn),
}},
}
policyBytes, err := json.Marshal(policyDoc)
if err != nil {
log.Printf("Couldn't create policy document for %v. Here's why: %v\n",
resourceArn, err)
return nil, err
Actions 206
AWS SDK for Go Code Examples Code Examples Guide
}
result, err := wrapper.IamClient.CreatePolicy(context.TODO(),
&iam.CreatePolicyInput{
PolicyDocument: aws.String(string(policyBytes)),
PolicyName: aws.String(policyName),
})
if err != nil {
log.Printf("Couldn't create policy %v. Here's why: %v\n", policyName, err)
} else {
policy = result.Policy
}
return policy, err
}
For API details, see CreatePolicy in AWS SDK for Go API Reference.
CreateRole
The following code example shows how to use CreateRole.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// CreateRole creates a role that trusts a specified user. The trusted user can
assume
Actions 207
AWS SDK for Go Code Examples Code Examples Guide
// the role to acquire its permissions.
// PolicyDocument shows how to work with a policy document as a data structure and
// serialize it to JSON by using Go's JSON marshaler.
func (wrapper RoleWrapper) CreateRole(roleName string, trustedUserArn string)
(*types.Role, error) {
var role *types.Role
trustPolicy := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Principal: map[string]string{"AWS": trustedUserArn},
Action: []string{"sts:AssumeRole"},
}},
}
policyBytes, err := json.Marshal(trustPolicy)
if err != nil {
log.Printf("Couldn't create trust policy for %v. Here's why: %v\n",
trustedUserArn, err)
return nil, err
}
result, err := wrapper.IamClient.CreateRole(context.TODO(), &iam.CreateRoleInput{
AssumeRolePolicyDocument: aws.String(string(policyBytes)),
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't create role %v. Here's why: %v\n", roleName, err)
} else {
role = result.Role
}
return role, err
}
For API details, see CreateRole in AWS SDK for Go API Reference.
CreateServiceLinkedRole
The following code example shows how to use CreateServiceLinkedRole.
Actions 208
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// CreateServiceLinkedRole creates a service-linked role that is owned by the
specified service.
func (wrapper RoleWrapper) CreateServiceLinkedRole(serviceName string, description
string) (*types.Role, error) {
var role *types.Role
result, err := wrapper.IamClient.CreateServiceLinkedRole(context.TODO(),
&iam.CreateServiceLinkedRoleInput{
AWSServiceName: aws.String(serviceName),
Description: aws.String(description),
})
if err != nil {
log.Printf("Couldn't create service-linked role %v. Here's why: %v\n",
serviceName, err)
} else {
role = result.Role
}
return role, err
}
For API details, see CreateServiceLinkedRole in AWS SDK for Go API Reference.
Actions 209
AWS SDK for Go Code Examples Code Examples Guide
CreateUser
The following code example shows how to use CreateUser.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// CreateUser creates a new user with the specified name.
func (wrapper UserWrapper) CreateUser(userName string) (*types.User, error) {
var user *types.User
result, err := wrapper.IamClient.CreateUser(context.TODO(), &iam.CreateUserInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
} else {
user = result.User
}
return user, err
}
For API details, see CreateUser in AWS SDK for Go API Reference.
DeleteAccessKey
The following code example shows how to use DeleteAccessKey.
Actions 210
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// DeleteAccessKey deletes an access key from a user.
func (wrapper UserWrapper) DeleteAccessKey(userName string, keyId string) error {
_, err := wrapper.IamClient.DeleteAccessKey(context.TODO(),
&iam.DeleteAccessKeyInput{
AccessKeyId: aws.String(keyId),
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't delete access key %v. Here's why: %v\n", keyId, err)
}
return err
}
For API details, see DeleteAccessKey in AWS SDK for Go API Reference.
DeletePolicy
The following code example shows how to use DeletePolicy.
Actions 211
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// PolicyWrapper encapsulates AWS Identity and Access Management (IAM) policy
actions
// used in the examples.
// It contains an IAM service client that is used to perform policy actions.
type PolicyWrapper struct {
IamClient *iam.Client
}
// DeletePolicy deletes a policy.
func (wrapper PolicyWrapper) DeletePolicy(policyArn string) error {
_, err := wrapper.IamClient.DeletePolicy(context.TODO(), &iam.DeletePolicyInput{
PolicyArn: aws.String(policyArn),
})
if err != nil {
log.Printf("Couldn't delete policy %v. Here's why: %v\n", policyArn, err)
}
return err
}
For API details, see DeletePolicy in AWS SDK for Go API Reference.
DeleteRole
The following code example shows how to use DeleteRole.
Actions 212
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// DeleteRole deletes a role. All attached policies must be detached before a
// role can be deleted.
func (wrapper RoleWrapper) DeleteRole(roleName string) error {
_, err := wrapper.IamClient.DeleteRole(context.TODO(), &iam.DeleteRoleInput{
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't delete role %v. Here's why: %v\n", roleName, err)
}
return err
}
For API details, see DeleteRole in AWS SDK for Go API Reference.
DeleteServiceLinkedRole
The following code example shows how to use DeleteServiceLinkedRole.
Actions 213
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// DeleteServiceLinkedRole deletes a service-linked role.
func (wrapper RoleWrapper) DeleteServiceLinkedRole(roleName string) error {
_, err := wrapper.IamClient.DeleteServiceLinkedRole(context.TODO(),
&iam.DeleteServiceLinkedRoleInput{
RoleName: aws.String(roleName)},
)
if err != nil {
log.Printf("Couldn't delete service-linked role %v. Here's why: %v\n", roleName,
err)
}
return err
}
For API details, see DeleteServiceLinkedRole in AWS SDK for Go API Reference.
DeleteUser
The following code example shows how to use DeleteUser.
Actions 214
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// DeleteUser deletes a user.
func (wrapper UserWrapper) DeleteUser(userName string) error {
_, err := wrapper.IamClient.DeleteUser(context.TODO(), &iam.DeleteUserInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't delete user %v. Here's why: %v\n", userName, err)
}
return err
}
For API details, see DeleteUser in AWS SDK for Go API Reference.
DeleteUserPolicy
The following code example shows how to use DeleteUserPolicy.
Actions 215
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// DeleteUserPolicy deletes an inline policy from a user.
func (wrapper UserWrapper) DeleteUserPolicy(userName string, policyName string)
error {
_, err := wrapper.IamClient.DeleteUserPolicy(context.TODO(),
&iam.DeleteUserPolicyInput{
PolicyName: aws.String(policyName),
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't delete policy from user %v. Here's why: %v\n", userName, err)
}
return err
}
For API details, see DeleteUserPolicy in AWS SDK for Go API Reference.
DetachRolePolicy
The following code example shows how to use DetachRolePolicy.
Actions 216
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// DetachRolePolicy detaches a policy from a role.
func (wrapper RoleWrapper) DetachRolePolicy(roleName string, policyArn string) error
{
_, err := wrapper.IamClient.DetachRolePolicy(context.TODO(),
&iam.DetachRolePolicyInput{
PolicyArn: aws.String(policyArn),
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't detach policy from role %v. Here's why: %v\n", roleName, err)
}
return err
}
For API details, see DetachRolePolicy in AWS SDK for Go API Reference.
GetAccountPasswordPolicy
The following code example shows how to use GetAccountPasswordPolicy.
Actions 217
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// AccountWrapper encapsulates AWS Identity and Access Management (IAM) account
actions
// used in the examples.
// It contains an IAM service client that is used to perform account actions.
type AccountWrapper struct {
IamClient *iam.Client
}
// GetAccountPasswordPolicy gets the account password policy for the current
account.
// If no policy has been set, a NoSuchEntityException is error is returned.
func (wrapper AccountWrapper) GetAccountPasswordPolicy() (*types.PasswordPolicy,
error) {
var pwPolicy *types.PasswordPolicy
result, err := wrapper.IamClient.GetAccountPasswordPolicy(context.TODO(),
&iam.GetAccountPasswordPolicyInput{})
if err != nil {
log.Printf("Couldn't get account password policy. Here's why: %v\n", err)
} else {
pwPolicy = result.PasswordPolicy
}
return pwPolicy, err
}
For API details, see GetAccountPasswordPolicy in AWS SDK for Go API Reference.
Actions 218
AWS SDK for Go Code Examples Code Examples Guide
GetPolicy
The following code example shows how to use GetPolicy.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// PolicyWrapper encapsulates AWS Identity and Access Management (IAM) policy
actions
// used in the examples.
// It contains an IAM service client that is used to perform policy actions.
type PolicyWrapper struct {
IamClient *iam.Client
}
// GetPolicy gets data about a policy.
func (wrapper PolicyWrapper) GetPolicy(policyArn string) (*types.Policy, error) {
var policy *types.Policy
result, err := wrapper.IamClient.GetPolicy(context.TODO(), &iam.GetPolicyInput{
PolicyArn: aws.String(policyArn),
})
if err != nil {
log.Printf("Couldn't get policy %v. Here's why: %v\n", policyArn, err)
} else {
policy = result.Policy
}
return policy, err
}
For API details, see GetPolicy in AWS SDK for Go API Reference.
Actions 219
AWS SDK for Go Code Examples Code Examples Guide
GetRole
The following code example shows how to use GetRole.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// GetRole gets data about a role.
func (wrapper RoleWrapper) GetRole(roleName string) (*types.Role, error) {
var role *types.Role
result, err := wrapper.IamClient.GetRole(context.TODO(),
&iam.GetRoleInput{RoleName: aws.String(roleName)})
if err != nil {
log.Printf("Couldn't get role %v. Here's why: %v\n", roleName, err)
} else {
role = result.Role
}
return role, err
}
For API details, see GetRole in AWS SDK for Go API Reference.
GetUser
The following code example shows how to use GetUser.
Actions 220
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// GetUser gets data about a user.
func (wrapper UserWrapper) GetUser(userName string) (*types.User, error) {
var user *types.User
result, err := wrapper.IamClient.GetUser(context.TODO(), &iam.GetUserInput{
UserName: aws.String(userName),
})
if err != nil {
var apiError smithy.APIError
if errors.As(err, &apiError) {
switch apiError.(type) {
case *types.NoSuchEntityException:
log.Printf("User %v does not exist.\n", userName)
err = nil
default:
log.Printf("Couldn't get user %v. Here's why: %v\n", userName, err)
}
}
} else {
user = result.User
}
return user, err
}
Actions 221
AWS SDK for Go Code Examples Code Examples Guide
For API details, see GetUser in AWS SDK for Go API Reference.
ListAccessKeys
The following code example shows how to use ListAccessKeys.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// ListAccessKeys lists the access keys for the specified user.
func (wrapper UserWrapper) ListAccessKeys(userName string)
([]types.AccessKeyMetadata, error) {
var keys []types.AccessKeyMetadata
result, err := wrapper.IamClient.ListAccessKeys(context.TODO(),
&iam.ListAccessKeysInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't list access keys for user %v. Here's why: %v\n", userName,
err)
} else {
keys = result.AccessKeyMetadata
}
return keys, err
}
Actions 222
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListAccessKeys in AWS SDK for Go API Reference.
ListAttachedRolePolicies
The following code example shows how to use ListAttachedRolePolicies.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// ListAttachedRolePolicies lists the policies that are attached to the specified
role.
func (wrapper RoleWrapper) ListAttachedRolePolicies(roleName string)
([]types.AttachedPolicy, error) {
var policies []types.AttachedPolicy
result, err := wrapper.IamClient.ListAttachedRolePolicies(context.TODO(),
&iam.ListAttachedRolePoliciesInput{
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't list attached policies for role %v. Here's why: %v\n",
roleName, err)
} else {
policies = result.AttachedPolicies
}
return policies, err
}
Actions 223
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListAttachedRolePolicies in AWS SDK for Go API Reference.
ListGroups
The following code example shows how to use ListGroups.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// GroupWrapper encapsulates AWS Identity and Access Management (IAM) group actions
// used in the examples.
// It contains an IAM service client that is used to perform group actions.
type GroupWrapper struct {
IamClient *iam.Client
}
// ListGroups lists up to maxGroups number of groups.
func (wrapper GroupWrapper) ListGroups(maxGroups int32) ([]types.Group, error) {
var groups []types.Group
result, err := wrapper.IamClient.ListGroups(context.TODO(), &iam.ListGroupsInput{
MaxItems: aws.Int32(maxGroups),
})
if err != nil {
log.Printf("Couldn't list groups. Here's why: %v\n", err)
} else {
groups = result.Groups
}
return groups, err
}
Actions 224
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListGroups in AWS SDK for Go API Reference.
ListPolicies
The following code example shows how to use ListPolicies.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// PolicyWrapper encapsulates AWS Identity and Access Management (IAM) policy
actions
// used in the examples.
// It contains an IAM service client that is used to perform policy actions.
type PolicyWrapper struct {
IamClient *iam.Client
}
// ListPolicies gets up to maxPolicies policies.
func (wrapper PolicyWrapper) ListPolicies(maxPolicies int32) ([]types.Policy, error)
{
var policies []types.Policy
result, err := wrapper.IamClient.ListPolicies(context.TODO(),
&iam.ListPoliciesInput{
MaxItems: aws.Int32(maxPolicies),
})
if err != nil {
log.Printf("Couldn't list policies. Here's why: %v\n", err)
} else {
policies = result.Policies
}
return policies, err
}
Actions 225
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListPolicies in AWS SDK for Go API Reference.
ListRolePolicies
The following code example shows how to use ListRolePolicies.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// ListRolePolicies lists the inline policies for a role.
func (wrapper RoleWrapper) ListRolePolicies(roleName string) ([]string, error) {
var policies []string
result, err := wrapper.IamClient.ListRolePolicies(context.TODO(),
&iam.ListRolePoliciesInput{
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't list policies for role %v. Here's why: %v\n", roleName, err)
} else {
policies = result.PolicyNames
}
return policies, err
}
Actions 226
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListRolePolicies in AWS SDK for Go API Reference.
ListRoles
The following code example shows how to use ListRoles.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// ListRoles gets up to maxRoles roles.
func (wrapper RoleWrapper) ListRoles(maxRoles int32) ([]types.Role, error) {
var roles []types.Role
result, err := wrapper.IamClient.ListRoles(context.TODO(),
&iam.ListRolesInput{MaxItems: aws.Int32(maxRoles)},
)
if err != nil {
log.Printf("Couldn't list roles. Here's why: %v\n", err)
} else {
roles = result.Roles
}
return roles, err
}
Actions 227
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListRoles in AWS SDK for Go API Reference.
ListSAMLProviders
The following code example shows how to use ListSAMLProviders.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// AccountWrapper encapsulates AWS Identity and Access Management (IAM) account
actions
// used in the examples.
// It contains an IAM service client that is used to perform account actions.
type AccountWrapper struct {
IamClient *iam.Client
}
// ListSAMLProviders gets the SAML providers for the account.
func (wrapper AccountWrapper) ListSAMLProviders() ([]types.SAMLProviderListEntry,
error) {
var providers []types.SAMLProviderListEntry
result, err := wrapper.IamClient.ListSAMLProviders(context.TODO(),
&iam.ListSAMLProvidersInput{})
if err != nil {
log.Printf("Couldn't list SAML providers. Here's why: %v\n", err)
} else {
providers = result.SAMLProviderList
}
return providers, err
}
Actions 228
AWS SDK for Go Code Examples Code Examples Guide
For API details, see ListSAMLProviders in AWS SDK for Go API Reference.
ListUserPolicies
The following code example shows how to use ListUserPolicies.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// ListUserPolicies lists the inline policies for the specified user.
func (wrapper UserWrapper) ListUserPolicies(userName string) ([]string, error) {
var policies []string
result, err := wrapper.IamClient.ListUserPolicies(context.TODO(),
&iam.ListUserPoliciesInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't list policies for user %v. Here's why: %v\n", userName, err)
} else {
policies = result.PolicyNames
}
return policies, err
}
For API details, see ListUserPolicies in AWS SDK for Go API Reference.
Actions 229
AWS SDK for Go Code Examples Code Examples Guide
ListUsers
The following code example shows how to use ListUsers.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// ListUsers gets up to maxUsers number of users.
func (wrapper UserWrapper) ListUsers(maxUsers int32) ([]types.User, error) {
var users []types.User
result, err := wrapper.IamClient.ListUsers(context.TODO(), &iam.ListUsersInput{
MaxItems: aws.Int32(maxUsers),
})
if err != nil {
log.Printf("Couldn't list users. Here's why: %v\n", err)
} else {
users = result.Users
}
return users, err
}
For API details, see ListUsers in AWS SDK for Go API Reference.
PutUserPolicy
The following code example shows how to use PutUserPolicy.
Actions 230
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// CreateUserPolicy adds an inline policy to a user. This example creates a policy
that
// grants a list of actions on a specified role.
// PolicyDocument shows how to work with a policy document as a data structure and
// serialize it to JSON by using Go's JSON marshaler.
func (wrapper UserWrapper) CreateUserPolicy(userName string, policyName string,
actions []string,
roleArn string) error {
policyDoc := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: actions,
Resource: aws.String(roleArn),
}},
}
policyBytes, err := json.Marshal(policyDoc)
if err != nil {
log.Printf("Couldn't create policy document for %v. Here's why: %v\n", roleArn,
err)
return err
}
_, err = wrapper.IamClient.PutUserPolicy(context.TODO(), &iam.PutUserPolicyInput{
PolicyDocument: aws.String(string(policyBytes)),
PolicyName: aws.String(policyName),
Actions 231
AWS SDK for Go Code Examples Code Examples Guide
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't create policy for user %v. Here's why: %v\n", userName, err)
}
return err
}
For API details, see PutUserPolicy in AWS SDK for Go API Reference.
Scenarios
Create a user and assume a role
The following code example shows how to create a user and assume a role.
Warning
To avoid security risks, don't use IAM users for authentication when developing purpose-
built software or working with real data. Instead, use federation with an identity provider
such as AWS IAM Identity Center.
Create a user with no permissions.
Create a role that grants permission to list Amazon S3 buckets for the account.
Add a policy to let the user assume the role.
Assume the role and list S3 buckets using temporary credentials, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
Scenarios 232
AWS SDK for Go Code Examples Code Examples Guide
// AssumeRoleScenario shows you how to use the AWS Identity and Access Management
(IAM)
// service to perform the following actions:
//
// 1. Create a user who has no permissions.
// 2. Create a role that grants permission to list Amazon Simple Storage Service
// (Amazon S3) buckets for the account.
// 3. Add a policy to let the user assume the role.
// 4. Try and fail to list buckets without permissions.
// 5. Assume the role and list S3 buckets using temporary credentials.
// 6. Delete the policy, role, and user.
type AssumeRoleScenario struct {
sdkConfig aws.Config
accountWrapper actions.AccountWrapper
policyWrapper actions.PolicyWrapper
roleWrapper actions.RoleWrapper
userWrapper actions.UserWrapper
questioner demotools.IQuestioner
helper IScenarioHelper
isTestRun bool
}
// NewAssumeRoleScenario constructs an AssumeRoleScenario instance from a
configuration.
// It uses the specified config to get an IAM client and create wrappers for the
actions
// used in the scenario.
func NewAssumeRoleScenario(sdkConfig aws.Config, questioner demotools.IQuestioner,
helper IScenarioHelper) AssumeRoleScenario {
iamClient := iam.NewFromConfig(sdkConfig)
return AssumeRoleScenario{
sdkConfig: sdkConfig,
accountWrapper: actions.AccountWrapper{IamClient: iamClient},
policyWrapper: actions.PolicyWrapper{IamClient: iamClient},
roleWrapper: actions.RoleWrapper{IamClient: iamClient},
userWrapper: actions.UserWrapper{IamClient: iamClient},
questioner: questioner,
helper: helper,
}
}
// addTestOptions appends the API options specified in the original configuration to
Scenarios 233
AWS SDK for Go Code Examples Code Examples Guide
// another configuration. This is used to attach the middleware stubber to clients
// that are constructed during the scenario, which is needed for unit testing.
func (scenario AssumeRoleScenario) addTestOptions(scenarioConfig *aws.Config) {
if scenario.isTestRun {
scenarioConfig.APIOptions = append(scenarioConfig.APIOptions,
scenario.sdkConfig.APIOptions...)
}
}
// Run runs the interactive scenario.
func (scenario AssumeRoleScenario) Run() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong with the demo.\n")
log.Println(r)
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the AWS Identity and Access Management (IAM) assume role
demo.")
log.Println(strings.Repeat("-", 88))
user := scenario.CreateUser()
accessKey := scenario.CreateAccessKey(user)
role := scenario.CreateRoleAndPolicies(user)
noPermsConfig := scenario.ListBucketsWithoutPermissions(accessKey)
scenario.ListBucketsWithAssumedRole(noPermsConfig, role)
scenario.Cleanup(user, role)
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
// CreateUser creates a new IAM user. This user has no permissions.
func (scenario AssumeRoleScenario) CreateUser() *types.User {
log.Println("Let's create an example user with no permissions.")
userName := scenario.questioner.Ask("Enter a name for the example user:",
demotools.NotEmpty{})
user, err := scenario.userWrapper.GetUser(userName)
if err != nil {
panic(err)
}
Scenarios 234
AWS SDK for Go Code Examples Code Examples Guide
if user == nil {
user, err = scenario.userWrapper.CreateUser(userName)
if err != nil {
panic(err)
}
log.Printf("Created user %v.\n", *user.UserName)
} else {
log.Printf("User %v already exists.\n", *user.UserName)
}
log.Println(strings.Repeat("-", 88))
return user
}
// CreateAccessKey creates an access key for the user.
func (scenario AssumeRoleScenario) CreateAccessKey(user *types.User)
*types.AccessKey {
accessKey, err := scenario.userWrapper.CreateAccessKeyPair(*user.UserName)
if err != nil {
panic(err)
}
log.Printf("Created access key %v for your user.", *accessKey.AccessKeyId)
log.Println("Waiting a few seconds for your user to be ready...")
scenario.helper.Pause(10)
log.Println(strings.Repeat("-", 88))
return accessKey
}
// CreateRoleAndPolicies creates a policy that grants permission to list S3 buckets
for
// the current account and attaches the policy to a newly created role. It also adds
an
// inline policy to the specified user that grants the user permission to assume the
role.
func (scenario AssumeRoleScenario) CreateRoleAndPolicies(user *types.User)
*types.Role {
log.Println("Let's create a role and policy that grant permission to list S3
buckets.")
scenario.questioner.Ask("Press Enter when you're ready.")
listBucketsRole, err := scenario.roleWrapper.CreateRole(scenario.helper.GetName(),
*user.Arn)
if err != nil {panic(err)}
log.Printf("Created role %v.\n", *listBucketsRole.RoleName)
listBucketsPolicy, err := scenario.policyWrapper.CreatePolicy(
scenario.helper.GetName(), []string{"s3:ListAllMyBuckets"}, "arn:aws:s3:::*")
Scenarios 235
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {panic(err)}
log.Printf("Created policy %v.\n", *listBucketsPolicy.PolicyName)
err = scenario.roleWrapper.AttachRolePolicy(*listBucketsPolicy.Arn,
*listBucketsRole.RoleName)
if err != nil {panic(err)}
log.Printf("Attached policy %v to role %v.\n", *listBucketsPolicy.PolicyName,
*listBucketsRole.RoleName)
err = scenario.userWrapper.CreateUserPolicy(*user.UserName,
scenario.helper.GetName(),
[]string{"sts:AssumeRole"}, *listBucketsRole.Arn)
if err != nil {panic(err)}
log.Printf("Created an inline policy for user %v that lets the user assume the
role.\n",
*user.UserName)
log.Println("Let's give AWS a few seconds to propagate these new resources and
connections...")
scenario.helper.Pause(10)
log.Println(strings.Repeat("-", 88))
return listBucketsRole
}
// ListBucketsWithoutPermissions creates an Amazon S3 client from the user's access
key
// credentials and tries to list buckets for the account. Because the user does not
have
// permission to perform this action, the action fails.
func (scenario AssumeRoleScenario) ListBucketsWithoutPermissions(accessKey
*types.AccessKey) *aws.Config {
log.Println("Let's try to list buckets without permissions. This should return an
AccessDenied error.")
scenario.questioner.Ask("Press Enter when you're ready.")
noPermsConfig, err := config.LoadDefaultConfig(context.TODO(),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
*accessKey.AccessKeyId, *accessKey.SecretAccessKey, ""),
))
if err != nil {panic(err)}
// Add test options if this is a test run. This is needed only for testing
purposes.
scenario.addTestOptions(&noPermsConfig)
s3Client := s3.NewFromConfig(noPermsConfig)
_, err = s3Client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
if err != nil {
Scenarios 236
AWS SDK for Go Code Examples Code Examples Guide
// The SDK for Go does not model the AccessDenied error, so check ErrorCode
directly.
var ae smithy.APIError
if errors.As(err, &ae) {
switch ae.ErrorCode() {
case "AccessDenied":
log.Println("Got AccessDenied error, which is the expected result because\n" +
"the ListBuckets call was made without permissions.")
default:
log.Println("Expected AccessDenied, got something else.")
panic(err)
}
}
} else {
log.Println("Expected AccessDenied error when calling ListBuckets without
permissions,\n" +
"but the call succeeded. Continuing the example anyway...")
}
log.Println(strings.Repeat("-", 88))
return &noPermsConfig
}
// ListBucketsWithAssumedRole performs the following actions:
//
// 1. Creates an AWS Security Token Service (AWS STS) client from the config created
from
// the user's access key credentials.
// 2. Gets temporary credentials by assuming the role that grants permission to list
the
// buckets.
// 3. Creates an Amazon S3 client from the temporary credentials.
// 4. Lists buckets for the account. Because the temporary credentials are generated
by
// assuming the role that grants permission, the action succeeds.
func (scenario AssumeRoleScenario) ListBucketsWithAssumedRole(noPermsConfig
*aws.Config, role *types.Role) {
log.Println("Let's assume the role that grants permission to list buckets and try
again.")
scenario.questioner.Ask("Press Enter when you're ready.")
stsClient := sts.NewFromConfig(*noPermsConfig)
tempCredentials, err := stsClient.AssumeRole(context.TODO(), &sts.AssumeRoleInput{
RoleArn: role.Arn,
RoleSessionName: aws.String("AssumeRoleExampleSession"),
DurationSeconds: aws.Int32(900),
Scenarios 237
AWS SDK for Go Code Examples Code Examples Guide
})
if err != nil {
log.Printf("Couldn't assume role %v.\n", *role.RoleName)
panic(err)
}
log.Printf("Assumed role %v, got temporary credentials.\n", *role.RoleName)
assumeRoleConfig, err := config.LoadDefaultConfig(context.TODO(),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
*tempCredentials.Credentials.AccessKeyId,
*tempCredentials.Credentials.SecretAccessKey,
*tempCredentials.Credentials.SessionToken),
),
)
if err != nil {panic(err)}
// Add test options if this is a test run. This is needed only for testing
purposes.
scenario.addTestOptions(&assumeRoleConfig)
s3Client := s3.NewFromConfig(assumeRoleConfig)
result, err := s3Client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
if err != nil {
log.Println("Couldn't list buckets with assumed role credentials.")
panic(err)
}
log.Println("Successfully called ListBuckets with assumed role credentials, \n" +
"here are some of them:")
for i := 0; i < len(result.Buckets) && i < 5; i++ {
log.Printf("\t%v\n", *result.Buckets[i].Name)
}
log.Println(strings.Repeat("-", 88))
}
// Cleanup deletes all resources created for the scenario.
func (scenario AssumeRoleScenario) Cleanup(user *types.User, role *types.Role) {
if scenario.questioner.AskBool(
"Do you want to delete the resources created for this example? (y/n)", "y",
) {
policies, err := scenario.roleWrapper.ListAttachedRolePolicies(*role.RoleName)
if err != nil {panic(err)}
for _, policy := range policies {
err = scenario.roleWrapper.DetachRolePolicy(*role.RoleName, *policy.PolicyArn)
if err != nil {panic(err)}
err = scenario.policyWrapper.DeletePolicy(*policy.PolicyArn)
Scenarios 238
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {panic(err)}
log.Printf("Detached policy %v from role %v and deleted the policy.\n",
*policy.PolicyName, *role.RoleName)
}
err = scenario.roleWrapper.DeleteRole(*role.RoleName)
if err != nil {panic(err)}
log.Printf("Deleted role %v.\n", *role.RoleName)
userPols, err := scenario.userWrapper.ListUserPolicies(*user.UserName)
if err != nil {panic(err)}
for _, userPol := range userPols {
err = scenario.userWrapper.DeleteUserPolicy(*user.UserName, userPol)
if err != nil {panic(err)}
log.Printf("Deleted policy %v from user %v.\n", userPol, *user.UserName)
}
keys, err := scenario.userWrapper.ListAccessKeys(*user.UserName)
if err != nil {panic(err)}
for _, key := range keys {
err = scenario.userWrapper.DeleteAccessKey(*user.UserName, *key.AccessKeyId)
if err != nil {panic(err)}
log.Printf("Deleted access key %v from user %v.\n", *key.AccessKeyId,
*user.UserName)
}
err = scenario.userWrapper.DeleteUser(*user.UserName)
if err != nil {panic(err)}
log.Printf("Deleted user %v.\n", *user.UserName)
log.Println(strings.Repeat("-", 88))
}
}
Define a struct that wraps account actions.
// AccountWrapper encapsulates AWS Identity and Access Management (IAM) account
actions
// used in the examples.
// It contains an IAM service client that is used to perform account actions.
type AccountWrapper struct {
IamClient *iam.Client
}
Scenarios 239
AWS SDK for Go Code Examples Code Examples Guide
// GetAccountPasswordPolicy gets the account password policy for the current
account.
// If no policy has been set, a NoSuchEntityException is error is returned.
func (wrapper AccountWrapper) GetAccountPasswordPolicy() (*types.PasswordPolicy,
error) {
var pwPolicy *types.PasswordPolicy
result, err := wrapper.IamClient.GetAccountPasswordPolicy(context.TODO(),
&iam.GetAccountPasswordPolicyInput{})
if err != nil {
log.Printf("Couldn't get account password policy. Here's why: %v\n", err)
} else {
pwPolicy = result.PasswordPolicy
}
return pwPolicy, err
}
// ListSAMLProviders gets the SAML providers for the account.
func (wrapper AccountWrapper) ListSAMLProviders() ([]types.SAMLProviderListEntry,
error) {
var providers []types.SAMLProviderListEntry
result, err := wrapper.IamClient.ListSAMLProviders(context.TODO(),
&iam.ListSAMLProvidersInput{})
if err != nil {
log.Printf("Couldn't list SAML providers. Here's why: %v\n", err)
} else {
providers = result.SAMLProviderList
}
return providers, err
}
Define a struct that wraps policy actions.
// PolicyDocument defines a policy document as a Go struct that can be serialized
// to JSON.
type PolicyDocument struct {
Scenarios 240
AWS SDK for Go Code Examples Code Examples Guide
Version string
Statement []PolicyStatement
}
// PolicyStatement defines a statement in a policy document.
type PolicyStatement struct {
Effect string
Action []string
Principal map[string]string `json:",omitempty"`
Resource *string `json:",omitempty"`
}
// PolicyWrapper encapsulates AWS Identity and Access Management (IAM) policy
actions
// used in the examples.
// It contains an IAM service client that is used to perform policy actions.
type PolicyWrapper struct {
IamClient *iam.Client
}
// ListPolicies gets up to maxPolicies policies.
func (wrapper PolicyWrapper) ListPolicies(maxPolicies int32) ([]types.Policy, error)
{
var policies []types.Policy
result, err := wrapper.IamClient.ListPolicies(context.TODO(),
&iam.ListPoliciesInput{
MaxItems: aws.Int32(maxPolicies),
})
if err != nil {
log.Printf("Couldn't list policies. Here's why: %v\n", err)
} else {
policies = result.Policies
}
return policies, err
}
// CreatePolicy creates a policy that grants a list of actions to the specified
resource.
Scenarios 241
AWS SDK for Go Code Examples Code Examples Guide
// PolicyDocument shows how to work with a policy document as a data structure and
// serialize it to JSON by using Go's JSON marshaler.
func (wrapper PolicyWrapper) CreatePolicy(policyName string, actions []string,
resourceArn string) (*types.Policy, error) {
var policy *types.Policy
policyDoc := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: actions,
Resource: aws.String(resourceArn),
}},
}
policyBytes, err := json.Marshal(policyDoc)
if err != nil {
log.Printf("Couldn't create policy document for %v. Here's why: %v\n",
resourceArn, err)
return nil, err
}
result, err := wrapper.IamClient.CreatePolicy(context.TODO(),
&iam.CreatePolicyInput{
PolicyDocument: aws.String(string(policyBytes)),
PolicyName: aws.String(policyName),
})
if err != nil {
log.Printf("Couldn't create policy %v. Here's why: %v\n", policyName, err)
} else {
policy = result.Policy
}
return policy, err
}
// GetPolicy gets data about a policy.
func (wrapper PolicyWrapper) GetPolicy(policyArn string) (*types.Policy, error) {
var policy *types.Policy
result, err := wrapper.IamClient.GetPolicy(context.TODO(), &iam.GetPolicyInput{
PolicyArn: aws.String(policyArn),
})
if err != nil {
log.Printf("Couldn't get policy %v. Here's why: %v\n", policyArn, err)
} else {
policy = result.Policy
Scenarios 242
AWS SDK for Go Code Examples Code Examples Guide
}
return policy, err
}
// DeletePolicy deletes a policy.
func (wrapper PolicyWrapper) DeletePolicy(policyArn string) error {
_, err := wrapper.IamClient.DeletePolicy(context.TODO(), &iam.DeletePolicyInput{
PolicyArn: aws.String(policyArn),
})
if err != nil {
log.Printf("Couldn't delete policy %v. Here's why: %v\n", policyArn, err)
}
return err
}
Define a struct that wraps role actions.
// RoleWrapper encapsulates AWS Identity and Access Management (IAM) role actions
// used in the examples.
// It contains an IAM service client that is used to perform role actions.
type RoleWrapper struct {
IamClient *iam.Client
}
// ListRoles gets up to maxRoles roles.
func (wrapper RoleWrapper) ListRoles(maxRoles int32) ([]types.Role, error) {
var roles []types.Role
result, err := wrapper.IamClient.ListRoles(context.TODO(),
&iam.ListRolesInput{MaxItems: aws.Int32(maxRoles)},
)
if err != nil {
log.Printf("Couldn't list roles. Here's why: %v\n", err)
} else {
roles = result.Roles
}
return roles, err
Scenarios 243
AWS SDK for Go Code Examples Code Examples Guide
}
// CreateRole creates a role that trusts a specified user. The trusted user can
assume
// the role to acquire its permissions.
// PolicyDocument shows how to work with a policy document as a data structure and
// serialize it to JSON by using Go's JSON marshaler.
func (wrapper RoleWrapper) CreateRole(roleName string, trustedUserArn string)
(*types.Role, error) {
var role *types.Role
trustPolicy := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Principal: map[string]string{"AWS": trustedUserArn},
Action: []string{"sts:AssumeRole"},
}},
}
policyBytes, err := json.Marshal(trustPolicy)
if err != nil {
log.Printf("Couldn't create trust policy for %v. Here's why: %v\n",
trustedUserArn, err)
return nil, err
}
result, err := wrapper.IamClient.CreateRole(context.TODO(), &iam.CreateRoleInput{
AssumeRolePolicyDocument: aws.String(string(policyBytes)),
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't create role %v. Here's why: %v\n", roleName, err)
} else {
role = result.Role
}
return role, err
}
// GetRole gets data about a role.
func (wrapper RoleWrapper) GetRole(roleName string) (*types.Role, error) {
var role *types.Role
result, err := wrapper.IamClient.GetRole(context.TODO(),
Scenarios 244
AWS SDK for Go Code Examples Code Examples Guide
&iam.GetRoleInput{RoleName: aws.String(roleName)})
if err != nil {
log.Printf("Couldn't get role %v. Here's why: %v\n", roleName, err)
} else {
role = result.Role
}
return role, err
}
// CreateServiceLinkedRole creates a service-linked role that is owned by the
specified service.
func (wrapper RoleWrapper) CreateServiceLinkedRole(serviceName string, description
string) (*types.Role, error) {
var role *types.Role
result, err := wrapper.IamClient.CreateServiceLinkedRole(context.TODO(),
&iam.CreateServiceLinkedRoleInput{
AWSServiceName: aws.String(serviceName),
Description: aws.String(description),
})
if err != nil {
log.Printf("Couldn't create service-linked role %v. Here's why: %v\n",
serviceName, err)
} else {
role = result.Role
}
return role, err
}
// DeleteServiceLinkedRole deletes a service-linked role.
func (wrapper RoleWrapper) DeleteServiceLinkedRole(roleName string) error {
_, err := wrapper.IamClient.DeleteServiceLinkedRole(context.TODO(),
&iam.DeleteServiceLinkedRoleInput{
RoleName: aws.String(roleName)},
)
if err != nil {
log.Printf("Couldn't delete service-linked role %v. Here's why: %v\n", roleName,
err)
}
return err
}
Scenarios 245
AWS SDK for Go Code Examples Code Examples Guide
// AttachRolePolicy attaches a policy to a role.
func (wrapper RoleWrapper) AttachRolePolicy(policyArn string, roleName string) error
{
_, err := wrapper.IamClient.AttachRolePolicy(context.TODO(),
&iam.AttachRolePolicyInput{
PolicyArn: aws.String(policyArn),
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't attach policy %v to role %v. Here's why: %v\n", policyArn,
roleName, err)
}
return err
}
// ListAttachedRolePolicies lists the policies that are attached to the specified
role.
func (wrapper RoleWrapper) ListAttachedRolePolicies(roleName string)
([]types.AttachedPolicy, error) {
var policies []types.AttachedPolicy
result, err := wrapper.IamClient.ListAttachedRolePolicies(context.TODO(),
&iam.ListAttachedRolePoliciesInput{
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't list attached policies for role %v. Here's why: %v\n",
roleName, err)
} else {
policies = result.AttachedPolicies
}
return policies, err
}
// DetachRolePolicy detaches a policy from a role.
func (wrapper RoleWrapper) DetachRolePolicy(roleName string, policyArn string) error
{
Scenarios 246
AWS SDK for Go Code Examples Code Examples Guide
_, err := wrapper.IamClient.DetachRolePolicy(context.TODO(),
&iam.DetachRolePolicyInput{
PolicyArn: aws.String(policyArn),
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't detach policy from role %v. Here's why: %v\n", roleName, err)
}
return err
}
// ListRolePolicies lists the inline policies for a role.
func (wrapper RoleWrapper) ListRolePolicies(roleName string) ([]string, error) {
var policies []string
result, err := wrapper.IamClient.ListRolePolicies(context.TODO(),
&iam.ListRolePoliciesInput{
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't list policies for role %v. Here's why: %v\n", roleName, err)
} else {
policies = result.PolicyNames
}
return policies, err
}
// DeleteRole deletes a role. All attached policies must be detached before a
// role can be deleted.
func (wrapper RoleWrapper) DeleteRole(roleName string) error {
_, err := wrapper.IamClient.DeleteRole(context.TODO(), &iam.DeleteRoleInput{
RoleName: aws.String(roleName),
})
if err != nil {
log.Printf("Couldn't delete role %v. Here's why: %v\n", roleName, err)
}
return err
}
Scenarios 247
AWS SDK for Go Code Examples Code Examples Guide
Define a struct that wraps user actions.
// UserWrapper encapsulates user actions used in the examples.
// It contains an IAM service client that is used to perform user actions.
type UserWrapper struct {
IamClient *iam.Client
}
// ListUsers gets up to maxUsers number of users.
func (wrapper UserWrapper) ListUsers(maxUsers int32) ([]types.User, error) {
var users []types.User
result, err := wrapper.IamClient.ListUsers(context.TODO(), &iam.ListUsersInput{
MaxItems: aws.Int32(maxUsers),
})
if err != nil {
log.Printf("Couldn't list users. Here's why: %v\n", err)
} else {
users = result.Users
}
return users, err
}
// GetUser gets data about a user.
func (wrapper UserWrapper) GetUser(userName string) (*types.User, error) {
var user *types.User
result, err := wrapper.IamClient.GetUser(context.TODO(), &iam.GetUserInput{
UserName: aws.String(userName),
})
if err != nil {
var apiError smithy.APIError
if errors.As(err, &apiError) {
switch apiError.(type) {
case *types.NoSuchEntityException:
log.Printf("User %v does not exist.\n", userName)
err = nil
default:
Scenarios 248
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't get user %v. Here's why: %v\n", userName, err)
}
}
} else {
user = result.User
}
return user, err
}
// CreateUser creates a new user with the specified name.
func (wrapper UserWrapper) CreateUser(userName string) (*types.User, error) {
var user *types.User
result, err := wrapper.IamClient.CreateUser(context.TODO(), &iam.CreateUserInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
} else {
user = result.User
}
return user, err
}
// CreateUserPolicy adds an inline policy to a user. This example creates a policy
that
// grants a list of actions on a specified role.
// PolicyDocument shows how to work with a policy document as a data structure and
// serialize it to JSON by using Go's JSON marshaler.
func (wrapper UserWrapper) CreateUserPolicy(userName string, policyName string,
actions []string,
roleArn string) error {
policyDoc := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: actions,
Resource: aws.String(roleArn),
}},
}
policyBytes, err := json.Marshal(policyDoc)
Scenarios 249
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't create policy document for %v. Here's why: %v\n", roleArn,
err)
return err
}
_, err = wrapper.IamClient.PutUserPolicy(context.TODO(), &iam.PutUserPolicyInput{
PolicyDocument: aws.String(string(policyBytes)),
PolicyName: aws.String(policyName),
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't create policy for user %v. Here's why: %v\n", userName, err)
}
return err
}
// ListUserPolicies lists the inline policies for the specified user.
func (wrapper UserWrapper) ListUserPolicies(userName string) ([]string, error) {
var policies []string
result, err := wrapper.IamClient.ListUserPolicies(context.TODO(),
&iam.ListUserPoliciesInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't list policies for user %v. Here's why: %v\n", userName, err)
} else {
policies = result.PolicyNames
}
return policies, err
}
// DeleteUserPolicy deletes an inline policy from a user.
func (wrapper UserWrapper) DeleteUserPolicy(userName string, policyName string)
error {
_, err := wrapper.IamClient.DeleteUserPolicy(context.TODO(),
&iam.DeleteUserPolicyInput{
PolicyName: aws.String(policyName),
UserName: aws.String(userName),
})
if err != nil {
Scenarios 250
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't delete policy from user %v. Here's why: %v\n", userName, err)
}
return err
}
// DeleteUser deletes a user.
func (wrapper UserWrapper) DeleteUser(userName string) error {
_, err := wrapper.IamClient.DeleteUser(context.TODO(), &iam.DeleteUserInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't delete user %v. Here's why: %v\n", userName, err)
}
return err
}
// CreateAccessKeyPair creates an access key for a user. The returned access key
contains
// the ID and secret credentials needed to use the key.
func (wrapper UserWrapper) CreateAccessKeyPair(userName string) (*types.AccessKey,
error) {
var key *types.AccessKey
result, err := wrapper.IamClient.CreateAccessKey(context.TODO(),
&iam.CreateAccessKeyInput{
UserName: aws.String(userName)})
if err != nil {
log.Printf("Couldn't create access key pair for user %v. Here's why: %v\n",
userName, err)
} else {
key = result.AccessKey
}
return key, err
}
// DeleteAccessKey deletes an access key from a user.
func (wrapper UserWrapper) DeleteAccessKey(userName string, keyId string) error {
_, err := wrapper.IamClient.DeleteAccessKey(context.TODO(),
&iam.DeleteAccessKeyInput{
Scenarios 251
AWS SDK for Go Code Examples Code Examples Guide
AccessKeyId: aws.String(keyId),
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't delete access key %v. Here's why: %v\n", keyId, err)
}
return err
}
// ListAccessKeys lists the access keys for the specified user.
func (wrapper UserWrapper) ListAccessKeys(userName string)
([]types.AccessKeyMetadata, error) {
var keys []types.AccessKeyMetadata
result, err := wrapper.IamClient.ListAccessKeys(context.TODO(),
&iam.ListAccessKeysInput{
UserName: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't list access keys for user %v. Here's why: %v\n", userName,
err)
} else {
keys = result.AccessKeyMetadata
}
return keys, err
}
For API details, see the following topics in AWS SDK for Go API Reference.
AttachRolePolicy
CreateAccessKey
CreatePolicy
CreateRole
CreateUser
DeleteAccessKey
DeletePolicy
DeleteRole
DeleteUser
Scenarios 252
AWS SDK for Go Code Examples Code Examples Guide
DeleteUserPolicy
DetachRolePolicy
PutUserPolicy
Kinesis examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Kinesis.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Topics
Serverless examples
Serverless examples
Invoke a Lambda function from a Kinesis trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving records from a Kinesis stream. The function retrieves the Kinesis payload,
decodes from Base64, and logs the record contents.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming a Kinesis event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
Kinesis 253
AWS SDK for Go Code Examples Code Examples Guide
"context"
"log"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, kinesisEvent events.KinesisEvent) error {
if len(kinesisEvent.Records) == 0 {
log.Printf("empty Kinesis event received")
return nil
}
for _, record := range kinesisEvent.Records {
log.Printf("processed Kinesis event with EventId: %v", record.EventID)
recordDataBytes := record.Kinesis.Data
recordDataText := string(recordDataBytes)
log.Printf("record data: %v", recordDataText)
// TODO: Do interesting work based on the new data
}
log.Printf("successfully processed %v records", len(kinesisEvent.Records))
return nil
}
func main() {
lambda.Start(handler)
}
Reporting batch item failures for Lambda functions with a Kinesis trigger
The following code example shows how to implement partial batch response for Lambda functions
that receive events from a Kinesis stream. The function reports the batch item failures in the
response, signaling to Lambda to retry those messages later.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Serverless examples 254
AWS SDK for Go Code Examples Code Examples Guide
Reporting Kinesis batch item failures with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, kinesisEvent events.KinesisEvent)
(map[string]interface{}, error) {
batchItemFailures := []map[string]interface{}{}
for _, record := range kinesisEvent.Records {
curRecordSequenceNumber := ""
// Process your record
if /* Your record processing condition here */ {
curRecordSequenceNumber = record.Kinesis.SequenceNumber
}
// Add a condition to check if the record processing failed
if curRecordSequenceNumber != "" {
batchItemFailures = append(batchItemFailures, map[string]interface{}
{"itemIdentifier": curRecordSequenceNumber})
}
}
kinesisBatchResponse := map[string]interface{}{
"batchItemFailures": batchItemFailures,
}
return kinesisBatchResponse, nil
}
func main() {
lambda.Start(handler)
}
Serverless examples 255
AWS SDK for Go Code Examples Code Examples Guide
Lambda examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Lambda.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Lambda
The following code examples show how to get started using Lambda.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/lambda"
)
Lambda 256
AWS SDK for Go Code Examples Code Examples Guide
// main uses the AWS SDK for Go (v2) to create an AWS Lambda client and list up to
10
// functions in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
lambdaClient := lambda.NewFromConfig(sdkConfig)
maxItems := 10
fmt.Printf("Let's list up to %v functions for your account.\n", maxItems)
result, err := lambdaClient.ListFunctions(context.TODO(),
&lambda.ListFunctionsInput{
MaxItems: aws.Int32(int32(maxItems)),
})
if err != nil {
fmt.Printf("Couldn't list functions for your account. Here's why: %v\n", err)
return
}
if len(result.Functions) == 0 {
fmt.Println("You don't have any functions!")
} else {
for _, function := range result.Functions {
fmt.Printf("\t%v\n", *function.FunctionName)
}
}
}
For API details, see ListFunctions in AWS SDK for Go API Reference.
Topics
Actions
Scenarios
Lambda 257
AWS SDK for Go Code Examples Code Examples Guide
Serverless examples
Actions
CreateFunction
The following code example shows how to use CreateFunction.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
// CreateFunction creates a new Lambda function from code contained in the
zipPackage
// buffer. The specified handlerName must match the name of the file and function
// contained in the uploaded code. The role specified by iamRoleArn is assumed by
// Lambda and grants specific permissions.
// When the function already exists, types.StateActive is returned.
// When the function is created, a lambda.FunctionActiveV2Waiter is used to wait
until the
// function is active.
func (wrapper FunctionWrapper) CreateFunction(functionName string, handlerName
string,
iamRoleArn *string, zipPackage *bytes.Buffer) types.State {
var state types.State
_, err := wrapper.LambdaClient.CreateFunction(context.TODO(),
&lambda.CreateFunctionInput{
Code: &types.FunctionCode{ZipFile: zipPackage.Bytes()},
Actions 258
AWS SDK for Go Code Examples Code Examples Guide
FunctionName: aws.String(functionName),
Role: iamRoleArn,
Handler: aws.String(handlerName),
Publish: true,
Runtime: types.RuntimePython38,
})
if err != nil {
var resConflict *types.ResourceConflictException
if errors.As(err, &resConflict) {
log.Printf("Function %v already exists.\n", functionName)
state = types.StateActive
} else {
log.Panicf("Couldn't create function %v. Here's why: %v\n", functionName, err)
}
} else {
waiter := lambda.NewFunctionActiveV2Waiter(wrapper.LambdaClient)
funcOutput, err := waiter.WaitForOutput(context.TODO(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName)}, 1*time.Minute)
if err != nil {
log.Panicf("Couldn't wait for function %v to be active. Here's why: %v\n",
functionName, err)
} else {
state = funcOutput.Configuration.State
}
}
return state
}
For API details, see CreateFunction in AWS SDK for Go API Reference.
DeleteFunction
The following code example shows how to use DeleteFunction.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Actions 259
AWS SDK for Go Code Examples Code Examples Guide
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
// DeleteFunction deletes the Lambda function specified by functionName.
func (wrapper FunctionWrapper) DeleteFunction(functionName string) {
_, err := wrapper.LambdaClient.DeleteFunction(context.TODO(),
&lambda.DeleteFunctionInput{
FunctionName: aws.String(functionName),
})
if err != nil {
log.Panicf("Couldn't delete function %v. Here's why: %v\n", functionName, err)
}
}
For API details, see DeleteFunction in AWS SDK for Go API Reference.
GetFunction
The following code example shows how to use GetFunction.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
Actions 260
AWS SDK for Go Code Examples Code Examples Guide
}
// GetFunction gets data about the Lambda function specified by functionName.
func (wrapper FunctionWrapper) GetFunction(functionName string) types.State {
var state types.State
funcOutput, err := wrapper.LambdaClient.GetFunction(context.TODO(),
&lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
})
if err != nil {
log.Panicf("Couldn't get function %v. Here's why: %v\n", functionName, err)
} else {
state = funcOutput.Configuration.State
}
return state
}
For API details, see GetFunction in AWS SDK for Go API Reference.
Invoke
The following code example shows how to use Invoke.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
Actions 261
AWS SDK for Go Code Examples Code Examples Guide
// Invoke invokes the Lambda function specified by functionName, passing the
parameters
// as a JSON payload. When getLog is true, types.LogTypeTail is specified, which
tells
// Lambda to include the last few log lines in the returned result.
func (wrapper FunctionWrapper) Invoke(functionName string, parameters any, getLog
bool) *lambda.InvokeOutput {
logType := types.LogTypeNone
if getLog {
logType = types.LogTypeTail
}
payload, err := json.Marshal(parameters)
if err != nil {
log.Panicf("Couldn't marshal parameters to JSON. Here's why %v\n", err)
}
invokeOutput, err := wrapper.LambdaClient.Invoke(context.TODO(),
&lambda.InvokeInput{
FunctionName: aws.String(functionName),
LogType: logType,
Payload: payload,
})
if err != nil {
log.Panicf("Couldn't invoke function %v. Here's why: %v\n", functionName, err)
}
return invokeOutput
}
For API details, see Invoke in AWS SDK for Go API Reference.
ListFunctions
The following code example shows how to use ListFunctions.
Actions 262
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
// ListFunctions lists up to maxItems functions for the account. This function uses
a
// lambda.ListFunctionsPaginator to paginate the results.
func (wrapper FunctionWrapper) ListFunctions(maxItems int)
[]types.FunctionConfiguration {
var functions []types.FunctionConfiguration
paginator := lambda.NewListFunctionsPaginator(wrapper.LambdaClient,
&lambda.ListFunctionsInput{
MaxItems: aws.Int32(int32(maxItems)),
})
for paginator.HasMorePages() && len(functions) < maxItems {
pageOutput, err := paginator.NextPage(context.TODO())
if err != nil {
log.Panicf("Couldn't list functions for your account. Here's why: %v\n", err)
}
functions = append(functions, pageOutput.Functions...)
}
return functions
}
For API details, see ListFunctions in AWS SDK for Go API Reference.
Actions 263
AWS SDK for Go Code Examples Code Examples Guide
UpdateFunctionCode
The following code example shows how to use UpdateFunctionCode.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
// UpdateFunctionCode updates the code for the Lambda function specified by
functionName.
// The existing code for the Lambda function is entirely replaced by the code in the
// zipPackage buffer. After the update action is called, a
lambda.FunctionUpdatedV2Waiter
// is used to wait until the update is successful.
func (wrapper FunctionWrapper) UpdateFunctionCode(functionName string, zipPackage
*bytes.Buffer) types.State {
var state types.State
_, err := wrapper.LambdaClient.UpdateFunctionCode(context.TODO(),
&lambda.UpdateFunctionCodeInput{
FunctionName: aws.String(functionName), ZipFile: zipPackage.Bytes(),
})
if err != nil {
log.Panicf("Couldn't update code for function %v. Here's why: %v\n", functionName,
err)
} else {
waiter := lambda.NewFunctionUpdatedV2Waiter(wrapper.LambdaClient)
funcOutput, err := waiter.WaitForOutput(context.TODO(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName)}, 1*time.Minute)
if err != nil {
Actions 264
AWS SDK for Go Code Examples Code Examples Guide
log.Panicf("Couldn't wait for function %v to be active. Here's why: %v\n",
functionName, err)
} else {
state = funcOutput.Configuration.State
}
}
return state
}
For API details, see UpdateFunctionCode in AWS SDK for Go API Reference.
UpdateFunctionConfiguration
The following code example shows how to use UpdateFunctionConfiguration.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
// UpdateFunctionConfiguration updates a map of environment variables configured for
// the Lambda function specified by functionName.
func (wrapper FunctionWrapper) UpdateFunctionConfiguration(functionName string,
envVars map[string]string) {
_, err := wrapper.LambdaClient.UpdateFunctionConfiguration(context.TODO(),
&lambda.UpdateFunctionConfigurationInput{
FunctionName: aws.String(functionName),
Environment: &types.Environment{Variables: envVars},
Actions 265
AWS SDK for Go Code Examples Code Examples Guide
})
if err != nil {
log.Panicf("Couldn't update configuration for %v. Here's why: %v", functionName,
err)
}
}
For API details, see UpdateFunctionConfiguration in AWS SDK for Go API Reference.
Scenarios
Automatically confirm known users with a Lambda function
The following code example shows how to automatically confirm known Amazon Cognito users
with a Lambda function.
Configure a user pool to call a Lambda function for the PreSignUp trigger.
Sign up a user with Amazon Cognito.
The Lambda function scans a DynamoDB table and automatically confirms known users.
Sign in as the new user, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
// AutoConfirm separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type AutoConfirm struct {
helper IScenarioHelper
Scenarios 266
AWS SDK for Go Code Examples Code Examples Guide
questioner demotools.IQuestioner
resources Resources
cognitoActor *actions.CognitoActions
}
// NewAutoConfirm constructs a new auto confirm runner.
func NewAutoConfirm(sdkConfig aws.Config, questioner demotools.IQuestioner, helper
IScenarioHelper) AutoConfirm {
scenario := AutoConfirm{
helper: helper,
questioner: questioner,
resources: Resources{},
cognitoActor: &actions.CognitoActions{CognitoClient:
cognitoidentityprovider.NewFromConfig(sdkConfig)},
}
scenario.resources.init(scenario.cognitoActor, questioner)
return scenario
}
// AddPreSignUpTrigger adds a Lambda handler as an invocation target for the
PreSignUp trigger.
func (runner *AutoConfirm) AddPreSignUpTrigger(userPoolId string, functionArn
string) {
log.Printf("Let's add a Lambda function to handle the PreSignUp trigger from
Cognito.\n" +
"This trigger happens when a user signs up, and lets your function take action
before the main Cognito\n" +
"sign up processing occurs.\n")
err := runner.cognitoActor.UpdateTriggers(
userPoolId,
actions.TriggerInfo{Trigger: actions.PreSignUp, HandlerArn:
aws.String(functionArn)})
if err != nil {
panic(err)
}
log.Printf("Lambda function %v added to user pool %v to handle the PreSignUp
trigger.\n",
functionArn, userPoolId)
}
// SignUpUser signs up a user from the known user table with a password you specify.
func (runner *AutoConfirm) SignUpUser(clientId string, usersTable string) (string,
string) {
Scenarios 267
AWS SDK for Go Code Examples Code Examples Guide
log.Println("Let's sign up a user to your Cognito user pool. When the user's email
matches an email in the\n" +
"DynamoDB known users table, it is automatically verified and the user is
confirmed.")
knownUsers, err := runner.helper.GetKnownUsers(usersTable)
if err != nil {
panic(err)
}
userChoice := runner.questioner.AskChoice("Which user do you want to use?\n",
knownUsers.UserNameList())
user := knownUsers.Users[userChoice]
var signedUp bool
var userConfirmed bool
password := runner.questioner.AskPassword("Enter a password that has at least eight
characters, uppercase, lowercase, numbers and symbols.\n"+
"(the password will not display as you type):", 8)
for !signedUp {
log.Printf("Signing up user '%v' with email '%v' to Cognito.\n", user.UserName,
user.UserEmail)
userConfirmed, err = runner.cognitoActor.SignUp(clientId, user.UserName, password,
user.UserEmail)
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
password = runner.questioner.AskPassword("Enter another password:", 8)
} else {
panic(err)
}
} else {
signedUp = true
}
}
log.Printf("User %v signed up, confirmed = %v.\n", user.UserName, userConfirmed)
log.Println(strings.Repeat("-", 88))
return user.UserName, password
}
// SignInUser signs in a user.
func (runner *AutoConfirm) SignInUser(clientId string, userName string, password
string) string {
Scenarios 268
AWS SDK for Go Code Examples Code Examples Guide
runner.questioner.Ask("Press Enter when you're ready to continue.")
log.Printf("Let's sign in as %v...\n", userName)
authResult, err := runner.cognitoActor.SignIn(clientId, userName, password)
if err != nil {
panic(err)
}
log.Printf("Successfully signed in. Your access token starts with: %v...\n",
(*authResult.AccessToken)[:10])
log.Println(strings.Repeat("-", 88))
return *authResult.AccessToken
}
// Run runs the scenario.
func (runner *AutoConfirm) Run(stackName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
runner.resources.Cleanup()
}
}()
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome\n")
log.Println(strings.Repeat("-", 88))
stackOutputs, err := runner.helper.GetStackOutputs(stackName)
if err != nil {
panic(err)
}
runner.resources.userPoolId = stackOutputs["UserPoolId"]
runner.helper.PopulateUserTable(stackOutputs["TableName"])
runner.AddPreSignUpTrigger(stackOutputs["UserPoolId"],
stackOutputs["AutoConfirmFunctionArn"])
runner.resources.triggers = append(runner.resources.triggers, actions.PreSignUp)
userName, password := runner.SignUpUser(stackOutputs["UserPoolClientId"],
stackOutputs["TableName"])
runner.helper.ListRecentLogEvents(stackOutputs["AutoConfirmFunction"])
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
runner.SignInUser(stackOutputs["UserPoolClientId"], userName, password))
runner.resources.Cleanup()
Scenarios 269
AWS SDK for Go Code Examples Code Examples Guide
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Handle the PreSignUp trigger with a Lambda function.
const TABLE_NAME = "TABLE_NAME"
// UserInfo defines structured user data that can be marshalled to a DynamoDB
format.
type UserInfo struct {
UserName string `dynamodbav:"UserName"`
UserEmail string `dynamodbav:"UserEmail"`
}
// GetKey marshals the user email value to a DynamoDB key format.
func (user UserInfo) GetKey() map[string]dynamodbtypes.AttributeValue {
userEmail, err := attributevalue.Marshal(user.UserEmail)
if err != nil {
panic(err)
}
return map[string]dynamodbtypes.AttributeValue{"UserEmail": userEmail}
}
type handler struct {
dynamoClient *dynamodb.Client
}
// HandleRequest handles the PreSignUp event by looking up a user in an Amazon
DynamoDB table and
// specifying whether they should be confirmed and verified.
func (h *handler) HandleRequest(ctx context.Context, event
events.CognitoEventUserPoolsPreSignup) (events.CognitoEventUserPoolsPreSignup,
error) {
log.Printf("Received presignup from %v for user '%v'", event.TriggerSource,
event.UserName)
if event.TriggerSource != "PreSignUp_SignUp" {
// Other trigger sources, such as PreSignUp_AdminInitiateAuth, ignore the response
from this handler.
Scenarios 270
AWS SDK for Go Code Examples Code Examples Guide
return event, nil
}
tableName := os.Getenv(TABLE_NAME)
user := UserInfo{
UserEmail: event.Request.UserAttributes["email"],
}
log.Printf("Looking up email %v in table %v.\n", user.UserEmail, tableName)
output, err := h.dynamoClient.GetItem(ctx, &dynamodb.GetItemInput{
Key: user.GetKey(),
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Error looking up email %v.\n", user.UserEmail)
return event, err
}
if output.Item == nil {
log.Printf("Email %v not found. Email verification is required.\n",
user.UserEmail)
return event, err
}
err = attributevalue.UnmarshalMap(output.Item, &user)
if err != nil {
log.Printf("Couldn't unmarshal DynamoDB item. Here's why: %v\n", err)
return event, err
}
if user.UserName != event.UserName {
log.Printf("UserEmail %v found, but stored UserName '%v' does not match supplied
UserName '%v'. Verification is required.\n",
user.UserEmail, user.UserName, event.UserName)
} else {
log.Printf("UserEmail %v found with matching UserName %v. User is confirmed.\n",
user.UserEmail, user.UserName)
event.Response.AutoConfirmUser = true
event.Response.AutoVerifyEmail = true
}
return event, err
}
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
Scenarios 271
AWS SDK for Go Code Examples Code Examples Guide
log.Panicln(err)
}
h := handler{
dynamoClient: dynamodb.NewFromConfig(sdkConfig),
}
lambda.Start(h.HandleRequest)
}
Create a struct that performs common tasks.
// IScenarioHelper defines common functions used by the workflows in this example.
type IScenarioHelper interface {
Pause(secs int)
GetStackOutputs(stackName string) (actions.StackOutputs, error)
PopulateUserTable(tableName string)
GetKnownUsers(tableName string) (actions.UserList, error)
AddKnownUser(tableName string, user actions.User)
ListRecentLogEvents(functionName string)
}
// ScenarioHelper contains AWS wrapper structs used by the workflows in this
example.
type ScenarioHelper struct {
questioner demotools.IQuestioner
dynamoActor *actions.DynamoActions
cfnActor *actions.CloudFormationActions
cwlActor *actions.CloudWatchLogsActions
isTestRun bool
}
// NewScenarioHelper constructs a new scenario helper.
func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner)
ScenarioHelper {
scenario := ScenarioHelper{
questioner: questioner,
dynamoActor: &actions.DynamoActions{DynamoClient:
dynamodb.NewFromConfig(sdkConfig)},
cfnActor: &actions.CloudFormationActions{CfnClient:
cloudformation.NewFromConfig(sdkConfig)},
Scenarios 272
AWS SDK for Go Code Examples Code Examples Guide
cwlActor: &actions.CloudWatchLogsActions{CwlClient:
cloudwatchlogs.NewFromConfig(sdkConfig)},
}
return scenario
}
// Pause waits for the specified number of seconds.
func (helper ScenarioHelper) Pause(secs int) {
if !helper.isTestRun {
time.Sleep(time.Duration(secs) * time.Second)
}
}
// GetStackOutputs gets the outputs from the specified CloudFormation stack in a
structured format.
func (helper ScenarioHelper) GetStackOutputs(stackName string)
(actions.StackOutputs, error) {
return helper.cfnActor.GetOutputs(stackName), nil
}
// PopulateUserTable fills the known user table with example data.
func (helper ScenarioHelper) PopulateUserTable(tableName string) {
log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this
example.\n", tableName)
err := helper.dynamoActor.PopulateTable(tableName)
if err != nil {
panic(err)
}
}
// GetKnownUsers gets the users from the known users table in a structured format.
func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList,
error) {
knownUsers, err := helper.dynamoActor.Scan(tableName)
if err != nil {
log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName,
err)
}
return knownUsers, err
}
// AddKnownUser adds a user to the known users table.
func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) {
Scenarios 273
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...
\n",
user.UserName, user.UserEmail)
err := helper.dynamoActor.AddUser(tableName, user)
if err != nil {
panic(err)
}
}
// ListRecentLogEvents gets the most recent log stream and events for the specified
Lambda function and displays them.
func (helper ScenarioHelper) ListRecentLogEvents(functionName string) {
log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...")
helper.Pause(10)
log.Println("Okay, let's check the logs to find what's happened recently with your
Lambda function.")
logStream, err := helper.cwlActor.GetLatestLogStream(functionName)
if err != nil {
panic(err)
}
log.Printf("Getting some recent events from log stream %v\n",
*logStream.LogStreamName)
events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName,
10)
if err != nil {
panic(err)
}
for _, event := range events {
log.Printf("\t%v", *event.Message)
}
log.Println(strings.Repeat("-", 88))
}
Create a struct that wraps Amazon Cognito actions.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
Scenarios 274
AWS SDK for Go Code Examples Code Examples Guide
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
lambdaConfig.PostAuthentication = trigger.HandlerArn
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
Scenarios 275
AWS SDK for Go Code Examples Code Examples Guide
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
Scenarios 276
AWS SDK for Go Code Examples Code Examples Guide
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
Scenarios 277
AWS SDK for Go Code Examples Code Examples Guide
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
// DeleteUser removes a user from the user pool.
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
Scenarios 278
AWS SDK for Go Code Examples Code Examples Guide
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
}
}
return err
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
return err
}
Create a struct that wraps DynamoDB actions.
Scenarios 279
AWS SDK for Go Code Examples Code Examples Guide
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type DynamoActions struct {
DynamoClient *dynamodb.Client
}
// User defines structured user data.
type User struct {
UserName string
UserEmail string
LastLogin *LoginInfo `dynamodbav:",omitempty"`
}
// LoginInfo defines structured custom login data.
type LoginInfo struct {
UserPoolId string
ClientId string
Time string
}
// UserList defines a list of users.
type UserList struct {
Users []User
}
// UserNameList returns the usernames contained in a UserList as a list of strings.
func (users *UserList) UserNameList() []string {
names := make([]string, len(users.Users))
for i := 0; i < len(users.Users); i++ {
names[i] = users.Users[i].UserName
}
return names
}
// PopulateTable adds a set of test users to the table.
func (actor DynamoActions) PopulateTable(tableName string) error {
var err error
var item map[string]types.AttributeValue
var writeReqs []types.WriteRequest
for i := 1; i < 4; i++ {
Scenarios 280
AWS SDK for Go Code Examples Code Examples Guide
item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v",
i), UserEmail: fmt.Sprintf("test_email_%[email protected]", i)})
if err != nil {
log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err)
return err
}
writeReqs = append(writeReqs, types.WriteRequest{PutRequest:
&types.PutRequest{Item: item}})
}
_, err = actor.DynamoClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{tableName: writeReqs},
})
if err != nil {
log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName,
err)
}
return err
}
// Scan scans the table for all items.
func (actor DynamoActions) Scan(tableName string) (UserList, error) {
var userList UserList
output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err)
} else {
err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users)
if err != nil {
log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err)
}
}
return userList, err
}
// AddUser adds a user item to a table.
func (actor DynamoActions) AddUser(tableName string, user User) error {
userItem, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshall user to item. Here's why: %v\n", err)
}
_, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
Scenarios 281
AWS SDK for Go Code Examples Code Examples Guide
Item: userItem,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err)
}
return err
}
Create a struct that wraps CloudWatch Logs actions.
type CloudWatchLogsActions struct {
CwlClient *cloudwatchlogs.Client
}
// GetLatestLogStream gets the most recent log stream for a Lambda function.
func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string)
(types.LogStream, error) {
var logStream types.LogStream
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.DescribeLogStreams(context.TODO(),
&cloudwatchlogs.DescribeLogStreamsInput{
Descending: aws.Bool(true),
Limit: aws.Int32(1),
LogGroupName: aws.String(logGroupName),
OrderBy: types.OrderByLastEventTime,
})
if err != nil {
log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n",
logGroupName, err)
} else {
logStream = output.LogStreams[0]
}
return logStream, err
}
// GetLogEvents gets the most recent eventCount events from the specified log
stream.
func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName
string, eventCount int32) (
Scenarios 282
AWS SDK for Go Code Examples Code Examples Guide
[]types.OutputLogEvent, error) {
var events []types.OutputLogEvent
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.GetLogEvents(context.TODO(),
&cloudwatchlogs.GetLogEventsInput{
LogStreamName: aws.String(logStreamName),
Limit: aws.Int32(eventCount),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n",
logStreamName, err)
} else {
events = output.Events
}
return events, err
}
Create a struct that wraps AWS CloudFormation actions.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
if err != nil || len(output.Stacks) == 0 {
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
Scenarios 283
AWS SDK for Go Code Examples Code Examples Guide
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
Clean up resources.
// Resources keeps track of AWS resources created during an example and handles
// cleanup when the example finishes.
type Resources struct {
userPoolId string
userAccessTokens []string
triggers []actions.Trigger
cognitoActor *actions.CognitoActions
questioner demotools.IQuestioner
}
func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner
demotools.IQuestioner) {
resources.userAccessTokens = []string{}
resources.triggers = []actions.Trigger{}
resources.cognitoActor = cognitoActor
resources.questioner = questioner
}
// Cleanup deletes all AWS resources created during an example.
func (resources *Resources) Cleanup() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources \n"
+
"that were created for this scenario.")
}
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
Scenarios 284
AWS SDK for Go Code Examples Code Examples Guide
if wantDelete {
for _, accessToken := range resources.userAccessTokens {
err := resources.cognitoActor.DeleteUser(accessToken)
if err != nil {
log.Println("Couldn't delete user during cleanup.")
panic(err)
}
log.Println("Deleted user.")
}
triggerList := make([]actions.TriggerInfo, len(resources.triggers))
for i := 0; i < len(resources.triggers); i++ {
triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn:
nil}
}
err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...)
if err != nil {
log.Println("Couldn't update Cognito triggers during cleanup.")
panic(err)
}
log.Println("Removed Cognito triggers from user pool.")
} else {
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
DeleteUser
InitiateAuth
SignUp
UpdateUserPool
Automatically migrate known users with a Lambda function
The following code example shows how to automatically migrate known Amazon Cognito users
with a Lambda function.
Configure a user pool to call a Lambda function for the MigrateUser trigger.
Sign in to Amazon Cognito with a username and email that is not in the user pool.
Scenarios 285
AWS SDK for Go Code Examples Code Examples Guide
The Lambda function scans a DynamoDB table and automatically migrates known users to the
user pool.
Perform the forgot password flow to reset the password for the migrated user.
Sign in as the new user, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
import (
"errors"
"fmt"
"log"
"strings"
"user_pools_and_lambda_triggers/actions"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
"github.com/awsdocs/aws-doc-sdk-examples/gov2/demotools"
)
// MigrateUser separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type MigrateUser struct {
helper IScenarioHelper
questioner demotools.IQuestioner
resources Resources
cognitoActor *actions.CognitoActions
}
// NewMigrateUser constructs a new migrate user runner.
Scenarios 286
AWS SDK for Go Code Examples Code Examples Guide
func NewMigrateUser(sdkConfig aws.Config, questioner demotools.IQuestioner, helper
IScenarioHelper) MigrateUser {
scenario := MigrateUser{
helper: helper,
questioner: questioner,
resources: Resources{},
cognitoActor: &actions.CognitoActions{CognitoClient:
cognitoidentityprovider.NewFromConfig(sdkConfig)},
}
scenario.resources.init(scenario.cognitoActor, questioner)
return scenario
}
// AddMigrateUserTrigger adds a Lambda handler as an invocation target for the
MigrateUser trigger.
func (runner *MigrateUser) AddMigrateUserTrigger(userPoolId string, functionArn
string) {
log.Printf("Let's add a Lambda function to handle the MigrateUser trigger from
Cognito.\n" +
"This trigger happens when an unknown user signs in, and lets your function take
action before Cognito\n" +
"rejects the user.\n\n")
err := runner.cognitoActor.UpdateTriggers(
userPoolId,
actions.TriggerInfo{Trigger: actions.UserMigration, HandlerArn:
aws.String(functionArn)})
if err != nil {
panic(err)
}
log.Printf("Lambda function %v added to user pool %v to handle the MigrateUser
trigger.\n",
functionArn, userPoolId)
log.Println(strings.Repeat("-", 88))
}
// SignInUser adds a new user to the known users table and signs that user in to
Amazon Cognito.
func (runner *MigrateUser) SignInUser(usersTable string, clientId string) (bool,
actions.User) {
log.Println("Let's sign in a user to your Cognito user pool. When the username and
email matches an entry in the\n" +
"DynamoDB known users table, the email is automatically verified and the user is
migrated to the Cognito user pool.")
Scenarios 287
AWS SDK for Go Code Examples Code Examples Guide
user := actions.User{}
user.UserName = runner.questioner.Ask("\nEnter a username:")
user.UserEmail = runner.questioner.Ask("\nEnter an email that you own. This email
will be used to confirm user migration\n" +
"during this example:")
runner.helper.AddKnownUser(usersTable, user)
var err error
var resetRequired *types.PasswordResetRequiredException
var authResult *types.AuthenticationResultType
signedIn := false
for !signedIn && resetRequired == nil {
log.Printf("Signing in to Cognito as user '%v'. The expected result is a
PasswordResetRequiredException.\n\n", user.UserName)
authResult, err = runner.cognitoActor.SignIn(clientId, user.UserName, "_")
if err != nil {
if errors.As(err, &resetRequired) {
log.Printf("\nUser '%v' is not in the Cognito user pool but was found in the
DynamoDB known users table.\n"+
"User migration is started and a password reset is required.", user.UserName)
} else {
panic(err)
}
} else {
log.Printf("User '%v' successfully signed in. This is unexpected and probably
means you have not\n"+
"cleaned up a previous run of this scenario, so the user exist in the Cognito
user pool.\n"+
"You can continue this example and select to clean up resources, or manually
remove\n"+
"the user from your user pool and try again.", user.UserName)
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
*authResult.AccessToken)
signedIn = true
}
}
log.Println(strings.Repeat("-", 88))
return resetRequired != nil, user
}
// ResetPassword starts a password recovery flow.
Scenarios 288
AWS SDK for Go Code Examples Code Examples Guide
func (runner *MigrateUser) ResetPassword(clientId string, user actions.User) {
wantCode := runner.questioner.AskBool(fmt.Sprintf("In order to migrate the user to
Cognito, you must be able to receive a confirmation\n"+
"code by email at %v. Do you want to send a code (y/n)?", user.UserEmail), "y")
if !wantCode {
log.Println("To complete this example and successfully migrate a user to Cognito,
you must enter an email\n" +
"you own that can receive a confirmation code.")
return
}
codeDelivery, err := runner.cognitoActor.ForgotPassword(clientId, user.UserName)
if err != nil {
panic(err)
}
log.Printf("\nA confirmation code has been sent to %v.", *codeDelivery.Destination)
code := runner.questioner.Ask("Check your email and enter it here:")
confirmed := false
password := runner.questioner.AskPassword("\nEnter a password that has at least
eight characters, uppercase, lowercase, numbers and symbols.\n"+
"(the password will not display as you type):", 8)
for !confirmed {
log.Printf("\nConfirming password reset for user '%v'.\n", user.UserName)
err = runner.cognitoActor.ConfirmForgotPassword(clientId, code, user.UserName,
password)
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
password = runner.questioner.AskPassword("\nEnter another password:", 8)
} else {
panic(err)
}
} else {
confirmed = true
}
}
log.Printf("User '%v' successfully confirmed and migrated.\n", user.UserName)
log.Println("Signing in with your username and password...")
authResult, err := runner.cognitoActor.SignIn(clientId, user.UserName, password)
if err != nil {
panic(err)
}
log.Printf("Successfully signed in. Your access token starts with: %v...\n",
(*authResult.AccessToken)[:10])
Scenarios 289
AWS SDK for Go Code Examples Code Examples Guide
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
*authResult.AccessToken)
log.Println(strings.Repeat("-", 88))
}
// Run runs the scenario.
func (runner *MigrateUser) Run(stackName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
runner.resources.Cleanup()
}
}()
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome\n")
log.Println(strings.Repeat("-", 88))
stackOutputs, err := runner.helper.GetStackOutputs(stackName)
if err != nil {
panic(err)
}
runner.resources.userPoolId = stackOutputs["UserPoolId"]
runner.AddMigrateUserTrigger(stackOutputs["UserPoolId"],
stackOutputs["MigrateUserFunctionArn"])
runner.resources.triggers = append(runner.resources.triggers,
actions.UserMigration)
resetNeeded, user := runner.SignInUser(stackOutputs["TableName"],
stackOutputs["UserPoolClientId"])
if resetNeeded {
runner.helper.ListRecentLogEvents(stackOutputs["MigrateUserFunction"])
runner.ResetPassword(stackOutputs["UserPoolClientId"], user)
}
runner.resources.Cleanup()
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Scenarios 290
AWS SDK for Go Code Examples Code Examples Guide
Handle the MigrateUser trigger with a Lambda function.
const TABLE_NAME = "TABLE_NAME"
// UserInfo defines structured user data that can be marshalled to a DynamoDB
format.
type UserInfo struct {
UserName string `dynamodbav:"UserName"`
UserEmail string `dynamodbav:"UserEmail"`
}
type handler struct {
dynamoClient *dynamodb.Client
}
// HandleRequest handles the MigrateUser event by looking up a user in an Amazon
DynamoDB table and
// specifying whether they should be migrated to the user pool.
func (h *handler) HandleRequest(ctx context.Context, event
events.CognitoEventUserPoolsMigrateUser) (events.CognitoEventUserPoolsMigrateUser,
error) {
log.Printf("Received migrate trigger from %v for user '%v'", event.TriggerSource,
event.UserName)
if event.TriggerSource != "UserMigration_Authentication" {
return event, nil
}
tableName := os.Getenv(TABLE_NAME)
user := UserInfo{
UserName: event.UserName,
}
log.Printf("Looking up user '%v' in table %v.\n", user.UserName, tableName)
filterEx := expression.Name("UserName").Equal(expression.Value(user.UserName))
expr, err := expression.NewBuilder().WithFilter(filterEx).Build()
if err != nil {
log.Printf("Error building expression to query for user '%v'.\n", user.UserName)
return event, err
}
output, err := h.dynamoClient.Scan(ctx, &dynamodb.ScanInput{
TableName: aws.String(tableName),
FilterExpression: expr.Filter(),
Scenarios 291
AWS SDK for Go Code Examples Code Examples Guide
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
})
if err != nil {
log.Printf("Error looking up user '%v'.\n", user.UserName)
return event, err
}
if output.Items == nil || len(output.Items) == 0 {
log.Printf("User '%v' not found, not migrating user.\n", user.UserName)
return event, err
}
var users []UserInfo
err = attributevalue.UnmarshalListOfMaps(output.Items, &users)
if err != nil {
log.Printf("Couldn't unmarshal DynamoDB items. Here's why: %v\n", err)
return event, err
}
user = users[0]
log.Printf("UserName '%v' found with email %v. User is migrated and must reset
password.\n", user.UserName, user.UserEmail)
event.CognitoEventUserPoolsMigrateUserResponse.UserAttributes = map[string]string{
"email": user.UserEmail,
"email_verified": "true", // email_verified is required for the forgot password
flow.
}
event.CognitoEventUserPoolsMigrateUserResponse.FinalUserStatus = "RESET_REQUIRED"
event.CognitoEventUserPoolsMigrateUserResponse.MessageAction = "SUPPRESS"
return event, err
}
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Panicln(err)
}
h := handler{
dynamoClient: dynamodb.NewFromConfig(sdkConfig),
}
lambda.Start(h.HandleRequest)
}
Scenarios 292
AWS SDK for Go Code Examples Code Examples Guide
Create a struct that performs common tasks.
// IScenarioHelper defines common functions used by the workflows in this example.
type IScenarioHelper interface {
Pause(secs int)
GetStackOutputs(stackName string) (actions.StackOutputs, error)
PopulateUserTable(tableName string)
GetKnownUsers(tableName string) (actions.UserList, error)
AddKnownUser(tableName string, user actions.User)
ListRecentLogEvents(functionName string)
}
// ScenarioHelper contains AWS wrapper structs used by the workflows in this
example.
type ScenarioHelper struct {
questioner demotools.IQuestioner
dynamoActor *actions.DynamoActions
cfnActor *actions.CloudFormationActions
cwlActor *actions.CloudWatchLogsActions
isTestRun bool
}
// NewScenarioHelper constructs a new scenario helper.
func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner)
ScenarioHelper {
scenario := ScenarioHelper{
questioner: questioner,
dynamoActor: &actions.DynamoActions{DynamoClient:
dynamodb.NewFromConfig(sdkConfig)},
cfnActor: &actions.CloudFormationActions{CfnClient:
cloudformation.NewFromConfig(sdkConfig)},
cwlActor: &actions.CloudWatchLogsActions{CwlClient:
cloudwatchlogs.NewFromConfig(sdkConfig)},
}
return scenario
}
// Pause waits for the specified number of seconds.
func (helper ScenarioHelper) Pause(secs int) {
if !helper.isTestRun {
Scenarios 293
AWS SDK for Go Code Examples Code Examples Guide
time.Sleep(time.Duration(secs) * time.Second)
}
}
// GetStackOutputs gets the outputs from the specified CloudFormation stack in a
structured format.
func (helper ScenarioHelper) GetStackOutputs(stackName string)
(actions.StackOutputs, error) {
return helper.cfnActor.GetOutputs(stackName), nil
}
// PopulateUserTable fills the known user table with example data.
func (helper ScenarioHelper) PopulateUserTable(tableName string) {
log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this
example.\n", tableName)
err := helper.dynamoActor.PopulateTable(tableName)
if err != nil {
panic(err)
}
}
// GetKnownUsers gets the users from the known users table in a structured format.
func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList,
error) {
knownUsers, err := helper.dynamoActor.Scan(tableName)
if err != nil {
log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName,
err)
}
return knownUsers, err
}
// AddKnownUser adds a user to the known users table.
func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) {
log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...
\n",
user.UserName, user.UserEmail)
err := helper.dynamoActor.AddUser(tableName, user)
if err != nil {
panic(err)
}
}
Scenarios 294
AWS SDK for Go Code Examples Code Examples Guide
// ListRecentLogEvents gets the most recent log stream and events for the specified
Lambda function and displays them.
func (helper ScenarioHelper) ListRecentLogEvents(functionName string) {
log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...")
helper.Pause(10)
log.Println("Okay, let's check the logs to find what's happened recently with your
Lambda function.")
logStream, err := helper.cwlActor.GetLatestLogStream(functionName)
if err != nil {
panic(err)
}
log.Printf("Getting some recent events from log stream %v\n",
*logStream.LogStreamName)
events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName,
10)
if err != nil {
panic(err)
}
for _, event := range events {
log.Printf("\t%v", *event.Message)
}
log.Println(strings.Repeat("-", 88))
}
Create a struct that wraps Amazon Cognito actions.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
Scenarios 295
AWS SDK for Go Code Examples Code Examples Guide
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
lambdaConfig.PostAuthentication = trigger.HandlerArn
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
Scenarios 296
AWS SDK for Go Code Examples Code Examples Guide
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
Scenarios 297
AWS SDK for Go Code Examples Code Examples Guide
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
Scenarios 298
AWS SDK for Go Code Examples Code Examples Guide
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
// DeleteUser removes a user from the user pool.
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
Scenarios 299
AWS SDK for Go Code Examples Code Examples Guide
}
}
return err
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
return err
}
Create a struct that wraps DynamoDB actions.
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type DynamoActions struct {
DynamoClient *dynamodb.Client
}
// User defines structured user data.
Scenarios 300
AWS SDK for Go Code Examples Code Examples Guide
type User struct {
UserName string
UserEmail string
LastLogin *LoginInfo `dynamodbav:",omitempty"`
}
// LoginInfo defines structured custom login data.
type LoginInfo struct {
UserPoolId string
ClientId string
Time string
}
// UserList defines a list of users.
type UserList struct {
Users []User
}
// UserNameList returns the usernames contained in a UserList as a list of strings.
func (users *UserList) UserNameList() []string {
names := make([]string, len(users.Users))
for i := 0; i < len(users.Users); i++ {
names[i] = users.Users[i].UserName
}
return names
}
// PopulateTable adds a set of test users to the table.
func (actor DynamoActions) PopulateTable(tableName string) error {
var err error
var item map[string]types.AttributeValue
var writeReqs []types.WriteRequest
for i := 1; i < 4; i++ {
item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v",
i), UserEmail: fmt.Sprintf("test_email_%[email protected]", i)})
if err != nil {
log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err)
return err
}
writeReqs = append(writeReqs, types.WriteRequest{PutRequest:
&types.PutRequest{Item: item}})
}
_, err = actor.DynamoClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
Scenarios 301
AWS SDK for Go Code Examples Code Examples Guide
RequestItems: map[string][]types.WriteRequest{tableName: writeReqs},
})
if err != nil {
log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName,
err)
}
return err
}
// Scan scans the table for all items.
func (actor DynamoActions) Scan(tableName string) (UserList, error) {
var userList UserList
output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err)
} else {
err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users)
if err != nil {
log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err)
}
}
return userList, err
}
// AddUser adds a user item to a table.
func (actor DynamoActions) AddUser(tableName string, user User) error {
userItem, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshall user to item. Here's why: %v\n", err)
}
_, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
Item: userItem,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err)
}
return err
}
Scenarios 302
AWS SDK for Go Code Examples Code Examples Guide
Create a struct that wraps CloudWatch Logs actions.
type CloudWatchLogsActions struct {
CwlClient *cloudwatchlogs.Client
}
// GetLatestLogStream gets the most recent log stream for a Lambda function.
func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string)
(types.LogStream, error) {
var logStream types.LogStream
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.DescribeLogStreams(context.TODO(),
&cloudwatchlogs.DescribeLogStreamsInput{
Descending: aws.Bool(true),
Limit: aws.Int32(1),
LogGroupName: aws.String(logGroupName),
OrderBy: types.OrderByLastEventTime,
})
if err != nil {
log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n",
logGroupName, err)
} else {
logStream = output.LogStreams[0]
}
return logStream, err
}
// GetLogEvents gets the most recent eventCount events from the specified log
stream.
func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName
string, eventCount int32) (
[]types.OutputLogEvent, error) {
var events []types.OutputLogEvent
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.GetLogEvents(context.TODO(),
&cloudwatchlogs.GetLogEventsInput{
LogStreamName: aws.String(logStreamName),
Limit: aws.Int32(eventCount),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n",
logStreamName, err)
Scenarios 303
AWS SDK for Go Code Examples Code Examples Guide
} else {
events = output.Events
}
return events, err
}
Create a struct that wraps AWS CloudFormation actions.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
if err != nil || len(output.Stacks) == 0 {
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
Clean up resources.
// Resources keeps track of AWS resources created during an example and handles
// cleanup when the example finishes.
Scenarios 304
AWS SDK for Go Code Examples Code Examples Guide
type Resources struct {
userPoolId string
userAccessTokens []string
triggers []actions.Trigger
cognitoActor *actions.CognitoActions
questioner demotools.IQuestioner
}
func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner
demotools.IQuestioner) {
resources.userAccessTokens = []string{}
resources.triggers = []actions.Trigger{}
resources.cognitoActor = cognitoActor
resources.questioner = questioner
}
// Cleanup deletes all AWS resources created during an example.
func (resources *Resources) Cleanup() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources \n"
+
"that were created for this scenario.")
}
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
if wantDelete {
for _, accessToken := range resources.userAccessTokens {
err := resources.cognitoActor.DeleteUser(accessToken)
if err != nil {
log.Println("Couldn't delete user during cleanup.")
panic(err)
}
log.Println("Deleted user.")
}
triggerList := make([]actions.TriggerInfo, len(resources.triggers))
for i := 0; i < len(resources.triggers); i++ {
triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn:
nil}
Scenarios 305
AWS SDK for Go Code Examples Code Examples Guide
}
err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...)
if err != nil {
log.Println("Couldn't update Cognito triggers during cleanup.")
panic(err)
}
log.Println("Removed Cognito triggers from user pool.")
} else {
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
ConfirmForgotPassword
DeleteUser
ForgotPassword
InitiateAuth
SignUp
UpdateUserPool
Get started with functions
The following code example shows how to:
Create an IAM role and Lambda function, then upload handler code.
Invoke the function with a single parameter and get results.
Update the function code and configure with an environment variable.
Invoke the function with new parameters and get results. Display the returned execution log.
List the functions for your account, then clean up resources.
For more information, see Create a Lambda function with the console.
Scenarios 306
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Create an interactive scenario that shows you how to get started with Lambda functions.
// GetStartedFunctionsScenario shows you how to use AWS Lambda to perform the
following
// actions:
//
// 1. Create an AWS Identity and Access Management (IAM) role and Lambda function,
then upload handler code.
// 2. Invoke the function with a single parameter and get results.
// 3. Update the function code and configure with an environment variable.
// 4. Invoke the function with new parameters and get results. Display the returned
execution log.
// 5. List the functions for your account, then clean up resources.
type GetStartedFunctionsScenario struct {
sdkConfig aws.Config
functionWrapper actions.FunctionWrapper
questioner demotools.IQuestioner
helper IScenarioHelper
isTestRun bool
}
// NewGetStartedFunctionsScenario constructs a GetStartedFunctionsScenario instance
from a configuration.
// It uses the specified config to get a Lambda client and create wrappers for the
actions
// used in the scenario.
func NewGetStartedFunctionsScenario(sdkConfig aws.Config, questioner
demotools.IQuestioner,
helper IScenarioHelper) GetStartedFunctionsScenario {
lambdaClient := lambda.NewFromConfig(sdkConfig)
return GetStartedFunctionsScenario{
sdkConfig: sdkConfig,
functionWrapper: actions.FunctionWrapper{LambdaClient: lambdaClient},
questioner: questioner,
Scenarios 307
AWS SDK for Go Code Examples Code Examples Guide
helper: helper,
}
}
// Run runs the interactive scenario.
func (scenario GetStartedFunctionsScenario) Run() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong with the demo.\n")
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the AWS Lambda get started with functions demo.")
log.Println(strings.Repeat("-", 88))
role := scenario.GetOrCreateRole()
funcName := scenario.CreateFunction(role)
scenario.InvokeIncrement(funcName)
scenario.UpdateFunction(funcName)
scenario.InvokeCalculator(funcName)
scenario.ListFunctions()
scenario.Cleanup(role, funcName)
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
// GetOrCreateRole checks whether the specified role exists and returns it if it
does.
// Otherwise, a role is created that specifies Lambda as a trusted principal.
// The AWSLambdaBasicExecutionRole managed policy is attached to the role and the
role
// is returned.
func (scenario GetStartedFunctionsScenario) GetOrCreateRole() *iamtypes.Role {
var role *iamtypes.Role
iamClient := iam.NewFromConfig(scenario.sdkConfig)
log.Println("First, we need an IAM role that Lambda can assume.")
roleName := scenario.questioner.Ask("Enter a name for the role:",
demotools.NotEmpty{})
getOutput, err := iamClient.GetRole(context.TODO(), &iam.GetRoleInput{
RoleName: aws.String(roleName)})
if err != nil {
Scenarios 308
AWS SDK for Go Code Examples Code Examples Guide
var noSuch *iamtypes.NoSuchEntityException
if errors.As(err, &noSuch) {
log.Printf("Role %v doesn't exist. Creating it....\n", roleName)
} else {
log.Panicf("Couldn't check whether role %v exists. Here's why: %v\n",
roleName, err)
}
} else {
role = getOutput.Role
log.Printf("Found role %v.\n", *role.RoleName)
}
if role == nil {
trustPolicy := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Principal: map[string]string{"Service": "lambda.amazonaws.com"},
Action: []string{"sts:AssumeRole"},
}},
}
policyArn := "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
createOutput, err := iamClient.CreateRole(context.TODO(), &iam.CreateRoleInput{
AssumeRolePolicyDocument: aws.String(trustPolicy.String()),
RoleName: aws.String(roleName),
})
if err != nil {
log.Panicf("Couldn't create role %v. Here's why: %v\n", roleName, err)
}
role = createOutput.Role
_, err = iamClient.AttachRolePolicy(context.TODO(), &iam.AttachRolePolicyInput{
PolicyArn: aws.String(policyArn),
RoleName: aws.String(roleName),
})
if err != nil {
log.Panicf("Couldn't attach a policy to role %v. Here's why: %v\n", roleName,
err)
}
log.Printf("Created role %v.\n", *role.RoleName)
log.Println("Let's give AWS a few seconds to propagate resources...")
scenario.helper.Pause(10)
}
log.Println(strings.Repeat("-", 88))
return role
}
Scenarios 309
AWS SDK for Go Code Examples Code Examples Guide
// CreateFunction creates a Lambda function and uploads a handler written in Python.
// The code for the Python handler is packaged as a []byte in .zip format.
func (scenario GetStartedFunctionsScenario) CreateFunction(role *iamtypes.Role)
string {
log.Println("Let's create a function that increments a number.\n" +
"The function uses the 'lambda_handler_basic.py' script found in the \n" +
"'handlers' directory of this project.")
funcName := scenario.questioner.Ask("Enter a name for the Lambda function:",
demotools.NotEmpty{})
zipPackage := scenario.helper.CreateDeploymentPackage("lambda_handler_basic.py",
fmt.Sprintf("%v.py", funcName))
log.Printf("Creating function %v and waiting for it to be ready.", funcName)
funcState := scenario.functionWrapper.CreateFunction(funcName,
fmt.Sprintf("%v.lambda_handler", funcName),
role.Arn, zipPackage)
log.Printf("Your function is %v.", funcState)
log.Println(strings.Repeat("-", 88))
return funcName
}
// InvokeIncrement invokes a Lambda function that increments a number. The function
// parameters are contained in a Go struct that is used to serialize the parameters
to
// a JSON payload that is passed to the function.
// The result payload is deserialized into a Go struct that contains an int value.
func (scenario GetStartedFunctionsScenario) InvokeIncrement(funcName string) {
parameters := actions.IncrementParameters{Action: "increment"}
log.Println("Let's invoke our function. This function increments a number.")
parameters.Number = scenario.questioner.AskInt("Enter a number to increment:",
demotools.NotEmpty{})
log.Printf("Invoking %v with %v...\n", funcName, parameters.Number)
invokeOutput := scenario.functionWrapper.Invoke(funcName, parameters, false)
var payload actions.LambdaResultInt
err := json.Unmarshal(invokeOutput.Payload, &payload)
if err != nil {
log.Panicf("Couldn't unmarshal payload from invoking %v. Here's why: %v\n",
funcName, err)
}
log.Printf("Invoking %v with %v returned %v.\n", funcName, parameters.Number,
payload)
log.Println(strings.Repeat("-", 88))
}
Scenarios 310
AWS SDK for Go Code Examples Code Examples Guide
// UpdateFunction updates the code for a Lambda function by uploading a simple
arithmetic
// calculator written in Python. The code for the Python handler is packaged as a
// []byte in .zip format.
// After the code is updated, the configuration is also updated with a new log
// level that instructs the handler to log additional information.
func (scenario GetStartedFunctionsScenario) UpdateFunction(funcName string) {
log.Println("Let's update the function to an arithmetic calculator.\n" +
"The function uses the 'lambda_handler_calculator.py' script found in the \n" +
"'handlers' directory of this project.")
scenario.questioner.Ask("Press Enter when you're ready.")
log.Println("Creating deployment package...")
zipPackage :=
scenario.helper.CreateDeploymentPackage("lambda_handler_calculator.py",
fmt.Sprintf("%v.py", funcName))
log.Println("...and updating the Lambda function and waiting for it to be ready.")
funcState := scenario.functionWrapper.UpdateFunctionCode(funcName, zipPackage)
log.Printf("Updated function %v. Its current state is %v.", funcName, funcState)
log.Println("This function uses an environment variable to control logging level.")
log.Println("Let's set it to DEBUG to get the most logging.")
scenario.functionWrapper.UpdateFunctionConfiguration(funcName,
map[string]string{"LOG_LEVEL": "DEBUG"})
log.Println(strings.Repeat("-", 88))
}
// InvokeCalculator invokes the Lambda calculator function. The parameters are
stored in a
// Go struct that is used to serialize the parameters to a JSON payload. That
payload is then passed
// to the function.
// The result payload is deserialized to a Go struct that stores the result as
either an
// int or float32, depending on the kind of operation that was specified.
func (scenario GetStartedFunctionsScenario) InvokeCalculator(funcName string) {
wantInvoke := true
choices := []string{"plus", "minus", "times", "divided-by"}
for wantInvoke {
choice := scenario.questioner.AskChoice("Select an arithmetic operation:\n",
choices)
x := scenario.questioner.AskInt("Enter a value for x:", demotools.NotEmpty{})
y := scenario.questioner.AskInt("Enter a value for y:", demotools.NotEmpty{})
log.Printf("Invoking %v %v %v...", x, choices[choice], y)
calcParameters := actions.CalculatorParameters{
Action: choices[choice],
Scenarios 311
AWS SDK for Go Code Examples Code Examples Guide
X: x,
Y: y,
}
invokeOutput := scenario.functionWrapper.Invoke(funcName, calcParameters, true)
var payload any
if choice == 3 { // divide-by results in a float.
payload = actions.LambdaResultFloat{}
} else {
payload = actions.LambdaResultInt{}
}
err := json.Unmarshal(invokeOutput.Payload, &payload)
if err != nil {
log.Panicf("Couldn't unmarshal payload from invoking %v. Here's why: %v\n",
funcName, err)
}
log.Printf("Invoking %v with %v %v %v returned %v.\n", funcName,
calcParameters.X, calcParameters.Action, calcParameters.Y, payload)
scenario.questioner.Ask("Press Enter to see the logs from the call.")
logRes, err := base64.StdEncoding.DecodeString(*invokeOutput.LogResult)
if err != nil {
log.Panicf("Couldn't decode log result. Here's why: %v\n", err)
}
log.Println(string(logRes))
wantInvoke = scenario.questioner.AskBool("Do you want to calculate again? (y/n)",
"y")
}
log.Println(strings.Repeat("-", 88))
}
// ListFunctions lists up to the specified number of functions for your account.
func (scenario GetStartedFunctionsScenario) ListFunctions() {
count := scenario.questioner.AskInt(
"Let's list functions for your account. How many do you want to see?",
demotools.NotEmpty{})
functions := scenario.functionWrapper.ListFunctions(count)
log.Printf("Found %v functions:", len(functions))
for _, function := range functions {
log.Printf("\t%v", *function.FunctionName)
}
log.Println(strings.Repeat("-", 88))
}
// Cleanup removes the IAM and Lambda resources created by the example.
Scenarios 312
AWS SDK for Go Code Examples Code Examples Guide
func (scenario GetStartedFunctionsScenario) Cleanup(role *iamtypes.Role, funcName
string) {
if scenario.questioner.AskBool("Do you want to clean up resources created for this
example? (y/n)",
"y") {
iamClient := iam.NewFromConfig(scenario.sdkConfig)
policiesOutput, err := iamClient.ListAttachedRolePolicies(context.TODO(),
&iam.ListAttachedRolePoliciesInput{RoleName: role.RoleName})
if err != nil {
log.Panicf("Couldn't get policies attached to role %v. Here's why: %v\n",
*role.RoleName, err)
}
for _, policy := range policiesOutput.AttachedPolicies {
_, err = iamClient.DetachRolePolicy(context.TODO(), &iam.DetachRolePolicyInput{
PolicyArn: policy.PolicyArn, RoleName: role.RoleName,
})
if err != nil {
log.Panicf("Couldn't detach policy %v from role %v. Here's why: %v\n",
*policy.PolicyArn, *role.RoleName, err)
}
}
_, err = iamClient.DeleteRole(context.TODO(), &iam.DeleteRoleInput{RoleName:
role.RoleName})
if err != nil {
log.Panicf("Couldn't delete role %v. Here's why: %v\n", *role.RoleName, err)
}
log.Printf("Deleted role %v.\n", *role.RoleName)
scenario.functionWrapper.DeleteFunction(funcName)
log.Printf("Deleted function %v.\n", funcName)
} else {
log.Println("Okay. Don't forget to delete the resources when you're done with
them.")
}
}
Create a struct that wraps individual Lambda actions.
// FunctionWrapper encapsulates function actions used in the examples.
// It contains an AWS Lambda service client that is used to perform user actions.
Scenarios 313
AWS SDK for Go Code Examples Code Examples Guide
type FunctionWrapper struct {
LambdaClient *lambda.Client
}
// GetFunction gets data about the Lambda function specified by functionName.
func (wrapper FunctionWrapper) GetFunction(functionName string) types.State {
var state types.State
funcOutput, err := wrapper.LambdaClient.GetFunction(context.TODO(),
&lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
})
if err != nil {
log.Panicf("Couldn't get function %v. Here's why: %v\n", functionName, err)
} else {
state = funcOutput.Configuration.State
}
return state
}
// CreateFunction creates a new Lambda function from code contained in the
zipPackage
// buffer. The specified handlerName must match the name of the file and function
// contained in the uploaded code. The role specified by iamRoleArn is assumed by
// Lambda and grants specific permissions.
// When the function already exists, types.StateActive is returned.
// When the function is created, a lambda.FunctionActiveV2Waiter is used to wait
until the
// function is active.
func (wrapper FunctionWrapper) CreateFunction(functionName string, handlerName
string,
iamRoleArn *string, zipPackage *bytes.Buffer) types.State {
var state types.State
_, err := wrapper.LambdaClient.CreateFunction(context.TODO(),
&lambda.CreateFunctionInput{
Code: &types.FunctionCode{ZipFile: zipPackage.Bytes()},
FunctionName: aws.String(functionName),
Role: iamRoleArn,
Handler: aws.String(handlerName),
Publish: true,
Runtime: types.RuntimePython38,
})
Scenarios 314
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
var resConflict *types.ResourceConflictException
if errors.As(err, &resConflict) {
log.Printf("Function %v already exists.\n", functionName)
state = types.StateActive
} else {
log.Panicf("Couldn't create function %v. Here's why: %v\n", functionName, err)
}
} else {
waiter := lambda.NewFunctionActiveV2Waiter(wrapper.LambdaClient)
funcOutput, err := waiter.WaitForOutput(context.TODO(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName)}, 1*time.Minute)
if err != nil {
log.Panicf("Couldn't wait for function %v to be active. Here's why: %v\n",
functionName, err)
} else {
state = funcOutput.Configuration.State
}
}
return state
}
// UpdateFunctionCode updates the code for the Lambda function specified by
functionName.
// The existing code for the Lambda function is entirely replaced by the code in the
// zipPackage buffer. After the update action is called, a
lambda.FunctionUpdatedV2Waiter
// is used to wait until the update is successful.
func (wrapper FunctionWrapper) UpdateFunctionCode(functionName string, zipPackage
*bytes.Buffer) types.State {
var state types.State
_, err := wrapper.LambdaClient.UpdateFunctionCode(context.TODO(),
&lambda.UpdateFunctionCodeInput{
FunctionName: aws.String(functionName), ZipFile: zipPackage.Bytes(),
})
if err != nil {
log.Panicf("Couldn't update code for function %v. Here's why: %v\n", functionName,
err)
} else {
waiter := lambda.NewFunctionUpdatedV2Waiter(wrapper.LambdaClient)
funcOutput, err := waiter.WaitForOutput(context.TODO(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName)}, 1*time.Minute)
Scenarios 315
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Panicf("Couldn't wait for function %v to be active. Here's why: %v\n",
functionName, err)
} else {
state = funcOutput.Configuration.State
}
}
return state
}
// UpdateFunctionConfiguration updates a map of environment variables configured for
// the Lambda function specified by functionName.
func (wrapper FunctionWrapper) UpdateFunctionConfiguration(functionName string,
envVars map[string]string) {
_, err := wrapper.LambdaClient.UpdateFunctionConfiguration(context.TODO(),
&lambda.UpdateFunctionConfigurationInput{
FunctionName: aws.String(functionName),
Environment: &types.Environment{Variables: envVars},
})
if err != nil {
log.Panicf("Couldn't update configuration for %v. Here's why: %v", functionName,
err)
}
}
// ListFunctions lists up to maxItems functions for the account. This function uses
a
// lambda.ListFunctionsPaginator to paginate the results.
func (wrapper FunctionWrapper) ListFunctions(maxItems int)
[]types.FunctionConfiguration {
var functions []types.FunctionConfiguration
paginator := lambda.NewListFunctionsPaginator(wrapper.LambdaClient,
&lambda.ListFunctionsInput{
MaxItems: aws.Int32(int32(maxItems)),
})
for paginator.HasMorePages() && len(functions) < maxItems {
pageOutput, err := paginator.NextPage(context.TODO())
if err != nil {
log.Panicf("Couldn't list functions for your account. Here's why: %v\n", err)
}
Scenarios 316
AWS SDK for Go Code Examples Code Examples Guide
functions = append(functions, pageOutput.Functions...)
}
return functions
}
// DeleteFunction deletes the Lambda function specified by functionName.
func (wrapper FunctionWrapper) DeleteFunction(functionName string) {
_, err := wrapper.LambdaClient.DeleteFunction(context.TODO(),
&lambda.DeleteFunctionInput{
FunctionName: aws.String(functionName),
})
if err != nil {
log.Panicf("Couldn't delete function %v. Here's why: %v\n", functionName, err)
}
}
// Invoke invokes the Lambda function specified by functionName, passing the
parameters
// as a JSON payload. When getLog is true, types.LogTypeTail is specified, which
tells
// Lambda to include the last few log lines in the returned result.
func (wrapper FunctionWrapper) Invoke(functionName string, parameters any, getLog
bool) *lambda.InvokeOutput {
logType := types.LogTypeNone
if getLog {
logType = types.LogTypeTail
}
payload, err := json.Marshal(parameters)
if err != nil {
log.Panicf("Couldn't marshal parameters to JSON. Here's why %v\n", err)
}
invokeOutput, err := wrapper.LambdaClient.Invoke(context.TODO(),
&lambda.InvokeInput{
FunctionName: aws.String(functionName),
LogType: logType,
Payload: payload,
})
if err != nil {
log.Panicf("Couldn't invoke function %v. Here's why: %v\n", functionName, err)
}
Scenarios 317
AWS SDK for Go Code Examples Code Examples Guide
return invokeOutput
}
// IncrementParameters is used to serialize parameters to the increment Lambda
handler.
type IncrementParameters struct {
Action string `json:"action"`
Number int `json:"number"`
}
// CalculatorParameters is used to serialize parameters to the calculator Lambda
handler.
type CalculatorParameters struct {
Action string `json:"action"`
X int `json:"x"`
Y int `json:"y"`
}
// LambdaResultInt is used to deserialize an int result from a Lambda handler.
type LambdaResultInt struct {
Result int `json:"result"`
}
// LambdaResultFloat is used to deserialize a float32 result from a Lambda handler.
type LambdaResultFloat struct {
Result float32 `json:"result"`
}
Create a struct that implements functions to help run the scenario.
// IScenarioHelper abstracts I/O and wait functions from a scenario so that they
// can be mocked for unit testing.
type IScenarioHelper interface {
Pause(secs int)
CreateDeploymentPackage(sourceFile string, destinationFile string) *bytes.Buffer
}
// ScenarioHelper lets the caller specify the path to Lambda handler functions.
Scenarios 318
AWS SDK for Go Code Examples Code Examples Guide
type ScenarioHelper struct {
HandlerPath string
}
// Pause waits for the specified number of seconds.
func (helper *ScenarioHelper) Pause(secs int) {
time.Sleep(time.Duration(secs) * time.Second)
}
// CreateDeploymentPackage creates an AWS Lambda deployment package from a source
file. The
// deployment package is stored in .zip format in a bytes.Buffer. The buffer can be
// used to pass a []byte to Lambda when creating the function.
// The specified destinationFile is the name to give the file when it's deployed to
Lambda.
func (helper *ScenarioHelper) CreateDeploymentPackage(sourceFile string,
destinationFile string) *bytes.Buffer {
var err error
buffer := &bytes.Buffer{}
writer := zip.NewWriter(buffer)
zFile, err := writer.Create(destinationFile)
if err != nil {
log.Panicf("Couldn't create destination archive %v. Here's why: %v\n",
destinationFile, err)
}
sourceBody, err := os.ReadFile(fmt.Sprintf("%v/%v", helper.HandlerPath,
sourceFile))
if err != nil {
log.Panicf("Couldn't read handler source file %v. Here's why: %v\n",
sourceFile, err)
} else {
_, err = zFile.Write(sourceBody)
if err != nil {
log.Panicf("Couldn't write handler %v to zip archive. Here's why: %v\n",
sourceFile, err)
}
}
err = writer.Close()
if err != nil {
log.Panicf("Couldn't close zip writer. Here's why: %v\n", err)
}
return buffer
}
Scenarios 319
AWS SDK for Go Code Examples Code Examples Guide
Define a Lambda handler that increments a number.
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
"""
Accepts an action and a single number, performs the specified action on the
number,
and returns the result. The only allowable action is 'increment'.
:param event: The event dict that contains the parameters sent when the function
is invoked.
:param context: The context in which the function is called.
:return: The result of the action.
"""
result = None
action = event.get("action")
if action == "increment":
result = event.get("number", 0) + 1
logger.info("Calculated result of %s", result)
else:
logger.error("%s is not a valid action.", action)
response = {"result": result}
return response
Define a second Lambda handler that performs arithmetic operations.
import logging
import os
logger = logging.getLogger()
Scenarios 320
AWS SDK for Go Code Examples Code Examples Guide
# Define a list of Python lambda functions that are called by this AWS Lambda
function.
ACTIONS = {
"plus": lambda x, y: x + y,
"minus": lambda x, y: x - y,
"times": lambda x, y: x * y,
"divided-by": lambda x, y: x / y,
}
def lambda_handler(event, context):
"""
Accepts an action and two numbers, performs the specified action on the numbers,
and returns the result.
:param event: The event dict that contains the parameters sent when the function
is invoked.
:param context: The context in which the function is called.
:return: The result of the specified action.
"""
# Set the log level based on a variable configured in the Lambda environment.
logger.setLevel(os.environ.get("LOG_LEVEL", logging.INFO))
logger.debug("Event: %s", event)
action = event.get("action")
func = ACTIONS.get(action)
x = event.get("x")
y = event.get("y")
result = None
try:
if func is not None and x is not None and y is not None:
result = func(x, y)
logger.info("%s %s %s is %s", x, action, y, result)
else:
logger.error("I can't calculate %s %s %s.", x, action, y)
except ZeroDivisionError:
logger.warning("I can't divide %s by 0!", x)
response = {"result": result}
return response
Scenarios 321
AWS SDK for Go Code Examples Code Examples Guide
For API details, see the following topics in AWS SDK for Go API Reference.
CreateFunction
DeleteFunction
GetFunction
Invoke
ListFunctions
UpdateFunctionCode
UpdateFunctionConfiguration
Write custom activity data with a Lambda function after Amazon Cognito user authentication
The following code example shows how to write custom activity data with a Lambda function after
Amazon Cognito user authentication.
Use administrator functions to add a user to a user pool.
Configure a user pool to call a Lambda function for the PostAuthentication trigger.
Sign the new user in to Amazon Cognito.
The Lambda function writes custom information to CloudWatch Logs and to an DynamoDB
table.
Get and display custom data from the DynamoDB table, then clean up resources.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
// ActivityLog separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type ActivityLog struct {
Scenarios 322
AWS SDK for Go Code Examples Code Examples Guide
helper IScenarioHelper
questioner demotools.IQuestioner
resources Resources
cognitoActor *actions.CognitoActions
}
// NewActivityLog constructs a new activity log runner.
func NewActivityLog(sdkConfig aws.Config, questioner demotools.IQuestioner, helper
IScenarioHelper) ActivityLog {
scenario := ActivityLog{
helper: helper,
questioner: questioner,
resources: Resources{},
cognitoActor: &actions.CognitoActions{CognitoClient:
cognitoidentityprovider.NewFromConfig(sdkConfig)},
}
scenario.resources.init(scenario.cognitoActor, questioner)
return scenario
}
// AddUserToPool selects a user from the known users table and uses administrator
credentials to add the user to the user pool.
func (runner *ActivityLog) AddUserToPool(userPoolId string, tableName string)
(string, string) {
log.Println("To facilitate this example, let's add a user to the user pool using
administrator privileges.")
users, err := runner.helper.GetKnownUsers(tableName)
if err != nil {
panic(err)
}
user := users.Users[0]
log.Printf("Adding known user %v to the user pool.\n", user.UserName)
err = runner.cognitoActor.AdminCreateUser(userPoolId, user.UserName,
user.UserEmail)
if err != nil {
panic(err)
}
pwSet := false
password := runner.questioner.AskPassword("\nEnter a password that has at least
eight characters, uppercase, lowercase, numbers and symbols.\n"+
"(the password will not display as you type):", 8)
for !pwSet {
log.Printf("\nSetting password for user '%v'.\n", user.UserName)
Scenarios 323
AWS SDK for Go Code Examples Code Examples Guide
err = runner.cognitoActor.AdminSetUserPassword(userPoolId, user.UserName,
password)
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
password = runner.questioner.AskPassword("\nEnter another password:", 8)
} else {
panic(err)
}
} else {
pwSet = true
}
}
log.Println(strings.Repeat("-", 88))
return user.UserName, password
}
// AddActivityLogTrigger adds a Lambda handler as an invocation target for the
PostAuthentication trigger.
func (runner *ActivityLog) AddActivityLogTrigger(userPoolId string, activityLogArn
string) {
log.Println("Let's add a Lambda function to handle the PostAuthentication trigger
from Cognito.\n" +
"This trigger happens after a user is authenticated, and lets your function take
action, such as logging\n" +
"the outcome.")
err := runner.cognitoActor.UpdateTriggers(
userPoolId,
actions.TriggerInfo{Trigger: actions.PostAuthentication, HandlerArn:
aws.String(activityLogArn)})
if err != nil {
panic(err)
}
runner.resources.triggers = append(runner.resources.triggers,
actions.PostAuthentication)
log.Printf("Lambda function %v added to user pool %v to handle PostAuthentication
Cognito trigger.\n",
activityLogArn, userPoolId)
log.Println(strings.Repeat("-", 88))
}
Scenarios 324
AWS SDK for Go Code Examples Code Examples Guide
// SignInUser signs in as the specified user.
func (runner *ActivityLog) SignInUser(clientId string, userName string, password
string) {
log.Printf("Now we'll sign in user %v and check the results in the logs and the
DynamoDB table.", userName)
runner.questioner.Ask("Press Enter when you're ready.")
authResult, err := runner.cognitoActor.SignIn(clientId, userName, password)
if err != nil {
panic(err)
}
log.Println("Sign in successful.",
"The PostAuthentication Lambda handler writes custom information to CloudWatch
Logs.")
runner.resources.userAccessTokens = append(runner.resources.userAccessTokens,
*authResult.AccessToken)
}
// GetKnownUserLastLogin gets the login info for a user from the Amazon DynamoDB
table and displays it.
func (runner *ActivityLog) GetKnownUserLastLogin(tableName string, userName string)
{
log.Println("The PostAuthentication handler also writes login data to the DynamoDB
table.")
runner.questioner.Ask("Press Enter when you're ready to continue.")
users, err := runner.helper.GetKnownUsers(tableName)
if err != nil {
panic(err)
}
for _, user := range users.Users {
if user.UserName == userName {
log.Println("The last login info for the user in the known users table is:")
log.Printf("\t%+v", *user.LastLogin)
}
}
log.Println(strings.Repeat("-", 88))
}
// Run runs the scenario.
func (runner *ActivityLog) Run(stackName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
runner.resources.Cleanup()
Scenarios 325
AWS SDK for Go Code Examples Code Examples Guide
}
}()
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome\n")
log.Println(strings.Repeat("-", 88))
stackOutputs, err := runner.helper.GetStackOutputs(stackName)
if err != nil {
panic(err)
}
runner.resources.userPoolId = stackOutputs["UserPoolId"]
runner.helper.PopulateUserTable(stackOutputs["TableName"])
userName, password := runner.AddUserToPool(stackOutputs["UserPoolId"],
stackOutputs["TableName"])
runner.AddActivityLogTrigger(stackOutputs["UserPoolId"],
stackOutputs["ActivityLogFunctionArn"])
runner.SignInUser(stackOutputs["UserPoolClientId"], userName, password)
runner.helper.ListRecentLogEvents(stackOutputs["ActivityLogFunction"])
runner.GetKnownUserLastLogin(stackOutputs["TableName"], userName)
runner.resources.Cleanup()
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Handle the PostAuthentication trigger with a Lambda function.
const TABLE_NAME = "TABLE_NAME"
// LoginInfo defines structured login data that can be marshalled to a DynamoDB
format.
type LoginInfo struct {
UserPoolId string `dynamodbav:"UserPoolId"`
ClientId string `dynamodbav:"ClientId"`
Time string `dynamodbav:"Time"`
Scenarios 326
AWS SDK for Go Code Examples Code Examples Guide
}
// UserInfo defines structured user data that can be marshalled to a DynamoDB
format.
type UserInfo struct {
UserName string `dynamodbav:"UserName"`
UserEmail string `dynamodbav:"UserEmail"`
LastLogin LoginInfo `dynamodbav:"LastLogin"`
}
// GetKey marshals the user email value to a DynamoDB key format.
func (user UserInfo) GetKey() map[string]dynamodbtypes.AttributeValue {
userEmail, err := attributevalue.Marshal(user.UserEmail)
if err != nil {
panic(err)
}
return map[string]dynamodbtypes.AttributeValue{"UserEmail": userEmail}
}
type handler struct {
dynamoClient *dynamodb.Client
}
// HandleRequest handles the PostAuthentication event by writing custom data to the
logs and
// to an Amazon DynamoDB table.
func (h *handler) HandleRequest(ctx context.Context,
event events.CognitoEventUserPoolsPostAuthentication)
(events.CognitoEventUserPoolsPostAuthentication, error) {
log.Printf("Received post authentication trigger from %v for user '%v'",
event.TriggerSource, event.UserName)
tableName := os.Getenv(TABLE_NAME)
user := UserInfo{
UserName: event.UserName,
UserEmail: event.Request.UserAttributes["email"],
LastLogin: LoginInfo{
UserPoolId: event.UserPoolID,
ClientId: event.CallerContext.ClientID,
Time: time.Now().Format(time.UnixDate),
},
}
// Write to CloudWatch Logs.
fmt.Printf("%#v", user)
Scenarios 327
AWS SDK for Go Code Examples Code Examples Guide
// Also write to an external system. This examples uses DynamoDB to demonstrate.
userMap, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshal to DynamoDB map. Here's why: %v\n", err)
} else if len(userMap) == 0 {
log.Printf("User info marshaled to an empty map.")
} else {
_, err := h.dynamoClient.PutItem(ctx, &dynamodb.PutItemInput{
Item: userMap,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't write to DynamoDB. Here's why: %v\n", err)
} else {
log.Printf("Wrote user info to DynamoDB table %v.\n", tableName)
}
}
return event, nil
}
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Panicln(err)
}
h := handler{
dynamoClient: dynamodb.NewFromConfig(sdkConfig),
}
lambda.Start(h.HandleRequest)
}
Create a struct that performs common tasks.
// IScenarioHelper defines common functions used by the workflows in this example.
type IScenarioHelper interface {
Pause(secs int)
GetStackOutputs(stackName string) (actions.StackOutputs, error)
PopulateUserTable(tableName string)
GetKnownUsers(tableName string) (actions.UserList, error)
Scenarios 328
AWS SDK for Go Code Examples Code Examples Guide
AddKnownUser(tableName string, user actions.User)
ListRecentLogEvents(functionName string)
}
// ScenarioHelper contains AWS wrapper structs used by the workflows in this
example.
type ScenarioHelper struct {
questioner demotools.IQuestioner
dynamoActor *actions.DynamoActions
cfnActor *actions.CloudFormationActions
cwlActor *actions.CloudWatchLogsActions
isTestRun bool
}
// NewScenarioHelper constructs a new scenario helper.
func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner)
ScenarioHelper {
scenario := ScenarioHelper{
questioner: questioner,
dynamoActor: &actions.DynamoActions{DynamoClient:
dynamodb.NewFromConfig(sdkConfig)},
cfnActor: &actions.CloudFormationActions{CfnClient:
cloudformation.NewFromConfig(sdkConfig)},
cwlActor: &actions.CloudWatchLogsActions{CwlClient:
cloudwatchlogs.NewFromConfig(sdkConfig)},
}
return scenario
}
// Pause waits for the specified number of seconds.
func (helper ScenarioHelper) Pause(secs int) {
if !helper.isTestRun {
time.Sleep(time.Duration(secs) * time.Second)
}
}
// GetStackOutputs gets the outputs from the specified CloudFormation stack in a
structured format.
func (helper ScenarioHelper) GetStackOutputs(stackName string)
(actions.StackOutputs, error) {
return helper.cfnActor.GetOutputs(stackName), nil
}
// PopulateUserTable fills the known user table with example data.
Scenarios 329
AWS SDK for Go Code Examples Code Examples Guide
func (helper ScenarioHelper) PopulateUserTable(tableName string) {
log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this
example.\n", tableName)
err := helper.dynamoActor.PopulateTable(tableName)
if err != nil {
panic(err)
}
}
// GetKnownUsers gets the users from the known users table in a structured format.
func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList,
error) {
knownUsers, err := helper.dynamoActor.Scan(tableName)
if err != nil {
log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName,
err)
}
return knownUsers, err
}
// AddKnownUser adds a user to the known users table.
func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) {
log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...
\n",
user.UserName, user.UserEmail)
err := helper.dynamoActor.AddUser(tableName, user)
if err != nil {
panic(err)
}
}
// ListRecentLogEvents gets the most recent log stream and events for the specified
Lambda function and displays them.
func (helper ScenarioHelper) ListRecentLogEvents(functionName string) {
log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...")
helper.Pause(10)
log.Println("Okay, let's check the logs to find what's happened recently with your
Lambda function.")
logStream, err := helper.cwlActor.GetLatestLogStream(functionName)
if err != nil {
panic(err)
}
log.Printf("Getting some recent events from log stream %v\n",
*logStream.LogStreamName)
Scenarios 330
AWS SDK for Go Code Examples Code Examples Guide
events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName,
10)
if err != nil {
panic(err)
}
for _, event := range events {
log.Printf("\t%v", *event.Message)
}
log.Println(strings.Repeat("-", 88))
}
Create a struct that wraps Amazon Cognito actions.
type CognitoActions struct {
CognitoClient *cognitoidentityprovider.Client
}
// Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger.
type Trigger int
const (
PreSignUp Trigger = iota
UserMigration
PostAuthentication
)
type TriggerInfo struct {
Trigger Trigger
HandlerArn *string
}
// UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is
specified with a `nil` value,
// it is removed from the user pool.
func (actor CognitoActions) UpdateTriggers(userPoolId string,
triggers ...TriggerInfo) error {
Scenarios 331
AWS SDK for Go Code Examples Code Examples Guide
output, err := actor.CognitoClient.DescribeUserPool(context.TODO(),
&cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: aws.String(userPoolId),
})
if err != nil {
log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId,
err)
return err
}
lambdaConfig := output.UserPool.LambdaConfig
for _, trigger := range triggers {
switch trigger.Trigger {
case PreSignUp:
lambdaConfig.PreSignUp = trigger.HandlerArn
case UserMigration:
lambdaConfig.UserMigration = trigger.HandlerArn
case PostAuthentication:
lambdaConfig.PostAuthentication = trigger.HandlerArn
}
}
_, err = actor.CognitoClient.UpdateUserPool(context.TODO(),
&cognitoidentityprovider.UpdateUserPoolInput{
UserPoolId: aws.String(userPoolId),
LambdaConfig: lambdaConfig,
})
if err != nil {
log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err)
}
return err
}
// SignUp signs up a user with Amazon Cognito.
func (actor CognitoActions) SignUp(clientId string, userName string, password
string, userEmail string) (bool, error) {
confirmed := false
output, err := actor.CognitoClient.SignUp(context.TODO(),
&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(clientId),
Password: aws.String(password),
Username: aws.String(userName),
UserAttributes: []types.AttributeType{
{Name: aws.String("email"), Value: aws.String(userEmail)},
Scenarios 332
AWS SDK for Go Code Examples Code Examples Guide
},
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err)
}
} else {
confirmed = output.UserConfirmed
}
return confirmed, err
}
// SignIn signs in a user to Amazon Cognito using a username and password
authentication flow.
func (actor CognitoActions) SignIn(clientId string, userName string, password
string) (*types.AuthenticationResultType, error) {
var authResult *types.AuthenticationResultType
output, err := actor.CognitoClient.InitiateAuth(context.TODO(),
&cognitoidentityprovider.InitiateAuthInput{
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: aws.String(clientId),
AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password},
})
if err != nil {
var resetRequired *types.PasswordResetRequiredException
if errors.As(err, &resetRequired) {
log.Println(*resetRequired.Message)
} else {
log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err)
}
} else {
authResult = output.AuthenticationResult
}
return authResult, err
}
Scenarios 333
AWS SDK for Go Code Examples Code Examples Guide
// ForgotPassword starts a password recovery flow for a user. This flow typically
sends a confirmation code
// to the user's configured notification destination, such as email.
func (actor CognitoActions) ForgotPassword(clientId string, userName string)
(*types.CodeDeliveryDetailsType, error) {
output, err := actor.CognitoClient.ForgotPassword(context.TODO(),
&cognitoidentityprovider.ForgotPasswordInput{
ClientId: aws.String(clientId),
Username: aws.String(userName),
})
if err != nil {
log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n",
userName, err)
}
return output.CodeDeliveryDetails, err
}
// ConfirmForgotPassword confirms a user with a confirmation code and a new
password.
func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string,
userName string, password string) error {
_, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(),
&cognitoidentityprovider.ConfirmForgotPasswordInput{
ClientId: aws.String(clientId),
ConfirmationCode: aws.String(code),
Password: aws.String(password),
Username: aws.String(userName),
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err)
}
}
return err
}
// DeleteUser removes a user from the user pool.
Scenarios 334
AWS SDK for Go Code Examples Code Examples Guide
func (actor CognitoActions) DeleteUser(userAccessToken string) error {
_, err := actor.CognitoClient.DeleteUser(context.TODO(),
&cognitoidentityprovider.DeleteUserInput{
AccessToken: aws.String(userAccessToken),
})
if err != nil {
log.Printf("Couldn't delete user. Here's why: %v\n", err)
}
return err
}
// AdminCreateUser uses administrator credentials to add a user to a user pool. This
method leaves the user
// in a state that requires they enter a new password next time they sign in.
func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string,
userEmail string) error {
_, err := actor.CognitoClient.AdminCreateUser(context.TODO(),
&cognitoidentityprovider.AdminCreateUserInput{
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
MessageAction: types.MessageActionTypeSuppress,
UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value:
aws.String(userEmail)}},
})
if err != nil {
var userExists *types.UsernameExistsException
if errors.As(err, &userExists) {
log.Printf("User %v already exists in the user pool.", userName)
err = nil
} else {
log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err)
}
}
return err
}
// AdminSetUserPassword uses administrator credentials to set a password for a user
without requiring a
// temporary password.
Scenarios 335
AWS SDK for Go Code Examples Code Examples Guide
func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string,
password string) error {
_, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(),
&cognitoidentityprovider.AdminSetUserPasswordInput{
Password: aws.String(password),
UserPoolId: aws.String(userPoolId),
Username: aws.String(userName),
Permanent: true,
})
if err != nil {
var invalidPassword *types.InvalidPasswordException
if errors.As(err, &invalidPassword) {
log.Println(*invalidPassword.Message)
} else {
log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err)
}
}
return err
}
Create a struct that wraps DynamoDB actions.
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type DynamoActions struct {
DynamoClient *dynamodb.Client
}
// User defines structured user data.
type User struct {
UserName string
UserEmail string
LastLogin *LoginInfo `dynamodbav:",omitempty"`
}
// LoginInfo defines structured custom login data.
type LoginInfo struct {
UserPoolId string
ClientId string
Scenarios 336
AWS SDK for Go Code Examples Code Examples Guide
Time string
}
// UserList defines a list of users.
type UserList struct {
Users []User
}
// UserNameList returns the usernames contained in a UserList as a list of strings.
func (users *UserList) UserNameList() []string {
names := make([]string, len(users.Users))
for i := 0; i < len(users.Users); i++ {
names[i] = users.Users[i].UserName
}
return names
}
// PopulateTable adds a set of test users to the table.
func (actor DynamoActions) PopulateTable(tableName string) error {
var err error
var item map[string]types.AttributeValue
var writeReqs []types.WriteRequest
for i := 1; i < 4; i++ {
item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v",
i), UserEmail: fmt.Sprintf("test_email_%[email protected]", i)})
if err != nil {
log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err)
return err
}
writeReqs = append(writeReqs, types.WriteRequest{PutRequest:
&types.PutRequest{Item: item}})
}
_, err = actor.DynamoClient.BatchWriteItem(context.TODO(),
&dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{tableName: writeReqs},
})
if err != nil {
log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName,
err)
}
return err
}
// Scan scans the table for all items.
Scenarios 337
AWS SDK for Go Code Examples Code Examples Guide
func (actor DynamoActions) Scan(tableName string) (UserList, error) {
var userList UserList
output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err)
} else {
err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users)
if err != nil {
log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err)
}
}
return userList, err
}
// AddUser adds a user item to a table.
func (actor DynamoActions) AddUser(tableName string, user User) error {
userItem, err := attributevalue.MarshalMap(user)
if err != nil {
log.Printf("Couldn't marshall user to item. Here's why: %v\n", err)
}
_, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
Item: userItem,
TableName: aws.String(tableName),
})
if err != nil {
log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err)
}
return err
}
Create a struct that wraps CloudWatch Logs actions.
type CloudWatchLogsActions struct {
CwlClient *cloudwatchlogs.Client
}
// GetLatestLogStream gets the most recent log stream for a Lambda function.
Scenarios 338
AWS SDK for Go Code Examples Code Examples Guide
func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string)
(types.LogStream, error) {
var logStream types.LogStream
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.DescribeLogStreams(context.TODO(),
&cloudwatchlogs.DescribeLogStreamsInput{
Descending: aws.Bool(true),
Limit: aws.Int32(1),
LogGroupName: aws.String(logGroupName),
OrderBy: types.OrderByLastEventTime,
})
if err != nil {
log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n",
logGroupName, err)
} else {
logStream = output.LogStreams[0]
}
return logStream, err
}
// GetLogEvents gets the most recent eventCount events from the specified log
stream.
func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName
string, eventCount int32) (
[]types.OutputLogEvent, error) {
var events []types.OutputLogEvent
logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName)
output, err := actor.CwlClient.GetLogEvents(context.TODO(),
&cloudwatchlogs.GetLogEventsInput{
LogStreamName: aws.String(logStreamName),
Limit: aws.Int32(eventCount),
LogGroupName: aws.String(logGroupName),
})
if err != nil {
log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n",
logStreamName, err)
} else {
events = output.Events
}
return events, err
}
Scenarios 339
AWS SDK for Go Code Examples Code Examples Guide
Create a struct that wraps AWS CloudFormation actions.
// StackOutputs defines a map of outputs from a specific stack.
type StackOutputs map[string]string
type CloudFormationActions struct {
CfnClient *cloudformation.Client
}
// GetOutputs gets the outputs from a CloudFormation stack and puts them into a
structured format.
func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs {
output, err := actor.CfnClient.DescribeStacks(context.TODO(),
&cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
})
if err != nil || len(output.Stacks) == 0 {
log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n",
stackName, err)
}
stackOutputs := StackOutputs{}
for _, out := range output.Stacks[0].Outputs {
stackOutputs[*out.OutputKey] = *out.OutputValue
}
return stackOutputs
}
Clean up resources.
// Resources keeps track of AWS resources created during an example and handles
// cleanup when the example finishes.
type Resources struct {
userPoolId string
userAccessTokens []string
triggers []actions.Trigger
cognitoActor *actions.CognitoActions
questioner demotools.IQuestioner
}
Scenarios 340
AWS SDK for Go Code Examples Code Examples Guide
func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner
demotools.IQuestioner) {
resources.userAccessTokens = []string{}
resources.triggers = []actions.Trigger{}
resources.cognitoActor = cognitoActor
resources.questioner = questioner
}
// Cleanup deletes all AWS resources created during an example.
func (resources *Resources) Cleanup() {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources \n"
+
"that were created for this scenario.")
}
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
if wantDelete {
for _, accessToken := range resources.userAccessTokens {
err := resources.cognitoActor.DeleteUser(accessToken)
if err != nil {
log.Println("Couldn't delete user during cleanup.")
panic(err)
}
log.Println("Deleted user.")
}
triggerList := make([]actions.TriggerInfo, len(resources.triggers))
for i := 0; i < len(resources.triggers); i++ {
triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn:
nil}
}
err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...)
if err != nil {
log.Println("Couldn't update Cognito triggers during cleanup.")
panic(err)
}
log.Println("Removed Cognito triggers from user pool.")
} else {
Scenarios 341
AWS SDK for Go Code Examples Code Examples Guide
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
AdminCreateUser
AdminSetUserPassword
DeleteUser
InitiateAuth
UpdateUserPool
Serverless examples
Connecting to an Amazon RDS database in a Lambda function
The following code example shows how to implement a Lambda function that connects to an RDS
database. The function makes a simple database request and returns the result.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Connecting to an Amazon RDS database in a Lambda function using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/*
Golang v2 code here.
*/
package main
Serverless examples 342
AWS SDK for Go Code Examples Code Examples Guide
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"os"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/rds/auth"
_ "github.com/go-sql-driver/mysql"
)
type MyEvent struct {
Name string `json:"name"`
}
func HandleRequest(event *MyEvent) (map[string]interface{}, error) {
var dbName string = os.Getenv("DatabaseName")
var dbUser string = os.Getenv("DatabaseUser")
var dbHost string = os.Getenv("DBHost") // Add hostname without https
var dbPort int = os.Getenv("Port") // Add port number
var dbEndpoint string = fmt.Sprintf("%s:%d", dbHost, dbPort)
var region string = os.Getenv("AWS_REGION")
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic("configuration error: " + err.Error())
}
authenticationToken, err := auth.BuildAuthToken(
context.TODO(), dbEndpoint, region, dbUser, cfg.Credentials)
if err != nil {
panic("failed to create authentication token: " + err.Error())
}
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=true&allowCleartextPasswords=true",
dbUser, authenticationToken, dbEndpoint, dbName,
)
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
Serverless examples 343
AWS SDK for Go Code Examples Code Examples Guide
}
defer db.Close()
var sum int
err = db.QueryRow("SELECT ?+? AS sum", 3, 2).Scan(&sum)
if err != nil {
panic(err)
}
s := fmt.Sprint(sum)
message := fmt.Sprintf("The selected sum is: %s", s)
messageBytes, err := json.Marshal(message)
if err != nil {
return nil, err
}
messageString := string(messageBytes)
return map[string]interface{}{
"statusCode": 200,
"headers": map[string]string{"Content-Type": "application/json"},
"body": messageString,
}, nil
}
func main() {
lambda.Start(HandleRequest)
}
Invoke a Lambda function from a Kinesis trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving records from a Kinesis stream. The function retrieves the Kinesis payload,
decodes from Base64, and logs the record contents.
Serverless examples 344
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming a Kinesis event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"log"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, kinesisEvent events.KinesisEvent) error {
if len(kinesisEvent.Records) == 0 {
log.Printf("empty Kinesis event received")
return nil
}
for _, record := range kinesisEvent.Records {
log.Printf("processed Kinesis event with EventId: %v", record.EventID)
recordDataBytes := record.Kinesis.Data
recordDataText := string(recordDataBytes)
log.Printf("record data: %v", recordDataText)
// TODO: Do interesting work based on the new data
}
log.Printf("successfully processed %v records", len(kinesisEvent.Records))
return nil
}
func main() {
lambda.Start(handler)
}
Serverless examples 345
AWS SDK for Go Code Examples Code Examples Guide
Invoke a Lambda function from a DynamoDB trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving records from a DynamoDB stream. The function retrieves the DynamoDB
payload and logs the record contents.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming a DynamoDB event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-lambda-go/events"
"fmt"
)
func HandleRequest(ctx context.Context, event events.DynamoDBEvent) (*string, error)
{
if len(event.Records) == 0 {
return nil, fmt.Errorf("received empty event")
}
for _, record := range event.Records {
LogDynamoDBRecord(record)
}
message := fmt.Sprintf("Records processed: %d", len(event.Records))
return &message, nil
Serverless examples 346
AWS SDK for Go Code Examples Code Examples Guide
}
func main() {
lambda.Start(HandleRequest)
}
func LogDynamoDBRecord(record events.DynamoDBEventRecord){
fmt.Println(record.EventID)
fmt.Println(record.EventName)
fmt.Printf("%+v\n", record.Change)
}
Invoke a Lambda function from a Amazon DocumentDB trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving records from a DocumentDB change stream. The function retrieves the
DocumentDB payload and logs the record contents.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming a Amazon DocumentDB event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/lambda"
)
Serverless examples 347
AWS SDK for Go Code Examples Code Examples Guide
type Event struct {
Events []Record `json:"events"`
}
type Record struct {
Event struct {
OperationType string `json:"operationType"`
NS struct {
DB string `json:"db"`
Coll string `json:"coll"`
} `json:"ns"`
FullDocument interface{} `json:"fullDocument"`
} `json:"event"`
}
func main() {
lambda.Start(handler)
}
func handler(ctx context.Context, event Event) (string, error) {
fmt.Println("Loading function")
for _, record := range event.Events {
logDocumentDBEvent(record)
}
return "OK", nil
}
func logDocumentDBEvent(record Record) {
fmt.Printf("Operation type: %s\n", record.Event.OperationType)
fmt.Printf("db: %s\n", record.Event.NS.DB)
fmt.Printf("collection: %s\n", record.Event.NS.Coll)
docBytes, _ := json.MarshalIndent(record.Event.FullDocument, "", " ")
fmt.Printf("Full document: %s\n", string(docBytes))
}
Invoke a Lambda function from an Amazon S3 trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by uploading an object to an S3 bucket. The function retrieves the S3 bucket name and
Serverless examples 348
AWS SDK for Go Code Examples Code Examples Guide
object key from the event parameter and calls the Amazon S3 API to retrieve and log the content
type of the object.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming an S3 event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"log"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
func handler(ctx context.Context, s3Event events.S3Event) error {
sdkConfig, err := config.LoadDefaultConfig(ctx)
if err != nil {
log.Printf("failed to load default config: %s", err)
return err
}
s3Client := s3.NewFromConfig(sdkConfig)
for _, record := range s3Event.Records {
bucket := record.S3.Bucket.Name
key := record.S3.Object.URLDecodedKey
headOutput, err := s3Client.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: &bucket,
Key: &key,
})
Serverless examples 349
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("error getting head of object %s/%s: %s", bucket, key, err)
return err
}
log.Printf("successfully retrieved %s/%s of type %s", bucket, key,
*headOutput.ContentType)
}
return nil
}
func main() {
lambda.Start(handler)
}
Invoke a Lambda function from an Amazon SNS trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving messages from an SNS topic. The function retrieves the messages from the
event parameter and logs the content of each message.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming an SNS event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
Serverless examples 350
AWS SDK for Go Code Examples Code Examples Guide
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, snsEvent events.SNSEvent) {
for _, record := range snsEvent.Records {
processMessage(record)
}
fmt.Println("done")
}
func processMessage(record events.SNSEventRecord) {
message := record.SNS.Message
fmt.Printf("Processed message: %s\n", message)
// TODO: Process your record here
}
func main() {
lambda.Start(handler)
}
Invoke a Lambda function from an Amazon SQS trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving messages from an SQS queue. The function retrieves the messages from the
event parameter and logs the content of each message.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming an SQS event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration_sqs_to_lambda
Serverless examples 351
AWS SDK for Go Code Examples Code Examples Guide
import (
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(event events.SQSEvent) error {
for _, record := range event.Records {
err := processMessage(record)
if err != nil {
return err
}
}
fmt.Println("done")
return nil
}
func processMessage(record events.SQSMessage) error {
fmt.Printf("Processed message %s\n", record.Body)
// TODO: Do interesting work based on the new message
return nil
}
func main() {
lambda.Start(handler)
}
Reporting batch item failures for Lambda functions with a Kinesis trigger
The following code example shows how to implement partial batch response for Lambda functions
that receive events from a Kinesis stream. The function reports the batch item failures in the
response, signaling to Lambda to retry those messages later.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Serverless examples 352
AWS SDK for Go Code Examples Code Examples Guide
Reporting Kinesis batch item failures with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, kinesisEvent events.KinesisEvent)
(map[string]interface{}, error) {
batchItemFailures := []map[string]interface{}{}
for _, record := range kinesisEvent.Records {
curRecordSequenceNumber := ""
// Process your record
if /* Your record processing condition here */ {
curRecordSequenceNumber = record.Kinesis.SequenceNumber
}
// Add a condition to check if the record processing failed
if curRecordSequenceNumber != "" {
batchItemFailures = append(batchItemFailures, map[string]interface{}
{"itemIdentifier": curRecordSequenceNumber})
}
}
kinesisBatchResponse := map[string]interface{}{
"batchItemFailures": batchItemFailures,
}
return kinesisBatchResponse, nil
}
func main() {
lambda.Start(handler)
}
Serverless examples 353
AWS SDK for Go Code Examples Code Examples Guide
Reporting batch item failures for Lambda functions with a DynamoDB trigger
The following code example shows how to implement partial batch response for Lambda functions
that receive events from a DynamoDB stream. The function reports the batch item failures in the
response, signaling to Lambda to retry those messages later.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Reporting DynamoDB batch item failures with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
type BatchItemFailure struct {
ItemIdentifier string `json:"ItemIdentifier"`
}
type BatchResult struct {
BatchItemFailures []BatchItemFailure `json:"BatchItemFailures"`
}
func HandleRequest(ctx context.Context, event events.DynamoDBEvent) (*BatchResult,
error) {
var batchItemFailures []BatchItemFailure
curRecordSequenceNumber := ""
for _, record := range event.Records {
// Process your record
curRecordSequenceNumber = record.Change.SequenceNumber
Serverless examples 354
AWS SDK for Go Code Examples Code Examples Guide
}
if curRecordSequenceNumber != "" {
batchItemFailures = append(batchItemFailures, BatchItemFailure{ItemIdentifier:
curRecordSequenceNumber})
}
batchResult := BatchResult{
BatchItemFailures: batchItemFailures,
}
return &batchResult, nil
}
func main() {
lambda.Start(HandleRequest)
}
Reporting batch item failures for Lambda functions with an Amazon SQS trigger
The following code example shows how to implement partial batch response for Lambda functions
that receive events from an SQS queue. The function reports the batch item failures in the
response, signaling to Lambda to retry those messages later.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Reporting SQS batch item failures with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
Serverless examples 355
AWS SDK for Go Code Examples Code Examples Guide
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, sqsEvent events.SQSEvent) (map[string]interface{},
error) {
batchItemFailures := []map[string]interface{}{}
for _, message := range sqsEvent.Records {
if /* Your message processing condition here */ {
batchItemFailures = append(batchItemFailures, map[string]interface{}
{"itemIdentifier": message.MessageId})
}
}
sqsBatchResponse := map[string]interface{}{
"batchItemFailures": batchItemFailures,
}
return sqsBatchResponse, nil
}
func main() {
lambda.Start(handler)
}
Amazon RDS examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon RDS.
Basics are code examples that show you how to perform the essential operations within a service.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Amazon RDS 356
AWS SDK for Go Code Examples Code Examples Guide
Get started
Hello Amazon RDS
The following code examples show how to get started using Amazon RDS.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/rds"
)
// main uses the AWS SDK for Go V2 to create an Amazon Relational Database Service
(Amazon RDS)
// client and list up to 20 DB instances in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
rdsClient := rds.NewFromConfig(sdkConfig)
const maxInstances = 20
fmt.Printf("Let's list up to %v DB instances.\n", maxInstances)
Amazon RDS 357
AWS SDK for Go Code Examples Code Examples Guide
output, err := rdsClient.DescribeDBInstances(context.TODO(),
&rds.DescribeDBInstancesInput{MaxRecords: aws.Int32(maxInstances)})
if err != nil {
fmt.Printf("Couldn't list DB instances: %v\n", err)
return
}
if len(output.DBInstances) == 0 {
fmt.Println("No DB instances found.")
} else {
for _, instance := range output.DBInstances {
fmt.Printf("DB instance %v has database %v.\n", *instance.DBInstanceIdentifier,
*instance.DBName)
}
}
}
For API details, see DescribeDBInstances in AWS SDK for Go API Reference.
Topics
Basics
Actions
Serverless examples
Basics
Learn the basics
The following code example shows how to:
Create a custom DB parameter group and set parameter values.
Create a DB instance that's configured to use the parameter group. The DB instance also contains
a database.
Take a snapshot of the instance.
Delete the instance and parameter group.
Basics 358
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
// GetStartedInstances is an interactive example that shows you how to use the AWS
SDK for Go
// with Amazon Relation Database Service (Amazon RDS) to do the following:
//
// 1. Create a custom DB parameter group and set parameter values.
// 2. Create a DB instance that is configured to use the parameter group. The DB
instance
// also contains a database.
// 3. Take a snapshot of the DB instance.
// 4. Delete the DB instance and parameter group.
type GetStartedInstances struct {
sdkConfig aws.Config
instances actions.DbInstances
questioner demotools.IQuestioner
helper IScenarioHelper
isTestRun bool
}
// NewGetStartedInstances constructs a GetStartedInstances instance from a
configuration.
// It uses the specified config to get an Amazon RDS
// client and create wrappers for the actions used in the scenario.
func NewGetStartedInstances(sdkConfig aws.Config, questioner demotools.IQuestioner,
helper IScenarioHelper) GetStartedInstances {
rdsClient := rds.NewFromConfig(sdkConfig)
return GetStartedInstances{
sdkConfig: sdkConfig,
instances: actions.DbInstances{RdsClient: rdsClient},
questioner: questioner,
helper: helper,
}
}
Basics 359
AWS SDK for Go Code Examples Code Examples Guide
// Run runs the interactive scenario.
func (scenario GetStartedInstances) Run(dbEngine string, parameterGroupName string,
instanceName string, dbName string) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon Relational Database Service (Amazon RDS) DB
Instance demo.")
log.Println(strings.Repeat("-", 88))
parameterGroup := scenario.CreateParameterGroup(dbEngine, parameterGroupName)
scenario.SetUserParameters(parameterGroupName)
instance := scenario.CreateInstance(instanceName, dbEngine, dbName, parameterGroup)
scenario.DisplayConnection(instance)
scenario.CreateSnapshot(instance)
scenario.Cleanup(instance, parameterGroup)
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
// CreateParameterGroup shows how to get available engine versions for a specified
// database engine and create a DB parameter group that is compatible with a
// selected engine family.
func (scenario GetStartedInstances) CreateParameterGroup(dbEngine string,
parameterGroupName string) *types.DBParameterGroup {
log.Printf("Checking for an existing DB parameter group named %v.\n",
parameterGroupName)
parameterGroup, err := scenario.instances.GetParameterGroup(parameterGroupName)
if err != nil {
panic(err)
}
if parameterGroup == nil {
log.Printf("Getting available database engine versions for %v.\n", dbEngine)
engineVersions, err := scenario.instances.GetEngineVersions(dbEngine, "")
if err != nil {
panic(err)
Basics 360
AWS SDK for Go Code Examples Code Examples Guide
}
familySet := map[string]struct{}{}
for _, family := range engineVersions {
familySet[*family.DBParameterGroupFamily] = struct{}{}
}
var families []string
for family := range familySet {
families = append(families, family)
}
sort.Strings(families)
familyIndex := scenario.questioner.AskChoice("Which family do you want to use?\n",
families)
log.Println("Creating a DB parameter group.")
_, err = scenario.instances.CreateParameterGroup(
parameterGroupName, families[familyIndex], "Example parameter group.")
if err != nil {
panic(err)
}
parameterGroup, err = scenario.instances.GetParameterGroup(parameterGroupName)
if err != nil {
panic(err)
}
}
log.Printf("Parameter group %v:\n", *parameterGroup.DBParameterGroupFamily)
log.Printf("\tName: %v\n", *parameterGroup.DBParameterGroupName)
log.Printf("\tARN: %v\n", *parameterGroup.DBParameterGroupArn)
log.Printf("\tFamily: %v\n", *parameterGroup.DBParameterGroupFamily)
log.Printf("\tDescription: %v\n", *parameterGroup.Description)
log.Println(strings.Repeat("-", 88))
return parameterGroup
}
// SetUserParameters shows how to get the parameters contained in a custom parameter
// group and update some of the parameter values in the group.
func (scenario GetStartedInstances) SetUserParameters(parameterGroupName string) {
log.Println("Let's set some parameter values in your parameter group.")
dbParameters, err := scenario.instances.GetParameters(parameterGroupName, "")
if err != nil {
panic(err)
}
var updateParams []types.Parameter
for _, dbParam := range dbParameters {
if strings.HasPrefix(*dbParam.ParameterName, "auto_increment") &&
Basics 361
AWS SDK for Go Code Examples Code Examples Guide
dbParam.IsModifiable && *dbParam.DataType == "integer" {
log.Printf("The %v parameter is described as:\n\t%v",
*dbParam.ParameterName, *dbParam.Description)
rangeSplit := strings.Split(*dbParam.AllowedValues, "-")
lower, _ := strconv.Atoi(rangeSplit[0])
upper, _ := strconv.Atoi(rangeSplit[1])
newValue := scenario.questioner.AskInt(
fmt.Sprintf("Enter a value between %v and %v:", lower, upper),
demotools.InIntRange{Lower: lower, Upper: upper})
dbParam.ParameterValue = aws.String(strconv.Itoa(newValue))
updateParams = append(updateParams, dbParam)
}
}
err = scenario.instances.UpdateParameters(parameterGroupName, updateParams)
if err != nil {
panic(err)
}
log.Println("To get a list of parameters that you set previously, specify a source
of 'user'.")
userParameters, err := scenario.instances.GetParameters(parameterGroupName, "user")
if err != nil {
panic(err)
}
log.Println("Here are the parameters you set:")
for _, param := range userParameters {
log.Printf("\t%v: %v\n", *param.ParameterName, *param.ParameterValue)
}
log.Println(strings.Repeat("-", 88))
}
// CreateInstance shows how to create a DB instance that contains a database of a
// specified type. The database is also configured to use a custom DB parameter
group.
func (scenario GetStartedInstances) CreateInstance(instanceName string, dbEngine
string,
dbName string, parameterGroup *types.DBParameterGroup) *types.DBInstance {
log.Println("Checking for an existing DB instance.")
instance, err := scenario.instances.GetInstance(instanceName)
if err != nil {
panic(err)
}
if instance == nil {
adminUsername := scenario.questioner.Ask(
Basics 362
AWS SDK for Go Code Examples Code Examples Guide
"Enter an administrator username for the database: ", demotools.NotEmpty{})
adminPassword := scenario.questioner.AskPassword(
"Enter a password for the administrator (at least 8 characters): ", 7)
engineVersions, err := scenario.instances.GetEngineVersions(dbEngine,
*parameterGroup.DBParameterGroupFamily)
if err != nil {
panic(err)
}
var engineChoices []string
for _, engine := range engineVersions {
engineChoices = append(engineChoices, *engine.EngineVersion)
}
engineIndex := scenario.questioner.AskChoice(
"The available engines for your parameter group are:\n", engineChoices)
engineSelection := engineVersions[engineIndex]
instOpts, err := scenario.instances.GetOrderableInstances(*engineSelection.Engine,
*engineSelection.EngineVersion)
if err != nil {
panic(err)
}
optSet := map[string]struct{}{}
for _, opt := range instOpts {
if strings.Contains(*opt.DBInstanceClass, "micro") {
optSet[*opt.DBInstanceClass] = struct{}{}
}
}
var optChoices []string
for opt := range optSet {
optChoices = append(optChoices, opt)
}
sort.Strings(optChoices)
optIndex := scenario.questioner.AskChoice(
"The available micro DB instance classes for your database engine are:\n",
optChoices)
storageType := "standard"
allocatedStorage := int32(5)
log.Printf("Creating a DB instance named %v and database %v.\n"+
"The DB instance is configured to use your custom parameter group %v,\n"+
"selected engine %v,\n"+
"selected DB instance class %v,"+
"and %v GiB of %v storage.\n"+
"This typically takes several minutes.",
instanceName, dbName, *parameterGroup.DBParameterGroupName,
*engineSelection.EngineVersion,
Basics 363
AWS SDK for Go Code Examples Code Examples Guide
optChoices[optIndex], allocatedStorage, storageType)
instance, err = scenario.instances.CreateInstance(
instanceName, dbName, *engineSelection.Engine, *engineSelection.EngineVersion,
*parameterGroup.DBParameterGroupName, optChoices[optIndex], storageType,
allocatedStorage, adminUsername, adminPassword)
if err != nil {
panic(err)
}
for *instance.DBInstanceStatus != "available" {
scenario.helper.Pause(30)
instance, err = scenario.instances.GetInstance(instanceName)
if err != nil {
panic(err)
}
}
log.Println("Instance created and available.")
}
log.Println("Instance data:")
log.Printf("\tDBInstanceIdentifier: %v\n", *instance.DBInstanceIdentifier)
log.Printf("\tARN: %v\n", *instance.DBInstanceArn)
log.Printf("\tStatus: %v\n", *instance.DBInstanceStatus)
log.Printf("\tEngine: %v\n", *instance.Engine)
log.Printf("\tEngine version: %v\n", *instance.EngineVersion)
log.Println(strings.Repeat("-", 88))
return instance
}
// DisplayConnection displays connection information about a DB instance and tips
// on how to connect to it.
func (scenario GetStartedInstances) DisplayConnection(instance *types.DBInstance) {
log.Println(
"You can now connect to your database by using your favorite MySQL client.\n" +
"One way to connect is by using the 'mysql' shell on an Amazon EC2 instance\n" +
"that is running in the same VPC as your DB instance. Pass the endpoint,\n" +
"port, and administrator username to 'mysql'. Then, enter your password\n" +
"when prompted:")
log.Printf("\n\tmysql -h %v -P %v -u %v -p\n",
*instance.Endpoint.Address, instance.Endpoint.Port, *instance.MasterUsername)
log.Println("For more information, see the User Guide for RDS:\n" +
"\thttps://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/
CHAP_GettingStarted.CreatingConnecting.MySQL.html#CHAP_GettingStarted.Connecting.MySQL")
log.Println(strings.Repeat("-", 88))
}
Basics 364
AWS SDK for Go Code Examples Code Examples Guide
// CreateSnapshot shows how to create a DB instance snapshot and wait until it's
available.
func (scenario GetStartedInstances) CreateSnapshot(instance *types.DBInstance) {
if scenario.questioner.AskBool(
"Do you want to create a snapshot of your DB instance (y/n)? ", "y") {
snapshotId := fmt.Sprintf("%v-%v", *instance.DBInstanceIdentifier,
scenario.helper.UniqueId())
log.Printf("Creating a snapshot named %v. This typically takes a few minutes.\n",
snapshotId)
snapshot, err := scenario.instances.CreateSnapshot(*instance.DBInstanceIdentifier,
snapshotId)
if err != nil {
panic(err)
}
for *snapshot.Status != "available" {
scenario.helper.Pause(30)
snapshot, err = scenario.instances.GetSnapshot(snapshotId)
if err != nil {
panic(err)
}
}
log.Println("Snapshot data:")
log.Printf("\tDBSnapshotIdentifier: %v\n", *snapshot.DBSnapshotIdentifier)
log.Printf("\tARN: %v\n", *snapshot.DBSnapshotArn)
log.Printf("\tStatus: %v\n", *snapshot.Status)
log.Printf("\tEngine: %v\n", *snapshot.Engine)
log.Printf("\tEngine version: %v\n", *snapshot.EngineVersion)
log.Printf("\tDBInstanceIdentifier: %v\n", *snapshot.DBInstanceIdentifier)
log.Printf("\tSnapshotCreateTime: %v\n", *snapshot.SnapshotCreateTime)
log.Println(strings.Repeat("-", 88))
}
}
// Cleanup shows how to clean up a DB instance and DB parameter group.
// Before the DB parameter group can be deleted, all associated DB instances must
first be deleted.
func (scenario GetStartedInstances) Cleanup(
instance *types.DBInstance, parameterGroup *types.DBParameterGroup) {
if scenario.questioner.AskBool(
"\nDo you want to delete the database instance and parameter group (y/n)? ", "y")
{
log.Printf("Deleting database instance %v.\n", *instance.DBInstanceIdentifier)
err := scenario.instances.DeleteInstance(*instance.DBInstanceIdentifier)
Basics 365
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
panic(err)
}
log.Println(
"Waiting for the DB instance to delete. This typically takes several minutes.")
for instance != nil {
scenario.helper.Pause(30)
instance, err = scenario.instances.GetInstance(*instance.DBInstanceIdentifier)
if err != nil {
panic(err)
}
}
log.Printf("Deleting parameter group %v.", *parameterGroup.DBParameterGroupName)
err =
scenario.instances.DeleteParameterGroup(*parameterGroup.DBParameterGroupName)
if err != nil {
panic(err)
}
}
}
Define functions that are called by the scenario to manage Amazon RDS actions.
type DbInstances struct {
RdsClient *rds.Client
}
// GetParameterGroup gets a DB parameter group by name.
func (instances *DbInstances) GetParameterGroup(parameterGroupName string) (
*types.DBParameterGroup, error) {
output, err := instances.RdsClient.DescribeDBParameterGroups(
context.TODO(), &rds.DescribeDBParameterGroupsInput{
DBParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
var notFoundError *types.DBParameterGroupNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("Parameter group %v does not exist.\n", parameterGroupName)
err = nil
Basics 366
AWS SDK for Go Code Examples Code Examples Guide
} else {
log.Printf("Error getting parameter group %v: %v\n", parameterGroupName, err)
}
return nil, err
} else {
return &output.DBParameterGroups[0], err
}
}
// CreateParameterGroup creates a DB parameter group that is based on the specified
// parameter group family.
func (instances *DbInstances) CreateParameterGroup(
parameterGroupName string, parameterGroupFamily string, description string) (
*types.DBParameterGroup, error) {
output, err := instances.RdsClient.CreateDBParameterGroup(context.TODO(),
&rds.CreateDBParameterGroupInput{
DBParameterGroupName: aws.String(parameterGroupName),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
Description: aws.String(description),
})
if err != nil {
log.Printf("Couldn't create parameter group %v: %v\n", parameterGroupName, err)
return nil, err
} else {
return output.DBParameterGroup, err
}
}
// DeleteParameterGroup deletes the named DB parameter group.
func (instances *DbInstances) DeleteParameterGroup(parameterGroupName string) error
{
_, err := instances.RdsClient.DeleteDBParameterGroup(context.TODO(),
&rds.DeleteDBParameterGroupInput{
DBParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
log.Printf("Couldn't delete parameter group %v: %v\n", parameterGroupName, err)
return err
} else {
Basics 367
AWS SDK for Go Code Examples Code Examples Guide
return nil
}
}
// GetParameters gets the parameters that are contained in a DB parameter group.
func (instances *DbInstances) GetParameters(parameterGroupName string, source
string) (
[]types.Parameter, error) {
var output *rds.DescribeDBParametersOutput
var params []types.Parameter
var err error
parameterPaginator := rds.NewDescribeDBParametersPaginator(instances.RdsClient,
&rds.DescribeDBParametersInput{
DBParameterGroupName: aws.String(parameterGroupName),
Source: aws.String(source),
})
for parameterPaginator.HasMorePages() {
output, err = parameterPaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get parameters for %v: %v\n", parameterGroupName, err)
break
} else {
params = append(params, output.Parameters...)
}
}
return params, err
}
// UpdateParameters updates parameters in a named DB parameter group.
func (instances *DbInstances) UpdateParameters(parameterGroupName string, params
[]types.Parameter) error {
_, err := instances.RdsClient.ModifyDBParameterGroup(context.TODO(),
&rds.ModifyDBParameterGroupInput{
DBParameterGroupName: aws.String(parameterGroupName),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't update parameters in %v: %v\n", parameterGroupName, err)
return err
Basics 368
AWS SDK for Go Code Examples Code Examples Guide
} else {
return nil
}
}
// CreateSnapshot creates a snapshot of a DB instance.
func (instances *DbInstances) CreateSnapshot(instanceName string, snapshotName
string) (
*types.DBSnapshot, error) {
output, err := instances.RdsClient.CreateDBSnapshot(context.TODO(),
&rds.CreateDBSnapshotInput{
DBInstanceIdentifier: aws.String(instanceName),
DBSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't create snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return output.DBSnapshot, nil
}
}
// GetSnapshot gets a DB instance snapshot.
func (instances *DbInstances) GetSnapshot(snapshotName string) (*types.DBSnapshot,
error) {
output, err := instances.RdsClient.DescribeDBSnapshots(context.TODO(),
&rds.DescribeDBSnapshotsInput{
DBSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't get snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return &output.DBSnapshots[0], nil
}
}
// CreateInstance creates a DB instance.
Basics 369
AWS SDK for Go Code Examples Code Examples Guide
func (instances *DbInstances) CreateInstance(instanceName string, dbName string,
dbEngine string, dbEngineVersion string, parameterGroupName string, dbInstanceClass
string,
storageType string, allocatedStorage int32, adminName string, adminPassword string)
(
*types.DBInstance, error) {
output, err := instances.RdsClient.CreateDBInstance(context.TODO(),
&rds.CreateDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
DBName: aws.String(dbName),
DBParameterGroupName: aws.String(parameterGroupName),
Engine: aws.String(dbEngine),
EngineVersion: aws.String(dbEngineVersion),
DBInstanceClass: aws.String(dbInstanceClass),
StorageType: aws.String(storageType),
AllocatedStorage: aws.Int32(allocatedStorage),
MasterUsername: aws.String(adminName),
MasterUserPassword: aws.String(adminPassword),
})
if err != nil {
log.Printf("Couldn't create instance %v: %v\n", instanceName, err)
return nil, err
} else {
return output.DBInstance, nil
}
}
// GetInstance gets data about a DB instance.
func (instances *DbInstances) GetInstance(instanceName string) (
*types.DBInstance, error) {
output, err := instances.RdsClient.DescribeDBInstances(context.TODO(),
&rds.DescribeDBInstancesInput{
DBInstanceIdentifier: aws.String(instanceName),
})
if err != nil {
var notFoundError *types.DBInstanceNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("DB instance %v does not exist.\n", instanceName)
err = nil
} else {
log.Printf("Couldn't get instance %v: %v\n", instanceName, err)
}
Basics 370
AWS SDK for Go Code Examples Code Examples Guide
return nil, err
} else {
return &output.DBInstances[0], nil
}
}
// DeleteInstance deletes a DB instance.
func (instances *DbInstances) DeleteInstance(instanceName string) error {
_, err := instances.RdsClient.DeleteDBInstance(context.TODO(),
&rds.DeleteDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
SkipFinalSnapshot: true,
DeleteAutomatedBackups: aws.Bool(true),
})
if err != nil {
log.Printf("Couldn't delete instance %v: %v\n", instanceName, err)
return err
} else {
return nil
}
}
// GetEngineVersions gets database engine versions that are available for the
specified engine
// and parameter group family.
func (instances *DbInstances) GetEngineVersions(engine string, parameterGroupFamily
string) (
[]types.DBEngineVersion, error) {
output, err := instances.RdsClient.DescribeDBEngineVersions(context.TODO(),
&rds.DescribeDBEngineVersionsInput{
Engine: aws.String(engine),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
})
if err != nil {
log.Printf("Couldn't get engine versions for %v: %v\n", engine, err)
return nil, err
} else {
return output.DBEngineVersions, nil
}
}
Basics 371
AWS SDK for Go Code Examples Code Examples Guide
// GetOrderableInstances uses a paginator to get DB instance options that can be
used to create DB instances that are
// compatible with a set of specifications.
func (instances *DbInstances) GetOrderableInstances(engine string, engineVersion
string) (
[]types.OrderableDBInstanceOption, error) {
var output *rds.DescribeOrderableDBInstanceOptionsOutput
var instanceOptions []types.OrderableDBInstanceOption
var err error
orderablePaginator :=
rds.NewDescribeOrderableDBInstanceOptionsPaginator(instances.RdsClient,
&rds.DescribeOrderableDBInstanceOptionsInput{
Engine: aws.String(engine),
EngineVersion: aws.String(engineVersion),
})
for orderablePaginator.HasMorePages() {
output, err = orderablePaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get orderable DB instance options: %v\n", err)
break
} else {
instanceOptions = append(instanceOptions, output.OrderableDBInstanceOptions...)
}
}
return instanceOptions, err
}
For API details, see the following topics in AWS SDK for Go API Reference.
CreateDBInstance
CreateDBParameterGroup
CreateDBSnapshot
DeleteDBInstance
DeleteDBParameterGroup
DescribeDBEngineVersions
Basics 372
AWS SDK for Go Code Examples Code Examples Guide
DescribeDBInstances
DescribeDBParameterGroups
DescribeDBParameters
DescribeDBSnapshots
DescribeOrderableDBInstanceOptions
ModifyDBParameterGroup
Actions
CreateDBInstance
The following code example shows how to use CreateDBInstance.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// CreateInstance creates a DB instance.
func (instances *DbInstances) CreateInstance(instanceName string, dbName string,
dbEngine string, dbEngineVersion string, parameterGroupName string, dbInstanceClass
string,
storageType string, allocatedStorage int32, adminName string, adminPassword string)
(
*types.DBInstance, error) {
output, err := instances.RdsClient.CreateDBInstance(context.TODO(),
&rds.CreateDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
DBName: aws.String(dbName),
Actions 373
AWS SDK for Go Code Examples Code Examples Guide
DBParameterGroupName: aws.String(parameterGroupName),
Engine: aws.String(dbEngine),
EngineVersion: aws.String(dbEngineVersion),
DBInstanceClass: aws.String(dbInstanceClass),
StorageType: aws.String(storageType),
AllocatedStorage: aws.Int32(allocatedStorage),
MasterUsername: aws.String(adminName),
MasterUserPassword: aws.String(adminPassword),
})
if err != nil {
log.Printf("Couldn't create instance %v: %v\n", instanceName, err)
return nil, err
} else {
return output.DBInstance, nil
}
}
For API details, see CreateDBInstance in AWS SDK for Go API Reference.
CreateDBParameterGroup
The following code example shows how to use CreateDBParameterGroup.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// CreateParameterGroup creates a DB parameter group that is based on the specified
Actions 374
AWS SDK for Go Code Examples Code Examples Guide
// parameter group family.
func (instances *DbInstances) CreateParameterGroup(
parameterGroupName string, parameterGroupFamily string, description string) (
*types.DBParameterGroup, error) {
output, err := instances.RdsClient.CreateDBParameterGroup(context.TODO(),
&rds.CreateDBParameterGroupInput{
DBParameterGroupName: aws.String(parameterGroupName),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
Description: aws.String(description),
})
if err != nil {
log.Printf("Couldn't create parameter group %v: %v\n", parameterGroupName, err)
return nil, err
} else {
return output.DBParameterGroup, err
}
}
For API details, see CreateDBParameterGroup in AWS SDK for Go API Reference.
CreateDBSnapshot
The following code example shows how to use CreateDBSnapshot.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
Actions 375
AWS SDK for Go Code Examples Code Examples Guide
// CreateSnapshot creates a snapshot of a DB instance.
func (instances *DbInstances) CreateSnapshot(instanceName string, snapshotName
string) (
*types.DBSnapshot, error) {
output, err := instances.RdsClient.CreateDBSnapshot(context.TODO(),
&rds.CreateDBSnapshotInput{
DBInstanceIdentifier: aws.String(instanceName),
DBSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't create snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return output.DBSnapshot, nil
}
}
For API details, see CreateDBSnapshot in AWS SDK for Go API Reference.
DeleteDBInstance
The following code example shows how to use DeleteDBInstance.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
Actions 376
AWS SDK for Go Code Examples Code Examples Guide
// DeleteInstance deletes a DB instance.
func (instances *DbInstances) DeleteInstance(instanceName string) error {
_, err := instances.RdsClient.DeleteDBInstance(context.TODO(),
&rds.DeleteDBInstanceInput{
DBInstanceIdentifier: aws.String(instanceName),
SkipFinalSnapshot: true,
DeleteAutomatedBackups: aws.Bool(true),
})
if err != nil {
log.Printf("Couldn't delete instance %v: %v\n", instanceName, err)
return err
} else {
return nil
}
}
For API details, see DeleteDBInstance in AWS SDK for Go API Reference.
DeleteDBParameterGroup
The following code example shows how to use DeleteDBParameterGroup.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// DeleteParameterGroup deletes the named DB parameter group.
func (instances *DbInstances) DeleteParameterGroup(parameterGroupName string) error
{
Actions 377
AWS SDK for Go Code Examples Code Examples Guide
_, err := instances.RdsClient.DeleteDBParameterGroup(context.TODO(),
&rds.DeleteDBParameterGroupInput{
DBParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
log.Printf("Couldn't delete parameter group %v: %v\n", parameterGroupName, err)
return err
} else {
return nil
}
}
For API details, see DeleteDBParameterGroup in AWS SDK for Go API Reference.
DescribeDBEngineVersions
The following code example shows how to use DescribeDBEngineVersions.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// GetEngineVersions gets database engine versions that are available for the
specified engine
// and parameter group family.
func (instances *DbInstances) GetEngineVersions(engine string, parameterGroupFamily
string) (
[]types.DBEngineVersion, error) {
output, err := instances.RdsClient.DescribeDBEngineVersions(context.TODO(),
Actions 378
AWS SDK for Go Code Examples Code Examples Guide
&rds.DescribeDBEngineVersionsInput{
Engine: aws.String(engine),
DBParameterGroupFamily: aws.String(parameterGroupFamily),
})
if err != nil {
log.Printf("Couldn't get engine versions for %v: %v\n", engine, err)
return nil, err
} else {
return output.DBEngineVersions, nil
}
}
For API details, see DescribeDBEngineVersions in AWS SDK for Go API Reference.
DescribeDBInstances
The following code example shows how to use DescribeDBInstances.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// GetInstance gets data about a DB instance.
func (instances *DbInstances) GetInstance(instanceName string) (
*types.DBInstance, error) {
output, err := instances.RdsClient.DescribeDBInstances(context.TODO(),
&rds.DescribeDBInstancesInput{
DBInstanceIdentifier: aws.String(instanceName),
})
Actions 379
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
var notFoundError *types.DBInstanceNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("DB instance %v does not exist.\n", instanceName)
err = nil
} else {
log.Printf("Couldn't get instance %v: %v\n", instanceName, err)
}
return nil, err
} else {
return &output.DBInstances[0], nil
}
}
For API details, see DescribeDBInstances in AWS SDK for Go API Reference.
DescribeDBParameterGroups
The following code example shows how to use DescribeDBParameterGroups.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// GetParameterGroup gets a DB parameter group by name.
func (instances *DbInstances) GetParameterGroup(parameterGroupName string) (
*types.DBParameterGroup, error) {
output, err := instances.RdsClient.DescribeDBParameterGroups(
context.TODO(), &rds.DescribeDBParameterGroupsInput{
Actions 380
AWS SDK for Go Code Examples Code Examples Guide
DBParameterGroupName: aws.String(parameterGroupName),
})
if err != nil {
var notFoundError *types.DBParameterGroupNotFoundFault
if errors.As(err, &notFoundError) {
log.Printf("Parameter group %v does not exist.\n", parameterGroupName)
err = nil
} else {
log.Printf("Error getting parameter group %v: %v\n", parameterGroupName, err)
}
return nil, err
} else {
return &output.DBParameterGroups[0], err
}
}
For API details, see DescribeDBParameterGroups in AWS SDK for Go API Reference.
DescribeDBParameters
The following code example shows how to use DescribeDBParameters.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
// GetParameters gets the parameters that are contained in a DB parameter group.
func (instances *DbInstances) GetParameters(parameterGroupName string, source
string) (
Actions 381
AWS SDK for Go Code Examples Code Examples Guide
[]types.Parameter, error) {
var output *rds.DescribeDBParametersOutput
var params []types.Parameter
var err error
parameterPaginator := rds.NewDescribeDBParametersPaginator(instances.RdsClient,
&rds.DescribeDBParametersInput{
DBParameterGroupName: aws.String(parameterGroupName),
Source: aws.String(source),
})
for parameterPaginator.HasMorePages() {
output, err = parameterPaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get parameters for %v: %v\n", parameterGroupName, err)
break
} else {
params = append(params, output.Parameters...)
}
}
return params, err
}
For API details, see DescribeDBParameters in AWS SDK for Go API Reference.
DescribeDBSnapshots
The following code example shows how to use DescribeDBSnapshots.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
Actions 382
AWS SDK for Go Code Examples Code Examples Guide
}
// GetSnapshot gets a DB instance snapshot.
func (instances *DbInstances) GetSnapshot(snapshotName string) (*types.DBSnapshot,
error) {
output, err := instances.RdsClient.DescribeDBSnapshots(context.TODO(),
&rds.DescribeDBSnapshotsInput{
DBSnapshotIdentifier: aws.String(snapshotName),
})
if err != nil {
log.Printf("Couldn't get snapshot %v: %v\n", snapshotName, err)
return nil, err
} else {
return &output.DBSnapshots[0], nil
}
}
For API details, see DescribeDBSnapshots in AWS SDK for Go API Reference.
DescribeOrderableDBInstanceOptions
The following code example shows how to use DescribeOrderableDBInstanceOptions.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
type DbInstances struct {
RdsClient *rds.Client
}
Actions 383
AWS SDK for Go Code Examples Code Examples Guide
// GetOrderableInstances uses a paginator to get DB instance options that can be
used to create DB instances that are
// compatible with a set of specifications.
func (instances *DbInstances) GetOrderableInstances(engine string, engineVersion
string) (
[]types.OrderableDBInstanceOption, error) {
var output *rds.DescribeOrderableDBInstanceOptionsOutput
var instanceOptions []types.OrderableDBInstanceOption
var err error
orderablePaginator :=
rds.NewDescribeOrderableDBInstanceOptionsPaginator(instances.RdsClient,
&rds.DescribeOrderableDBInstanceOptionsInput{
Engine: aws.String(engine),
EngineVersion: aws.String(engineVersion),
})
for orderablePaginator.HasMorePages() {
output, err = orderablePaginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get orderable DB instance options: %v\n", err)
break
} else {
instanceOptions = append(instanceOptions, output.OrderableDBInstanceOptions...)
}
}
return instanceOptions, err
}
For API details, see DescribeOrderableDBInstanceOptions in AWS SDK for Go API Reference.
ModifyDBParameterGroup
The following code example shows how to use ModifyDBParameterGroup.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Actions 384
AWS SDK for Go Code Examples Code Examples Guide
type DbInstances struct {
RdsClient *rds.Client
}
// UpdateParameters updates parameters in a named DB parameter group.
func (instances *DbInstances) UpdateParameters(parameterGroupName string, params
[]types.Parameter) error {
_, err := instances.RdsClient.ModifyDBParameterGroup(context.TODO(),
&rds.ModifyDBParameterGroupInput{
DBParameterGroupName: aws.String(parameterGroupName),
Parameters: params,
})
if err != nil {
log.Printf("Couldn't update parameters in %v: %v\n", parameterGroupName, err)
return err
} else {
return nil
}
}
For API details, see ModifyDBParameterGroup in AWS SDK for Go API Reference.
Serverless examples
Connecting to an Amazon RDS database in a Lambda function
The following code example shows how to implement a Lambda function that connects to an RDS
database. The function makes a simple database request and returns the result.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Serverless examples 385
AWS SDK for Go Code Examples Code Examples Guide
Connecting to an Amazon RDS database in a Lambda function using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/*
Golang v2 code here.
*/
package main
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"os"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/rds/auth"
_ "github.com/go-sql-driver/mysql"
)
type MyEvent struct {
Name string `json:"name"`
}
func HandleRequest(event *MyEvent) (map[string]interface{}, error) {
var dbName string = os.Getenv("DatabaseName")
var dbUser string = os.Getenv("DatabaseUser")
var dbHost string = os.Getenv("DBHost") // Add hostname without https
var dbPort int = os.Getenv("Port") // Add port number
var dbEndpoint string = fmt.Sprintf("%s:%d", dbHost, dbPort)
var region string = os.Getenv("AWS_REGION")
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic("configuration error: " + err.Error())
}
authenticationToken, err := auth.BuildAuthToken(
context.TODO(), dbEndpoint, region, dbUser, cfg.Credentials)
if err != nil {
Serverless examples 386
AWS SDK for Go Code Examples Code Examples Guide
panic("failed to create authentication token: " + err.Error())
}
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=true&allowCleartextPasswords=true",
dbUser, authenticationToken, dbEndpoint, dbName,
)
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
}
defer db.Close()
var sum int
err = db.QueryRow("SELECT ?+? AS sum", 3, 2).Scan(&sum)
if err != nil {
panic(err)
}
s := fmt.Sprint(sum)
message := fmt.Sprintf("The selected sum is: %s", s)
messageBytes, err := json.Marshal(message)
if err != nil {
return nil, err
}
messageString := string(messageBytes)
return map[string]interface{}{
"statusCode": 200,
"headers": map[string]string{"Content-Type": "application/json"},
"body": messageString,
}, nil
}
func main() {
lambda.Start(HandleRequest)
}
Serverless examples 387
AWS SDK for Go Code Examples Code Examples Guide
Amazon S3 examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon S3.
Basics are code examples that show you how to perform the essential operations within a service.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Amazon S3
The following code examples show how to get started using Amazon S3.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
Amazon S3 388
AWS SDK for Go Code Examples Code Examples Guide
// main uses the AWS SDK for Go V2 to create an Amazon Simple Storage Service
// (Amazon S3) client and list up to 10 buckets in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
s3Client := s3.NewFromConfig(sdkConfig)
count := 10
fmt.Printf("Let's list up to %v buckets for your account.\n", count)
result, err := s3Client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
if err != nil {
fmt.Printf("Couldn't list buckets for your account. Here's why: %v\n", err)
return
}
if len(result.Buckets) == 0 {
fmt.Println("You don't have any buckets!")
} else {
if count > len(result.Buckets) {
count = len(result.Buckets)
}
for _, bucket := range result.Buckets[:count] {
fmt.Printf("\t%v\n", *bucket.Name)
}
}
}
For API details, see ListBuckets in AWS SDK for Go API Reference.
Topics
Basics
Actions
Scenarios
Serverless examples
Amazon S3 389
AWS SDK for Go Code Examples Code Examples Guide
Basics
Learn the basics
The following code example shows how to:
Create a bucket and upload a file to it.
Download an object from a bucket.
Copy an object to a subfolder in a bucket.
List the objects in a bucket.
Delete the bucket objects and the bucket.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Define a struct that wraps bucket and object actions used by the scenario.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// ListBuckets lists the buckets in the current account.
func (basics BucketBasics) ListBuckets() ([]types.Bucket, error) {
result, err := basics.S3Client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
var buckets []types.Bucket
if err != nil {
log.Printf("Couldn't list buckets for your account. Here's why: %v\n", err)
} else {
Basics 390
AWS SDK for Go Code Examples Code Examples Guide
buckets = result.Buckets
}
return buckets, err
}
// BucketExists checks whether a bucket exists in the current account.
func (basics BucketBasics) BucketExists(bucketName string) (bool, error) {
_, err := basics.S3Client.HeadBucket(context.TODO(), &s3.HeadBucketInput{
Bucket: aws.String(bucketName),
})
exists := true
if err != nil {
var apiError smithy.APIError
if errors.As(err, &apiError) {
switch apiError.(type) {
case *types.NotFound:
log.Printf("Bucket %v is available.\n", bucketName)
exists = false
err = nil
default:
log.Printf("Either you don't have access to bucket %v or another error occurred.
"+
"Here's what happened: %v\n", bucketName, err)
}
}
} else {
log.Printf("Bucket %v exists and you already own it.", bucketName)
}
return exists, err
}
// CreateBucket creates a bucket with the specified name in the specified Region.
func (basics BucketBasics) CreateBucket(name string, region string) error {
_, err := basics.S3Client.CreateBucket(context.TODO(), &s3.CreateBucketInput{
Bucket: aws.String(name),
CreateBucketConfiguration: &types.CreateBucketConfiguration{
LocationConstraint: types.BucketLocationConstraint(region),
},
})
Basics 391
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't create bucket %v in Region %v. Here's why: %v\n",
name, region, err)
}
return err
}
// UploadFile reads from a file and puts the data into an object in a bucket.
func (basics BucketBasics) UploadFile(bucketName string, objectKey string, fileName
string) error {
file, err := os.Open(fileName)
if err != nil {
log.Printf("Couldn't open file %v to upload. Here's why: %v\n", fileName, err)
} else {
defer file.Close()
_, err = basics.S3Client.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: file,
})
if err != nil {
log.Printf("Couldn't upload file %v to %v:%v. Here's why: %v\n",
fileName, bucketName, objectKey, err)
}
}
return err
}
// UploadLargeObject uses an upload manager to upload data to an object in a bucket.
// The upload manager breaks large data into parts and uploads the parts
concurrently.
func (basics BucketBasics) UploadLargeObject(bucketName string, objectKey string,
largeObject []byte) error {
largeBuffer := bytes.NewReader(largeObject)
var partMiBs int64 = 10
uploader := manager.NewUploader(basics.S3Client, func(u *manager.Uploader) {
u.PartSize = partMiBs * 1024 * 1024
})
_, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Basics 392
AWS SDK for Go Code Examples Code Examples Guide
Key: aws.String(objectKey),
Body: largeBuffer,
})
if err != nil {
log.Printf("Couldn't upload large object to %v:%v. Here's why: %v\n",
bucketName, objectKey, err)
}
return err
}
// DownloadFile gets an object from a bucket and stores it in a local file.
func (basics BucketBasics) DownloadFile(bucketName string, objectKey string,
fileName string) error {
result, err := basics.S3Client.GetObject(context.TODO(), &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
if err != nil {
log.Printf("Couldn't get object %v:%v. Here's why: %v\n", bucketName, objectKey,
err)
return err
}
defer result.Body.Close()
file, err := os.Create(fileName)
if err != nil {
log.Printf("Couldn't create file %v. Here's why: %v\n", fileName, err)
return err
}
defer file.Close()
body, err := io.ReadAll(result.Body)
if err != nil {
log.Printf("Couldn't read object body from %v. Here's why: %v\n", objectKey, err)
}
_, err = file.Write(body)
return err
}
// DownloadLargeObject uses a download manager to download an object from a bucket.
Basics 393
AWS SDK for Go Code Examples Code Examples Guide
// The download manager gets the data in parts and writes them to a buffer until all
of
// the data has been downloaded.
func (basics BucketBasics) DownloadLargeObject(bucketName string, objectKey string)
([]byte, error) {
var partMiBs int64 = 10
downloader := manager.NewDownloader(basics.S3Client, func(d *manager.Downloader) {
d.PartSize = partMiBs * 1024 * 1024
})
buffer := manager.NewWriteAtBuffer([]byte{})
_, err := downloader.Download(context.TODO(), buffer, &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
if err != nil {
log.Printf("Couldn't download large object from %v:%v. Here's why: %v\n",
bucketName, objectKey, err)
}
return buffer.Bytes(), err
}
// CopyToFolder copies an object in a bucket to a subfolder in the same bucket.
func (basics BucketBasics) CopyToFolder(bucketName string, objectKey string,
folderName string) error {
_, err := basics.S3Client.CopyObject(context.TODO(), &s3.CopyObjectInput{
Bucket: aws.String(bucketName),
CopySource: aws.String(fmt.Sprintf("%v/%v", bucketName, objectKey)),
Key: aws.String(fmt.Sprintf("%v/%v", folderName, objectKey)),
})
if err != nil {
log.Printf("Couldn't copy object from %v:%v to %v:%v/%v. Here's why: %v\n",
bucketName, objectKey, bucketName, folderName, objectKey, err)
}
return err
}
// CopyToBucket copies an object in a bucket to another bucket.
func (basics BucketBasics) CopyToBucket(sourceBucket string, destinationBucket
string, objectKey string) error {
_, err := basics.S3Client.CopyObject(context.TODO(), &s3.CopyObjectInput{
Basics 394
AWS SDK for Go Code Examples Code Examples Guide
Bucket: aws.String(destinationBucket),
CopySource: aws.String(fmt.Sprintf("%v/%v", sourceBucket, objectKey)),
Key: aws.String(objectKey),
})
if err != nil {
log.Printf("Couldn't copy object from %v:%v to %v:%v. Here's why: %v\n",
sourceBucket, objectKey, destinationBucket, objectKey, err)
}
return err
}
// ListObjects lists the objects in a bucket.
func (basics BucketBasics) ListObjects(bucketName string) ([]types.Object, error) {
result, err := basics.S3Client.ListObjectsV2(context.TODO(),
&s3.ListObjectsV2Input{
Bucket: aws.String(bucketName),
})
var contents []types.Object
if err != nil {
log.Printf("Couldn't list objects in bucket %v. Here's why: %v\n", bucketName,
err)
} else {
contents = result.Contents
}
return contents, err
}
// DeleteObjects deletes a list of objects from a bucket.
func (basics BucketBasics) DeleteObjects(bucketName string, objectKeys []string)
error {
var objectIds []types.ObjectIdentifier
for _, key := range objectKeys {
objectIds = append(objectIds, types.ObjectIdentifier{Key: aws.String(key)})
}
output, err := basics.S3Client.DeleteObjects(context.TODO(),
&s3.DeleteObjectsInput{
Bucket: aws.String(bucketName),
Delete: &types.Delete{Objects: objectIds},
})
if err != nil {
Basics 395
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't delete objects from bucket %v. Here's why: %v\n", bucketName,
err)
} else {
log.Printf("Deleted %v objects.\n", len(output.Deleted))
}
return err
}
// DeleteBucket deletes a bucket. The bucket must be empty or an error is returned.
func (basics BucketBasics) DeleteBucket(bucketName string) error {
_, err := basics.S3Client.DeleteBucket(context.TODO(), &s3.DeleteBucketInput{
Bucket: aws.String(bucketName)})
if err != nil {
log.Printf("Couldn't delete bucket %v. Here's why: %v\n", bucketName, err)
}
return err
}
Run an interactive scenario that shows you how work with S3 buckets and objects.
// RunGetStartedScenario is an interactive example that shows you how to use Amazon
// Simple Storage Service (Amazon S3) to create an S3 bucket and use it to store
objects.
//
// 1. Create a bucket.
// 2. Upload a local file to the bucket.
// 3. Upload a large object to the bucket by using an upload manager.
// 4. Download an object to a local file.
// 5. Download a large object by using a download manager.
// 6. Copy an object to a different folder in the bucket.
// 7. List objects in the bucket.
// 8. Delete all objects in the bucket.
// 9. Delete the bucket.
//
// This example creates an Amazon S3 service client from the specified sdkConfig so
that
// you can replace it with a mocked or stubbed config for unit testing.
//
Basics 396
AWS SDK for Go Code Examples Code Examples Guide
// It uses a questioner from the `demotools` package to get input during the
example.
// This package can be found in the ..\..\demotools folder of this repo.
func RunGetStartedScenario(sdkConfig aws.Config, questioner demotools.IQuestioner) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Something went wrong with the demo.\n", r)
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon S3 getting started demo.")
log.Println(strings.Repeat("-", 88))
s3Client := s3.NewFromConfig(sdkConfig)
bucketBasics := actions.BucketBasics{S3Client: s3Client}
count := 10
log.Printf("Let's list up to %v buckets for your account:", count)
buckets, err := bucketBasics.ListBuckets()
if err != nil {
panic(err)
}
if len(buckets) == 0 {
log.Println("You don't have any buckets!")
} else {
if count > len(buckets) {
count = len(buckets)
}
for _, bucket := range buckets[:count] {
log.Printf("\t%v\n", *bucket.Name)
}
}
bucketName := questioner.Ask("Let's create a bucket. Enter a name for your
bucket:",
demotools.NotEmpty{})
bucketExists, err := bucketBasics.BucketExists(bucketName)
if err != nil {
panic(err)
}
if !bucketExists {
err = bucketBasics.CreateBucket(bucketName, sdkConfig.Region)
if err != nil {
Basics 397
AWS SDK for Go Code Examples Code Examples Guide
panic(err)
} else {
log.Println("Bucket created.")
}
}
log.Println(strings.Repeat("-", 88))
fmt.Println("Let's upload a file to your bucket.")
smallFile := questioner.Ask("Enter the path to a file you want to upload:",
demotools.NotEmpty{})
const smallKey = "doc-example-key"
err = bucketBasics.UploadFile(bucketName, smallKey, smallFile)
if err != nil {
panic(err)
}
log.Printf("Uploaded %v as %v.\n", smallFile, smallKey)
log.Println(strings.Repeat("-", 88))
mibs := 30
log.Printf("Let's create a slice of %v MiB of random bytes and upload it to your
bucket. ", mibs)
questioner.Ask("Press Enter when you're ready.")
largeBytes := make([]byte, 1024*1024*mibs)
rand.Seed(time.Now().Unix())
rand.Read(largeBytes)
largeKey := "doc-example-large"
log.Println("Uploading...")
err = bucketBasics.UploadLargeObject(bucketName, largeKey, largeBytes)
if err != nil {
panic(err)
}
log.Printf("Uploaded %v MiB object as %v", mibs, largeKey)
log.Println(strings.Repeat("-", 88))
log.Printf("Let's download %v to a file.", smallKey)
downloadFileName := questioner.Ask("Enter a name for the downloaded file:",
demotools.NotEmpty{})
err = bucketBasics.DownloadFile(bucketName, smallKey, downloadFileName)
if err != nil {
panic(err)
}
log.Printf("File %v downloaded.", downloadFileName)
log.Println(strings.Repeat("-", 88))
Basics 398
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Let's download the %v MiB object.", mibs)
questioner.Ask("Press Enter when you're ready.")
log.Println("Downloading...")
largeDownload, err := bucketBasics.DownloadLargeObject(bucketName, largeKey)
if err != nil {
panic(err)
}
log.Printf("Downloaded %v bytes.", len(largeDownload))
log.Println(strings.Repeat("-", 88))
log.Printf("Let's copy %v to a folder in the same bucket.", smallKey)
folderName := questioner.Ask("Enter a folder name: ", demotools.NotEmpty{})
err = bucketBasics.CopyToFolder(bucketName, smallKey, folderName)
if err != nil {
panic(err)
}
log.Printf("Copied %v to %v/%v.\n", smallKey, folderName, smallKey)
log.Println(strings.Repeat("-", 88))
log.Println("Let's list the objects in your bucket.")
questioner.Ask("Press Enter when you're ready.")
objects, err := bucketBasics.ListObjects(bucketName)
if err != nil {
panic(err)
}
log.Printf("Found %v objects.\n", len(objects))
var objKeys []string
for _, object := range objects {
objKeys = append(objKeys, *object.Key)
log.Printf("\t%v\n", *object.Key)
}
log.Println(strings.Repeat("-", 88))
if questioner.AskBool("Do you want to delete your bucket and all of its "+
"contents? (y/n)", "y") {
log.Println("Deleting objects.")
err = bucketBasics.DeleteObjects(bucketName, objKeys)
if err != nil {
panic(err)
}
log.Println("Deleting bucket.")
err = bucketBasics.DeleteBucket(bucketName)
if err != nil {
panic(err)
Basics 399
AWS SDK for Go Code Examples Code Examples Guide
}
log.Printf("Deleting downloaded file %v.\n", downloadFileName)
err = os.Remove(downloadFileName)
if err != nil {
panic(err)
}
} else {
log.Println("Okay. Don't forget to delete objects from your bucket to avoid
charges.")
}
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
For API details, see the following topics in AWS SDK for Go API Reference.
CopyObject
CreateBucket
DeleteBucket
DeleteObjects
GetObject
ListObjectsV2
PutObject
Actions
CopyObject
The following code example shows how to use CopyObject.
Actions 400
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// CopyToBucket copies an object in a bucket to another bucket.
func (basics BucketBasics) CopyToBucket(sourceBucket string, destinationBucket
string, objectKey string) error {
_, err := basics.S3Client.CopyObject(context.TODO(), &s3.CopyObjectInput{
Bucket: aws.String(destinationBucket),
CopySource: aws.String(fmt.Sprintf("%v/%v", sourceBucket, objectKey)),
Key: aws.String(objectKey),
})
if err != nil {
log.Printf("Couldn't copy object from %v:%v to %v:%v. Here's why: %v\n",
sourceBucket, objectKey, destinationBucket, objectKey, err)
}
return err
}
For API details, see CopyObject in AWS SDK for Go API Reference.
CreateBucket
The following code example shows how to use CreateBucket.
Actions 401
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Create a bucket with default configuration.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// CreateBucket creates a bucket with the specified name in the specified Region.
func (basics BucketBasics) CreateBucket(name string, region string) error {
_, err := basics.S3Client.CreateBucket(context.TODO(), &s3.CreateBucketInput{
Bucket: aws.String(name),
CreateBucketConfiguration: &types.CreateBucketConfiguration{
LocationConstraint: types.BucketLocationConstraint(region),
},
})
if err != nil {
log.Printf("Couldn't create bucket %v in Region %v. Here's why: %v\n",
name, region, err)
}
return err
}
Create a bucket with object locking and wait for it to exist.
// S3Actions wraps S3 service actions.
Actions 402
AWS SDK for Go Code Examples Code Examples Guide
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// CreateBucketWithLock creates a new S3 bucket with optional object locking enabled
// and waits for the bucket to exist before returning.
func (actor S3Actions) CreateBucketWithLock(ctx context.Context, bucket string,
region string, enableObjectLock bool) (string, error) {
input := &s3.CreateBucketInput{
Bucket: aws.String(bucket),
CreateBucketConfiguration: &types.CreateBucketConfiguration{
LocationConstraint: types.BucketLocationConstraint(region),
},
}
if enableObjectLock {
input.ObjectLockEnabledForBucket = aws.Bool(true)
}
_, err := actor.S3Client.CreateBucket(ctx, input)
if err != nil {
var owned *types.BucketAlreadyOwnedByYou
var exists *types.BucketAlreadyExists
if errors.As(err, &owned) {
log.Printf("You already own bucket %s.\n", bucket)
err = owned
} else if errors.As(err, &exists) {
log.Printf("Bucket %s already exists.\n", bucket)
err = exists
}
} else {
err = s3.NewBucketExistsWaiter(actor.S3Client).Wait(
ctx, &s3.HeadBucketInput{Bucket: aws.String(bucket)}, time.Minute)
if err != nil {
log.Printf("Failed attempt to wait for bucket %s to exist.\n", bucket)
}
}
return bucket, err
}
Actions 403
AWS SDK for Go Code Examples Code Examples Guide
For API details, see CreateBucket in AWS SDK for Go API Reference.
DeleteBucket
The following code example shows how to use DeleteBucket.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// DeleteBucket deletes a bucket. The bucket must be empty or an error is returned.
func (basics BucketBasics) DeleteBucket(bucketName string) error {
_, err := basics.S3Client.DeleteBucket(context.TODO(), &s3.DeleteBucketInput{
Bucket: aws.String(bucketName)})
if err != nil {
log.Printf("Couldn't delete bucket %v. Here's why: %v\n", bucketName, err)
}
return err
}
For API details, see DeleteBucket in AWS SDK for Go API Reference.
Actions 404
AWS SDK for Go Code Examples Code Examples Guide
DeleteObject
The following code example shows how to use DeleteObject.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// DeleteObject deletes an object from a bucket.
func (actor S3Actions) DeleteObject(ctx context.Context, bucket string, key string,
versionId string, bypassGovernance bool) (bool, error) {
deleted := false
input := &s3.DeleteObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}
if versionId != "" {
input.VersionId = aws.String(versionId)
}
if bypassGovernance {
input.BypassGovernanceRetention = aws.Bool(true)
}
_, err := actor.S3Client.DeleteObject(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
var apiErr *smithy.GenericAPIError
if errors.As(err, &noKey) {
log.Printf("Object %s does not exist in %s.\n", key, bucket)
err = noKey
} else if errors.As(err, &apiErr) {
Actions 405
AWS SDK for Go Code Examples Code Examples Guide
switch apiErr.ErrorCode() {
case "AccessDenied":
log.Printf("Access denied: cannot delete object %s from %s.\n", key, bucket)
err = nil
case "InvalidArgument":
if bypassGovernance {
log.Printf("You cannot specify bypass governance on a bucket without lock
enabled.")
err = nil
}
}
}
} else {
deleted = true
}
return deleted, err
}
For API details, see DeleteObject in AWS SDK for Go API Reference.
DeleteObjects
The following code example shows how to use DeleteObjects.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
Actions 406
AWS SDK for Go Code Examples Code Examples Guide
// DeleteObjects deletes a list of objects from a bucket.
func (actor S3Actions) DeleteObjects(ctx context.Context, bucket string, objects
[]types.ObjectIdentifier, bypassGovernance bool) error {
if len(objects) == 0 {
return nil
}
input := s3.DeleteObjectsInput{
Bucket: aws.String(bucket),
Delete: &types.Delete{
Objects: objects,
Quiet: aws.Bool(true),
},
}
if bypassGovernance {
input.BypassGovernanceRetention = aws.Bool(true)
}
delOut, err := actor.S3Client.DeleteObjects(ctx, &input)
if err != nil || len(delOut.Errors) > 0 {
log.Printf("Error deleting objects from bucket %s.\n", bucket)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
} else if len(delOut.Errors) > 0 {
for _, outErr := range delOut.Errors {
log.Printf("%s: %s\n", *outErr.Key, *outErr.Message)
}
err = fmt.Errorf("%s", *delOut.Errors[0].Message)
}
}
return err
}
For API details, see DeleteObjects in AWS SDK for Go API Reference.
Actions 407
AWS SDK for Go Code Examples Code Examples Guide
GetObject
The following code example shows how to use GetObject.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// DownloadFile gets an object from a bucket and stores it in a local file.
func (basics BucketBasics) DownloadFile(bucketName string, objectKey string,
fileName string) error {
result, err := basics.S3Client.GetObject(context.TODO(), &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
if err != nil {
log.Printf("Couldn't get object %v:%v. Here's why: %v\n", bucketName, objectKey,
err)
return err
}
defer result.Body.Close()
file, err := os.Create(fileName)
if err != nil {
log.Printf("Couldn't create file %v. Here's why: %v\n", fileName, err)
return err
}
defer file.Close()
body, err := io.ReadAll(result.Body)
Actions 408
AWS SDK for Go Code Examples Code Examples Guide
if err != nil {
log.Printf("Couldn't read object body from %v. Here's why: %v\n", objectKey, err)
}
_, err = file.Write(body)
return err
}
For API details, see GetObject in AWS SDK for Go API Reference.
GetObjectLegalHold
The following code example shows how to use GetObjectLegalHold.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// GetObjectLegalHold retrieves the legal hold status for an S3 object.
func (actor S3Actions) GetObjectLegalHold(ctx context.Context, bucket string, key
string, versionId string) (*types.ObjectLockLegalHoldStatus, error) {
var status *types.ObjectLockLegalHoldStatus
input := &s3.GetObjectLegalHoldInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
VersionId: aws.String(versionId),
}
Actions 409
AWS SDK for Go Code Examples Code Examples Guide
output, err := actor.S3Client.GetObjectLegalHold(ctx, input)
if err != nil {
var noSuchKeyErr *types.NoSuchKey
var apiErr *smithy.GenericAPIError
if errors.As(err, &noSuchKeyErr) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noSuchKeyErr
} else if errors.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case "NoSuchObjectLockConfiguration":
log.Printf("Object %s does not have an object lock configuration.\n", key)
err = nil
case "InvalidRequest":
log.Printf("Bucket %s does not have an object lock configuration.\n", bucket)
err = nil
}
}
} else {
status = &output.LegalHold.Status
}
return status, err
}
For API details, see GetObjectLegalHold in AWS SDK for Go API Reference.
GetObjectLockConfiguration
The following code example shows how to use GetObjectLockConfiguration.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Actions 410
AWS SDK for Go Code Examples Code Examples Guide
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// GetObjectLockConfiguration retrieves the object lock configuration for an S3
bucket.
func (actor S3Actions) GetObjectLockConfiguration(ctx context.Context, bucket
string) (*types.ObjectLockConfiguration, error) {
var lockConfig *types.ObjectLockConfiguration
input := &s3.GetObjectLockConfigurationInput{
Bucket: aws.String(bucket),
}
output, err := actor.S3Client.GetObjectLockConfiguration(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
var apiErr *smithy.GenericAPIError
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
} else if errors.As(err, &apiErr) && apiErr.ErrorCode() ==
"ObjectLockConfigurationNotFoundError" {
log.Printf("Bucket %s does not have an object lock configuration.\n", bucket)
err = nil
}
} else {
lockConfig = output.ObjectLockConfiguration
}
return lockConfig, err
}
For API details, see GetObjectLockConfiguration in AWS SDK for Go API Reference.
GetObjectRetention
The following code example shows how to use GetObjectRetention.
Actions 411
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// GetObjectRetention retrieves the object retention configuration for an S3 object.
func (actor S3Actions) GetObjectRetention(ctx context.Context, bucket string, key
string) (*types.ObjectLockRetention, error) {
var retention *types.ObjectLockRetention
input := &s3.GetObjectRetentionInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}
output, err := actor.S3Client.GetObjectRetention(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
var apiErr *smithy.GenericAPIError
if errors.As(err, &noKey) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noKey
} else if errors.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case "NoSuchObjectLockConfiguration":
err = nil
case "InvalidRequest":
log.Printf("Bucket %s does not have locking enabled.", bucket)
err = nil
}
}
Actions 412
AWS SDK for Go Code Examples Code Examples Guide
} else {
retention = output.Retention
}
return retention, err
}
For API details, see GetObjectRetention in AWS SDK for Go API Reference.
HeadBucket
The following code example shows how to use HeadBucket.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// BucketExists checks whether a bucket exists in the current account.
func (basics BucketBasics) BucketExists(bucketName string) (bool, error) {
_, err := basics.S3Client.HeadBucket(context.TODO(), &s3.HeadBucketInput{
Bucket: aws.String(bucketName),
})
exists := true
if err != nil {
Actions 413
AWS SDK for Go Code Examples Code Examples Guide
var apiError smithy.APIError
if errors.As(err, &apiError) {
switch apiError.(type) {
case *types.NotFound:
log.Printf("Bucket %v is available.\n", bucketName)
exists = false
err = nil
default:
log.Printf("Either you don't have access to bucket %v or another error occurred.
"+
"Here's what happened: %v\n", bucketName, err)
}
}
} else {
log.Printf("Bucket %v exists and you already own it.", bucketName)
}
return exists, err
}
For API details, see HeadBucket in AWS SDK for Go API Reference.
ListBuckets
The following code example shows how to use ListBuckets.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
Actions 414
AWS SDK for Go Code Examples Code Examples Guide
S3Client *s3.Client
}
// ListBuckets lists the buckets in the current account.
func (basics BucketBasics) ListBuckets() ([]types.Bucket, error) {
result, err := basics.S3Client.ListBuckets(context.TODO(), &s3.ListBucketsInput{})
var buckets []types.Bucket
if err != nil {
log.Printf("Couldn't list buckets for your account. Here's why: %v\n", err)
} else {
buckets = result.Buckets
}
return buckets, err
}
For API details, see ListBuckets in AWS SDK for Go API Reference.
ListObjectVersions
The following code example shows how to use ListObjectVersions.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
Actions 415
AWS SDK for Go Code Examples Code Examples Guide
// ListObjectVersions lists all versions of all objects in a bucket.
func (actor S3Actions) ListObjectVersions(ctx context.Context, bucket string)
([]types.ObjectVersion, error) {
var err error
var output *s3.ListObjectVersionsOutput
var versions []types.ObjectVersion
input := &s3.ListObjectVersionsInput{Bucket: aws.String(bucket)}
versionPaginator := s3.NewListObjectVersionsPaginator(actor.S3Client, input)
for versionPaginator.HasMorePages() {
output, err = versionPaginator.NextPage(ctx)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
break
} else {
versions = append(versions, output.Versions...)
}
}
return versions, err
}
For API details, see ListObjectVersions in AWS SDK for Go API Reference.
ListObjectsV2
The following code example shows how to use ListObjectsV2.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
Actions 416
AWS SDK for Go Code Examples Code Examples Guide
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// ListObjects lists the objects in a bucket.
func (basics BucketBasics) ListObjects(bucketName string) ([]types.Object, error) {
result, err := basics.S3Client.ListObjectsV2(context.TODO(),
&s3.ListObjectsV2Input{
Bucket: aws.String(bucketName),
})
var contents []types.Object
if err != nil {
log.Printf("Couldn't list objects in bucket %v. Here's why: %v\n", bucketName,
err)
} else {
contents = result.Contents
}
return contents, err
}
For API details, see ListObjectsV2 in AWS SDK for Go API Reference.
PutObject
The following code example shows how to use PutObject.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Put an object in a bucket by using the low-level API.
Actions 417
AWS SDK for Go Code Examples Code Examples Guide
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// UploadFile reads from a file and puts the data into an object in a bucket.
func (basics BucketBasics) UploadFile(bucketName string, objectKey string, fileName
string) error {
file, err := os.Open(fileName)
if err != nil {
log.Printf("Couldn't open file %v to upload. Here's why: %v\n", fileName, err)
} else {
defer file.Close()
_, err = basics.S3Client.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: file,
})
if err != nil {
log.Printf("Couldn't upload file %v to %v:%v. Here's why: %v\n",
fileName, bucketName, objectKey, err)
}
}
return err
}
Upload an object to a bucket by using a transfer manager.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
Actions 418
AWS SDK for Go Code Examples Code Examples Guide
// UploadObject uses the S3 upload manager to upload an object to a bucket.
func (actor S3Actions) UploadObject(ctx context.Context, bucket string, key string,
contents string) (string, error) {
var outKey string
input := &s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: bytes.NewReader([]byte(contents)),
ChecksumAlgorithm: types.ChecksumAlgorithmSha256,
}
output, err := actor.S3Manager.Upload(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
} else {
err := s3.NewObjectExistsWaiter(actor.S3Client).Wait(ctx, &s3.HeadObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}, time.Minute)
if err != nil {
log.Printf("Failed attempt to wait for object %s to exist in %s.\n", key, bucket)
} else {
outKey = *output.Key
}
}
return outKey, err
}
For API details, see PutObject in AWS SDK for Go API Reference.
PutObjectLegalHold
The following code example shows how to use PutObjectLegalHold.
Actions 419
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// PutObjectLegalHold sets the legal hold configuration for an S3 object.
func (actor S3Actions) PutObjectLegalHold(ctx context.Context, bucket string, key
string, versionId string, legalHoldStatus types.ObjectLockLegalHoldStatus) error {
input := &s3.PutObjectLegalHoldInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
LegalHold: &types.ObjectLockLegalHold{
Status: legalHoldStatus,
},
}
if versionId != "" {
input.VersionId = aws.String(versionId)
}
_, err := actor.S3Client.PutObjectLegalHold(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
if errors.As(err, &noKey) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noKey
}
}
return err
}
Actions 420
AWS SDK for Go Code Examples Code Examples Guide
For API details, see PutObjectLegalHold in AWS SDK for Go API Reference.
PutObjectLockConfiguration
The following code example shows how to use PutObjectLockConfiguration.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Set the object lock configuration of a bucket.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// EnableObjectLockOnBucket enables object locking on an existing bucket.
func (actor S3Actions) EnableObjectLockOnBucket(ctx context.Context, bucket string)
error {
// Versioning must be enabled on the bucket before object locking is enabled.
verInput := &s3.PutBucketVersioningInput{
Bucket: aws.String(bucket),
VersioningConfiguration: &types.VersioningConfiguration{
MFADelete: types.MFADeleteDisabled,
Status: types.BucketVersioningStatusEnabled,
},
}
_, err := actor.S3Client.PutBucketVersioning(ctx, verInput)
if err != nil {
var noBucket *types.NoSuchBucket
Actions 421
AWS SDK for Go Code Examples Code Examples Guide
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
return err
}
input := &s3.PutObjectLockConfigurationInput{
Bucket: aws.String(bucket),
ObjectLockConfiguration: &types.ObjectLockConfiguration{
ObjectLockEnabled: types.ObjectLockEnabledEnabled,
},
}
_, err = actor.S3Client.PutObjectLockConfiguration(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
}
return err
}
Set the default retention period of a bucket.
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// ModifyDefaultBucketRetention modifies the default retention period of an existing
bucket.
func (actor S3Actions) ModifyDefaultBucketRetention(
ctx context.Context, bucket string, lockMode types.ObjectLockEnabled,
retentionPeriod int32, retentionMode types.ObjectLockRetentionMode) error {
Actions 422
AWS SDK for Go Code Examples Code Examples Guide
input := &s3.PutObjectLockConfigurationInput{
Bucket: aws.String(bucket),
ObjectLockConfiguration: &types.ObjectLockConfiguration{
ObjectLockEnabled: lockMode,
Rule: &types.ObjectLockRule{
DefaultRetention: &types.DefaultRetention{
Days: aws.Int32(retentionPeriod),
Mode: retentionMode,
},
},
},
}
_, err := actor.S3Client.PutObjectLockConfiguration(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
}
return err
}
For API details, see PutObjectLockConfiguration in AWS SDK for Go API Reference.
PutObjectRetention
The following code example shows how to use PutObjectRetention.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Actions 423
AWS SDK for Go Code Examples Code Examples Guide
// S3Actions wraps S3 service actions.
type S3Actions struct {
S3Client *s3.Client
S3Manager *manager.Uploader
}
// PutObjectRetention sets the object retention configuration for an S3 object.
func (actor S3Actions) PutObjectRetention(ctx context.Context, bucket string, key
string, retentionMode types.ObjectLockRetentionMode, retentionPeriodDays int32)
error {
input := &s3.PutObjectRetentionInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Retention: &types.ObjectLockRetention{
Mode: retentionMode,
RetainUntilDate: aws.Time(time.Now().AddDate(0, 0, int(retentionPeriodDays))),
},
BypassGovernanceRetention: aws.Bool(true),
}
_, err := actor.S3Client.PutObjectRetention(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
if errors.As(err, &noKey) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noKey
}
}
return err
}
For API details, see PutObjectRetention in AWS SDK for Go API Reference.
Actions 424
AWS SDK for Go Code Examples Code Examples Guide
Scenarios
Create a presigned URL
The following code example shows how to create a presigned URL for Amazon S3 and upload an
object.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Create functions that wrap S3 presigning actions.
// Presigner encapsulates the Amazon Simple Storage Service (Amazon S3) presign
actions
// used in the examples.
// It contains PresignClient, a client that is used to presign requests to Amazon
S3.
// Presigned requests contain temporary credentials and can be made from any HTTP
client.
type Presigner struct {
PresignClient *s3.PresignClient
}
// GetObject makes a presigned request that can be used to get an object from a
bucket.
// The presigned request is valid for the specified number of seconds.
func (presigner Presigner) GetObject(
bucketName string, objectKey string, lifetimeSecs int64) (*v4.PresignedHTTPRequest,
error) {
request, err := presigner.PresignClient.PresignGetObject(context.TODO(),
&s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
}, func(opts *s3.PresignOptions) {
Scenarios 425
AWS SDK for Go Code Examples Code Examples Guide
opts.Expires = time.Duration(lifetimeSecs * int64(time.Second))
})
if err != nil {
log.Printf("Couldn't get a presigned request to get %v:%v. Here's why: %v\n",
bucketName, objectKey, err)
}
return request, err
}
// PutObject makes a presigned request that can be used to put an object in a
bucket.
// The presigned request is valid for the specified number of seconds.
func (presigner Presigner) PutObject(
bucketName string, objectKey string, lifetimeSecs int64) (*v4.PresignedHTTPRequest,
error) {
request, err := presigner.PresignClient.PresignPutObject(context.TODO(),
&s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
}, func(opts *s3.PresignOptions) {
opts.Expires = time.Duration(lifetimeSecs * int64(time.Second))
})
if err != nil {
log.Printf("Couldn't get a presigned request to put %v:%v. Here's why: %v\n",
bucketName, objectKey, err)
}
return request, err
}
// DeleteObject makes a presigned request that can be used to delete an object from
a bucket.
func (presigner Presigner) DeleteObject(bucketName string, objectKey string)
(*v4.PresignedHTTPRequest, error) {
request, err := presigner.PresignClient.PresignDeleteObject(context.TODO(),
&s3.DeleteObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
if err != nil {
Scenarios 426
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't get a presigned request to delete object %v. Here's why: %v
\n", objectKey, err)
}
return request, err
}
Run an interactive example that generates and uses presigned URLs to upload, download, and
delete an S3 object.
// RunPresigningScenario is an interactive example that shows you how to get
presigned
// HTTP requests that you can use to move data into and out of Amazon Simple Storage
// Service (Amazon S3). The presigned requests contain temporary credentials and can
// be used by an HTTP client.
//
// 1. Get a presigned request to put an object in a bucket.
// 2. Use the net/http package to use the presigned request to upload a local file
to the bucket.
// 3. Get a presigned request to get an object from a bucket.
// 4. Use the net/http package to use the presigned request to download the object
to a local file.
// 5. Get a presigned request to delete an object from a bucket.
// 6. Use the net/http package to use the presigned request to delete the object.
//
// This example creates an Amazon S3 presign client from the specified sdkConfig so
that
// you can replace it with a mocked or stubbed config for unit testing.
//
// It uses a questioner from the `demotools` package to get input during the
example.
// This package can be found in the ..\..\demotools folder of this repo.
//
// It uses an IHttpRequester interface to abstract HTTP requests so they can be
mocked
// during testing.
func RunPresigningScenario(sdkConfig aws.Config, questioner demotools.IQuestioner,
httpRequester IHttpRequester) {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Something went wrong with the demo.")
Scenarios 427
AWS SDK for Go Code Examples Code Examples Guide
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon S3 presigning demo.")
log.Println(strings.Repeat("-", 88))
s3Client := s3.NewFromConfig(sdkConfig)
bucketBasics := actions.BucketBasics{S3Client: s3Client}
presignClient := s3.NewPresignClient(s3Client)
presigner := actions.Presigner{PresignClient: presignClient}
bucketName := questioner.Ask("We'll need a bucket. Enter a name for a bucket "+
"you own or one you want to create:", demotools.NotEmpty{})
bucketExists, err := bucketBasics.BucketExists(bucketName)
if err != nil {
panic(err)
}
if !bucketExists {
err = bucketBasics.CreateBucket(bucketName, sdkConfig.Region)
if err != nil {
panic(err)
} else {
log.Println("Bucket created.")
}
}
log.Println(strings.Repeat("-", 88))
log.Printf("Let's presign a request to upload a file to your bucket.")
uploadFilename := questioner.Ask("Enter the path to a file you want to upload:",
demotools.NotEmpty{})
uploadKey := questioner.Ask("What would you like to name the uploaded object?",
demotools.NotEmpty{})
uploadFile, err := os.Open(uploadFilename)
if err != nil {
panic(err)
}
defer uploadFile.Close()
presignedPutRequest, err := presigner.PutObject(bucketName, uploadKey, 60)
if err != nil {
panic(err)
}
log.Printf("Got a presigned %v request to URL:\n\t%v\n",
presignedPutRequest.Method,
Scenarios 428
AWS SDK for Go Code Examples Code Examples Guide
presignedPutRequest.URL)
log.Println("Using net/http to send the request...")
info, err := uploadFile.Stat()
if err != nil {
panic(err)
}
putResponse, err := httpRequester.Put(presignedPutRequest.URL, info.Size(),
uploadFile)
if err != nil {
panic(err)
}
log.Printf("%v object %v with presigned URL returned %v.",
presignedPutRequest.Method,
uploadKey, putResponse.StatusCode)
log.Println(strings.Repeat("-", 88))
log.Printf("Let's presign a request to download the object.")
questioner.Ask("Press Enter when you're ready.")
presignedGetRequest, err := presigner.GetObject(bucketName, uploadKey, 60)
if err != nil {
panic(err)
}
log.Printf("Got a presigned %v request to URL:\n\t%v\n",
presignedGetRequest.Method,
presignedGetRequest.URL)
log.Println("Using net/http to send the request...")
getResponse, err := httpRequester.Get(presignedGetRequest.URL)
if err != nil {
panic(err)
}
log.Printf("%v object %v with presigned URL returned %v.",
presignedGetRequest.Method,
uploadKey, getResponse.StatusCode)
defer getResponse.Body.Close()
downloadBody, err := io.ReadAll(getResponse.Body)
if err != nil {
panic(err)
}
log.Printf("Downloaded %v bytes. Here are the first 100 of them:\n",
len(downloadBody))
log.Println(strings.Repeat("-", 88))
log.Println(string(downloadBody[:100]))
log.Println(strings.Repeat("-", 88))
Scenarios 429
AWS SDK for Go Code Examples Code Examples Guide
log.Println("Let's presign a request to delete the object.")
questioner.Ask("Press Enter when you're ready.")
presignedDelRequest, err := presigner.DeleteObject(bucketName, uploadKey)
if err != nil {
panic(err)
}
log.Printf("Got a presigned %v request to URL:\n\t%v\n",
presignedDelRequest.Method,
presignedDelRequest.URL)
log.Println("Using net/http to send the request...")
delResponse, err := httpRequester.Delete(presignedDelRequest.URL)
if err != nil {
panic(err)
}
log.Printf("%v object %v with presigned URL returned %v.\n",
presignedDelRequest.Method,
uploadKey, delResponse.StatusCode)
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define an HTTP request wrapper used by the example to make HTTP requests.
// IHttpRequester abstracts HTTP requests into an interface so it can be mocked
during
// unit testing.
type IHttpRequester interface {
Get(url string) (resp *http.Response, err error)
Put(url string, contentLength int64, body io.Reader) (resp *http.Response, err
error)
Delete(url string) (resp *http.Response, err error)
}
// HttpRequester uses the net/http package to make HTTP requests during the
scenario.
type HttpRequester struct{}
func (httpReq HttpRequester) Get(url string) (resp *http.Response, err error) {
Scenarios 430
AWS SDK for Go Code Examples Code Examples Guide
return http.Get(url)
}
func (httpReq HttpRequester) Put(url string, contentLength int64, body io.Reader)
(resp *http.Response, err error) {
putRequest, err := http.NewRequest("PUT", url, body)
if err != nil {
return nil, err
}
putRequest.ContentLength = contentLength
return http.DefaultClient.Do(putRequest)
}
func (httpReq HttpRequester) Delete(url string) (resp *http.Response, err error) {
delRequest, err := http.NewRequest("DELETE", url, nil)
if err != nil {
return nil, err
}
return http.DefaultClient.Do(delRequest)
}
Lock Amazon S3 objects
The following code example shows how to work with S3 object lock features.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario demonstrating Amazon S3 object lock features.
// ObjectLockScenario contains the steps to run the S3 Object Lock workflow.
type ObjectLockScenario struct {
questioner demotools.IQuestioner
resources Resources
s3Actions *actions.S3Actions
sdkConfig aws.Config
Scenarios 431
AWS SDK for Go Code Examples Code Examples Guide
}
// NewObjectLockScenario constructs a new ObjectLockScenario instance.
func NewObjectLockScenario(sdkConfig aws.Config, questioner demotools.IQuestioner)
ObjectLockScenario {
scenario := ObjectLockScenario{
questioner: questioner,
resources: Resources{},
s3Actions: &actions.S3Actions{S3Client: s3.NewFromConfig(sdkConfig)},
sdkConfig: sdkConfig,
}
scenario.s3Actions.S3Manager = manager.NewUploader(scenario.s3Actions.S3Client)
scenario.resources.init(scenario.s3Actions, questioner)
return scenario
}
type nameLocked struct {
name string
locked bool
}
var createInfo = []nameLocked{
{"standard-bucket", false},
{"lock-bucket", true},
{"retention-bucket", false},
}
// CreateBuckets creates the S3 buckets required for the workflow.
func (scenario *ObjectLockScenario) CreateBuckets(ctx context.Context) {
log.Println("Let's create some S3 buckets to use for this workflow.")
success := false
for !success {
prefix := scenario.questioner.Ask(
"This example creates three buckets. Enter a prefix to name your buckets
(remember bucket names must be globally unique):")
for _, info := range createInfo {
bucketName, err := scenario.s3Actions.CreateBucketWithLock(ctx, fmt.Sprintf("%s.
%s", prefix, info.name), scenario.sdkConfig.Region, info.locked)
if err != nil {
switch err.(type) {
case *types.BucketAlreadyExists, *types.BucketAlreadyOwnedByYou:
log.Printf("Couldn't create bucket %s.\n", bucketName)
default:
Scenarios 432
AWS SDK for Go Code Examples Code Examples Guide
panic(err)
}
break
}
scenario.resources.demoBuckets[info.name] = &DemoBucket{
name: bucketName,
objectKeys: []string{},
}
log.Printf("Created bucket %s.\n", bucketName)
}
if len(scenario.resources.demoBuckets) < len(createInfo) {
scenario.resources.deleteBuckets(ctx)
} else {
success = true
}
}
log.Println("S3 buckets created.")
log.Println(strings.Repeat("-", 88))
}
// EnableLockOnBucket enables object locking on an existing bucket.
func (scenario *ObjectLockScenario) EnableLockOnBucket(ctx context.Context) {
log.Println("\nA bucket can be configured to use object locking.")
scenario.questioner.Ask("Press Enter to continue.")
var err error
bucket := scenario.resources.demoBuckets["retention-bucket"]
err = scenario.s3Actions.EnableObjectLockOnBucket(ctx, bucket.name)
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Printf("Couldn't enable object locking on bucket %s.\n", bucket.name)
default:
panic(err)
}
} else {
log.Printf("Object locking enabled on bucket %s.", bucket.name)
}
log.Println(strings.Repeat("-", 88))
}
Scenarios 433
AWS SDK for Go Code Examples Code Examples Guide
// SetDefaultRetentionPolicy sets a default retention governance policy on a bucket.
func (scenario *ObjectLockScenario) SetDefaultRetentionPolicy(ctx context.Context) {
log.Println("\nA bucket can be configured to use object locking with a default
retention period.")
bucket := scenario.resources.demoBuckets["retention-bucket"]
retentionPeriod := scenario.questioner.AskInt("Enter the default retention period
in days: ")
err := scenario.s3Actions.ModifyDefaultBucketRetention(ctx,
bucket.name, types.ObjectLockEnabledEnabled, int32(retentionPeriod),
types.ObjectLockRetentionModeGovernance)
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Printf("Couldn't configure a default retention period on bucket %s.\n",
bucket.name)
default:
panic(err)
}
} else {
log.Printf("Default retention policy set on bucket %s with %d day retention
period.", bucket.name, retentionPeriod)
bucket.retentionEnabled = true
}
log.Println(strings.Repeat("-", 88))
}
// UploadTestObjects uploads test objects to the S3 buckets.
func (scenario *ObjectLockScenario) UploadTestObjects(ctx context.Context) {
log.Println("Uploading test objects to S3 buckets.")
for _, info := range createInfo {
bucket := scenario.resources.demoBuckets[info.name]
for i := 0; i < 2; i++ {
key, err := scenario.s3Actions.UploadObject(ctx, bucket.name,
fmt.Sprintf("example-%d", i),
fmt.Sprintf("Example object content #%d in bucket %s.", i, bucket.name))
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Printf("Couldn't upload %s to bucket %s.\n", key, bucket.name)
default:
panic(err)
Scenarios 434
AWS SDK for Go Code Examples Code Examples Guide
}
} else {
log.Printf("Uploaded %s to bucket %s.\n", key, bucket.name)
bucket.objectKeys = append(bucket.objectKeys, key)
}
}
}
scenario.questioner.Ask("Test objects uploaded. Press Enter to continue.")
log.Println(strings.Repeat("-", 88))
}
// SetObjectLockConfigurations sets object lock configurations on the test objects.
func (scenario *ObjectLockScenario) SetObjectLockConfigurations(ctx context.Context)
{
log.Println("Now let's set object lock configurations on individual objects.")
buckets := []*DemoBucket{scenario.resources.demoBuckets["lock-bucket"],
scenario.resources.demoBuckets["retention-bucket"]}
for _, bucket := range buckets {
for index, objKey := range bucket.objectKeys {
switch index {
case 0:
if scenario.questioner.AskBool(fmt.Sprintf("\nDo you want to add a legal hold to
%s in %s (y/n)? ", objKey, bucket.name), "y") {
err := scenario.s3Actions.PutObjectLegalHold(ctx, bucket.name, objKey, "",
types.ObjectLockLegalHoldStatusOn)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Printf("Couldn't set legal hold on %s.\n", objKey)
default:
panic(err)
}
} else {
log.Printf("Legal hold set on %s.\n", objKey)
}
}
case 1:
q := fmt.Sprintf("\nDo you want to add a 1 day Governance retention period to %s
in %s?\n"+
"Reminder: Only a user with the s3:BypassGovernanceRetention permission is able
to delete this object\n"+
Scenarios 435
AWS SDK for Go Code Examples Code Examples Guide
"or its bucket until the retention period has expired. (y/n) ", objKey,
bucket.name)
if scenario.questioner.AskBool(q, "y") {
err := scenario.s3Actions.PutObjectRetention(ctx, bucket.name, objKey,
types.ObjectLockRetentionModeGovernance, 1)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Printf("Couldn't set retention period on %s in %s.\n", objKey,
bucket.name)
default:
panic(err)
}
} else {
log.Printf("Retention period set to 1 for %s.", objKey)
bucket.retentionEnabled = true
}
}
}
}
}
log.Println(strings.Repeat("-", 88))
}
const (
ListAll = iota
DeleteObject
DeleteRetentionObject
OverwriteObject
ViewRetention
ViewLegalHold
Finish
)
// InteractWithObjects allows the user to interact with the objects and test the
object lock configurations.
func (scenario *ObjectLockScenario) InteractWithObjects(ctx context.Context) {
log.Println("Now you can interact with the objects to explore the object lock
configurations.")
interactiveChoices := []string{
"List all objects and buckets.",
"Attempt to delete an object.",
"Attempt to delete an object with retention period bypass.",
"Attempt to overwrite a file.",
Scenarios 436
AWS SDK for Go Code Examples Code Examples Guide
"View the retention settings for an object.",
"View the legal hold settings for an object.",
"Finish the workflow."}
choice := ListAll
for choice != Finish {
objList := scenario.GetAllObjects(ctx)
objChoices := scenario.makeObjectChoiceList(objList)
choice = scenario.questioner.AskChoice("Choose an action from the menu:\n",
interactiveChoices)
switch choice {
case ListAll:
log.Println("The current objects in the example buckets are:")
for _, objChoice := range objChoices {
log.Println("\t", objChoice)
}
case DeleteObject, DeleteRetentionObject:
objChoice := scenario.questioner.AskChoice("Enter the number of the object to
delete:\n", objChoices)
obj := objList[objChoice]
deleted, err := scenario.s3Actions.DeleteObject(ctx, obj.bucket, obj.key,
obj.versionId, choice == DeleteRetentionObject)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Println("Nothing to delete.")
default:
panic(err)
}
} else if deleted {
log.Printf("Object %s deleted.\n", obj.key)
}
case OverwriteObject:
objChoice := scenario.questioner.AskChoice("Enter the number of the object to
overwrite:\n", objChoices)
obj := objList[objChoice]
_, err := scenario.s3Actions.UploadObject(ctx, obj.bucket, obj.key,
fmt.Sprintf("New content in object %s.", obj.key))
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Println("Couldn't upload to nonexistent bucket.")
default:
panic(err)
Scenarios 437
AWS SDK for Go Code Examples Code Examples Guide
}
} else {
log.Printf("Uploaded new content to object %s.\n", obj.key)
}
case ViewRetention:
objChoice := scenario.questioner.AskChoice("Enter the number of the object to
view:\n", objChoices)
obj := objList[objChoice]
retention, err := scenario.s3Actions.GetObjectRetention(ctx, obj.bucket, obj.key)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Printf("Can't get retention configuration for %s.\n", obj.key)
default:
panic(err)
}
} else if retention != nil {
log.Printf("Object %s has retention mode %s until %v.\n", obj.key,
retention.Mode, retention.RetainUntilDate)
} else {
log.Printf("Object %s does not have object retention configured.\n", obj.key)
}
case ViewLegalHold:
objChoice := scenario.questioner.AskChoice("Enter the number of the object to
view:\n", objChoices)
obj := objList[objChoice]
legalHold, err := scenario.s3Actions.GetObjectLegalHold(ctx, obj.bucket, obj.key,
obj.versionId)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Printf("Can't get legal hold configuration for %s.\n", obj.key)
default:
panic(err)
}
} else if legalHold != nil {
log.Printf("Object %s has legal hold %v.", obj.key, *legalHold)
} else {
log.Printf("Object %s does not have legal hold configured.", obj.key)
}
case Finish:
log.Println("Let's clean up.")
}
log.Println(strings.Repeat("-", 88))
Scenarios 438
AWS SDK for Go Code Examples Code Examples Guide
}
}
type BucketKeyVersionId struct {
bucket string
key string
versionId string
}
// GetAllObjects gets the object versions in the example S3 buckets and returns them
in a flattened list.
func (scenario *ObjectLockScenario) GetAllObjects(ctx context.Context)
[]BucketKeyVersionId {
var objectList []BucketKeyVersionId
for _, info := range createInfo {
bucket := scenario.resources.demoBuckets[info.name]
versions, err := scenario.s3Actions.ListObjectVersions(ctx, bucket.name)
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Printf("Couldn't get object versions for %s.\n", bucket.name)
default:
panic(err)
}
} else {
for _, version := range versions {
objectList = append(objectList,
BucketKeyVersionId{bucket: bucket.name, key: *version.Key, versionId:
*version.VersionId})
}
}
}
return objectList
}
// makeObjectChoiceList makes the object version list into a list of strings that
are displayed
// as choices.
func (scenario *ObjectLockScenario) makeObjectChoiceList(bucketObjects
[]BucketKeyVersionId) []string {
choices := make([]string, len(bucketObjects))
for i := 0; i < len(bucketObjects); i++ {
choices[i] = fmt.Sprintf("%s in %s with VersionId %s.",
bucketObjects[i].key, bucketObjects[i].bucket, bucketObjects[i].versionId)
Scenarios 439
AWS SDK for Go Code Examples Code Examples Guide
}
return choices
}
// Run runs the S3 Object Lock workflow scenario.
func (scenario *ObjectLockScenario) Run(ctx context.Context) {
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.")
_, isMock := scenario.questioner.(*demotools.MockQuestioner)
if isMock || scenario.questioner.AskBool("Do you want to see the full error
message (y/n)?", "y") {
log.Println(r)
}
scenario.resources.Cleanup(ctx)
}
}()
log.Println(strings.Repeat("-", 88))
log.Println("Welcome to the Amazon S3 Object Lock Workflow Scenario.")
log.Println(strings.Repeat("-", 88))
scenario.CreateBuckets(ctx)
scenario.EnableLockOnBucket(ctx)
scenario.SetDefaultRetentionPolicy(ctx)
scenario.UploadTestObjects(ctx)
scenario.SetObjectLockConfigurations(ctx)
scenario.InteractWithObjects(ctx)
scenario.resources.Cleanup(ctx)
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define a struct that wraps S3 actions used in this example.
// S3Actions wraps S3 service actions.
type S3Actions struct {
Scenarios 440
AWS SDK for Go Code Examples Code Examples Guide
S3Client *s3.Client
S3Manager *manager.Uploader
}
// CreateBucketWithLock creates a new S3 bucket with optional object locking enabled
// and waits for the bucket to exist before returning.
func (actor S3Actions) CreateBucketWithLock(ctx context.Context, bucket string,
region string, enableObjectLock bool) (string, error) {
input := &s3.CreateBucketInput{
Bucket: aws.String(bucket),
CreateBucketConfiguration: &types.CreateBucketConfiguration{
LocationConstraint: types.BucketLocationConstraint(region),
},
}
if enableObjectLock {
input.ObjectLockEnabledForBucket = aws.Bool(true)
}
_, err := actor.S3Client.CreateBucket(ctx, input)
if err != nil {
var owned *types.BucketAlreadyOwnedByYou
var exists *types.BucketAlreadyExists
if errors.As(err, &owned) {
log.Printf("You already own bucket %s.\n", bucket)
err = owned
} else if errors.As(err, &exists) {
log.Printf("Bucket %s already exists.\n", bucket)
err = exists
}
} else {
err = s3.NewBucketExistsWaiter(actor.S3Client).Wait(
ctx, &s3.HeadBucketInput{Bucket: aws.String(bucket)}, time.Minute)
if err != nil {
log.Printf("Failed attempt to wait for bucket %s to exist.\n", bucket)
}
}
return bucket, err
}
Scenarios 441
AWS SDK for Go Code Examples Code Examples Guide
// GetObjectLegalHold retrieves the legal hold status for an S3 object.
func (actor S3Actions) GetObjectLegalHold(ctx context.Context, bucket string, key
string, versionId string) (*types.ObjectLockLegalHoldStatus, error) {
var status *types.ObjectLockLegalHoldStatus
input := &s3.GetObjectLegalHoldInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
VersionId: aws.String(versionId),
}
output, err := actor.S3Client.GetObjectLegalHold(ctx, input)
if err != nil {
var noSuchKeyErr *types.NoSuchKey
var apiErr *smithy.GenericAPIError
if errors.As(err, &noSuchKeyErr) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noSuchKeyErr
} else if errors.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case "NoSuchObjectLockConfiguration":
log.Printf("Object %s does not have an object lock configuration.\n", key)
err = nil
case "InvalidRequest":
log.Printf("Bucket %s does not have an object lock configuration.\n", bucket)
err = nil
}
}
} else {
status = &output.LegalHold.Status
}
return status, err
}
// GetObjectLockConfiguration retrieves the object lock configuration for an S3
bucket.
func (actor S3Actions) GetObjectLockConfiguration(ctx context.Context, bucket
string) (*types.ObjectLockConfiguration, error) {
var lockConfig *types.ObjectLockConfiguration
input := &s3.GetObjectLockConfigurationInput{
Bucket: aws.String(bucket),
Scenarios 442
AWS SDK for Go Code Examples Code Examples Guide
}
output, err := actor.S3Client.GetObjectLockConfiguration(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
var apiErr *smithy.GenericAPIError
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
} else if errors.As(err, &apiErr) && apiErr.ErrorCode() ==
"ObjectLockConfigurationNotFoundError" {
log.Printf("Bucket %s does not have an object lock configuration.\n", bucket)
err = nil
}
} else {
lockConfig = output.ObjectLockConfiguration
}
return lockConfig, err
}
// GetObjectRetention retrieves the object retention configuration for an S3 object.
func (actor S3Actions) GetObjectRetention(ctx context.Context, bucket string, key
string) (*types.ObjectLockRetention, error) {
var retention *types.ObjectLockRetention
input := &s3.GetObjectRetentionInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}
output, err := actor.S3Client.GetObjectRetention(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
var apiErr *smithy.GenericAPIError
if errors.As(err, &noKey) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noKey
} else if errors.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case "NoSuchObjectLockConfiguration":
err = nil
case "InvalidRequest":
Scenarios 443
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Bucket %s does not have locking enabled.", bucket)
err = nil
}
}
} else {
retention = output.Retention
}
return retention, err
}
// PutObjectLegalHold sets the legal hold configuration for an S3 object.
func (actor S3Actions) PutObjectLegalHold(ctx context.Context, bucket string, key
string, versionId string, legalHoldStatus types.ObjectLockLegalHoldStatus) error {
input := &s3.PutObjectLegalHoldInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
LegalHold: &types.ObjectLockLegalHold{
Status: legalHoldStatus,
},
}
if versionId != "" {
input.VersionId = aws.String(versionId)
}
_, err := actor.S3Client.PutObjectLegalHold(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
if errors.As(err, &noKey) {
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noKey
}
}
return err
}
// ModifyDefaultBucketRetention modifies the default retention period of an existing
bucket.
func (actor S3Actions) ModifyDefaultBucketRetention(
Scenarios 444
AWS SDK for Go Code Examples Code Examples Guide
ctx context.Context, bucket string, lockMode types.ObjectLockEnabled,
retentionPeriod int32, retentionMode types.ObjectLockRetentionMode) error {
input := &s3.PutObjectLockConfigurationInput{
Bucket: aws.String(bucket),
ObjectLockConfiguration: &types.ObjectLockConfiguration{
ObjectLockEnabled: lockMode,
Rule: &types.ObjectLockRule{
DefaultRetention: &types.DefaultRetention{
Days: aws.Int32(retentionPeriod),
Mode: retentionMode,
},
},
},
}
_, err := actor.S3Client.PutObjectLockConfiguration(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
}
return err
}
// EnableObjectLockOnBucket enables object locking on an existing bucket.
func (actor S3Actions) EnableObjectLockOnBucket(ctx context.Context, bucket string)
error {
// Versioning must be enabled on the bucket before object locking is enabled.
verInput := &s3.PutBucketVersioningInput{
Bucket: aws.String(bucket),
VersioningConfiguration: &types.VersioningConfiguration{
MFADelete: types.MFADeleteDisabled,
Status: types.BucketVersioningStatusEnabled,
},
}
_, err := actor.S3Client.PutBucketVersioning(ctx, verInput)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
Scenarios 445
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
return err
}
input := &s3.PutObjectLockConfigurationInput{
Bucket: aws.String(bucket),
ObjectLockConfiguration: &types.ObjectLockConfiguration{
ObjectLockEnabled: types.ObjectLockEnabledEnabled,
},
}
_, err = actor.S3Client.PutObjectLockConfiguration(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
}
return err
}
// PutObjectRetention sets the object retention configuration for an S3 object.
func (actor S3Actions) PutObjectRetention(ctx context.Context, bucket string, key
string, retentionMode types.ObjectLockRetentionMode, retentionPeriodDays int32)
error {
input := &s3.PutObjectRetentionInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Retention: &types.ObjectLockRetention{
Mode: retentionMode,
RetainUntilDate: aws.Time(time.Now().AddDate(0, 0, int(retentionPeriodDays))),
},
BypassGovernanceRetention: aws.Bool(true),
}
_, err := actor.S3Client.PutObjectRetention(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
if errors.As(err, &noKey) {
Scenarios 446
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Object %s does not exist in bucket %s.\n", key, bucket)
err = noKey
}
}
return err
}
// UploadObject uses the S3 upload manager to upload an object to a bucket.
func (actor S3Actions) UploadObject(ctx context.Context, bucket string, key string,
contents string) (string, error) {
var outKey string
input := &s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: bytes.NewReader([]byte(contents)),
ChecksumAlgorithm: types.ChecksumAlgorithmSha256,
}
output, err := actor.S3Manager.Upload(ctx, input)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
} else {
err := s3.NewObjectExistsWaiter(actor.S3Client).Wait(ctx, &s3.HeadObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}, time.Minute)
if err != nil {
log.Printf("Failed attempt to wait for object %s to exist in %s.\n", key, bucket)
} else {
outKey = *output.Key
}
}
return outKey, err
}
// ListObjectVersions lists all versions of all objects in a bucket.
Scenarios 447
AWS SDK for Go Code Examples Code Examples Guide
func (actor S3Actions) ListObjectVersions(ctx context.Context, bucket string)
([]types.ObjectVersion, error) {
var err error
var output *s3.ListObjectVersionsOutput
var versions []types.ObjectVersion
input := &s3.ListObjectVersionsInput{Bucket: aws.String(bucket)}
versionPaginator := s3.NewListObjectVersionsPaginator(actor.S3Client, input)
for versionPaginator.HasMorePages() {
output, err = versionPaginator.NextPage(ctx)
if err != nil {
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
break
} else {
versions = append(versions, output.Versions...)
}
}
return versions, err
}
// DeleteObject deletes an object from a bucket.
func (actor S3Actions) DeleteObject(ctx context.Context, bucket string, key string,
versionId string, bypassGovernance bool) (bool, error) {
deleted := false
input := &s3.DeleteObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}
if versionId != "" {
input.VersionId = aws.String(versionId)
}
if bypassGovernance {
input.BypassGovernanceRetention = aws.Bool(true)
}
_, err := actor.S3Client.DeleteObject(ctx, input)
if err != nil {
var noKey *types.NoSuchKey
var apiErr *smithy.GenericAPIError
if errors.As(err, &noKey) {
Scenarios 448
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Object %s does not exist in %s.\n", key, bucket)
err = noKey
} else if errors.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case "AccessDenied":
log.Printf("Access denied: cannot delete object %s from %s.\n", key, bucket)
err = nil
case "InvalidArgument":
if bypassGovernance {
log.Printf("You cannot specify bypass governance on a bucket without lock
enabled.")
err = nil
}
}
}
} else {
deleted = true
}
return deleted, err
}
// DeleteObjects deletes a list of objects from a bucket.
func (actor S3Actions) DeleteObjects(ctx context.Context, bucket string, objects
[]types.ObjectIdentifier, bypassGovernance bool) error {
if len(objects) == 0 {
return nil
}
input := s3.DeleteObjectsInput{
Bucket: aws.String(bucket),
Delete: &types.Delete{
Objects: objects,
Quiet: aws.Bool(true),
},
}
if bypassGovernance {
input.BypassGovernanceRetention = aws.Bool(true)
}
delOut, err := actor.S3Client.DeleteObjects(ctx, &input)
if err != nil || len(delOut.Errors) > 0 {
log.Printf("Error deleting objects from bucket %s.\n", bucket)
if err != nil {
Scenarios 449
AWS SDK for Go Code Examples Code Examples Guide
var noBucket *types.NoSuchBucket
if errors.As(err, &noBucket) {
log.Printf("Bucket %s does not exist.\n", bucket)
err = noBucket
}
} else if len(delOut.Errors) > 0 {
for _, outErr := range delOut.Errors {
log.Printf("%s: %s\n", *outErr.Key, *outErr.Message)
}
err = fmt.Errorf("%s", *delOut.Errors[0].Message)
}
}
return err
}
Clean up resources.
// DemoBucket contains metadata for buckets used in this example.
type DemoBucket struct {
name string
legalHold bool
retentionEnabled bool
objectKeys []string
}
// Resources keeps track of AWS resources created during the ObjectLockScenario and
handles
// cleanup when the scenario finishes.
type Resources struct {
demoBuckets map[string]*DemoBucket
s3Actions *actions.S3Actions
questioner demotools.IQuestioner
}
// init initializes objects in the Resources struct.
func (resources *Resources) init(s3Actions *actions.S3Actions, questioner
demotools.IQuestioner) {
resources.s3Actions = s3Actions
Scenarios 450
AWS SDK for Go Code Examples Code Examples Guide
resources.questioner = questioner
resources.demoBuckets = map[string]*DemoBucket{}
}
// Cleanup deletes all AWS resources created during the ObjectLockScenario.
func (resources *Resources) Cleanup(ctx context.Context) {
defer func() {
if r := recover(); r != nil {
log.Printf("Something went wrong during cleanup.\n%v\n", r)
log.Println("Use the AWS Management Console to remove any remaining resources " +
"that were created for this scenario.")
}
}()
wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS
resources that were created "+
"during this demo (y/n)?", "y")
if !wantDelete {
log.Println("Be sure to remove resources when you're done with them to avoid
unexpected charges!")
return
}
log.Println("Removing objects from S3 buckets and deleting buckets...")
resources.deleteBuckets(ctx)
//resources.deleteRetentionObjects(resources.retentionBucket,
resources.retentionObjects)
log.Println("Cleanup complete.")
}
// deleteBuckets empties and then deletes all buckets created during the
ObjectLockScenario.
func (resources *Resources) deleteBuckets(ctx context.Context) {
for _, info := range createInfo {
bucket := resources.demoBuckets[info.name]
resources.deleteObjects(ctx, bucket)
_, err := resources.s3Actions.S3Client.DeleteBucket(ctx, &s3.DeleteBucketInput{
Bucket: aws.String(bucket.name),
})
if err != nil {
panic(err)
}
}
Scenarios 451
AWS SDK for Go Code Examples Code Examples Guide
resources.demoBuckets = map[string]*DemoBucket{}
}
// deleteObjects deletes all objects in the specified bucket.
func (resources *Resources) deleteObjects(ctx context.Context, bucket *DemoBucket) {
lockConfig, err := resources.s3Actions.GetObjectLockConfiguration(ctx, bucket.name)
if err != nil {
panic(err)
}
versions, err := resources.s3Actions.ListObjectVersions(ctx, bucket.name)
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Printf("No objects to get from %s.\n", bucket.name)
default:
panic(err)
}
}
delObjects := make([]types.ObjectIdentifier, len(versions))
for i, version := range versions {
if lockConfig != nil && lockConfig.ObjectLockEnabled ==
types.ObjectLockEnabledEnabled {
status, err := resources.s3Actions.GetObjectLegalHold(ctx, bucket.name,
*version.Key, *version.VersionId)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Printf("Couldn't determine legal hold status for %s in %s.\n",
*version.Key, bucket.name)
default:
panic(err)
}
} else if status != nil && *status == types.ObjectLockLegalHoldStatusOn {
err = resources.s3Actions.PutObjectLegalHold(ctx, bucket.name, *version.Key,
*version.VersionId, types.ObjectLockLegalHoldStatusOff)
if err != nil {
switch err.(type) {
case *types.NoSuchKey:
log.Printf("Couldn't turn off legal hold for %s in %s.\n", *version.Key,
bucket.name)
default:
panic(err)
}
}
Scenarios 452
AWS SDK for Go Code Examples Code Examples Guide
}
}
delObjects[i] = types.ObjectIdentifier{Key: version.Key, VersionId:
version.VersionId}
}
err = resources.s3Actions.DeleteObjects(ctx, bucket.name, delObjects,
bucket.retentionEnabled)
if err != nil {
switch err.(type) {
case *types.NoSuchBucket:
log.Println("Nothing to delete.")
default:
panic(err)
}
}
}
For API details, see the following topics in AWS SDK for Go API Reference.
GetObjectLegalHold
GetObjectLockConfiguration
GetObjectRetention
PutObjectLegalHold
PutObjectLockConfiguration
PutObjectRetention
Upload or download large files
The following code example shows how to upload or download large files to and from Amazon S3.
For more information, see Uploading an object using multipart upload.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Scenarios 453
AWS SDK for Go Code Examples Code Examples Guide
Upload a large object by using an upload manager to break the data into parts and upload
them concurrently.
// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
S3Client *s3.Client
}
// UploadLargeObject uses an upload manager to upload data to an object in a bucket.
// The upload manager breaks large data into parts and uploads the parts
concurrently.
func (basics BucketBasics) UploadLargeObject(bucketName string, objectKey string,
largeObject []byte) error {
largeBuffer := bytes.NewReader(largeObject)
var partMiBs int64 = 10
uploader := manager.NewUploader(basics.S3Client, func(u *manager.Uploader) {
u.PartSize = partMiBs * 1024 * 1024
})
_, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: largeBuffer,
})
if err != nil {
log.Printf("Couldn't upload large object to %v:%v. Here's why: %v\n",
bucketName, objectKey, err)
}
return err
}
Download a large object by using a download manager to get the data in parts and download
them concurrently.
Scenarios 454
AWS SDK for Go Code Examples Code Examples Guide
// DownloadLargeObject uses a download manager to download an object from a bucket.
// The download manager gets the data in parts and writes them to a buffer until all
of
// the data has been downloaded.
func (basics BucketBasics) DownloadLargeObject(bucketName string, objectKey string)
([]byte, error) {
var partMiBs int64 = 10
downloader := manager.NewDownloader(basics.S3Client, func(d *manager.Downloader) {
d.PartSize = partMiBs * 1024 * 1024
})
buffer := manager.NewWriteAtBuffer([]byte{})
_, err := downloader.Download(context.TODO(), buffer, &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
if err != nil {
log.Printf("Couldn't download large object from %v:%v. Here's why: %v\n",
bucketName, objectKey, err)
}
return buffer.Bytes(), err
}
Serverless examples
Invoke a Lambda function from an Amazon S3 trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by uploading an object to an S3 bucket. The function retrieves the S3 bucket name and
object key from the event parameter and calls the Amazon S3 API to retrieve and log the content
type of the object.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Serverless examples 455
AWS SDK for Go Code Examples Code Examples Guide
Consuming an S3 event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"log"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
func handler(ctx context.Context, s3Event events.S3Event) error {
sdkConfig, err := config.LoadDefaultConfig(ctx)
if err != nil {
log.Printf("failed to load default config: %s", err)
return err
}
s3Client := s3.NewFromConfig(sdkConfig)
for _, record := range s3Event.Records {
bucket := record.S3.Bucket.Name
key := record.S3.Object.URLDecodedKey
headOutput, err := s3Client.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: &bucket,
Key: &key,
})
if err != nil {
log.Printf("error getting head of object %s/%s: %s", bucket, key, err)
return err
}
log.Printf("successfully retrieved %s/%s of type %s", bucket, key,
*headOutput.ContentType)
}
return nil
}
func main() {
lambda.Start(handler)
Serverless examples 456
AWS SDK for Go Code Examples Code Examples Guide
}
Amazon SNS examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon SNS.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Amazon SNS
The following code examples show how to get started using Amazon SNS.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
Amazon SNS 457
AWS SDK for Go Code Examples Code Examples Guide
"github.com/aws/aws-sdk-go-v2/service/sns"
"github.com/aws/aws-sdk-go-v2/service/sns/types"
)
// main uses the AWS SDK for Go V2 to create an Amazon Simple Notification Service
// (Amazon SNS) client and list the topics in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
snsClient := sns.NewFromConfig(sdkConfig)
fmt.Println("Let's list the topics for your account.")
var topics []types.Topic
paginator := sns.NewListTopicsPaginator(snsClient, &sns.ListTopicsInput{})
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get topics. Here's why: %v\n", err)
break
} else {
topics = append(topics, output.Topics...)
}
}
if len(topics) == 0 {
fmt.Println("You don't have any topics!")
} else {
for _, topic := range topics {
fmt.Printf("\t%v\n", *topic.TopicArn)
}
}
}
For API details, see ListTopics in AWS SDK for Go API Reference.
Topics
Amazon SNS 458
AWS SDK for Go Code Examples Code Examples Guide
Actions
Scenarios
Serverless examples
Actions
CreateTopic
The following code example shows how to use CreateTopic.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SnsActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type SnsActions struct {
SnsClient *sns.Client
}
// CreateTopic creates an Amazon SNS topic with the specified name. You can
optionally
// specify that the topic is created as a FIFO topic and whether it uses content-
based
// deduplication instead of ID-based deduplication.
func (actor SnsActions) CreateTopic(topicName string, isFifoTopic bool,
contentBasedDeduplication bool) (string, error) {
var topicArn string
topicAttributes := map[string]string{}
if isFifoTopic {
topicAttributes["FifoTopic"] = "true"
}
Actions 459
AWS SDK for Go Code Examples Code Examples Guide
if contentBasedDeduplication {
topicAttributes["ContentBasedDeduplication"] = "true"
}
topic, err := actor.SnsClient.CreateTopic(context.TODO(), &sns.CreateTopicInput{
Name: aws.String(topicName),
Attributes: topicAttributes,
})
if err != nil {
log.Printf("Couldn't create topic %v. Here's why: %v\n", topicName, err)
} else {
topicArn = *topic.TopicArn
}
return topicArn, err
}
For API details, see CreateTopic in AWS SDK for Go API Reference.
DeleteTopic
The following code example shows how to use DeleteTopic.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SnsActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type SnsActions struct {
SnsClient *sns.Client
}
Actions 460
AWS SDK for Go Code Examples Code Examples Guide
// DeleteTopic delete an Amazon SNS topic.
func (actor SnsActions) DeleteTopic(topicArn string) error {
_, err := actor.SnsClient.DeleteTopic(context.TODO(), &sns.DeleteTopicInput{
TopicArn: aws.String(topicArn)})
if err != nil {
log.Printf("Couldn't delete topic %v. Here's why: %v\n", topicArn, err)
}
return err
}
For API details, see DeleteTopic in AWS SDK for Go API Reference.
ListTopics
The following code example shows how to use ListTopics.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sns"
"github.com/aws/aws-sdk-go-v2/service/sns/types"
)
// main uses the AWS SDK for Go V2 to create an Amazon Simple Notification Service
Actions 461
AWS SDK for Go Code Examples Code Examples Guide
// (Amazon SNS) client and list the topics in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
snsClient := sns.NewFromConfig(sdkConfig)
fmt.Println("Let's list the topics for your account.")
var topics []types.Topic
paginator := sns.NewListTopicsPaginator(snsClient, &sns.ListTopicsInput{})
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get topics. Here's why: %v\n", err)
break
} else {
topics = append(topics, output.Topics...)
}
}
if len(topics) == 0 {
fmt.Println("You don't have any topics!")
} else {
for _, topic := range topics {
fmt.Printf("\t%v\n", *topic.TopicArn)
}
}
}
For API details, see ListTopics in AWS SDK for Go API Reference.
Publish
The following code example shows how to use Publish.
Actions 462
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SnsActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type SnsActions struct {
SnsClient *sns.Client
}
// Publish publishes a message to an Amazon SNS topic. The message is then sent to
all
// subscribers. When the topic is a FIFO topic, the message must also contain a
group ID
// and, when ID-based deduplication is used, a deduplication ID. An optional key-
value
// filter attribute can be specified so that the message can be filtered according
to
// a filter policy.
func (actor SnsActions) Publish(topicArn string, message string, groupId string,
dedupId string, filterKey string, filterValue string) error {
publishInput := sns.PublishInput{TopicArn: aws.String(topicArn), Message:
aws.String(message)}
if groupId != "" {
publishInput.MessageGroupId = aws.String(groupId)
}
if dedupId != "" {
publishInput.MessageDeduplicationId = aws.String(dedupId)
}
if filterKey != "" && filterValue != "" {
publishInput.MessageAttributes = map[string]types.MessageAttributeValue{
filterKey: {DataType: aws.String("String"), StringValue:
aws.String(filterValue)},
}
Actions 463
AWS SDK for Go Code Examples Code Examples Guide
}
_, err := actor.SnsClient.Publish(context.TODO(), &publishInput)
if err != nil {
log.Printf("Couldn't publish message to topic %v. Here's why: %v", topicArn, err)
}
return err
}
For API details, see Publish in AWS SDK for Go API Reference.
Subscribe
The following code example shows how to use Subscribe.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Subscribe a queue to a topic with optional filters.
// SnsActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type SnsActions struct {
SnsClient *sns.Client
}
// SubscribeQueue subscribes an Amazon Simple Queue Service (Amazon SQS) queue to an
// Amazon SNS topic. When filterMap is not nil, it is used to specify a filter
policy
// so that messages are only sent to the queue when the message has the specified
attributes.
Actions 464
AWS SDK for Go Code Examples Code Examples Guide
func (actor SnsActions) SubscribeQueue(topicArn string, queueArn string, filterMap
map[string][]string) (string, error) {
var subscriptionArn string
var attributes map[string]string
if filterMap != nil {
filterBytes, err := json.Marshal(filterMap)
if err != nil {
log.Printf("Couldn't create filter policy, here's why: %v\n", err)
return "", err
}
attributes = map[string]string{"FilterPolicy": string(filterBytes)}
}
output, err := actor.SnsClient.Subscribe(context.TODO(), &sns.SubscribeInput{
Protocol: aws.String("sqs"),
TopicArn: aws.String(topicArn),
Attributes: attributes,
Endpoint: aws.String(queueArn),
ReturnSubscriptionArn: true,
})
if err != nil {
log.Printf("Couldn't susbscribe queue %v to topic %v. Here's why: %v\n",
queueArn, topicArn, err)
} else {
subscriptionArn = *output.SubscriptionArn
}
return subscriptionArn, err
}
For API details, see Subscribe in AWS SDK for Go API Reference.
Scenarios
Publish messages to queues
The following code example shows how to:
Create topic (FIFO or non-FIFO).
Subscribe several queues to the topic with an option to apply a filter.
Publish messages to the topic.
Scenarios 465
AWS SDK for Go Code Examples Code Examples Guide
Poll the queues for messages received.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
const FIFO_SUFFIX = ".fifo"
const TONE_KEY = "tone"
var ToneChoices = []string{"cheerful", "funny", "serious", "sincere"}
// MessageBody is used to deserialize the body of a message from a JSON string.
type MessageBody struct {
Message string
}
// ScenarioRunner separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type ScenarioRunner struct {
questioner demotools.IQuestioner
snsActor *actions.SnsActions
sqsActor *actions.SqsActions
}
func (runner ScenarioRunner) CreateTopic() (string, string, bool, bool) {
log.Println("SNS topics can be configured as FIFO (First-In-First-Out) or standard.
\n" +
"FIFO topics deliver messages in order and support deduplication and message
filtering.")
isFifoTopic := runner.questioner.AskBool("\nWould you like to work with FIFO
topics? (y/n) ", "y")
contentBasedDeduplication := false
if isFifoTopic {
Scenarios 466
AWS SDK for Go Code Examples Code Examples Guide
log.Println(strings.Repeat("-", 88))
log.Println("Because you have chosen a FIFO topic, deduplication is supported.\n"
+
"Deduplication IDs are either set in the message or are automatically generated
\n" +
"from content using a hash function. If a message is successfully published to\n"
+
"an SNS FIFO topic, any message published and determined to have the same\n" +
"deduplication ID, within the five-minute deduplication interval, is accepted\n"
+
"but not delivered. For more information about deduplication, see:\n" +
"\thttps://docs.aws.amazon.com/sns/latest/dg/fifo-message-dedup.html.")
contentBasedDeduplication = runner.questioner.AskBool(
"\nDo you want to use content-based deduplication instead of entering a
deduplication ID? (y/n) ", "y")
}
log.Println(strings.Repeat("-", 88))
topicName := runner.questioner.Ask("Enter a name for your SNS topic. ")
if isFifoTopic {
topicName = fmt.Sprintf("%v%v", topicName, FIFO_SUFFIX)
log.Printf("Because you have selected a FIFO topic, '%v' must be appended to\n"+
"the topic name.", FIFO_SUFFIX)
}
topicArn, err := runner.snsActor.CreateTopic(topicName, isFifoTopic,
contentBasedDeduplication)
if err != nil {
panic(err)
}
log.Printf("Your new topic with the name '%v' and Amazon Resource Name (ARN) \n"+
"'%v' has been created.", topicName, topicArn)
return topicName, topicArn, isFifoTopic, contentBasedDeduplication
}
func (runner ScenarioRunner) CreateQueue(ordinal string, isFifoTopic bool) (string,
string) {
queueName := runner.questioner.Ask(fmt.Sprintf("Enter a name for the %v SQS queue.
", ordinal))
if isFifoTopic {
queueName = fmt.Sprintf("%v%v", queueName, FIFO_SUFFIX)
if ordinal == "first" {
log.Printf("Because you are creating a FIFO SQS queue, '%v' must "+
Scenarios 467
AWS SDK for Go Code Examples Code Examples Guide
"be appended to the queue name.\n", FIFO_SUFFIX)
}
}
queueUrl, err := runner.sqsActor.CreateQueue(queueName, isFifoTopic)
if err != nil {
panic(err)
}
log.Printf("Your new SQS queue with the name '%v' and the queue URL "+
"'%v' has been created.", queueName, queueUrl)
return queueName, queueUrl
}
func (runner ScenarioRunner) SubscribeQueueToTopic(
queueName string, queueUrl string, topicName string, topicArn string, ordinal
string,
isFifoTopic bool) (string, bool) {
queueArn, err := runner.sqsActor.GetQueueArn(queueUrl)
if err != nil {
panic(err)
}
log.Printf("The ARN of your queue is: %v.\n", queueArn)
err = runner.sqsActor.AttachSendMessagePolicy(queueUrl, queueArn, topicArn)
if err != nil {
panic(err)
}
log.Println("Attached an IAM policy to the queue so the SNS topic can send " +
"messages to it.")
log.Println(strings.Repeat("-", 88))
var filterPolicy map[string][]string
if isFifoTopic {
if ordinal == "first" {
log.Println("Subscriptions to a FIFO topic can have filters.\n" +
"If you add a filter to this subscription, then only the filtered messages\n" +
"will be received in the queue.\n" +
"For information about message filtering, see\n" +
"\thttps://docs.aws.amazon.com/sns/latest/dg/sns-message-filtering.html\n" +
"For this example, you can filter messages by a \"tone\" attribute.")
}
wantFiltering := runner.questioner.AskBool(
Scenarios 468
AWS SDK for Go Code Examples Code Examples Guide
fmt.Sprintf("Do you want to filter messages that are sent to \"%v\"\n"+
"from the %v topic? (y/n) ", queueName, topicName), "y")
if wantFiltering {
log.Println("You can filter messages by one or more of the following \"tone\"
attributes.")
var toneSelections []string
askAboutTones := true
for askAboutTones {
toneIndex := runner.questioner.AskChoice(
"Enter the number of the tone you want to filter by:\n", ToneChoices)
toneSelections = append(toneSelections, ToneChoices[toneIndex])
askAboutTones = runner.questioner.AskBool("Do you want to add another tone to
the filter? (y/n) ", "y")
}
log.Printf("Your subscription will be filtered to only pass the following tones:
%v\n", toneSelections)
filterPolicy = map[string][]string{TONE_KEY: toneSelections}
}
}
subscriptionArn, err := runner.snsActor.SubscribeQueue(topicArn, queueArn,
filterPolicy)
if err != nil {
panic(err)
}
log.Printf("The queue %v is now subscribed to the topic %v with the subscription
ARN %v.\n",
queueName, topicName, subscriptionArn)
return subscriptionArn, filterPolicy != nil
}
func (runner ScenarioRunner) PublishMessages(topicArn string, isFifoTopic bool,
contentBasedDeduplication bool, usingFilters bool) {
var message string
var groupId string
var dedupId string
var toneSelection string
publishMore := true
for publishMore {
groupId = ""
dedupId = ""
toneSelection = ""
Scenarios 469
AWS SDK for Go Code Examples Code Examples Guide
message = runner.questioner.Ask("Enter a message to publish: ")
if isFifoTopic {
log.Println("Because you are using a FIFO topic, you must set a message group ID.
\n" +
"All messages within the same group will be received in the order they were
published.")
groupId = runner.questioner.Ask("Enter a message group ID: ")
if !contentBasedDeduplication {
log.Println("Because you are not using content-based deduplication,\n" +
"you must enter a deduplication ID.")
dedupId = runner.questioner.Ask("Enter a deduplication ID: ")
}
}
if usingFilters {
if runner.questioner.AskBool("Add a tone attribute so this message can be
filtered? (y/n) ", "y") {
toneIndex := runner.questioner.AskChoice(
"Enter the number of the tone you want to filter by:\n", ToneChoices)
toneSelection = ToneChoices[toneIndex]
}
}
err := runner.snsActor.Publish(topicArn, message, groupId, dedupId, TONE_KEY,
toneSelection)
if err != nil {
panic(err)
}
log.Println(("Your message was published."))
publishMore = runner.questioner.AskBool("Do you want to publish another messsage?
(y/n) ", "y")
}
}
func (runner ScenarioRunner) PollForMessages(queueUrls []string) {
log.Println("Polling queues for messages...")
for _, queueUrl := range queueUrls {
var messages []types.Message
for {
currentMsgs, err := runner.sqsActor.GetMessages(queueUrl, 10, 1)
if err != nil {
panic(err)
}
if len(currentMsgs) == 0 {
Scenarios 470
AWS SDK for Go Code Examples Code Examples Guide
break
}
messages = append(messages, currentMsgs...)
}
if len(messages) == 0 {
log.Printf("No messages were received by queue %v.\n", queueUrl)
} else if len(messages) == 1 {
log.Printf("One message was received by queue %v:\n", queueUrl)
} else {
log.Printf("%v messages were received by queue %v:\n", len(messages), queueUrl)
}
for msgIndex, message := range messages {
messageBody := MessageBody{}
err := json.Unmarshal([]byte(*message.Body), &messageBody)
if err != nil {
panic(err)
}
log.Printf("Message %v: %v\n", msgIndex+1, messageBody.Message)
}
if len(messages) > 0 {
log.Printf("Deleting %v messages from queue %v.\n", len(messages), queueUrl)
err := runner.sqsActor.DeleteMessages(queueUrl, messages)
if err != nil {
panic(err)
}
}
}
}
// RunTopicsAndQueuesScenario is an interactive example that shows you how to use
the
// AWS SDK for Go to create and use Amazon SNS topics and Amazon SQS queues.
//
// 1. Create a topic (FIFO or non-FIFO).
// 2. Subscribe several queues to the topic with an option to apply a filter.
// 3. Publish messages to the topic.
// 4. Poll the queues for messages received.
// 5. Delete the topic and the queues.
//
// This example creates service clients from the specified sdkConfig so that
// you can replace it with a mocked or stubbed config for unit testing.
//
Scenarios 471
AWS SDK for Go Code Examples Code Examples Guide
// It uses a questioner from the `demotools` package to get input during the
example.
// This package can be found in the ..\..\demotools folder of this repo.
func RunTopicsAndQueuesScenario(
sdkConfig aws.Config, questioner demotools.IQuestioner) {
resources := Resources{}
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.\n" +
"Cleaning up any resources that were created...")
resources.Cleanup()
}
}()
queueCount := 2
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome to messaging with topics and queues.\n\n"+
"In this workflow, you will create an SNS topic and subscribe %v SQS queues to the
\n"+
"topic. You can select from several options for configuring the topic and the\n"+
"subscriptions for the queues. You can then post to the topic and see the results
\n"+
"in the queues.\n", queueCount)
log.Println(strings.Repeat("-", 88))
runner := ScenarioRunner{
questioner: questioner,
snsActor: &actions.SnsActions{SnsClient: sns.NewFromConfig(sdkConfig)},
sqsActor: &actions.SqsActions{SqsClient: sqs.NewFromConfig(sdkConfig)},
}
resources.snsActor = runner.snsActor
resources.sqsActor = runner.sqsActor
topicName, topicArn, isFifoTopic, contentBasedDeduplication := runner.CreateTopic()
resources.topicArn = topicArn
log.Println(strings.Repeat("-", 88))
log.Printf("Now you will create %v SQS queues and subscribe them to the topic.\n",
queueCount)
ordinals := []string{"first", "next"}
usingFilters := false
for _, ordinal := range ordinals {
queueName, queueUrl := runner.CreateQueue(ordinal, isFifoTopic)
Scenarios 472
AWS SDK for Go Code Examples Code Examples Guide
resources.queueUrls = append(resources.queueUrls, queueUrl)
_, filtering := runner.SubscribeQueueToTopic(queueName, queueUrl, topicName,
topicArn, ordinal, isFifoTopic)
usingFilters = usingFilters || filtering
}
log.Println(strings.Repeat("-", 88))
runner.PublishMessages(topicArn, isFifoTopic, contentBasedDeduplication,
usingFilters)
log.Println(strings.Repeat("-", 88))
runner.PollForMessages(resources.queueUrls)
log.Println(strings.Repeat("-", 88))
wantCleanup := questioner.AskBool("Do you want to remove all AWS resources created
for this scenario? (y/n) ", "y")
if wantCleanup {
log.Println("Cleaning up resources...")
resources.Cleanup()
}
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define a struct that wraps Amazon SNS actions used in this example.
// SnsActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type SnsActions struct {
SnsClient *sns.Client
}
// CreateTopic creates an Amazon SNS topic with the specified name. You can
optionally
Scenarios 473
AWS SDK for Go Code Examples Code Examples Guide
// specify that the topic is created as a FIFO topic and whether it uses content-
based
// deduplication instead of ID-based deduplication.
func (actor SnsActions) CreateTopic(topicName string, isFifoTopic bool,
contentBasedDeduplication bool) (string, error) {
var topicArn string
topicAttributes := map[string]string{}
if isFifoTopic {
topicAttributes["FifoTopic"] = "true"
}
if contentBasedDeduplication {
topicAttributes["ContentBasedDeduplication"] = "true"
}
topic, err := actor.SnsClient.CreateTopic(context.TODO(), &sns.CreateTopicInput{
Name: aws.String(topicName),
Attributes: topicAttributes,
})
if err != nil {
log.Printf("Couldn't create topic %v. Here's why: %v\n", topicName, err)
} else {
topicArn = *topic.TopicArn
}
return topicArn, err
}
// DeleteTopic delete an Amazon SNS topic.
func (actor SnsActions) DeleteTopic(topicArn string) error {
_, err := actor.SnsClient.DeleteTopic(context.TODO(), &sns.DeleteTopicInput{
TopicArn: aws.String(topicArn)})
if err != nil {
log.Printf("Couldn't delete topic %v. Here's why: %v\n", topicArn, err)
}
return err
}
// SubscribeQueue subscribes an Amazon Simple Queue Service (Amazon SQS) queue to an
// Amazon SNS topic. When filterMap is not nil, it is used to specify a filter
policy
Scenarios 474
AWS SDK for Go Code Examples Code Examples Guide
// so that messages are only sent to the queue when the message has the specified
attributes.
func (actor SnsActions) SubscribeQueue(topicArn string, queueArn string, filterMap
map[string][]string) (string, error) {
var subscriptionArn string
var attributes map[string]string
if filterMap != nil {
filterBytes, err := json.Marshal(filterMap)
if err != nil {
log.Printf("Couldn't create filter policy, here's why: %v\n", err)
return "", err
}
attributes = map[string]string{"FilterPolicy": string(filterBytes)}
}
output, err := actor.SnsClient.Subscribe(context.TODO(), &sns.SubscribeInput{
Protocol: aws.String("sqs"),
TopicArn: aws.String(topicArn),
Attributes: attributes,
Endpoint: aws.String(queueArn),
ReturnSubscriptionArn: true,
})
if err != nil {
log.Printf("Couldn't susbscribe queue %v to topic %v. Here's why: %v\n",
queueArn, topicArn, err)
} else {
subscriptionArn = *output.SubscriptionArn
}
return subscriptionArn, err
}
// Publish publishes a message to an Amazon SNS topic. The message is then sent to
all
// subscribers. When the topic is a FIFO topic, the message must also contain a
group ID
// and, when ID-based deduplication is used, a deduplication ID. An optional key-
value
// filter attribute can be specified so that the message can be filtered according
to
// a filter policy.
func (actor SnsActions) Publish(topicArn string, message string, groupId string,
dedupId string, filterKey string, filterValue string) error {
Scenarios 475
AWS SDK for Go Code Examples Code Examples Guide
publishInput := sns.PublishInput{TopicArn: aws.String(topicArn), Message:
aws.String(message)}
if groupId != "" {
publishInput.MessageGroupId = aws.String(groupId)
}
if dedupId != "" {
publishInput.MessageDeduplicationId = aws.String(dedupId)
}
if filterKey != "" && filterValue != "" {
publishInput.MessageAttributes = map[string]types.MessageAttributeValue{
filterKey: {DataType: aws.String("String"), StringValue:
aws.String(filterValue)},
}
}
_, err := actor.SnsClient.Publish(context.TODO(), &publishInput)
if err != nil {
log.Printf("Couldn't publish message to topic %v. Here's why: %v", topicArn, err)
}
return err
}
Define a struct that wraps Amazon SQS actions used in this example.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// CreateQueue creates an Amazon SQS queue with the specified name. You can specify
// whether the queue is created as a FIFO queue.
func (actor SqsActions) CreateQueue(queueName string, isFifoQueue bool) (string,
error) {
var queueUrl string
queueAttributes := map[string]string{}
if isFifoQueue {
queueAttributes["FifoQueue"] = "true"
}
Scenarios 476
AWS SDK for Go Code Examples Code Examples Guide
queue, err := actor.SqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{
QueueName: aws.String(queueName),
Attributes: queueAttributes,
})
if err != nil {
log.Printf("Couldn't create queue %v. Here's why: %v\n", queueName, err)
} else {
queueUrl = *queue.QueueUrl
}
return queueUrl, err
}
// GetQueueArn uses the GetQueueAttributes action to get the Amazon Resource Name
(ARN)
// of an Amazon SQS queue.
func (actor SqsActions) GetQueueArn(queueUrl string) (string, error) {
var queueArn string
arnAttributeName := types.QueueAttributeNameQueueArn
attribute, err := actor.SqsClient.GetQueueAttributes(context.TODO(),
&sqs.GetQueueAttributesInput{
QueueUrl: aws.String(queueUrl),
AttributeNames: []types.QueueAttributeName{arnAttributeName},
})
if err != nil {
log.Printf("Couldn't get ARN for queue %v. Here's why: %v\n", queueUrl, err)
} else {
queueArn = attribute.Attributes[string(arnAttributeName)]
}
return queueArn, err
}
// AttachSendMessagePolicy uses the SetQueueAttributes action to attach a policy to
an
// Amazon SQS queue that allows the specified Amazon SNS topic to send messages to
the
// queue.
func (actor SqsActions) AttachSendMessagePolicy(queueUrl string, queueArn string,
topicArn string) error {
policyDoc := PolicyDocument{
Scenarios 477
AWS SDK for Go Code Examples Code Examples Guide
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: "sqs:SendMessage",
Principal: map[string]string{"Service": "sns.amazonaws.com"},
Resource: aws.String(queueArn),
Condition: PolicyCondition{"ArnEquals": map[string]string{"aws:SourceArn":
topicArn}},
}},
}
policyBytes, err := json.Marshal(policyDoc)
if err != nil {
log.Printf("Couldn't create policy document. Here's why: %v\n", err)
return err
}
_, err = actor.SqsClient.SetQueueAttributes(context.TODO(),
&sqs.SetQueueAttributesInput{
Attributes: map[string]string{
string(types.QueueAttributeNamePolicy): string(policyBytes),
},
QueueUrl: aws.String(queueUrl),
})
if err != nil {
log.Printf("Couldn't set send message policy on queue %v. Here's why: %v\n",
queueUrl, err)
}
return err
}
// PolicyDocument defines a policy document as a Go struct that can be serialized
// to JSON.
type PolicyDocument struct {
Version string
Statement []PolicyStatement
}
// PolicyStatement defines a statement in a policy document.
type PolicyStatement struct {
Effect string
Action string
Principal map[string]string `json:",omitempty"`
Resource *string `json:",omitempty"`
Condition PolicyCondition `json:",omitempty"`
}
Scenarios 478
AWS SDK for Go Code Examples Code Examples Guide
// PolicyCondition defines a condition in a policy.
type PolicyCondition map[string]map[string]string
// GetMessages uses the ReceiveMessage action to get messages from an Amazon SQS
queue.
func (actor SqsActions) GetMessages(queueUrl string, maxMessages int32, waitTime
int32) ([]types.Message, error) {
var messages []types.Message
result, err := actor.SqsClient.ReceiveMessage(context.TODO(),
&sqs.ReceiveMessageInput{
QueueUrl: aws.String(queueUrl),
MaxNumberOfMessages: maxMessages,
WaitTimeSeconds: waitTime,
})
if err != nil {
log.Printf("Couldn't get messages from queue %v. Here's why: %v\n", queueUrl, err)
} else {
messages = result.Messages
}
return messages, err
}
// DeleteMessages uses the DeleteMessageBatch action to delete a batch of messages
from
// an Amazon SQS queue.
func (actor SqsActions) DeleteMessages(queueUrl string, messages []types.Message)
error {
entries := make([]types.DeleteMessageBatchRequestEntry, len(messages))
for msgIndex := range messages {
entries[msgIndex].Id = aws.String(fmt.Sprintf("%v", msgIndex))
entries[msgIndex].ReceiptHandle = messages[msgIndex].ReceiptHandle
}
_, err := actor.SqsClient.DeleteMessageBatch(context.TODO(),
&sqs.DeleteMessageBatchInput{
Entries: entries,
QueueUrl: aws.String(queueUrl),
})
if err != nil {
Scenarios 479
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Couldn't delete messages from queue %v. Here's why: %v\n", queueUrl,
err)
}
return err
}
// DeleteQueue deletes an Amazon SQS queue.
func (actor SqsActions) DeleteQueue(queueUrl string) error {
_, err := actor.SqsClient.DeleteQueue(context.TODO(), &sqs.DeleteQueueInput{
QueueUrl: aws.String(queueUrl)})
if err != nil {
log.Printf("Couldn't delete queue %v. Here's why: %v\n", queueUrl, err)
}
return err
}
For API details, see the following topics in AWS SDK for Go API Reference.
CreateQueue
CreateTopic
DeleteMessageBatch
DeleteQueue
DeleteTopic
GetQueueAttributes
Publish
ReceiveMessage
SetQueueAttributes
Subscribe
Unsubscribe
Scenarios 480
AWS SDK for Go Code Examples Code Examples Guide
Serverless examples
Invoke a Lambda function from an Amazon SNS trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving messages from an SNS topic. The function retrieves the messages from the
event parameter and logs the content of each message.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming an SNS event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, snsEvent events.SNSEvent) {
for _, record := range snsEvent.Records {
processMessage(record)
}
fmt.Println("done")
}
func processMessage(record events.SNSEventRecord) {
message := record.SNS.Message
fmt.Printf("Processed message: %s\n", message)
// TODO: Process your record here
}
Serverless examples 481
AWS SDK for Go Code Examples Code Examples Guide
func main() {
lambda.Start(handler)
}
Amazon SQS examples using SDK for Go V2
The following code examples show you how to perform actions and implement common scenarios
by using the AWS SDK for Go V2 with Amazon SQS.
Actions are code excerpts from larger programs and must be run in context. While actions show you
how to call individual service functions, you can see actions in context in their related scenarios.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple
functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how
to set up and run the code in context.
Get started
Hello Amazon SQS
The following code examples show how to get started using Amazon SQS.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
Amazon SQS 482
AWS SDK for Go Code Examples Code Examples Guide
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sqs"
)
// main uses the AWS SDK for Go V2 to create an Amazon Simple Queue Service
// (Amazon SQS) client and list the queues in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
sqsClient := sqs.NewFromConfig(sdkConfig)
fmt.Println("Let's list the queues for your account.")
var queueUrls []string
paginator := sqs.NewListQueuesPaginator(sqsClient, &sqs.ListQueuesInput{})
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get queues. Here's why: %v\n", err)
break
} else {
queueUrls = append(queueUrls, output.QueueUrls...)
}
}
if len(queueUrls) == 0 {
fmt.Println("You don't have any queues!")
} else {
for _, queueUrl := range queueUrls {
fmt.Printf("\t%v\n", queueUrl)
}
}
}
For API details, see ListQueues in AWS SDK for Go API Reference.
Amazon SQS 483
AWS SDK for Go Code Examples Code Examples Guide
Topics
Actions
Scenarios
Serverless examples
Actions
CreateQueue
The following code example shows how to use CreateQueue.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// CreateQueue creates an Amazon SQS queue with the specified name. You can specify
// whether the queue is created as a FIFO queue.
func (actor SqsActions) CreateQueue(queueName string, isFifoQueue bool) (string,
error) {
var queueUrl string
queueAttributes := map[string]string{}
if isFifoQueue {
queueAttributes["FifoQueue"] = "true"
}
queue, err := actor.SqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{
QueueName: aws.String(queueName),
Actions 484
AWS SDK for Go Code Examples Code Examples Guide
Attributes: queueAttributes,
})
if err != nil {
log.Printf("Couldn't create queue %v. Here's why: %v\n", queueName, err)
} else {
queueUrl = *queue.QueueUrl
}
return queueUrl, err
}
For API details, see CreateQueue in AWS SDK for Go API Reference.
DeleteMessageBatch
The following code example shows how to use DeleteMessageBatch.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// DeleteMessages uses the DeleteMessageBatch action to delete a batch of messages
from
// an Amazon SQS queue.
func (actor SqsActions) DeleteMessages(queueUrl string, messages []types.Message)
error {
Actions 485
AWS SDK for Go Code Examples Code Examples Guide
entries := make([]types.DeleteMessageBatchRequestEntry, len(messages))
for msgIndex := range messages {
entries[msgIndex].Id = aws.String(fmt.Sprintf("%v", msgIndex))
entries[msgIndex].ReceiptHandle = messages[msgIndex].ReceiptHandle
}
_, err := actor.SqsClient.DeleteMessageBatch(context.TODO(),
&sqs.DeleteMessageBatchInput{
Entries: entries,
QueueUrl: aws.String(queueUrl),
})
if err != nil {
log.Printf("Couldn't delete messages from queue %v. Here's why: %v\n", queueUrl,
err)
}
return err
}
For API details, see DeleteMessageBatch in AWS SDK for Go API Reference.
DeleteQueue
The following code example shows how to use DeleteQueue.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
Actions 486
AWS SDK for Go Code Examples Code Examples Guide
// DeleteQueue deletes an Amazon SQS queue.
func (actor SqsActions) DeleteQueue(queueUrl string) error {
_, err := actor.SqsClient.DeleteQueue(context.TODO(), &sqs.DeleteQueueInput{
QueueUrl: aws.String(queueUrl)})
if err != nil {
log.Printf("Couldn't delete queue %v. Here's why: %v\n", queueUrl, err)
}
return err
}
For API details, see DeleteQueue in AWS SDK for Go API Reference.
GetQueueAttributes
The following code example shows how to use GetQueueAttributes.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// GetQueueArn uses the GetQueueAttributes action to get the Amazon Resource Name
(ARN)
// of an Amazon SQS queue.
func (actor SqsActions) GetQueueArn(queueUrl string) (string, error) {
var queueArn string
Actions 487
AWS SDK for Go Code Examples Code Examples Guide
arnAttributeName := types.QueueAttributeNameQueueArn
attribute, err := actor.SqsClient.GetQueueAttributes(context.TODO(),
&sqs.GetQueueAttributesInput{
QueueUrl: aws.String(queueUrl),
AttributeNames: []types.QueueAttributeName{arnAttributeName},
})
if err != nil {
log.Printf("Couldn't get ARN for queue %v. Here's why: %v\n", queueUrl, err)
} else {
queueArn = attribute.Attributes[string(arnAttributeName)]
}
return queueArn, err
}
For API details, see GetQueueAttributes in AWS SDK for Go API Reference.
ListQueues
The following code example shows how to use ListQueues.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sqs"
)
Actions 488
AWS SDK for Go Code Examples Code Examples Guide
// main uses the AWS SDK for Go V2 to create an Amazon Simple Queue Service
// (Amazon SQS) client and list the queues in your account.
// This example uses the default settings specified in your shared credentials
// and config files.
func main() {
sdkConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
fmt.Println("Couldn't load default configuration. Have you set up your AWS
account?")
fmt.Println(err)
return
}
sqsClient := sqs.NewFromConfig(sdkConfig)
fmt.Println("Let's list the queues for your account.")
var queueUrls []string
paginator := sqs.NewListQueuesPaginator(sqsClient, &sqs.ListQueuesInput{})
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.TODO())
if err != nil {
log.Printf("Couldn't get queues. Here's why: %v\n", err)
break
} else {
queueUrls = append(queueUrls, output.QueueUrls...)
}
}
if len(queueUrls) == 0 {
fmt.Println("You don't have any queues!")
} else {
for _, queueUrl := range queueUrls {
fmt.Printf("\t%v\n", queueUrl)
}
}
}
For API details, see ListQueues in AWS SDK for Go API Reference.
ReceiveMessage
The following code example shows how to use ReceiveMessage.
Actions 489
AWS SDK for Go Code Examples Code Examples Guide
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// GetMessages uses the ReceiveMessage action to get messages from an Amazon SQS
queue.
func (actor SqsActions) GetMessages(queueUrl string, maxMessages int32, waitTime
int32) ([]types.Message, error) {
var messages []types.Message
result, err := actor.SqsClient.ReceiveMessage(context.TODO(),
&sqs.ReceiveMessageInput{
QueueUrl: aws.String(queueUrl),
MaxNumberOfMessages: maxMessages,
WaitTimeSeconds: waitTime,
})
if err != nil {
log.Printf("Couldn't get messages from queue %v. Here's why: %v\n", queueUrl, err)
} else {
messages = result.Messages
}
return messages, err
}
For API details, see ReceiveMessage in AWS SDK for Go API Reference.
Actions 490
AWS SDK for Go Code Examples Code Examples Guide
SetQueueAttributes
The following code example shows how to use SetQueueAttributes.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// AttachSendMessagePolicy uses the SetQueueAttributes action to attach a policy to
an
// Amazon SQS queue that allows the specified Amazon SNS topic to send messages to
the
// queue.
func (actor SqsActions) AttachSendMessagePolicy(queueUrl string, queueArn string,
topicArn string) error {
policyDoc := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: "sqs:SendMessage",
Principal: map[string]string{"Service": "sns.amazonaws.com"},
Resource: aws.String(queueArn),
Condition: PolicyCondition{"ArnEquals": map[string]string{"aws:SourceArn":
topicArn}},
}},
}
policyBytes, err := json.Marshal(policyDoc)
if err != nil {
log.Printf("Couldn't create policy document. Here's why: %v\n", err)
return err
Actions 491
AWS SDK for Go Code Examples Code Examples Guide
}
_, err = actor.SqsClient.SetQueueAttributes(context.TODO(),
&sqs.SetQueueAttributesInput{
Attributes: map[string]string{
string(types.QueueAttributeNamePolicy): string(policyBytes),
},
QueueUrl: aws.String(queueUrl),
})
if err != nil {
log.Printf("Couldn't set send message policy on queue %v. Here's why: %v\n",
queueUrl, err)
}
return err
}
// PolicyDocument defines a policy document as a Go struct that can be serialized
// to JSON.
type PolicyDocument struct {
Version string
Statement []PolicyStatement
}
// PolicyStatement defines a statement in a policy document.
type PolicyStatement struct {
Effect string
Action string
Principal map[string]string `json:",omitempty"`
Resource *string `json:",omitempty"`
Condition PolicyCondition `json:",omitempty"`
}
// PolicyCondition defines a condition in a policy.
type PolicyCondition map[string]map[string]string
For API details, see SetQueueAttributes in AWS SDK for Go API Reference.
Scenarios
Publish messages to queues
The following code example shows how to:
Scenarios 492
AWS SDK for Go Code Examples Code Examples Guide
Create topic (FIFO or non-FIFO).
Subscribe several queues to the topic with an option to apply a filter.
Publish messages to the topic.
Poll the queues for messages received.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the AWS Code Examples Repository.
Run an interactive scenario at a command prompt.
const FIFO_SUFFIX = ".fifo"
const TONE_KEY = "tone"
var ToneChoices = []string{"cheerful", "funny", "serious", "sincere"}
// MessageBody is used to deserialize the body of a message from a JSON string.
type MessageBody struct {
Message string
}
// ScenarioRunner separates the steps of this scenario into individual functions so
that
// they are simpler to read and understand.
type ScenarioRunner struct {
questioner demotools.IQuestioner
snsActor *actions.SnsActions
sqsActor *actions.SqsActions
}
func (runner ScenarioRunner) CreateTopic() (string, string, bool, bool) {
log.Println("SNS topics can be configured as FIFO (First-In-First-Out) or standard.
\n" +
"FIFO topics deliver messages in order and support deduplication and message
filtering.")
Scenarios 493
AWS SDK for Go Code Examples Code Examples Guide
isFifoTopic := runner.questioner.AskBool("\nWould you like to work with FIFO
topics? (y/n) ", "y")
contentBasedDeduplication := false
if isFifoTopic {
log.Println(strings.Repeat("-", 88))
log.Println("Because you have chosen a FIFO topic, deduplication is supported.\n"
+
"Deduplication IDs are either set in the message or are automatically generated
\n" +
"from content using a hash function. If a message is successfully published to\n"
+
"an SNS FIFO topic, any message published and determined to have the same\n" +
"deduplication ID, within the five-minute deduplication interval, is accepted\n"
+
"but not delivered. For more information about deduplication, see:\n" +
"\thttps://docs.aws.amazon.com/sns/latest/dg/fifo-message-dedup.html.")
contentBasedDeduplication = runner.questioner.AskBool(
"\nDo you want to use content-based deduplication instead of entering a
deduplication ID? (y/n) ", "y")
}
log.Println(strings.Repeat("-", 88))
topicName := runner.questioner.Ask("Enter a name for your SNS topic. ")
if isFifoTopic {
topicName = fmt.Sprintf("%v%v", topicName, FIFO_SUFFIX)
log.Printf("Because you have selected a FIFO topic, '%v' must be appended to\n"+
"the topic name.", FIFO_SUFFIX)
}
topicArn, err := runner.snsActor.CreateTopic(topicName, isFifoTopic,
contentBasedDeduplication)
if err != nil {
panic(err)
}
log.Printf("Your new topic with the name '%v' and Amazon Resource Name (ARN) \n"+
"'%v' has been created.", topicName, topicArn)
return topicName, topicArn, isFifoTopic, contentBasedDeduplication
}
func (runner ScenarioRunner) CreateQueue(ordinal string, isFifoTopic bool) (string,
string) {
Scenarios 494
AWS SDK for Go Code Examples Code Examples Guide
queueName := runner.questioner.Ask(fmt.Sprintf("Enter a name for the %v SQS queue.
", ordinal))
if isFifoTopic {
queueName = fmt.Sprintf("%v%v", queueName, FIFO_SUFFIX)
if ordinal == "first" {
log.Printf("Because you are creating a FIFO SQS queue, '%v' must "+
"be appended to the queue name.\n", FIFO_SUFFIX)
}
}
queueUrl, err := runner.sqsActor.CreateQueue(queueName, isFifoTopic)
if err != nil {
panic(err)
}
log.Printf("Your new SQS queue with the name '%v' and the queue URL "+
"'%v' has been created.", queueName, queueUrl)
return queueName, queueUrl
}
func (runner ScenarioRunner) SubscribeQueueToTopic(
queueName string, queueUrl string, topicName string, topicArn string, ordinal
string,
isFifoTopic bool) (string, bool) {
queueArn, err := runner.sqsActor.GetQueueArn(queueUrl)
if err != nil {
panic(err)
}
log.Printf("The ARN of your queue is: %v.\n", queueArn)
err = runner.sqsActor.AttachSendMessagePolicy(queueUrl, queueArn, topicArn)
if err != nil {
panic(err)
}
log.Println("Attached an IAM policy to the queue so the SNS topic can send " +
"messages to it.")
log.Println(strings.Repeat("-", 88))
var filterPolicy map[string][]string
if isFifoTopic {
if ordinal == "first" {
log.Println("Subscriptions to a FIFO topic can have filters.\n" +
"If you add a filter to this subscription, then only the filtered messages\n" +
"will be received in the queue.\n" +
Scenarios 495
AWS SDK for Go Code Examples Code Examples Guide
"For information about message filtering, see\n" +
"\thttps://docs.aws.amazon.com/sns/latest/dg/sns-message-filtering.html\n" +
"For this example, you can filter messages by a \"tone\" attribute.")
}
wantFiltering := runner.questioner.AskBool(
fmt.Sprintf("Do you want to filter messages that are sent to \"%v\"\n"+
"from the %v topic? (y/n) ", queueName, topicName), "y")
if wantFiltering {
log.Println("You can filter messages by one or more of the following \"tone\"
attributes.")
var toneSelections []string
askAboutTones := true
for askAboutTones {
toneIndex := runner.questioner.AskChoice(
"Enter the number of the tone you want to filter by:\n", ToneChoices)
toneSelections = append(toneSelections, ToneChoices[toneIndex])
askAboutTones = runner.questioner.AskBool("Do you want to add another tone to
the filter? (y/n) ", "y")
}
log.Printf("Your subscription will be filtered to only pass the following tones:
%v\n", toneSelections)
filterPolicy = map[string][]string{TONE_KEY: toneSelections}
}
}
subscriptionArn, err := runner.snsActor.SubscribeQueue(topicArn, queueArn,
filterPolicy)
if err != nil {
panic(err)
}
log.Printf("The queue %v is now subscribed to the topic %v with the subscription
ARN %v.\n",
queueName, topicName, subscriptionArn)
return subscriptionArn, filterPolicy != nil
}
func (runner ScenarioRunner) PublishMessages(topicArn string, isFifoTopic bool,
contentBasedDeduplication bool, usingFilters bool) {
var message string
var groupId string
var dedupId string
Scenarios 496
AWS SDK for Go Code Examples Code Examples Guide
var toneSelection string
publishMore := true
for publishMore {
groupId = ""
dedupId = ""
toneSelection = ""
message = runner.questioner.Ask("Enter a message to publish: ")
if isFifoTopic {
log.Println("Because you are using a FIFO topic, you must set a message group ID.
\n" +
"All messages within the same group will be received in the order they were
published.")
groupId = runner.questioner.Ask("Enter a message group ID: ")
if !contentBasedDeduplication {
log.Println("Because you are not using content-based deduplication,\n" +
"you must enter a deduplication ID.")
dedupId = runner.questioner.Ask("Enter a deduplication ID: ")
}
}
if usingFilters {
if runner.questioner.AskBool("Add a tone attribute so this message can be
filtered? (y/n) ", "y") {
toneIndex := runner.questioner.AskChoice(
"Enter the number of the tone you want to filter by:\n", ToneChoices)
toneSelection = ToneChoices[toneIndex]
}
}
err := runner.snsActor.Publish(topicArn, message, groupId, dedupId, TONE_KEY,
toneSelection)
if err != nil {
panic(err)
}
log.Println(("Your message was published."))
publishMore = runner.questioner.AskBool("Do you want to publish another messsage?
(y/n) ", "y")
}
}
func (runner ScenarioRunner) PollForMessages(queueUrls []string) {
log.Println("Polling queues for messages...")
for _, queueUrl := range queueUrls {
var messages []types.Message
Scenarios 497
AWS SDK for Go Code Examples Code Examples Guide
for {
currentMsgs, err := runner.sqsActor.GetMessages(queueUrl, 10, 1)
if err != nil {
panic(err)
}
if len(currentMsgs) == 0 {
break
}
messages = append(messages, currentMsgs...)
}
if len(messages) == 0 {
log.Printf("No messages were received by queue %v.\n", queueUrl)
} else if len(messages) == 1 {
log.Printf("One message was received by queue %v:\n", queueUrl)
} else {
log.Printf("%v messages were received by queue %v:\n", len(messages), queueUrl)
}
for msgIndex, message := range messages {
messageBody := MessageBody{}
err := json.Unmarshal([]byte(*message.Body), &messageBody)
if err != nil {
panic(err)
}
log.Printf("Message %v: %v\n", msgIndex+1, messageBody.Message)
}
if len(messages) > 0 {
log.Printf("Deleting %v messages from queue %v.\n", len(messages), queueUrl)
err := runner.sqsActor.DeleteMessages(queueUrl, messages)
if err != nil {
panic(err)
}
}
}
}
// RunTopicsAndQueuesScenario is an interactive example that shows you how to use
the
// AWS SDK for Go to create and use Amazon SNS topics and Amazon SQS queues.
//
// 1. Create a topic (FIFO or non-FIFO).
// 2. Subscribe several queues to the topic with an option to apply a filter.
// 3. Publish messages to the topic.
Scenarios 498
AWS SDK for Go Code Examples Code Examples Guide
// 4. Poll the queues for messages received.
// 5. Delete the topic and the queues.
//
// This example creates service clients from the specified sdkConfig so that
// you can replace it with a mocked or stubbed config for unit testing.
//
// It uses a questioner from the `demotools` package to get input during the
example.
// This package can be found in the ..\..\demotools folder of this repo.
func RunTopicsAndQueuesScenario(
sdkConfig aws.Config, questioner demotools.IQuestioner) {
resources := Resources{}
defer func() {
if r := recover(); r != nil {
log.Println("Something went wrong with the demo.\n" +
"Cleaning up any resources that were created...")
resources.Cleanup()
}
}()
queueCount := 2
log.Println(strings.Repeat("-", 88))
log.Printf("Welcome to messaging with topics and queues.\n\n"+
"In this workflow, you will create an SNS topic and subscribe %v SQS queues to the
\n"+
"topic. You can select from several options for configuring the topic and the\n"+
"subscriptions for the queues. You can then post to the topic and see the results
\n"+
"in the queues.\n", queueCount)
log.Println(strings.Repeat("-", 88))
runner := ScenarioRunner{
questioner: questioner,
snsActor: &actions.SnsActions{SnsClient: sns.NewFromConfig(sdkConfig)},
sqsActor: &actions.SqsActions{SqsClient: sqs.NewFromConfig(sdkConfig)},
}
resources.snsActor = runner.snsActor
resources.sqsActor = runner.sqsActor
topicName, topicArn, isFifoTopic, contentBasedDeduplication := runner.CreateTopic()
resources.topicArn = topicArn
log.Println(strings.Repeat("-", 88))
Scenarios 499
AWS SDK for Go Code Examples Code Examples Guide
log.Printf("Now you will create %v SQS queues and subscribe them to the topic.\n",
queueCount)
ordinals := []string{"first", "next"}
usingFilters := false
for _, ordinal := range ordinals {
queueName, queueUrl := runner.CreateQueue(ordinal, isFifoTopic)
resources.queueUrls = append(resources.queueUrls, queueUrl)
_, filtering := runner.SubscribeQueueToTopic(queueName, queueUrl, topicName,
topicArn, ordinal, isFifoTopic)
usingFilters = usingFilters || filtering
}
log.Println(strings.Repeat("-", 88))
runner.PublishMessages(topicArn, isFifoTopic, contentBasedDeduplication,
usingFilters)
log.Println(strings.Repeat("-", 88))
runner.PollForMessages(resources.queueUrls)
log.Println(strings.Repeat("-", 88))
wantCleanup := questioner.AskBool("Do you want to remove all AWS resources created
for this scenario? (y/n) ", "y")
if wantCleanup {
log.Println("Cleaning up resources...")
resources.Cleanup()
}
log.Println(strings.Repeat("-", 88))
log.Println("Thanks for watching!")
log.Println(strings.Repeat("-", 88))
}
Define a struct that wraps Amazon SNS actions used in this example.
// SnsActions encapsulates the Amazon Simple Notification Service (Amazon SNS)
actions
// used in the examples.
type SnsActions struct {
SnsClient *sns.Client
Scenarios 500
AWS SDK for Go Code Examples Code Examples Guide
}
// CreateTopic creates an Amazon SNS topic with the specified name. You can
optionally
// specify that the topic is created as a FIFO topic and whether it uses content-
based
// deduplication instead of ID-based deduplication.
func (actor SnsActions) CreateTopic(topicName string, isFifoTopic bool,
contentBasedDeduplication bool) (string, error) {
var topicArn string
topicAttributes := map[string]string{}
if isFifoTopic {
topicAttributes["FifoTopic"] = "true"
}
if contentBasedDeduplication {
topicAttributes["ContentBasedDeduplication"] = "true"
}
topic, err := actor.SnsClient.CreateTopic(context.TODO(), &sns.CreateTopicInput{
Name: aws.String(topicName),
Attributes: topicAttributes,
})
if err != nil {
log.Printf("Couldn't create topic %v. Here's why: %v\n", topicName, err)
} else {
topicArn = *topic.TopicArn
}
return topicArn, err
}
// DeleteTopic delete an Amazon SNS topic.
func (actor SnsActions) DeleteTopic(topicArn string) error {
_, err := actor.SnsClient.DeleteTopic(context.TODO(), &sns.DeleteTopicInput{
TopicArn: aws.String(topicArn)})
if err != nil {
log.Printf("Couldn't delete topic %v. Here's why: %v\n", topicArn, err)
}
return err
}
Scenarios 501
AWS SDK for Go Code Examples Code Examples Guide
// SubscribeQueue subscribes an Amazon Simple Queue Service (Amazon SQS) queue to an
// Amazon SNS topic. When filterMap is not nil, it is used to specify a filter
policy
// so that messages are only sent to the queue when the message has the specified
attributes.
func (actor SnsActions) SubscribeQueue(topicArn string, queueArn string, filterMap
map[string][]string) (string, error) {
var subscriptionArn string
var attributes map[string]string
if filterMap != nil {
filterBytes, err := json.Marshal(filterMap)
if err != nil {
log.Printf("Couldn't create filter policy, here's why: %v\n", err)
return "", err
}
attributes = map[string]string{"FilterPolicy": string(filterBytes)}
}
output, err := actor.SnsClient.Subscribe(context.TODO(), &sns.SubscribeInput{
Protocol: aws.String("sqs"),
TopicArn: aws.String(topicArn),
Attributes: attributes,
Endpoint: aws.String(queueArn),
ReturnSubscriptionArn: true,
})
if err != nil {
log.Printf("Couldn't susbscribe queue %v to topic %v. Here's why: %v\n",
queueArn, topicArn, err)
} else {
subscriptionArn = *output.SubscriptionArn
}
return subscriptionArn, err
}
// Publish publishes a message to an Amazon SNS topic. The message is then sent to
all
// subscribers. When the topic is a FIFO topic, the message must also contain a
group ID
// and, when ID-based deduplication is used, a deduplication ID. An optional key-
value
Scenarios 502
AWS SDK for Go Code Examples Code Examples Guide
// filter attribute can be specified so that the message can be filtered according
to
// a filter policy.
func (actor SnsActions) Publish(topicArn string, message string, groupId string,
dedupId string, filterKey string, filterValue string) error {
publishInput := sns.PublishInput{TopicArn: aws.String(topicArn), Message:
aws.String(message)}
if groupId != "" {
publishInput.MessageGroupId = aws.String(groupId)
}
if dedupId != "" {
publishInput.MessageDeduplicationId = aws.String(dedupId)
}
if filterKey != "" && filterValue != "" {
publishInput.MessageAttributes = map[string]types.MessageAttributeValue{
filterKey: {DataType: aws.String("String"), StringValue:
aws.String(filterValue)},
}
}
_, err := actor.SnsClient.Publish(context.TODO(), &publishInput)
if err != nil {
log.Printf("Couldn't publish message to topic %v. Here's why: %v", topicArn, err)
}
return err
}
Define a struct that wraps Amazon SQS actions used in this example.
// SqsActions encapsulates the Amazon Simple Queue Service (Amazon SQS) actions
// used in the examples.
type SqsActions struct {
SqsClient *sqs.Client
}
// CreateQueue creates an Amazon SQS queue with the specified name. You can specify
// whether the queue is created as a FIFO queue.
func (actor SqsActions) CreateQueue(queueName string, isFifoQueue bool) (string,
error) {
Scenarios 503
AWS SDK for Go Code Examples Code Examples Guide
var queueUrl string
queueAttributes := map[string]string{}
if isFifoQueue {
queueAttributes["FifoQueue"] = "true"
}
queue, err := actor.SqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{
QueueName: aws.String(queueName),
Attributes: queueAttributes,
})
if err != nil {
log.Printf("Couldn't create queue %v. Here's why: %v\n", queueName, err)
} else {
queueUrl = *queue.QueueUrl
}
return queueUrl, err
}
// GetQueueArn uses the GetQueueAttributes action to get the Amazon Resource Name
(ARN)
// of an Amazon SQS queue.
func (actor SqsActions) GetQueueArn(queueUrl string) (string, error) {
var queueArn string
arnAttributeName := types.QueueAttributeNameQueueArn
attribute, err := actor.SqsClient.GetQueueAttributes(context.TODO(),
&sqs.GetQueueAttributesInput{
QueueUrl: aws.String(queueUrl),
AttributeNames: []types.QueueAttributeName{arnAttributeName},
})
if err != nil {
log.Printf("Couldn't get ARN for queue %v. Here's why: %v\n", queueUrl, err)
} else {
queueArn = attribute.Attributes[string(arnAttributeName)]
}
return queueArn, err
}
// AttachSendMessagePolicy uses the SetQueueAttributes action to attach a policy to
an
Scenarios 504
AWS SDK for Go Code Examples Code Examples Guide
// Amazon SQS queue that allows the specified Amazon SNS topic to send messages to
the
// queue.
func (actor SqsActions) AttachSendMessagePolicy(queueUrl string, queueArn string,
topicArn string) error {
policyDoc := PolicyDocument{
Version: "2012-10-17",
Statement: []PolicyStatement{{
Effect: "Allow",
Action: "sqs:SendMessage",
Principal: map[string]string{"Service": "sns.amazonaws.com"},
Resource: aws.String(queueArn),
Condition: PolicyCondition{"ArnEquals": map[string]string{"aws:SourceArn":
topicArn}},
}},
}
policyBytes, err := json.Marshal(policyDoc)
if err != nil {
log.Printf("Couldn't create policy document. Here's why: %v\n", err)
return err
}
_, err = actor.SqsClient.SetQueueAttributes(context.TODO(),
&sqs.SetQueueAttributesInput{
Attributes: map[string]string{
string(types.QueueAttributeNamePolicy): string(policyBytes),
},
QueueUrl: aws.String(queueUrl),
})
if err != nil {
log.Printf("Couldn't set send message policy on queue %v. Here's why: %v\n",
queueUrl, err)
}
return err
}
// PolicyDocument defines a policy document as a Go struct that can be serialized
// to JSON.
type PolicyDocument struct {
Version string
Statement []PolicyStatement
}
// PolicyStatement defines a statement in a policy document.
type PolicyStatement struct {
Scenarios 505
AWS SDK for Go Code Examples Code Examples Guide
Effect string
Action string
Principal map[string]string `json:",omitempty"`
Resource *string `json:",omitempty"`
Condition PolicyCondition `json:",omitempty"`
}
// PolicyCondition defines a condition in a policy.
type PolicyCondition map[string]map[string]string
// GetMessages uses the ReceiveMessage action to get messages from an Amazon SQS
queue.
func (actor SqsActions) GetMessages(queueUrl string, maxMessages int32, waitTime
int32) ([]types.Message, error) {
var messages []types.Message
result, err := actor.SqsClient.ReceiveMessage(context.TODO(),
&sqs.ReceiveMessageInput{
QueueUrl: aws.String(queueUrl),
MaxNumberOfMessages: maxMessages,
WaitTimeSeconds: waitTime,
})
if err != nil {
log.Printf("Couldn't get messages from queue %v. Here's why: %v\n", queueUrl, err)
} else {
messages = result.Messages
}
return messages, err
}
// DeleteMessages uses the DeleteMessageBatch action to delete a batch of messages
from
// an Amazon SQS queue.
func (actor SqsActions) DeleteMessages(queueUrl string, messages []types.Message)
error {
entries := make([]types.DeleteMessageBatchRequestEntry, len(messages))
for msgIndex := range messages {
entries[msgIndex].Id = aws.String(fmt.Sprintf("%v", msgIndex))
entries[msgIndex].ReceiptHandle = messages[msgIndex].ReceiptHandle
}
Scenarios 506
AWS SDK for Go Code Examples Code Examples Guide
_, err := actor.SqsClient.DeleteMessageBatch(context.TODO(),
&sqs.DeleteMessageBatchInput{
Entries: entries,
QueueUrl: aws.String(queueUrl),
})
if err != nil {
log.Printf("Couldn't delete messages from queue %v. Here's why: %v\n", queueUrl,
err)
}
return err
}
// DeleteQueue deletes an Amazon SQS queue.
func (actor SqsActions) DeleteQueue(queueUrl string) error {
_, err := actor.SqsClient.DeleteQueue(context.TODO(), &sqs.DeleteQueueInput{
QueueUrl: aws.String(queueUrl)})
if err != nil {
log.Printf("Couldn't delete queue %v. Here's why: %v\n", queueUrl, err)
}
return err
}
For API details, see the following topics in AWS SDK for Go API Reference.
CreateQueue
CreateTopic
DeleteMessageBatch
DeleteQueue
DeleteTopic
GetQueueAttributes
Publish
ReceiveMessage
SetQueueAttributes
Subscribe
Unsubscribe
Scenarios 507
AWS SDK for Go Code Examples Code Examples Guide
Serverless examples
Invoke a Lambda function from an Amazon SQS trigger
The following code example shows how to implement a Lambda function that receives an event
triggered by receiving messages from an SQS queue. The function retrieves the messages from the
event parameter and logs the content of each message.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Consuming an SQS event with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration_sqs_to_lambda
import (
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(event events.SQSEvent) error {
for _, record := range event.Records {
err := processMessage(record)
if err != nil {
return err
}
}
fmt.Println("done")
return nil
}
func processMessage(record events.SQSMessage) error {
fmt.Printf("Processed message %s\n", record.Body)
// TODO: Do interesting work based on the new message
Serverless examples 508
AWS SDK for Go Code Examples Code Examples Guide
return nil
}
func main() {
lambda.Start(handler)
}
Reporting batch item failures for Lambda functions with an Amazon SQS trigger
The following code example shows how to implement partial batch response for Lambda functions
that receive events from an SQS queue. The function reports the batch item failures in the
response, signaling to Lambda to retry those messages later.
SDK for Go V2
Note
There's more on GitHub. Find the complete example and learn how to set up and run in
the Serverless examples repository.
Reporting SQS batch item failures with Lambda using Go.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(ctx context.Context, sqsEvent events.SQSEvent) (map[string]interface{},
error) {
batchItemFailures := []map[string]interface{}{}
for _, message := range sqsEvent.Records {
Serverless examples 509
AWS SDK for Go Code Examples Code Examples Guide
if /* Your message processing condition here */ {
batchItemFailures = append(batchItemFailures, map[string]interface{}
{"itemIdentifier": message.MessageId})
}
}
sqsBatchResponse := map[string]interface{}{
"batchItemFailures": batchItemFailures,
}
return sqsBatchResponse, nil
}
func main() {
lambda.Start(handler)
}
Serverless examples 510
AWS SDK for Go Code Examples Code Examples Guide
Document history for the AWS SDK for Go V2 Code
Examples guide.
The following table describes the documentation releases for AWS SDK for Go code examples.
Change Description Date
Initial release Initial release of the AWS SDK
for Go Code Examples guide
February 22, 2024
511