aws

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2025 License: MIT Imports: 7 Imported by: 0

README

AWS Utilities for Go

Go GoDoc

v1 - Experimental: This library is in its initial release phase. APIs may change in future versions.

Idiomatic Go helpers for AWS SDK v2, designed for production use.

Features

  • No global state: All clients are explicitly created and passed
  • Context-aware: All operations accept context.Context for cancellation and timeouts
  • Testable: Interfaces enable mocking without real AWS calls
  • Explicit configuration: No magic; all settings are visible
  • Safe defaults: Sensible retry policies out of the box
  • Minimal abstraction: Helpers augment the SDK, not replace it

Installation

go get github.com/alessiosavi/GoGPUtils/aws

Supported Services

Package Service Description
aws Core Configuration, errors, common utilities
aws/s3 S3 Object storage operations
aws/dynamodb DynamoDB NoSQL database operations
aws/sqs SQS Message queue operations
aws/secretsmanager Secrets Manager Secret storage and retrieval
aws/ssm SSM Parameter Store Configuration parameter storage
aws/lambda Lambda Serverless function operations

Quick Start

Configuration
package main

import (
    "context"
    "log"

    "github.com/alessiosavi/GoGPUtils/aws"
    "github.com/alessiosavi/GoGPUtils/aws/s3"
)

func main() {
    ctx := context.Background()

    // Load AWS configuration
    cfg, err := aws.LoadConfig(ctx,
        aws.WithRegion("us-west-2"),
        aws.WithRetryMaxAttempts(5),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Create S3 client
    s3Client, err := s3.NewClient(cfg)
    if err != nil {
        log.Fatal(err)
    }

    // Use the client
    data, err := s3Client.GetObject(ctx, "my-bucket", "my-key")
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Downloaded %d bytes", len(data))
}

Service Examples

S3
// Upload an object
err := client.PutObject(ctx, "bucket", "key", []byte("content"),
    s3.WithContentType("text/plain"),
    s3.WithStorageClass(types.StorageClassStandardIa),
)

// Download an object
data, err := client.GetObject(ctx, "bucket", "key")

// List objects with prefix
objects, err := client.ListObjects(ctx, "bucket",
    s3.WithPrefix("logs/"),
    s3.WithMaxKeys(100),
)

// Check if object exists
exists, err := client.ObjectExists(ctx, "bucket", "key")

// Copy/Move objects
err := client.CopyObject(ctx, "src-bucket", "src-key", "dst-bucket", "dst-key")
err := client.MoveObject(ctx, "bucket", "old-key", "bucket", "new-key")

// Parse S3 URIs
bucket, key, err := s3.ParseS3Path("s3://my-bucket/path/to/file.txt")
DynamoDB
// Define your item struct
type User struct {
    ID    string `dynamodbav:"pk"`
    Email string `dynamodbav:"email"`
    Name  string `dynamodbav:"name"`
}

// Put an item
user := User{ID: "user-123", Email: "[email protected]", Name: "Alice"}
err := client.PutItem(ctx, "users", user)

// Get an item
var result User
err := client.GetItem(ctx, "users", dynamodb.Key{"pk": "user-123"}, &result)

// Query items
keyExpr := expression.Key("pk").Equal(expression.Value("user-123"))
result, err := client.Query(ctx, "users", keyExpr)

var users []User
err = result.Unmarshal(&users)

// Batch operations
items := []any{user1, user2, user3}
unprocessed, err := client.BatchWriteItems(ctx, "users", items)
SQS
// Send a message
msgID, err := client.SendMessage(ctx, queueURL, "Hello World",
    sqs.WithDelaySeconds(60),
)

// Receive messages with long polling
messages, err := client.ReceiveMessages(ctx, queueURL,
    sqs.WithMaxMessages(10),
    sqs.WithWaitTimeSeconds(20),
)

// Process and delete
for _, msg := range messages {
    process(msg.Body)
    client.DeleteMessage(ctx, queueURL, msg.ReceiptHandle)
}

// Resolve queue name to URL
queueURL, err := client.GetQueueURL(ctx, "my-queue")
Secrets Manager
// Get a secret as string
apiKey, err := client.GetSecretString(ctx, "api-key")

// Get and unmarshal JSON secret
type DBConfig struct {
    Host     string `json:"host"`
    Port     int    `json:"port"`
    Username string `json:"username"`
    Password string `json:"password"`
}

var config DBConfig
err := client.GetSecretJSON(ctx, "db-credentials", &config)

// List all secrets
secrets, err := client.ListSecrets(ctx,
    secretsmanager.WithNameFilter("prod/"),
)
SSM Parameter Store
// Get a parameter (auto-decrypts SecureString)
value, err := client.GetParameter(ctx, "/app/config/database_url")

// Get multiple parameters
values, invalid, err := client.GetParameters(ctx, []string{
    "/app/config/a",
    "/app/config/b",
})

// List parameters by path
params, err := client.ListParametersByPath(ctx, "/app/config/",
    ssm.WithRecursive(true),
)

// Put a parameter
err := client.PutParameter(ctx, "/app/config/key", "value",
    ssm.WithParameterType(types.ParameterTypeSecureString),
    ssm.WithOverwrite(true),
)
Lambda
// Invoke synchronously
result, err := client.Invoke(ctx, "my-function", payload)
if result.HasError() {
    log.Printf("Function error: %s", result.FunctionError)
}

var response MyResponse
err = result.Unmarshal(&response)

// Invoke asynchronously
err := client.InvokeAsync(ctx, "my-function", payload)

// List functions
functions, err := client.ListFunctions(ctx)

// Deploy from S3
err := client.DeployFromS3(ctx, "my-function", "bucket", "code.zip")

// Deploy from local ZIP
err := client.DeployFromZip(ctx, "my-function", "function.zip")

Testing

All clients accept interfaces that can be mocked for testing:

package mypackage_test

import (
    "context"
    "testing"

    "github.com/alessiosavi/GoGPUtils/aws/s3"
)

type mockS3API struct {
    s3.API
    getObjectData []byte
}

func (m *mockS3API) GetObject(ctx context.Context, params *s3sdk.GetObjectInput, optFns ...func(*s3sdk.Options)) (*s3sdk.GetObjectOutput, error) {
    return &s3sdk.GetObjectOutput{
        Body: io.NopCloser(bytes.NewReader(m.getObjectData)),
    }, nil
}

func TestMyFunction(t *testing.T) {
    mock := &mockS3API{getObjectData: []byte("test content")}
    client := s3.NewClientWithAPI(mock, nil, nil)

    data, err := client.GetObject(context.Background(), "bucket", "key")
    if err != nil {
        t.Fatal(err)
    }

    if string(data) != "test content" {
        t.Errorf("unexpected data: %s", data)
    }
}

Configuration Options

AWS Config
cfg, err := aws.LoadConfig(ctx,
    aws.WithRegion("us-west-2"),           // Set region
    aws.WithProfile("production"),         // Use named profile
    aws.WithRetryMaxAttempts(5),           // Set retry attempts
    aws.WithRetryMode(aws.RetryModeAdaptive), // Set retry mode
    aws.WithEndpoint("http://localhost:4566"), // Custom endpoint (LocalStack)
    aws.WithCredentials(credsProvider),    // Custom credentials
)
Client Options

Each service client supports additional options:

// S3 with custom part size for multipart uploads
s3Client, err := s3.NewClient(cfg,
    s3.WithUploaderConcurrency(10),
    s3.WithDownloaderConcurrency(10),
    s3.WithPartSize(10 * 1024 * 1024), // 10 MB parts
)

Error Handling

All errors are wrapped with context:

data, err := client.GetObject(ctx, "bucket", "key")
if err != nil {
    // Check for specific errors
    if errors.Is(err, s3.ErrObjectNotFound) {
        // Handle not found
    }

    // Or check the operation error type
    var opErr *aws.OperationError
    if errors.As(err, &opErr) {
        log.Printf("Service: %s, Operation: %s", opErr.Service, opErr.Operation)
    }
}

Migration from Old Implementation

If migrating from the old AWS helpers (commit b7a0843), note these changes:

  1. No global clients: Create clients explicitly with NewClient(cfg)
  2. No panics: All errors are returned, never panic
  3. Context required: All operations require context.Context
  4. Explicit imports: Import each service package separately
  5. Interface-based: Use NewClientWithAPI() for testing
Before (old)
import "github.com/alessiosavi/GoGPUtils/aws/S3"

// Global client initialized in init()
data, err := S3utils.GetObject("bucket", "key")
After (new)
import (
    "github.com/alessiosavi/GoGPUtils/aws"
    "github.com/alessiosavi/GoGPUtils/aws/s3"
)

cfg, _ := aws.LoadConfig(ctx)
client, _ := s3.NewClient(cfg)
data, err := client.GetObject(ctx, "bucket", "key")

Design Principles

  1. Explicit over implicit: No hidden state or magic configuration
  2. Composition over inheritance: Small, focused packages
  3. Errors over panics: All failures return errors
  4. Interfaces for testing: Every client can be mocked
  5. Context everywhere: Cancellation and timeouts are first-class
  6. Safe defaults: Sensible retry and timeout configurations
  7. Minimal surface: Only expose what's necessary

Contributing

Contributions are welcome! Please ensure:

  1. All code follows Go conventions (run gofmt)
  2. Tests cover new functionality
  3. Documentation is updated
  4. No breaking changes to public API

License

MIT License - see LICENSE file for details.

Documentation

Overview

Package aws provides idiomatic Go helpers for AWS SDK v2.

Design Philosophy

This package follows several key principles:

  • No global state: All clients are explicitly created and passed
  • Context-aware: All operations accept context.Context for cancellation
  • Testable: Interfaces enable mocking without real AWS calls
  • Explicit configuration: No magic; all settings are visible
  • Safe defaults: Sensible retry policies and timeouts out of the box
  • Minimal abstraction: Helpers augment the SDK, not replace it

Package Structure

The aws package is organized into focused sub-packages:

  • aws: Core configuration and common utilities
  • aws/s3: S3 object and bucket operations
  • aws/dynamodb: DynamoDB item and table operations
  • aws/sqs: SQS message operations
  • aws/secretsmanager: Secrets Manager operations
  • aws/ssm: SSM Parameter Store operations
  • aws/lambda: Lambda function operations

Configuration

All clients are created with explicit configuration:

cfg, err := aws.LoadConfig(ctx, aws.WithRegion("us-west-2"))
if err != nil {
    return err
}

s3Client := s3.NewClient(cfg)

Error Handling

All operations return wrapped errors with context:

obj, err := client.GetObject(ctx, bucket, key)
if errors.Is(err, s3.ErrObjectNotFound) {
    // Handle not found
}

Testing

Each client accepts interfaces that can be mocked:

mock := &MockS3API{}
client := s3.NewClientWithAPI(mock)
// Use client in tests

Index

Constants

View Source
const DefaultRetryMaxAttempts = 3

DefaultRetryMaxAttempts is the default number of retry attempts for AWS operations.

View Source
const DefaultTimeout = 30 * time.Second

DefaultTimeout is the default timeout for AWS operations.

Variables

View Source
var (
	// ErrNilConfig is returned when a nil config is provided.
	ErrNilConfig = errors.New("aws: config is nil")

	// ErrNilClient is returned when a nil client is provided.
	ErrNilClient = errors.New("aws: client is nil")

	// ErrEmptyBucket is returned when a bucket name is empty.
	ErrEmptyBucket = errors.New("aws: bucket name is empty")

	// ErrEmptyKey is returned when a key/path is empty.
	ErrEmptyKey = errors.New("aws: key is empty")

	// ErrEmptyTable is returned when a table name is empty.
	ErrEmptyTable = errors.New("aws: table name is empty")

	// ErrEmptyQueue is returned when a queue name/URL is empty.
	ErrEmptyQueue = errors.New("aws: queue name is empty")

	// ErrEmptySecret is returned when a secret name is empty.
	ErrEmptySecret = errors.New("aws: secret name is empty")

	// ErrEmptyParameter is returned when a parameter name is empty.
	ErrEmptyParameter = errors.New("aws: parameter name is empty")

	// ErrEmptyFunction is returned when a function name is empty.
	ErrEmptyFunction = errors.New("aws: function name is empty")

	// ErrInvalidInput is returned when input validation fails.
	ErrInvalidInput = errors.New("aws: invalid input")
)

Common sentinel errors.

Functions

func WrapError added in v1.0.0

func WrapError(service, operation string, err error) error

WrapError wraps an error with service and operation context.

Types

type Config added in v1.0.0

type Config struct {
	aws.Config
}

Config wraps aws.Config with additional helper methods.

func LoadConfig added in v1.0.0

func LoadConfig(ctx context.Context, opts ...ConfigOption) (*Config, error)

LoadConfig loads AWS configuration with the specified options. If no options are provided, it uses default configuration from environment variables, shared credentials, and IAM roles.

Example:

// Load with defaults
cfg, err := aws.LoadConfig(ctx)

// Load with specific region and profile
cfg, err := aws.LoadConfig(ctx,
    aws.WithRegion("us-west-2"),
    aws.WithProfile("production"),
)

func (*Config) AWS added in v1.0.0

func (c *Config) AWS() aws.Config

AWS returns the underlying aws.Config for direct SDK usage.

func (*Config) Region added in v1.0.0

func (c *Config) Region() string

Region returns the configured region.

type ConfigError added in v1.0.0

type ConfigError struct {
	Err error
}

ConfigError represents an error loading AWS configuration.

func (*ConfigError) Error added in v1.0.0

func (e *ConfigError) Error() string

func (*ConfigError) Unwrap added in v1.0.0

func (e *ConfigError) Unwrap() error

type ConfigOption added in v1.0.0

type ConfigOption func(*configOptions)

ConfigOption configures AWS config loading.

func WithCredentials added in v1.0.0

func WithCredentials(provider aws.CredentialsProvider) ConfigOption

WithCredentials sets explicit credentials provider.

Example:

creds := credentials.NewStaticCredentialsProvider("key", "secret", "")
cfg, err := aws.LoadConfig(ctx, aws.WithCredentials(creds))

func WithEndpoint added in v1.0.0

func WithEndpoint(endpoint string) ConfigOption

WithEndpoint sets a custom endpoint URL for all services. Useful for testing with LocalStack or other AWS-compatible services.

Example:

cfg, err := aws.LoadConfig(ctx, aws.WithEndpoint("http://localhost:4566"))

func WithLoadOption added in v1.0.0

func WithLoadOption(opt func(*config.LoadOptions) error) ConfigOption

WithLoadOption adds a raw AWS SDK config load option. Use this for advanced configuration not covered by other options.

func WithProfile added in v1.0.0

func WithProfile(profile string) ConfigOption

WithProfile sets the AWS profile to use from shared credentials.

Example:

cfg, err := aws.LoadConfig(ctx, aws.WithProfile("production"))

func WithRegion added in v1.0.0

func WithRegion(region string) ConfigOption

WithRegion sets the AWS region.

Example:

cfg, err := aws.LoadConfig(ctx, aws.WithRegion("us-west-2"))

func WithRetryMaxAttempts added in v1.0.0

func WithRetryMaxAttempts(attempts int) ConfigOption

WithRetryMaxAttempts sets the maximum number of retry attempts. Default is 3 attempts.

Example:

cfg, err := aws.LoadConfig(ctx, aws.WithRetryMaxAttempts(5))

func WithRetryMode added in v1.0.0

func WithRetryMode(mode aws.RetryMode) ConfigOption

WithRetryMode sets the retry mode (standard or adaptive). Default is adaptive retry mode.

Example:

cfg, err := aws.LoadConfig(ctx, aws.WithRetryMode(aws.RetryModeAdaptive))

type NotFoundError added in v1.0.0

type NotFoundError struct {
	Resource string
	ID       string
}

NotFoundError represents a resource not found error.

func NewNotFoundError added in v1.0.0

func NewNotFoundError(resource, id string) *NotFoundError

NewNotFoundError creates a new NotFoundError.

func (*NotFoundError) Error added in v1.0.0

func (e *NotFoundError) Error() string

type OperationError added in v1.0.0

type OperationError struct {
	Service   string
	Operation string
	Err       error
}

OperationError represents an error during an AWS operation.

func (*OperationError) Error added in v1.0.0

func (e *OperationError) Error() string

func (*OperationError) Unwrap added in v1.0.0

func (e *OperationError) Unwrap() error

type ValidationError added in v1.0.0

type ValidationError struct {
	Field   string
	Message string
}

ValidationError represents an input validation error.

func NewValidationError added in v1.0.0

func NewValidationError(field, message string) *ValidationError

NewValidationError creates a new ValidationError.

func (*ValidationError) Error added in v1.0.0

func (e *ValidationError) Error() string

Directories

Path Synopsis
Package dynamodb provides helpers for Amazon DynamoDB operations.
Package dynamodb provides helpers for Amazon DynamoDB operations.
internal
pagination
Package pagination provides internal helpers for AWS paginated operations.
Package pagination provides internal helpers for AWS paginated operations.
testutil
Package testutil provides utilities for testing AWS helpers with LocalStack.
Package testutil provides utilities for testing AWS helpers with LocalStack.
Package lambda provides helpers for AWS Lambda operations.
Package lambda provides helpers for AWS Lambda operations.
Package s3 provides helpers for Amazon S3 operations.
Package s3 provides helpers for Amazon S3 operations.
Package secretsmanager provides helpers for AWS Secrets Manager operations.
Package secretsmanager provides helpers for AWS Secrets Manager operations.
Package sqs provides helpers for Amazon SQS operations.
Package sqs provides helpers for Amazon SQS operations.
Package ssm provides helpers for AWS Systems Manager Parameter Store operations.
Package ssm provides helpers for AWS Systems Manager Parameter Store operations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL