Skip to content

Commit

Permalink
create integration tests for setup
Browse files Browse the repository at this point in the history
Start using embed instead of bindata.
  • Loading branch information
ianic committed Sep 27, 2021
1 parent 3a1e306 commit fb2c7aa
Show file tree
Hide file tree
Showing 26 changed files with 1,213 additions and 90 deletions.
74 changes: 35 additions & 39 deletions api/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import (
"fmt"

"github.com/mantil-io/mantil/api/dto"
"github.com/mantil-io/mantil/assets"
"github.com/mantil-io/mantil/aws"
"github.com/mantil-io/mantil/config"
"github.com/mantil-io/mantil/terraform"
)

type Setup struct {
tf *terraform.Terraform
req *dto.SetupRequest
awsClient *aws.AWS
bucketName string
Expand All @@ -26,20 +24,14 @@ func (s *Setup) Invoke(ctx context.Context, req *dto.SetupRequest) (*dto.SetupRe
if err := s.init(req, nil); err != nil {
return nil, err
}
defer s.cleanup()

if req.Destroy {
return nil, s.destroy()
}

if err := s.create(); err != nil {
return nil, err
}
return s.readTerraformOutput()
return s.create()
}

func (s *Setup) destroy() error {
if err := s.terraformApply(); err != nil {
if err := s.terraformDestroy(); err != nil {
return err
}
if err := s.deleteBucket(); err != nil {
Expand All @@ -48,25 +40,23 @@ func (s *Setup) destroy() error {
return nil
}

func (s *Setup) create() error {
func (s *Setup) create() (*dto.SetupResponse, error) {
if err := s.createBucket(); err != nil {
return err
return nil, err
}
if err := s.terraformApply(); err != nil {
return err
out, err := s.terraformCreate()
if err != nil {
return nil, err
}
if err := s.saveConfig(); err != nil {
return err
return nil, err
}
return nil
return out, err
}

func (s *Setup) init(req *dto.SetupRequest, awsClient *aws.AWS) error {
tf, err := terraform.New("mantil-setup")
if err != nil {
return err
}
if awsClient == nil {
var err error
awsClient, err = aws.New()
if err != nil {
return fmt.Errorf("error initializing AWS client - %w", err)
Expand All @@ -76,7 +66,6 @@ func (s *Setup) init(req *dto.SetupRequest, awsClient *aws.AWS) error {
if err != nil {
return err
}
s.tf = tf
s.awsClient = awsClient
s.req = req
s.bucketName = bucketName
Expand All @@ -92,39 +81,46 @@ func (s *Setup) saveConfig() error {
})
}

func (s *Setup) cleanup() {
if s.tf != nil {
s.tf.Cleanup()
}
}

func (s *Setup) terraformApply() error {
assets.StartServer()
func (s *Setup) terraformCreate() (*dto.SetupResponse, error) {
data := terraform.SetupTemplateData{
Bucket: s.bucketName,
BucketPrefix: config.SetupBucketPrefix,
Region: s.awsClient.Region(),
FunctionsBucket: s.req.FunctionsBucket,
FunctionsPath: s.req.FunctionsPath,
Region: s.awsClient.Region(),
PublicKey: s.req.PublicKey,
}
if err := s.tf.RenderSetupTemplate(data); err != nil {
return err
tf, err := terraform.Setup(data)
if err != nil {
return nil, err
}
if err := s.tf.Apply(s.req.Destroy); err != nil {
if err := tf.Create(); err != nil {
return nil, err
}
return s.readTerraformOutput(tf)
}

func (s *Setup) terraformDestroy() error {
data := terraform.SetupTemplateData{
Bucket: s.bucketName,
BucketPrefix: config.SetupBucketPrefix,
Region: s.awsClient.Region(),
}
tf, err := terraform.Setup(data)
if err != nil {
return err
}
return nil
return tf.Destroy()
}

func (s *Setup) readTerraformOutput() (*dto.SetupResponse, error) {
restURL, err := s.tf.Output("url", true)
func (s *Setup) readTerraformOutput(tf *terraform.Terraform) (*dto.SetupResponse, error) {
restURL, err := tf.Output("url", true)
if err != nil {
return nil, fmt.Errorf("error reading api gateway rest url - %v", err)
return nil, fmt.Errorf("error reading api gateway rest url - %w", err)
}
wsURL, err := s.tf.Output("ws_url", true)
wsURL, err := tf.Output("ws_url", true)
if err != nil {
return nil, fmt.Errorf("error reading api gateway ws url - %v", err)
return nil, fmt.Errorf("error reading api gateway ws url - %w", err)
}
return &dto.SetupResponse{
APIGatewayRestURL: restURL,
Expand Down
73 changes: 46 additions & 27 deletions api/setup/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package setup
import (
"flag"
"io/ioutil"
"log"
"strings"
"testing"

Expand All @@ -15,50 +16,68 @@ import (

var update = flag.Bool("update", false, "update expected files")

func TestInit(t *testing.T) {
func TestTerraformRender(t *testing.T) {
data := terraform.SetupTemplateData{
Bucket: "bucket-name",
BucketPrefix: "bucket-prefix/",
FunctionsBucket: "functions-bucket",
FunctionsPath: "functions-path",
Region: "aws-region",
PublicKey: "public-key",
}
tf, err := terraform.Setup(data)
require.NoError(t, err)
equalFiles(t, "./testdata/create.tf", tf.CreateTf())
equalFiles(t, "./testdata/destroy.tf", tf.DestroyTf())
}

func TestIntegration(t *testing.T) {
cli := aws.NewForTests(t)
if cli == nil {
t.Skip("skip: AWS client not initialized")
}
init := func() *Setup {
req := dto.SetupRequest{}
s := func() *Setup {
req := dto.SetupRequest{
FunctionsBucket: "mantil-downloads",
FunctionsPath: "functions/latest",
PublicKey: "my-test-public-key",
}
s := New()
err := s.init(&req, cli)
require.NoError(t, err)
return s
}

}()
t.Run("init", func(t *testing.T) {
s := init()
require.NotNil(t, s.tf)
require.NotNil(t, s.awsClient)
id, err := s.awsClient.AccountID()
require.NoError(t, err)
require.True(t, strings.HasSuffix(s.bucketName, id))

t.Logf("accountID: %s\n", id)
t.Logf("bucket: %s\n", s.bucketName)
t.Logf("accountID: %s", id)
t.Logf("bucket: %s", s.bucketName)
})

t.Run("create bucket", func(t *testing.T) {
require.NoError(t, s.createBucket())
})
t.Run("create", func(t *testing.T) {
out, err := s.terraformCreate()
require.NoError(t, err)
require.NotEmpty(t, out.APIGatewayRestURL)
require.NotEmpty(t, out.APIGatewayWsURL)
log.Printf("output: %#v", out)
})
t.Run("destroy", func(t *testing.T) {
err := s.terraformDestroy()
require.NoError(t, err)
})
t.Run("delete bucket", func(t *testing.T) {
require.NoError(t, s.deleteBucket())
})
}

func TestTerraformRender(t *testing.T) {
tf, err := terraform.New("mantil-setup")
require.NoError(t, err)
data := terraform.SetupTemplateData{
Bucket: "bucket-name",
BucketPrefix: "bucket-prefix",
FunctionsBucket: "functions-bucket",
FunctionsPath: "functions-path",
Region: "aws-region",
PublicKey: "public-key",
}
err = tf.RenderSetupTemplate(data)
require.NoError(t, err)
requireEqual(t, "./testdata/mantil-setup-main.tf", "/tmp/mantil-setup/main.tf")
}

func requireEqual(t *testing.T, expected, actual string) {
// TODO: same function in terraform package
func equalFiles(t *testing.T, expected, actual string) {
actualContent, err := ioutil.ReadFile(actual)
if err != nil {
t.Fatalf("failed reading actual file: %s", err)
Expand All @@ -79,7 +98,7 @@ func requireEqual(t *testing.T, expected, actual string) {

if string(actualContent) != string(expectedContent) {
args := []string{"diff", expected, actual}
out, err := shell.Output(args, "")
out, err := shell.Output(shell.ExecOptions{Args: args})
if err != nil {
t.Logf("diff of files")
t.Logf("expected %s, actual %s", expected, actual)
Expand Down
112 changes: 112 additions & 0 deletions api/setup/testdata/create.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
locals {
aws_region = "aws-region"
functions_bucket = "functions-bucket" # bucket with backend functions
project_bucket = "bucket-name" # bucket for backend configuration/state
functions = {
"init" = {
s3_key = "functions-path/init.zip"
memory_size = 128
timeout = 900
},
"deploy" = {
s3_key = "functions-path/deploy.zip"
memory_size = 512,
timeout = 900
layers = ["arn:aws:lambda:aws-region:553035198032:layer:git-lambda2:8", "arn:aws:lambda:aws-region:477361877445:layer:terraform-lambda:1"]
},
"data" = {
s3_key = "functions-path/data.zip"
memory_size = 128,
timeout = 900
},
"security" = {
s3_key = "functions-path/security.zip"
memory_size = 128,
timeout = 900,
},
"destroy" = {
s3_key = "functions-path/destroy.zip"
memory_size = 512,
timeout = 900
layers = ["arn:aws:lambda:aws-region:553035198032:layer:git-lambda2:8", "arn:aws:lambda:aws-region:477361877445:layer:terraform-lambda:1"]
}
}
ws_handler = {
name = "ws-handler"
s3_key = "functions-path/ws-handler.zip"
memory_size = 128
timeout = 900
}
ws_sqs_forwarder = {
name = "ws-sqs-forwarder"
s3_key = "functions-path/ws-sqs-forwarder.zip"
memory_size = 128
timeout = 900
}
}

terraform {
backend "s3" {
bucket = "bucket-name"
key = "bucket-prefix/terraform/state.tfstate"
region = "aws-region"
}
}

provider "aws" {
region = "aws-region"
skip_get_ec2_platforms = true
}

module "funcs" {
source = "../modules/backend-funcs"
functions = local.functions
s3_bucket = local.functions_bucket
}

module "iam" {
source = "../modules/backend-iam"
backend_role_arn = module.funcs.role_arn
}

module "api" {
source = "../modules/api"
name_prefix = "mantil"
functions_bucket = local.functions_bucket
integrations = [for f in module.funcs.functions :
{
type : "AWS_PROXY"
method : "POST"
route : "/${f.name}"
uri : f.invoke_arn,
lambda_name : f.arn,
enable_auth : false,
}
]
authorizer = {
authorization_header = "X-Mantil-Access-Token"
public_key = "public-key"
s3_key = "functions-path/authorizer.zip"
}
}

# expose aws region and profile for use in shell scripts
output "aws_region" {
value = local.aws_region
}

output "project_bucket" {
value = local.project_bucket
}

output "url" {
value = module.api.http_url
}

output "cli_role" {
value = module.iam.cli_role
}

output "ws_url" {
value = module.api.ws_url
}
12 changes: 12 additions & 0 deletions api/setup/testdata/destroy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
backend "s3" {
bucket = "bucket-name"
key = "bucket-prefix/terraform/state.tfstate"
region = "aws-region"
}
}

provider "aws" {
region = "aws-region"
skip_get_ec2_platforms = true
}
Loading

0 comments on commit fb2c7aa

Please sign in to comment.