Skip to content

Commit

Permalink
cleanup container name logic
Browse files Browse the repository at this point in the history
  • Loading branch information
aksiksi committed Nov 5, 2023
1 parent e2a467e commit 2aa85bb
Show file tree
Hide file tree
Showing 11 changed files with 608 additions and 51 deletions.
2 changes: 1 addition & 1 deletion cmd/nixose/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func main() {

start := time.Now()
g := nixose.Generator{
Project: nixose.NewProject(*project, *projectSeparator),
Project: nixose.NewProjectWithSeparator(*project, *projectSeparator),
Runtime: containerRuntime,
Paths: paths,
EnvFiles: envFiles,
Expand Down
63 changes: 30 additions & 33 deletions compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,36 +181,37 @@ func (g *Generator) Run(ctx context.Context) (*NixContainerConfig, error) {
}, nil
}

func (g *Generator) postProcessContainers(containers []NixContainer) {
func (g *Generator) postProcessContainers(containers []*NixContainer) {
serviceToContainer := make(map[string]*NixContainer)
for _, c := range containers {
serviceToContainer[c.service.Name] = &c
serviceToContainer[c.service.Name] = c
}

for _, c := range containers {
if networkMode := c.service.NetworkMode; strings.HasPrefix(networkMode, "service:") {
targetService := strings.Split(networkMode, ":")[1]
targetContainerName := serviceToContainer[targetService].Name
c.ExtraOptions = append(c.ExtraOptions, "--network=container:"+targetContainerName)
}
}
}

func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer {
dependsOn := service.GetDependencies()
if g.Project != nil {
for i := range dependsOn {
dependsOn[i] = g.Project.With(dependsOn[i])
dependsOn := c.service.GetDependencies()
for i, service := range dependsOn {
dependsOn[i] = serviceToContainer[service].Name
}
c.DependsOn = dependsOn

// Drop the reference to the service at the end of post-processing. This allows GC to
// kick in and free the service allocation.
c.service = nil
}
}

func (g *Generator) buildNixContainer(service types.ServiceConfig) *NixContainer {
var name string
if service.ContainerName != "" {
name = service.ContainerName
} else {
// TODO(aksiksi): We should try to use the same convention as Docker Compose
// when container_name is not set.
// See: https://github.com/docker/compose/issues/6316
name = service.Name
name = g.Project.With(service.Name)
}

systemdConfig, err := parseRestartPolicyAndSystemdLabels(&service)
Expand All @@ -219,8 +220,7 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer
panic(err)
}

c := NixContainer{
Project: g.Project,
c := &NixContainer{
Runtime: g.Runtime,
Name: name,
Image: service.Image,
Expand All @@ -230,7 +230,6 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer
Volumes: make(map[string]string),
Networks: maps.Keys(service.Networks),
SystemdConfig: systemdConfig,
DependsOn: dependsOn,
AutoStart: g.AutoStart,
service: &service,
}
Expand All @@ -245,7 +244,7 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer
for _, name := range c.Networks {
networkName := g.Project.With(name)
c.ExtraOptions = append(c.ExtraOptions, fmt.Sprintf("--network=%s", networkName))
// Allow other containers to use bare container name as an alias even when a project is set.
// Allow other containers to use service name as an alias when a project is set.
c.ExtraOptions = append(c.ExtraOptions, fmt.Sprintf("--network-alias=%s", service.Name))
}

Expand Down Expand Up @@ -298,45 +297,43 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer
return c
}

func (g *Generator) buildNixContainers() []NixContainer {
var containers []NixContainer
func (g *Generator) buildNixContainers() []*NixContainer {
var containers []*NixContainer
for _, s := range g.composeProject.Services {
containers = append(containers, g.buildNixContainer(s))
}
slices.SortFunc(containers, func(c1, c2 NixContainer) int {
slices.SortFunc(containers, func(c1, c2 *NixContainer) int {
return cmp.Compare(c1.Name, c2.Name)
})
return containers
}

func (g *Generator) buildNixNetworks(containers []NixContainer) []NixNetwork {
var networks []NixNetwork
func (g *Generator) buildNixNetworks(containers []*NixContainer) []*NixNetwork {
var networks []*NixNetwork
for name, network := range g.composeProject.Networks {
n := NixNetwork{
Project: g.Project,
n := &NixNetwork{
Runtime: g.Runtime,
Name: name,
Name: g.Project.With(name),
Labels: network.Labels,
}
// Keep track of all containers that are in this network.
for _, c := range containers {
if slices.Contains(c.Networks, name) {
n.Containers = append(n.Containers, fmt.Sprintf("%s-%s", g.Runtime, g.Project.With(c.Name)))
n.Containers = append(n.Containers, fmt.Sprintf("%s-%s", g.Runtime, c.Name))
}
}
networks = append(networks, n)
}
slices.SortFunc(networks, func(n1, n2 NixNetwork) int {
slices.SortFunc(networks, func(n1, n2 *NixNetwork) int {
return cmp.Compare(n1.Name, n2.Name)
})
return networks
}

func (g *Generator) buildNixVolumes(containers []NixContainer) []NixVolume {
var volumes []NixVolume
func (g *Generator) buildNixVolumes(containers []*NixContainer) []*NixVolume {
var volumes []*NixVolume
for name, volume := range g.composeProject.Volumes {
v := NixVolume{
Project: g.Project,
v := &NixVolume{
Runtime: g.Runtime,
Name: name,
Driver: volume.Driver,
Expand Down Expand Up @@ -364,12 +361,12 @@ func (g *Generator) buildNixVolumes(containers []NixContainer) []NixVolume {
// Keep track of all containers that use this named volume.
for _, c := range containers {
if _, ok := c.Volumes[name]; ok {
v.Containers = append(v.Containers, fmt.Sprintf("%s-%s", g.Runtime, g.Project.With(c.Name)))
v.Containers = append(v.Containers, fmt.Sprintf("%s-%s", g.Runtime, c.Name))
}
}
volumes = append(volumes, v)
}
slices.SortFunc(volumes, func(n1, n2 NixVolume) int {
slices.SortFunc(volumes, func(n1, n2 *NixVolume) int {
return cmp.Compare(n1.Name, n2.Name)
})
return volumes
Expand Down
28 changes: 20 additions & 8 deletions nixose.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/compose-spec/compose-go/types"
)

const DefaultProjectSeparator = "-"
const DefaultProjectSeparator = "_"

type ContainerRuntime int

Expand Down Expand Up @@ -36,7 +36,14 @@ type Project struct {
separator string
}

func NewProject(name, separator string) *Project {
func NewProject(name string) *Project {
if name == "" {
return nil
}
return &Project{Name: name, separator: DefaultProjectSeparator}
}

func NewProjectWithSeparator(name, separator string) *Project {
if name == "" {
return nil
}
Expand All @@ -53,16 +60,21 @@ func (p *Project) With(name string) string {
return fmt.Sprintf("%s%s%s", p.Name, p.separator, name)
}

func (p *Project) WithSeparator(name, separator string) string {
if p == nil {
return name
}
return fmt.Sprintf("%s%s%s", p.Name, separator, name)
}

type NixNetwork struct {
Project *Project
Runtime ContainerRuntime
Name string
Labels map[string]string
Containers []string
}

type NixVolume struct {
Project *Project
Runtime ContainerRuntime
Name string
Driver string
Expand All @@ -88,7 +100,6 @@ type NixContainerSystemdConfig struct {

// https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=oci-container
type NixContainer struct {
Project *Project
Runtime ContainerRuntime
Name string
Image string
Expand All @@ -105,15 +116,16 @@ type NixContainer struct {
AutoStart bool

// Original Docker Compose service.
// Used for post-processing containers and reset to nil right afterwards.
service *types.ServiceConfig
}

type NixContainerConfig struct {
Project *Project
Runtime ContainerRuntime
Containers []NixContainer
Networks []NixNetwork
Volumes []NixVolume
Containers []*NixContainer
Networks []*NixNetwork
Volumes []*NixVolume
}

func (c NixContainerConfig) String() string {
Expand Down
54 changes: 54 additions & 0 deletions nixose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,33 @@ func TestDocker(t *testing.T) {
}
}

func TestDocker_WithProject(t *testing.T) {
ctx := context.Background()
composePath, envFilePath, outFilePath := getPaths(t)
g := Generator{
Project: NewProject("myproject"),
Runtime: ContainerRuntimeDocker,
Paths: []string{composePath},
EnvFiles: []string{envFilePath},
}
c, err := g.Run(ctx)
if err != nil {
t.Fatal(err)
}
wantOutput, err := os.ReadFile(outFilePath)
if err != nil {
t.Fatal(err)
}
got, want := c.String(), string(wantOutput)
if *update {
if err := os.WriteFile(outFilePath, []byte(got), 0644); err != nil {
t.Fatal(err)
}
} else if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("output diff: %s\n", diff)
}
}

func TestPodman(t *testing.T) {
ctx := context.Background()
composePath, envFilePath, outFilePath := getPaths(t)
Expand All @@ -72,3 +99,30 @@ func TestPodman(t *testing.T) {
t.Errorf("output diff: %s\n", diff)
}
}

func TestPodman_WithProject(t *testing.T) {
ctx := context.Background()
composePath, envFilePath, outFilePath := getPaths(t)
g := Generator{
Project: NewProject("myproject"),
Runtime: ContainerRuntimePodman,
Paths: []string{composePath},
EnvFiles: []string{envFilePath},
}
c, err := g.Run(ctx)
if err != nil {
t.Fatal(err)
}
wantOutput, err := os.ReadFile(outFilePath)
if err != nil {
t.Fatal(err)
}
got, want := c.String(), string(wantOutput)
if *update {
if err := os.WriteFile(outFilePath, []byte(got), 0644); err != nil {
t.Fatal(err)
}
} else if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("output diff: %s\n", diff)
}
}
5 changes: 2 additions & 3 deletions templates/container.nix.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{{- $name := .Project.With .Name -}}
{{- $runtime := .Runtime | printf "%s" -}}
virtualisation.oci-containers.containers."{{$name}}" = {
virtualisation.oci-containers.containers."{{.Name}}" = {
image = "{{.Image}}";

{{- if .Environment}}
Expand Down Expand Up @@ -68,7 +67,7 @@ virtualisation.oci-containers.containers."{{$name}}" = {
{{- end}}
};
{{- if .SystemdConfig}}
systemd.services."{{$runtime}}-{{$name}}" = {
systemd.services."{{$runtime}}-{{.Name}}" = {
{{- if .SystemdConfig.Service}}
serviceConfig = {
{{- range $k, $v := .SystemdConfig.Service}}
Expand Down
7 changes: 3 additions & 4 deletions templates/network.nix.tmpl
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
{{- $name := .Project.With .Name -}}
{{- $runtime := .Runtime | printf "%s" -}}
{{- $labels := mapToRepeatedKeyValFlag "--label" .Labels -}}
systemd.services."create-{{$runtime}}-network-{{$name}}" = {
systemd.services."create-{{$runtime}}-network-{{.Name}}" = {
serviceConfig.Type = "oneshot";
path = [ pkgs.{{$runtime}} ];
{{- if eq $runtime "docker"}}
script = ''
docker network inspect {{$name}} || docker network create {{$name}}{{ $labels | join " "}}
docker network inspect {{.Name}} || docker network create {{.Name}}{{ $labels | join " "}}
'';
{{- else}}
script = ''
podman network create {{$name}} --opt isolate=true --ignore{{ $labels | join " "}}
podman network create {{.Name}} --opt isolate=true --ignore{{ $labels | join " "}}
'';
{{- end}}
{{- if .Containers}}
Expand Down
Loading

0 comments on commit 2aa85bb

Please sign in to comment.