github.com/mweagle/Sparta@v1.15.0/decorator/apigateway_domain.go (about) 1 package decorator 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/aws/aws-sdk-go/aws/session" 8 sparta "github.com/mweagle/Sparta" 9 spartaCF "github.com/mweagle/Sparta/aws/cloudformation" 10 gocf "github.com/mweagle/go-cloudformation" 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 ) 14 15 const ( 16 // APIGatewayMappingEntry is the keyname used to store the API Gateway mappings 17 APIGatewayMappingEntry = "APIGatewayMappings" 18 ) 19 20 // APIGatewayDomainDecorator returns a ServiceDecoratorHookHandler 21 // implementation that registers a custom domain for an API Gateway 22 // service 23 func APIGatewayDomainDecorator(apiGateway *sparta.API, 24 acmCertARN gocf.Stringable, 25 basePath string, 26 domainName string) sparta.ServiceDecoratorHookHandler { 27 28 // Attach the domain decorator to the API GW instance 29 domainDecorator := func(context map[string]interface{}, 30 serviceName string, 31 template *gocf.Template, 32 S3Bucket string, 33 S3Key string, 34 buildID string, 35 awsSession *session.Session, 36 noop bool, 37 logger *logrus.Logger) error { 38 39 domainParts := strings.Split(domainName, ".") 40 if len(domainParts) != 3 { 41 return errors.Errorf("Invalid domain name supplied to APIGatewayDomainDecorator: %s", 42 domainName) 43 } 44 // Add the mapping 45 template.Mappings = map[string]*gocf.Mapping{ 46 APIGatewayMappingEntry: spartaCF.APIGatewayMapping, 47 } 48 // Resource names 49 domainInfoResourceName := sparta.CloudFormationResourceName(apiGateway.LogicalResourceName(), 50 "Domain") 51 basePathMappingResourceName := sparta.CloudFormationResourceName(apiGateway.LogicalResourceName(), "BasePathMapping") 52 dnsRecordResourceName := sparta.CloudFormationResourceName(apiGateway.LogicalResourceName(), 53 "CloudFrontDNS") 54 55 // Then add all the resources 56 domainInfo := &gocf.APIGatewayDomainName{ 57 DomainName: gocf.String(domainName), 58 } 59 apiGatewayType := "" 60 apiGWEndpointConfiguration := apiGateway.EndpointConfiguration 61 if apiGWEndpointConfiguration != nil && apiGWEndpointConfiguration.Types != nil { 62 typesList := apiGWEndpointConfiguration.Types 63 if len(typesList.Literal) == 1 { 64 apiGatewayType = typesList.Literal[0].Literal 65 } else { 66 return errors.Errorf("Invalid API GW types provided to decorator: %#v", 67 apiGWEndpointConfiguration.Types) 68 } 69 } 70 attrName := "" 71 switch apiGatewayType { 72 case "REGIONAL": 73 { 74 domainInfo.RegionalCertificateArn = acmCertARN.String() 75 domainInfo.EndpointConfiguration = &gocf.APIGatewayDomainNameEndpointConfiguration{ 76 Types: gocf.StringList(gocf.String("REGIONAL")), 77 } 78 attrName = "RegionalDomainName" 79 } 80 case "EDGE": 81 { 82 domainInfo.CertificateArn = acmCertARN.String() 83 domainInfo.EndpointConfiguration = &gocf.APIGatewayDomainNameEndpointConfiguration{ 84 Types: gocf.StringList(gocf.String("EDGE")), 85 } 86 attrName = "DistributionDomainName" 87 } 88 default: 89 return errors.Errorf("Unsupported API Gateway type: %#v", apiGatewayType) 90 } 91 template.AddResource(domainInfoResourceName, domainInfo) 92 93 basePathMapping := gocf.APIGatewayBasePathMapping{ 94 BasePath: gocf.String(basePath), 95 DomainName: gocf.Ref(domainInfoResourceName).String(), 96 RestAPIID: gocf.Ref(apiGateway.LogicalResourceName()).String(), 97 } 98 mappingResource := template.AddResource(basePathMappingResourceName, basePathMapping) 99 mappingResource.DependsOn = []string{domainInfoResourceName, 100 apiGateway.LogicalResourceName()} 101 102 // Use the HostedZoneName to create the record 103 domainZone := domainParts[1:] 104 dnsRecordResource := &gocf.Route53RecordSet{ 105 HostedZoneName: gocf.String(fmt.Sprintf("%s.", strings.Join(domainZone, "."))), 106 Name: gocf.String(fmt.Sprintf("%s.", domainName)), 107 Type: gocf.String("A"), 108 AliasTarget: &gocf.Route53RecordSetAliasTarget{ 109 HostedZoneID: gocf.FindInMap(APIGatewayMappingEntry, 110 gocf.Ref("AWS::Region"), 111 gocf.String(spartaCF.HostedZoneID)), 112 DNSName: gocf.GetAtt(domainInfoResourceName, attrName).String(), 113 }, 114 } 115 template.AddResource(dnsRecordResourceName, dnsRecordResource) 116 117 // Add an output... 118 template.Outputs["APIGatewayCustomDomain"] = &gocf.Output{ 119 Description: "Custom API Gateway Domain", 120 Value: gocf.String(domainName), 121 } 122 return nil 123 } 124 return sparta.ServiceDecoratorHookFunc(domainDecorator) 125 }