mirror of https://github.com/docker/compose.git
`parse` to return awsResources then convert into CF template
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
7034254911
commit
d5e0ec7aa6
|
@ -32,7 +32,6 @@ import (
|
||||||
|
|
||||||
// awsResources hold the AWS component being used or created to support services definition
|
// awsResources hold the AWS component being used or created to support services definition
|
||||||
type awsResources struct {
|
type awsResources struct {
|
||||||
sdk sdk
|
|
||||||
vpc string
|
vpc string
|
||||||
subnets []string
|
subnets []string
|
||||||
cluster string
|
cluster string
|
||||||
|
@ -58,101 +57,120 @@ func (r *awsResources) allSecurityGroups() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse look into compose project for configured resource to use, and check they are valid
|
// parse look into compose project for configured resource to use, and check they are valid
|
||||||
func (r *awsResources) parse(ctx context.Context, project *types.Project) error {
|
func (b *ecsAPIService) parse(ctx context.Context, project *types.Project) (awsResources, error) {
|
||||||
return findProjectFnError(ctx, project,
|
r := awsResources{}
|
||||||
r.parseClusterExtension,
|
var err error
|
||||||
r.parseVPCExtension,
|
r.cluster, err = b.parseClusterExtension(ctx, project)
|
||||||
r.parseLoadBalancerExtension,
|
if err != nil {
|
||||||
r.parseSecurityGroupExtension,
|
return r, err
|
||||||
)
|
}
|
||||||
|
r.vpc, r.subnets, err = b.parseVPCExtension(ctx, project)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
r.loadBalancer, r.loadBalancerType, err = b.parseLoadBalancerExtension(ctx, project)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
r.securityGroups, err = b.parseSecurityGroupExtension(ctx, project)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) parseClusterExtension(ctx context.Context, project *types.Project) error {
|
func (b *ecsAPIService) parseClusterExtension(ctx context.Context, project *types.Project) (string, error) {
|
||||||
if x, ok := project.Extensions[extensionCluster]; ok {
|
if x, ok := project.Extensions[extensionCluster]; ok {
|
||||||
cluster := x.(string)
|
cluster := x.(string)
|
||||||
ok, err := r.sdk.ClusterExists(ctx, cluster)
|
ok, err := b.SDK.ClusterExists(ctx, cluster)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("cluster does not exist: %s", cluster)
|
return "", fmt.Errorf("cluster does not exist: %s", cluster)
|
||||||
}
|
}
|
||||||
r.cluster = cluster
|
return cluster, nil
|
||||||
}
|
}
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) parseVPCExtension(ctx context.Context, project *types.Project) error {
|
func (b *ecsAPIService) parseVPCExtension(ctx context.Context, project *types.Project) (string, []string, error) {
|
||||||
|
var vpc string
|
||||||
if x, ok := project.Extensions[extensionVPC]; ok {
|
if x, ok := project.Extensions[extensionVPC]; ok {
|
||||||
vpc := x.(string)
|
vpc = x.(string)
|
||||||
err := r.sdk.CheckVPC(ctx, vpc)
|
err := b.SDK.CheckVPC(ctx, vpc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", nil, err
|
||||||
}
|
|
||||||
r.vpc = vpc
|
|
||||||
} else {
|
|
||||||
defaultVPC, err := r.sdk.GetDefaultVPC(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.vpc = defaultVPC
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subNets, err := r.sdk.GetSubNets(ctx, r.vpc)
|
} else {
|
||||||
|
defaultVPC, err := b.SDK.GetDefaultVPC(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", nil, err
|
||||||
|
}
|
||||||
|
vpc = defaultVPC
|
||||||
|
}
|
||||||
|
|
||||||
|
subNets, err := b.SDK.GetSubNets(ctx, vpc)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
}
|
}
|
||||||
if len(subNets) < 2 {
|
if len(subNets) < 2 {
|
||||||
return fmt.Errorf("VPC %s should have at least 2 associated subnets in different availability zones", r.vpc)
|
return "", nil, fmt.Errorf("VPC %s should have at least 2 associated subnets in different availability zones", vpc)
|
||||||
}
|
}
|
||||||
r.subnets = subNets
|
return vpc, subNets, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) parseLoadBalancerExtension(ctx context.Context, project *types.Project) error {
|
func (b *ecsAPIService) parseLoadBalancerExtension(ctx context.Context, project *types.Project) (string, string, error) {
|
||||||
if x, ok := project.Extensions[extensionLoadBalancer]; ok {
|
if x, ok := project.Extensions[extensionLoadBalancer]; ok {
|
||||||
loadBalancer := x.(string)
|
loadBalancer := x.(string)
|
||||||
loadBalancerType, err := r.sdk.LoadBalancerType(ctx, loadBalancer)
|
loadBalancerType, err := b.SDK.LoadBalancerType(ctx, loadBalancer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
required := getRequiredLoadBalancerType(project)
|
required := getRequiredLoadBalancerType(project)
|
||||||
if loadBalancerType != required {
|
if loadBalancerType != required {
|
||||||
return fmt.Errorf("load balancer %s is of type %s, project require a %s", loadBalancer, loadBalancerType, required)
|
return "", "", fmt.Errorf("load balancer %s is of type %s, project require a %s", loadBalancer, loadBalancerType, required)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.loadBalancer = loadBalancer
|
return loadBalancer, loadBalancerType, nil
|
||||||
r.loadBalancerType = loadBalancerType
|
|
||||||
}
|
}
|
||||||
return nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) parseSecurityGroupExtension(ctx context.Context, project *types.Project) error {
|
func (b *ecsAPIService) parseSecurityGroupExtension(ctx context.Context, project *types.Project) (map[string]string, error) {
|
||||||
if r.securityGroups == nil {
|
securityGroups := make(map[string]string, len(project.Networks))
|
||||||
r.securityGroups = make(map[string]string, len(project.Networks))
|
|
||||||
}
|
|
||||||
for name, net := range project.Networks {
|
for name, net := range project.Networks {
|
||||||
|
var sg string
|
||||||
if net.External.External {
|
if net.External.External {
|
||||||
r.securityGroups[name] = net.Name
|
sg = net.Name
|
||||||
}
|
}
|
||||||
if x, ok := net.Extensions[extensionSecurityGroup]; ok {
|
if x, ok := net.Extensions[extensionSecurityGroup]; ok {
|
||||||
logrus.Warn("to use an existing security-group, use `network.external` and `network.name` in your compose file")
|
logrus.Warn("to use an existing security-group, use `network.external` and `network.name` in your compose file")
|
||||||
logrus.Debugf("Security Group for network %q set by user to %q", net.Name, x)
|
logrus.Debugf("Security Group for network %q set by user to %q", net.Name, x)
|
||||||
r.securityGroups[name] = x.(string)
|
sg = x.(string)
|
||||||
}
|
}
|
||||||
|
exists, err := b.SDK.SecurityGroupExists(ctx, sg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil
|
if !exists {
|
||||||
|
return nil, fmt.Errorf("security group %s doesn't exist", sg)
|
||||||
|
}
|
||||||
|
securityGroups[name] = sg
|
||||||
|
}
|
||||||
|
return securityGroups, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure all required resources pre-exists or are defined as cloudformation resources
|
// ensureResources create required resources in template if not yet defined
|
||||||
func (r *awsResources) ensure(project *types.Project, template *cloudformation.Template) {
|
func (b *ecsAPIService) ensureResources(resources *awsResources, project *types.Project, template *cloudformation.Template) {
|
||||||
r.ensureCluster(project, template)
|
b.ensureCluster(resources, project, template)
|
||||||
r.ensureNetworks(project, template)
|
b.ensureNetworks(resources, project, template)
|
||||||
r.ensureLoadBalancer(project, template)
|
b.ensureLoadBalancer(resources, project, template)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) ensureCluster(project *types.Project, template *cloudformation.Template) {
|
func (b *ecsAPIService) ensureCluster(r *awsResources, project *types.Project, template *cloudformation.Template) {
|
||||||
if r.cluster != "" {
|
if r.cluster != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -163,7 +181,7 @@ func (r *awsResources) ensureCluster(project *types.Project, template *cloudform
|
||||||
r.cluster = cloudformation.Ref("Cluster")
|
r.cluster = cloudformation.Ref("Cluster")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) ensureNetworks(project *types.Project, template *cloudformation.Template) {
|
func (b *ecsAPIService) ensureNetworks(r *awsResources, project *types.Project, template *cloudformation.Template) {
|
||||||
if r.securityGroups == nil {
|
if r.securityGroups == nil {
|
||||||
r.securityGroups = make(map[string]string, len(project.Networks))
|
r.securityGroups = make(map[string]string, len(project.Networks))
|
||||||
}
|
}
|
||||||
|
@ -179,7 +197,7 @@ func (r *awsResources) ensureNetworks(project *types.Project, template *cloudfor
|
||||||
ingress := securityGroup + "Ingress"
|
ingress := securityGroup + "Ingress"
|
||||||
template.Resources[ingress] = &ec2.SecurityGroupIngress{
|
template.Resources[ingress] = &ec2.SecurityGroupIngress{
|
||||||
Description: fmt.Sprintf("Allow communication within network %s", name),
|
Description: fmt.Sprintf("Allow communication within network %s", name),
|
||||||
IpProtocol: "-1", // all protocols
|
IpProtocol: allProtocols,
|
||||||
GroupId: cloudformation.Ref(securityGroup),
|
GroupId: cloudformation.Ref(securityGroup),
|
||||||
SourceSecurityGroupId: cloudformation.Ref(securityGroup),
|
SourceSecurityGroupId: cloudformation.Ref(securityGroup),
|
||||||
}
|
}
|
||||||
|
@ -188,7 +206,7 @@ func (r *awsResources) ensureNetworks(project *types.Project, template *cloudfor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *awsResources) ensureLoadBalancer(project *types.Project, template *cloudformation.Template) {
|
func (b *ecsAPIService) ensureLoadBalancer(r *awsResources, project *types.Project, template *cloudformation.Template) {
|
||||||
if r.loadBalancer != "" {
|
if r.loadBalancer != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -239,18 +257,6 @@ func portIsHTTP(it types.ServicePortConfig) bool {
|
||||||
return it.Target == 80 || it.Target == 443
|
return it.Target == 80 || it.Target == 443
|
||||||
}
|
}
|
||||||
|
|
||||||
type projectFn func(ctx context.Context, project *types.Project) error
|
|
||||||
|
|
||||||
func findProjectFnError(ctx context.Context, project *types.Project, funcs ...projectFn) error {
|
|
||||||
for _, fn := range funcs {
|
|
||||||
err := fn(ctx, project)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// predicate[types.ServiceConfig]
|
// predicate[types.ServiceConfig]
|
||||||
type servicePredicate func(it types.ServiceConfig) bool
|
type servicePredicate func(it types.ServiceConfig) bool
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ func getEcsAPIService(ecsCtx store.EcsContext) (*ecsAPIService, error) {
|
||||||
ctx: ecsCtx,
|
ctx: ecsCtx,
|
||||||
Region: ecsCtx.Region,
|
Region: ecsCtx.Region,
|
||||||
SDK: sdk,
|
SDK: sdk,
|
||||||
resources: awsResources{sdk: sdk},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +85,6 @@ type ecsAPIService struct {
|
||||||
ctx store.EcsContext
|
ctx store.EcsContext
|
||||||
Region string
|
Region string
|
||||||
SDK sdk
|
SDK sdk
|
||||||
resources awsResources
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ecsAPIService) ContainerService() containers.Service {
|
func (a *ecsAPIService) ContainerService() containers.Service {
|
||||||
|
|
|
@ -43,12 +43,12 @@ func (b *ecsAPIService) Convert(ctx context.Context, project *types.Project) ([]
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.resources.parse(ctx, project)
|
resources, err := b.parse(ctx, project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
template, err := b.convert(project)
|
template, err := b.convert(project, resources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ func (b *ecsAPIService) Convert(ctx context.Context, project *types.Project) ([]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.createCapacityProvider(ctx, project, template)
|
err = b.createCapacityProvider(ctx, project, template, resources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -73,9 +73,9 @@ func (b *ecsAPIService) Convert(ctx context.Context, project *types.Project) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a compose project into a CloudFormation template
|
// Convert a compose project into a CloudFormation template
|
||||||
func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Template, error) { //nolint:gocyclo
|
func (b *ecsAPIService) convert(project *types.Project, resources awsResources) (*cloudformation.Template, error) {
|
||||||
template := cloudformation.NewTemplate()
|
template := cloudformation.NewTemplate()
|
||||||
b.resources.ensure(project, template)
|
b.ensureResources(&resources, project, template)
|
||||||
|
|
||||||
for name, secret := range project.Secrets {
|
for name, secret := range project.Secrets {
|
||||||
err := b.createSecret(project, name, secret, template)
|
err := b.createSecret(project, name, secret, template)
|
||||||
|
@ -87,7 +87,7 @@ func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Templat
|
||||||
b.createLogGroup(project, template)
|
b.createLogGroup(project, template)
|
||||||
|
|
||||||
// Private DNS namespace will allow DNS name for the services to be <service>.<project>.local
|
// Private DNS namespace will allow DNS name for the services to be <service>.<project>.local
|
||||||
b.createCloudMap(project, template)
|
b.createCloudMap(project, template, resources.vpc)
|
||||||
|
|
||||||
for _, service := range project.Services {
|
for _, service := range project.Services {
|
||||||
taskExecutionRole := b.createTaskExecutionRole(project, service, template)
|
taskExecutionRole := b.createTaskExecutionRole(project, service, template)
|
||||||
|
@ -114,16 +114,16 @@ func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Templat
|
||||||
)
|
)
|
||||||
for _, port := range service.Ports {
|
for _, port := range service.Ports {
|
||||||
for net := range service.Networks {
|
for net := range service.Networks {
|
||||||
b.createIngress(service, net, port, template)
|
b.createIngress(service, net, port, template, resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := strings.ToUpper(port.Protocol)
|
protocol := strings.ToUpper(port.Protocol)
|
||||||
if b.resources.loadBalancerType == elbv2.LoadBalancerTypeEnumApplication {
|
if resources.loadBalancerType == elbv2.LoadBalancerTypeEnumApplication {
|
||||||
// we don't set Https as a certificate must be specified for HTTPS listeners
|
// we don't set Https as a certificate must be specified for HTTPS listeners
|
||||||
protocol = elbv2.ProtocolEnumHttp
|
protocol = elbv2.ProtocolEnumHttp
|
||||||
}
|
}
|
||||||
targetGroupName := b.createTargetGroup(project, service, port, template, protocol)
|
targetGroupName := b.createTargetGroup(project, service, port, template, protocol, resources.vpc)
|
||||||
listenerName := b.createListener(service, port, template, targetGroupName, b.resources.loadBalancer, protocol)
|
listenerName := b.createListener(service, port, template, targetGroupName, resources.loadBalancer, protocol)
|
||||||
dependsOn = append(dependsOn, listenerName)
|
dependsOn = append(dependsOn, listenerName)
|
||||||
serviceLB = append(serviceLB, ecs.Service_LoadBalancer{
|
serviceLB = append(serviceLB, ecs.Service_LoadBalancer{
|
||||||
ContainerName: service.Name,
|
ContainerName: service.Name,
|
||||||
|
@ -157,7 +157,7 @@ func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Templat
|
||||||
|
|
||||||
template.Resources[serviceResourceName(service.Name)] = &ecs.Service{
|
template.Resources[serviceResourceName(service.Name)] = &ecs.Service{
|
||||||
AWSCloudFormationDependsOn: dependsOn,
|
AWSCloudFormationDependsOn: dependsOn,
|
||||||
Cluster: b.resources.cluster,
|
Cluster: resources.cluster,
|
||||||
DesiredCount: desiredCount,
|
DesiredCount: desiredCount,
|
||||||
DeploymentController: &ecs.Service_DeploymentController{
|
DeploymentController: &ecs.Service_DeploymentController{
|
||||||
Type: ecsapi.DeploymentControllerTypeEcs,
|
Type: ecsapi.DeploymentControllerTypeEcs,
|
||||||
|
@ -172,8 +172,8 @@ func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Templat
|
||||||
NetworkConfiguration: &ecs.Service_NetworkConfiguration{
|
NetworkConfiguration: &ecs.Service_NetworkConfiguration{
|
||||||
AwsvpcConfiguration: &ecs.Service_AwsVpcConfiguration{
|
AwsvpcConfiguration: &ecs.Service_AwsVpcConfiguration{
|
||||||
AssignPublicIp: assignPublicIP,
|
AssignPublicIp: assignPublicIP,
|
||||||
SecurityGroups: b.resources.serviceSecurityGroups(service),
|
SecurityGroups: resources.serviceSecurityGroups(service),
|
||||||
Subnets: b.resources.subnets,
|
Subnets: resources.subnets,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PlatformVersion: platformVersion,
|
PlatformVersion: platformVersion,
|
||||||
|
@ -187,16 +187,18 @@ func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Templat
|
||||||
return template, nil
|
return template, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) createIngress(service types.ServiceConfig, net string, port types.ServicePortConfig, template *cloudformation.Template) {
|
const allProtocols = "-1"
|
||||||
|
|
||||||
|
func (b *ecsAPIService) createIngress(service types.ServiceConfig, net string, port types.ServicePortConfig, template *cloudformation.Template, resources awsResources) {
|
||||||
protocol := strings.ToUpper(port.Protocol)
|
protocol := strings.ToUpper(port.Protocol)
|
||||||
if protocol == "" {
|
if protocol == "" {
|
||||||
protocol = "-1"
|
protocol = allProtocols
|
||||||
}
|
}
|
||||||
ingress := fmt.Sprintf("%s%dIngress", normalizeResourceName(net), port.Target)
|
ingress := fmt.Sprintf("%s%dIngress", normalizeResourceName(net), port.Target)
|
||||||
template.Resources[ingress] = &ec2.SecurityGroupIngress{
|
template.Resources[ingress] = &ec2.SecurityGroupIngress{
|
||||||
CidrIp: "0.0.0.0/0",
|
CidrIp: "0.0.0.0/0",
|
||||||
Description: fmt.Sprintf("%s:%d/%s on %s nextwork", service.Name, port.Target, port.Protocol, net),
|
Description: fmt.Sprintf("%s:%d/%s on %s nextwork", service.Name, port.Target, port.Protocol, net),
|
||||||
GroupId: b.resources.securityGroups[net],
|
GroupId: resources.securityGroups[net],
|
||||||
FromPort: int(port.Target),
|
FromPort: int(port.Target),
|
||||||
IpProtocol: protocol,
|
IpProtocol: protocol,
|
||||||
ToPort: int(port.Target),
|
ToPort: int(port.Target),
|
||||||
|
@ -306,7 +308,7 @@ func (b *ecsAPIService) createListener(service types.ServiceConfig, port types.S
|
||||||
return listenerName
|
return listenerName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) createTargetGroup(project *types.Project, service types.ServiceConfig, port types.ServicePortConfig, template *cloudformation.Template, protocol string) string {
|
func (b *ecsAPIService) createTargetGroup(project *types.Project, service types.ServiceConfig, port types.ServicePortConfig, template *cloudformation.Template, protocol string, vpc string) string {
|
||||||
targetGroupName := fmt.Sprintf(
|
targetGroupName := fmt.Sprintf(
|
||||||
"%s%s%dTargetGroup",
|
"%s%s%dTargetGroup",
|
||||||
normalizeResourceName(service.Name),
|
normalizeResourceName(service.Name),
|
||||||
|
@ -319,7 +321,7 @@ func (b *ecsAPIService) createTargetGroup(project *types.Project, service types.
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Tags: projectTags(project),
|
Tags: projectTags(project),
|
||||||
TargetType: elbv2.TargetTypeEnumIp,
|
TargetType: elbv2.TargetTypeEnumIp,
|
||||||
VpcId: b.resources.vpc,
|
VpcId: vpc,
|
||||||
}
|
}
|
||||||
return targetGroupName
|
return targetGroupName
|
||||||
}
|
}
|
||||||
|
@ -390,11 +392,11 @@ func (b *ecsAPIService) createTaskRole(service types.ServiceConfig, template *cl
|
||||||
return taskRole
|
return taskRole
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) createCloudMap(project *types.Project, template *cloudformation.Template) {
|
func (b *ecsAPIService) createCloudMap(project *types.Project, template *cloudformation.Template, vpc string) {
|
||||||
template.Resources["CloudMap"] = &cloudmap.PrivateDnsNamespace{
|
template.Resources["CloudMap"] = &cloudmap.PrivateDnsNamespace{
|
||||||
Description: fmt.Sprintf("Service Map for Docker Compose project %s", project.Name),
|
Description: fmt.Sprintf("Service Map for Docker Compose project %s", project.Name),
|
||||||
Name: fmt.Sprintf("%s.local", project.Name),
|
Name: fmt.Sprintf("%s.local", project.Name),
|
||||||
Vpc: b.resources.vpc,
|
Vpc: vpc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -321,7 +321,7 @@ services:
|
||||||
memory: 2043248M
|
memory: 2043248M
|
||||||
`)
|
`)
|
||||||
backend := &ecsAPIService{}
|
backend := &ecsAPIService{}
|
||||||
_, err := backend.convert(model)
|
_, err := backend.convert(model, awsResources{})
|
||||||
assert.ErrorContains(t, err, "the resources requested are not supported by ECS/Fargate")
|
assert.ErrorContains(t, err, "the resources requested are not supported by ECS/Fargate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,13 +404,11 @@ services:
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertResultAsString(t *testing.T, project *types.Project) string {
|
func convertResultAsString(t *testing.T, project *types.Project) string {
|
||||||
backend := &ecsAPIService{
|
backend := &ecsAPIService{}
|
||||||
resources: awsResources{
|
template, err := backend.convert(project, awsResources{
|
||||||
vpc: "vpcID",
|
vpc: "vpcID",
|
||||||
subnets: []string{"subnet1", "subnet2"},
|
subnets: []string{"subnet1", "subnet2"},
|
||||||
},
|
})
|
||||||
}
|
|
||||||
template, err := backend.convert(project)
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
resultAsJSON, err := marshall(template)
|
resultAsJSON, err := marshall(template)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -430,7 +428,7 @@ func load(t *testing.T, paths ...string) *types.Project {
|
||||||
func convertYaml(t *testing.T, yaml string) *cloudformation.Template {
|
func convertYaml(t *testing.T, yaml string) *cloudformation.Template {
|
||||||
project := loadConfig(t, yaml)
|
project := loadConfig(t, yaml)
|
||||||
backend := &ecsAPIService{}
|
backend := &ecsAPIService{}
|
||||||
template, err := backend.convert(project)
|
template, err := backend.convert(project, awsResources{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
return template
|
return template
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *ecsAPIService) createCapacityProvider(ctx context.Context, project *types.Project, template *cloudformation.Template) error {
|
func (b *ecsAPIService) createCapacityProvider(ctx context.Context, project *types.Project, template *cloudformation.Template, resources awsResources) error {
|
||||||
var ec2 bool
|
var ec2 bool
|
||||||
for _, s := range project.Services {
|
for _, s := range project.Services {
|
||||||
if requireEC2(s) {
|
if requireEC2(s) {
|
||||||
|
@ -65,7 +65,7 @@ func (b *ecsAPIService) createCapacityProvider(ctx context.Context, project *typ
|
||||||
LaunchConfigurationName: cloudformation.Ref("LaunchConfiguration"),
|
LaunchConfigurationName: cloudformation.Ref("LaunchConfiguration"),
|
||||||
MaxSize: "10", //TODO
|
MaxSize: "10", //TODO
|
||||||
MinSize: "1",
|
MinSize: "1",
|
||||||
VPCZoneIdentifier: b.resources.subnets,
|
VPCZoneIdentifier: resources.subnets,
|
||||||
}
|
}
|
||||||
|
|
||||||
userData := base64.StdEncoding.EncodeToString([]byte(
|
userData := base64.StdEncoding.EncodeToString([]byte(
|
||||||
|
@ -74,7 +74,7 @@ func (b *ecsAPIService) createCapacityProvider(ctx context.Context, project *typ
|
||||||
template.Resources["LaunchConfiguration"] = &autoscaling.LaunchConfiguration{
|
template.Resources["LaunchConfiguration"] = &autoscaling.LaunchConfiguration{
|
||||||
ImageId: ami,
|
ImageId: ami,
|
||||||
InstanceType: machineType,
|
InstanceType: machineType,
|
||||||
SecurityGroups: b.resources.allSecurityGroups(),
|
SecurityGroups: resources.allSecurityGroups(),
|
||||||
IamInstanceProfile: cloudformation.Ref("EC2InstanceProfile"),
|
IamInstanceProfile: cloudformation.Ref("EC2InstanceProfile"),
|
||||||
UserData: userData,
|
UserData: userData,
|
||||||
}
|
}
|
||||||
|
|
10
ecs/sdk.go
10
ecs/sdk.go
|
@ -704,3 +704,13 @@ func (s sdk) GetParameter(ctx context.Context, name string) (string, error) {
|
||||||
|
|
||||||
return ami.ImageID, nil
|
return ami.ImageID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s sdk) SecurityGroupExists(ctx context.Context, sg string) (bool, error) {
|
||||||
|
desc, err := s.EC2.DescribeSecurityGroupsWithContext(ctx, &ec2.DescribeSecurityGroupsInput{
|
||||||
|
GroupIds: aws.StringSlice([]string{sg}),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return len(desc.SecurityGroups) > 0, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue