Repository: gruntwork-io/terragrunt (language: go)

Issue:
Terragrunt User Agent for API request
It would be usefull for CloudTrail debugging.
I found a similar issue for [Terraform](https://github.com/hashicorp/terraform/issues/5020).


Discussion / hints:
Ah, that seems like a good idea. Terragrunt doesn't make too many API calls to AWS itself, but for the ones it does, we should add this. PRs welcome!

Fix patch:
diff --git a/aws_helper/config.go b/aws_helper/config.go
index 897cb277ca..5a4c470f1e 100644
--- a/aws_helper/config.go
+++ b/aws_helper/config.go
@@ -4,6 +4,9 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/gruntwork-io/go-commons/version"
+
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/arn"
 	"github.com/aws/aws-sdk-go/aws/credentials"
@@ -29,6 +32,13 @@ type AwsSessionConfig struct {
 	SessionName             string
 }
 
+// addUserAgent - Add terragrunt version to the user agent for AWS API calls.
+var addUserAgent = request.NamedHandler{
+	Name: "terragrunt.UserAgentHandler",
+	Fn: request.MakeAddToUserAgentHandler(
+		"terragrunt", version.GetVersion()),
+}
+
 // Returns an AWS session object for the given config region (required), profile name (optional), and IAM role to assume
 // (optional), ensuring that the credentials are available.
 func CreateAwsSessionFromConfig(config *AwsSessionConfig, terragruntOptions *options.TerragruntOptions) (*session.Session, error) {
@@ -71,6 +81,8 @@ func CreateAwsSessionFromConfig(config *AwsSessionConfig, terragruntOptions *opt
 		return nil, errors.WithStackTraceAndPrefix(err, "Error initializing session")
 	}
 
+	sess.Handlers.Build.PushFrontNamed(addUserAgent)
+
 	// Merge the config based IAMRole options into the original one, as the config has higher precedence than CLI.
 	iamRoleOptions := terragruntOptions.IAMRoleOptions
 	if config.RoleArn != "" {
@@ -125,6 +137,7 @@ func CreateAwsSession(config *AwsSessionConfig, terragruntOptions *options.Terra
 		if err != nil {
 			return nil, errors.WithStackTrace(err)
 		}
+		sess.Handlers.Build.PushFrontNamed(addUserAgent)
 		if terragruntOptions.IAMRoleOptions.RoleARN != "" {
 			terragruntOptions.Logger.Debugf("Assuming role %s", terragruntOptions.IAMRoleOptions.RoleARN)
 			sess.Config.Credentials = getSTSCredentialsFromIAMRoleOptions(sess, terragruntOptions.IAMRoleOptions)
@@ -156,6 +169,8 @@ func AssumeIamRole(iamRoleOpts options.IAMRoleOptions) (*sts.Credentials, error)
 		return nil, errors.WithStackTrace(err)
 	}
 
+	sess.Handlers.Build.PushFrontNamed(addUserAgent)
+
 	_, err = sess.Config.Credentials.Get()
 	if err != nil {
 		return nil, errors.WithStackTraceAndPrefix(err, "Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?)")


Test patch:
diff --git a/aws_helper/config_test.go b/aws_helper/config_test.go
new file mode 100644
index 0000000000..9e94b54f44
--- /dev/null
+++ b/aws_helper/config_test.go
@@ -0,0 +1,30 @@
+package aws_helper
+
+import (
+	"testing"
+
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/service/sts"
+	"github.com/gruntwork-io/terragrunt/options"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestTerragruntIsAddedInUserAgent(t *testing.T) {
+	t.Parallel()
+
+	sess, err := CreateAwsSession(nil, options.NewTerragruntOptions())
+	assert.NoError(t, err)
+
+	op := &request.Operation{
+		Name:       "",
+		HTTPMethod: "POST",
+		HTTPPath:   "/",
+	}
+	input := &sts.GetCallerIdentityInput{}
+	output := &sts.GetCallerIdentityOutput{}
+
+	r := sts.New(sess).NewRequest(op, input, output)
+	sess.Handlers.Build.Run(r)
+
+	assert.Contains(t, r.HTTPRequest.Header.Get("User-Agent"), "terragrunt")
+}