Skip to content

Commit

Permalink
feat: added support for multiple containers in the same network
Browse files Browse the repository at this point in the history
  • Loading branch information
astromechza committed Feb 1, 2024
1 parent 63ba6de commit aeaca72
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 28 deletions.
78 changes: 50 additions & 28 deletions internal/compose/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package compose
import (
"errors"
"fmt"
"slices"

Check failure on line 13 in internal/compose/convert.go

View workflow job for this annotation

GitHub Actions / test

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.19.13/x64/src/slices)
"sort"

compose "github.com/compose-spec/compose-go/types"
Expand All @@ -23,29 +24,51 @@ func ConvertSpec(spec *score.WorkloadSpec) (*compose.Project, ExternalVariables,
return nil, nil, fmt.Errorf("preparing context: %w", err)
}

for _, cSpec := range spec.Containers {
if len(spec.Containers) == 0 {
return nil, nil, errors.New("workload does not have any containers to convert into a compose service")
}

var project = compose.Project{
Services: make(compose.Services, 0, len(spec.Containers)),
}

externalVars := ExternalVariables(ctx.ListEnvVars())

var ports []compose.ServicePortConfig
if len(spec.Service.Ports) > 0 {
ports = []compose.ServicePortConfig{}
for _, pSpec := range spec.Service.Ports {
var pubPort = fmt.Sprintf("%v", pSpec.Port)
var tgtPort = pSpec.TargetPort
if pSpec.TargetPort == 0 {
tgtPort = pSpec.Port
}
ports = append(ports, compose.ServicePortConfig{
Published: pubPort,
Target: uint32(tgtPort),
Protocol: pSpec.Protocol,
})
}
}

// When multiple containers are specified we need to identify one container as the "main" container which will own
// the network and use the native workload name. All other containers in this workload will have the container
// name appended as a suffix. We use the natural sort order of the container names and pick the first one
containerNames := make([]string, 0, len(spec.Containers))
for name := range spec.Containers {
containerNames = append(containerNames, name)
}
slices.Sort(containerNames)

for _, containerName := range containerNames {
cSpec := spec.Containers[containerName]

var env = make(compose.MappingWithEquals, len(cSpec.Variables))
for key, val := range cSpec.Variables {
var envVarVal = ctx.Substitute(val)
env[key] = &envVarVal
}

var ports []compose.ServicePortConfig
if len(spec.Service.Ports) > 0 {
ports = []compose.ServicePortConfig{}
for _, pSpec := range spec.Service.Ports {
var pubPort = fmt.Sprintf("%v", pSpec.Port)
var tgtPort = pSpec.TargetPort
if pSpec.TargetPort == 0 {
tgtPort = pSpec.Port
}
ports = append(ports, compose.ServicePortConfig{
Published: pubPort,
Target: uint32(tgtPort),
Protocol: pSpec.Protocol,
})
}
}
// NOTE: Sorting is necessary for DeepEqual call within our Unit Tests to work reliably
sort.Slice(ports, func(i, j int) bool {
return ports[i].Published < ports[j].Published
Expand Down Expand Up @@ -83,18 +106,17 @@ func ConvertSpec(spec *score.WorkloadSpec) (*compose.Project, ExternalVariables,
Volumes: volumes,
}

var proj = compose.Project{
Services: compose.Services{
svc,
},
if len(spec.Containers) > 1 {
// if we have more than 1 container then namespace them with the container name
svc.Name += "-" + containerName
// if we are not the "first" service, then inherit the network from the first service
if len(project.Services) > 0 {
svc.Ports = nil
svc.NetworkMode = "service:" + project.Services[0].Name
}
}

var externalVars = ExternalVariables(ctx.ListEnvVars())

// NOTE: Only one container per workload can be defined for compose.
// All other containers will be ignored by this tool.
return &proj, externalVars, nil
project.Services = append(project.Services, svc)
}

return nil, nil, errors.New("workload does not have any containers to convert into a compose service")
return &project, externalVars, nil
}
52 changes: 52 additions & 0 deletions internal/compose/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,58 @@ func TestScoreConvert(t *testing.T) {
"APP_DB_NAME": "",
},
},
{
Name: "Should support multiple containers",
Source: &score.WorkloadSpec{
Metadata: score.WorkloadMeta{
Name: "test",
},
Containers: score.ContainersSpecs{
"frontend": score.ContainerSpec{
Image: "busybox",
Variables: map[string]string{
"PORT": "80",
},
},
"backend": score.ContainerSpec{
Image: "busybox",
Variables: map[string]string{
"PORT": "81",
},
},
},
Service: score.ServiceSpec{
Ports: map[string]score.ServicePortSpec{
"frontend": {Port: 8080, TargetPort: 80},
"backend": {Port: 8081, TargetPort: 81},
},
},
},
Project: &compose.Project{
Services: compose.Services{
{
Name: "test-backend",
Image: "busybox",
Environment: compose.MappingWithEquals{
"PORT": stringPtr("81"),
},
Ports: []compose.ServicePortConfig{
{Target: 80, Published: "8080"},
{Target: 81, Published: "8081"},
},
},
{
Name: "test-frontend",
Image: "busybox",
Environment: compose.MappingWithEquals{
"PORT": stringPtr("80"),
},
NetworkMode: "service:test-backend",
},
},
},
Vars: ExternalVariables{},
},

// Errors handling
//
Expand Down

0 comments on commit aeaca72

Please sign in to comment.