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 }