Skip to content

Commit

Permalink
improve template structure and add basic tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aksiksi committed Nov 5, 2023
1 parent 45172b3 commit 59ac2d3
Show file tree
Hide file tree
Showing 14 changed files with 724 additions and 23 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Test

on:
push:
paths-ignore:
- '**/*.md'
branches:
- main
pull_request:
paths-ignore:
- '**/*.md'

jobs:
linux-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: '>=1.21'
- run: go version
- name: Test
run: go test -v -covermode=count -coverprofile=coverage.out
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
files: coverage.out
20 changes: 19 additions & 1 deletion compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,21 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer
dependsOn[i] = g.Project.With(dependsOn[i])
}
}

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
}

c := NixContainer{
Project: g.Project,
Runtime: g.Runtime,
Name: service.Name,
Name: name,
Image: service.Image,
Labels: service.Labels,
Ports: portConfigsToPortStrings(service.Ports),
Expand All @@ -120,6 +131,13 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig) NixContainer
c.ExtraOptions = append(c.ExtraOptions, fmt.Sprintf("--network-alias=%s", service.Name))
}

// TODO(aksiksi): Handle the service's "network_mode"
// We can only parse the network mode at this point if it points to host or container.
// If it points to a service, we'll need to do a scan when we've finished parsing all
// containers.
// Compose: https://docs.docker.com/compose/compose-file/compose-file-v3/#network_mode
// Podman: https://docs.podman.io/en/latest/markdown/podman-run.1.html#network-mode-net

for _, v := range service.Volumes {
c.Volumes[v.Source] = v.String()
}
Expand Down
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ require (
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
)

// Test
require (
github.com/google/go-cmp v0.5.9
)

require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
Expand All @@ -17,6 +22,7 @@ require (
github.com/google/uuid v1.1.1 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
Expand All @@ -30,5 +36,6 @@ require (
golang.org/x/crypto v0.3.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.2.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
8 changes: 7 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
Expand Down Expand Up @@ -59,8 +64,9 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
12 changes: 7 additions & 5 deletions nixose.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ var templateFS embed.FS
var nixTemplates = template.New("nix").Funcs(sprig.FuncMap()).Funcs(funcMap)

func labelMapToLabelFlags(l map[string]string) []string {
// https://docs.docker.com/engine/reference/commandline/run/#label
// https://docs.podman.io/en/latest/markdown/podman-run.1.html#label-l-key-value
labels := mapToKeyValArray(l)
for i, label := range labels {
labels[i] = fmt.Sprintf("--label=%s", label)
}
return labels
}

func execTemplate(t *template.Template) func(string, interface{}) (string, error) {
return func(name string, v interface{}) (string, error) {
var buf strings.Builder
err := t.ExecuteTemplate(&buf, name, v)
return buf.String(), err
func execTemplate(t *template.Template) func(string, any) (string, error) {
return func(name string, v any) (string, error) {
var s strings.Builder
err := t.ExecuteTemplate(&s, name, v)
return s.String(), err
}
}

Expand Down
63 changes: 63 additions & 0 deletions nixose_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package nixose

import (
"context"
"fmt"
"os"
"path"
"testing"

"github.com/google/go-cmp/cmp"
)

func getPaths(t *testing.T) (string, string, string) {
outFileName := fmt.Sprintf("%s_out.nix", t.Name())
composePath := path.Join("testdata", "docker-compose.yml")
envFilePath := path.Join("testdata", "input.env")
outFilePath := path.Join("testdata", outFileName)
return composePath, envFilePath, outFilePath
}

func TestDocker(t *testing.T) {
ctx := context.Background()
composePath, envFilePath, outFilePath := getPaths(t)
g := Generator{
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 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)
g := Generator{
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 diff := cmp.Diff(want, got); diff != "" {
t.Errorf("output diff: %s\n", diff)
}
}
6 changes: 3 additions & 3 deletions templates/container.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{- $name := .Project.With .Name}}
{{- $runtime := .Runtime | printf "%s"}}
{{- $labels := labelMapToLabelFlags .Labels}}
{{- $name := .Project.With .Name -}}
{{- $runtime := .Runtime | printf "%s" -}}
{{- $labels := labelMapToLabelFlags .Labels -}}
virtualisation.oci-containers.containers."{{$name}}" = {
image = "{{.Image}}";

Expand Down
27 changes: 21 additions & 6 deletions templates/main.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- $runtime := .Runtime | printf "%s"}}
{{- $runtime := .Runtime | printf "%s" -}}
{ pkgs, ... }:

{
Expand All @@ -16,20 +16,35 @@
};
virtualisation.oci-containers.backend = "{{$runtime}}";

{{- if .Containers}}

# Containers
{{- range .Containers}}{{execTemplate "container.tmpl" . | indent 2}}{{end}}
{{- range .Containers}}
{{execTemplate "container.tmpl" . | indent 2}}
{{- end}}
{{- end}}

{{- if .Networks}}

# Networks
{{- range .Networks}}{{execTemplate "network.tmpl" . | indent 2}}{{end}}
{{- range .Networks}}
{{execTemplate "network.tmpl" . | indent 2}}
{{- end}}
{{- end}}

{{- if .Volumes}}

# Volumes
{{- range .Volumes}}{{execTemplate "volume.tmpl" . | indent 2}}{{end}}
{{- range .Volumes}}
{{execTemplate "volume.tmpl" . | indent 2}}
{{- end}}
{{- end}}

# Scripts
up = writeShellScript "compose-{{.Project.Name}}-up.sh" ''
up = writeShellScript "compose-{{.Project.With "up"}}.sh" ''
echo "TODO: Create resources."
'';
down = writeShellScript "compose-{{.Project.Name}}-down.sh" ''
down = writeShellScript "compose-{{.Project.With "down"}}.sh" ''
echo "TODO: Remove resources."
'';
}
6 changes: 3 additions & 3 deletions templates/network.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{- $name := .Project.With .Name}}
{{- $runtime := .Runtime | printf "%s"}}
{{- $labels := labelMapToLabelFlags .Labels}}
{{- $name := .Project.With .Name -}}
{{- $runtime := .Runtime | printf "%s" -}}
{{- $labels := labelMapToLabelFlags .Labels -}}
systemd.services."create-{{$runtime}}-network-{{$name}}" = {
serviceConfig.Type = "oneshot";
path = [ pkgs.{{$runtime}} ];
Expand Down
8 changes: 4 additions & 4 deletions templates/volume.tmpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{/* NOTE(aksiksi): Volume name is _not_ project scoped to match Compose semantics. */}}
{{- $name := .Name}}
{{- $runtime := .Runtime | printf "%s"}}
{{- $driverOptsString := mapToKeyValArray .DriverOpts | join ","}}
{{- /* NOTE(aksiksi): Volume name is _not_ project scoped to match Compose semantics. */ -}}
{{- $name := .Name -}}
{{- $runtime := .Runtime | printf "%s" -}}
{{- $driverOptsString := mapToKeyValArray .DriverOpts | join "," -}}
systemd.services."create-{{$runtime}}-volume-{{$name}}" = {
serviceConfig.Type = "oneshot";
path = [ pkgs.{{$runtime}} ];
Expand Down
Loading

0 comments on commit 59ac2d3

Please sign in to comment.