github.com/tilotech/tilores-cli@v0.28.0/cmd/localstack_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/aws/aws-sdk-go-v2/aws"
    13  	"github.com/aws/aws-sdk-go-v2/config"
    14  	"github.com/aws/aws-sdk-go-v2/credentials"
    15  	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
    16  	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
    17  	"github.com/ory/dockertest"
    18  	"github.com/ory/dockertest/docker"
    19  )
    20  
    21  func TestMain(m *testing.M) {
    22  	// set fake default region for tests
    23  	os.Setenv("AWS_REGION", "eu-west-1")
    24  
    25  	flag.Parse()
    26  	if testing.Short() {
    27  		code := m.Run()
    28  		os.Exit(code)
    29  	}
    30  
    31  	pool, resource := startLocalStack()
    32  	err := waitForServicesAndInit(pool)
    33  	if err != nil {
    34  		stopLocalStack(pool, resource)
    35  		log.Fatalf("Could not init services: %s", err)
    36  	}
    37  	code := m.Run()
    38  	stopLocalStack(pool, resource)
    39  	os.Exit(code)
    40  }
    41  
    42  func startLocalStack() (*dockertest.Pool, *dockertest.Resource) {
    43  	host := os.Getenv("LOCALSTACK_HOSTNAME_EXTERNAL")
    44  	if host != "" {
    45  		return nil, nil
    46  	}
    47  
    48  	pool, err := dockertest.NewPool("")
    49  	if err != nil {
    50  		log.Fatalf("Could not connect to docker: %s", err)
    51  	}
    52  
    53  	resource, err := pool.RunWithOptions(&dockertest.RunOptions{
    54  		Repository: "localstack/localstack",
    55  		Tag:        "0.13",
    56  		PortBindings: map[docker.Port][]docker.PortBinding{
    57  			"4566/tcp": {{HostPort: "4566"}}, // Port for all services
    58  		},
    59  		Env: []string{
    60  			"SERVICES=dynamodb",
    61  			"ENABLE_CONFIG_UPDATES=1",
    62  		},
    63  	})
    64  	if err != nil {
    65  		log.Fatalf("Cloud not start resource: %s", err)
    66  	}
    67  	return pool, resource
    68  }
    69  
    70  func waitForServicesAndInit(pool *dockertest.Pool) error {
    71  	var host string
    72  	var retry func(op func() error) error
    73  	if pool == nil {
    74  		host = os.Getenv("LOCALSTACK_HOSTNAME_EXTERNAL")
    75  		retry = func(op func() error) error {
    76  			i := 0
    77  			for {
    78  				err := op()
    79  				if err == nil || i > 30 {
    80  					return err
    81  				}
    82  				i++
    83  				time.Sleep(1 * time.Second)
    84  			}
    85  		}
    86  	} else {
    87  		host = "localhost"
    88  		retry = pool.Retry
    89  	}
    90  
    91  	os.Setenv("LOCALSTACK_HOST", host)
    92  
    93  	// wait for DynamoDB to become available
    94  	err := retry(func() error {
    95  		_, err := createTestTable("pulse")
    96  		return err
    97  	})
    98  
    99  	if err != nil {
   100  		return err
   101  	}
   102  	return nil
   103  }
   104  
   105  func stopLocalStack(pool *dockertest.Pool, resource *dockertest.Resource) {
   106  	if pool == nil || resource == nil {
   107  		return
   108  	}
   109  	if err := pool.Purge(resource); err != nil {
   110  		log.Fatalf("Could not purge resource: %s", err)
   111  	}
   112  }
   113  
   114  func newTestConfig(ctx context.Context) (aws.Config, error) {
   115  	host := os.Getenv("LOCALSTACK_HOST")
   116  	endpointResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
   117  		return aws.Endpoint{
   118  			URL:           fmt.Sprintf("http://%v:4566", host),
   119  			SigningRegion: region,
   120  		}, nil
   121  	})
   122  	cfg, err := config.LoadDefaultConfig(ctx,
   123  		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("not", "required", "")),
   124  		config.WithEndpointResolverWithOptions(endpointResolver),
   125  	)
   126  	if err != nil {
   127  		return aws.Config{}, err
   128  	}
   129  	return cfg, nil
   130  }
   131  
   132  func createTestTable(tableName string) (*dynamodb.CreateTableOutput, error) {
   133  	ctx := context.Background()
   134  	cfg, err := newTestConfig(ctx)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	ddbClient := dynamodb.NewFromConfig(cfg)
   139  
   140  	attributeDefinitions := []types.AttributeDefinition{
   141  		{
   142  			AttributeName: aws.String("id"),
   143  			AttributeType: types.ScalarAttributeTypeS,
   144  		},
   145  	}
   146  
   147  	keySchema := []types.KeySchemaElement{
   148  		{
   149  			AttributeName: aws.String("id"),
   150  			KeyType:       types.KeyTypeHash,
   151  		},
   152  	}
   153  
   154  	return ddbClient.CreateTable(ctx, &dynamodb.CreateTableInput{
   155  		TableName:            aws.String(tableName),
   156  		AttributeDefinitions: attributeDefinitions,
   157  		KeySchema:            keySchema,
   158  		ProvisionedThroughput: &types.ProvisionedThroughput{
   159  			ReadCapacityUnits:  aws.Int64(1000),
   160  			WriteCapacityUnits: aws.Int64(10000),
   161  		},
   162  	})
   163  }