Skip to content

Commit

Permalink
Update confort: add test for (*composeBackend).Load
Browse files Browse the repository at this point in the history
  • Loading branch information
daichitakahashi committed Feb 16, 2023
1 parent 7fb8dfc commit c3354e8
Show file tree
Hide file tree
Showing 22 changed files with 436 additions and 23 deletions.
33 changes: 32 additions & 1 deletion compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,13 @@ func WithComposeBackend(b compose.Backend) ComposeOption {
}

func Compose(ctx context.Context, configFile string, opts ...ComposeOption) (*ComposeProject, error) {
absConfigFile, err := filepath.Abs(configFile)
if err != nil {
return nil, err
}
configFile = filepath.Base(configFile)
var (
projectDir string
projectDir = filepath.Dir(absConfigFile)
projectName string
overrideConfigFiles []string
profiles []string
Expand Down Expand Up @@ -171,6 +176,11 @@ func Compose(ctx context.Context, configFile string, opts ...ComposeOption) (*Co
}
}
}
// Make all configuration file paths relative from projectDir.
overrideConfigFiles = resolveConfigFilePaths(projectDir, overrideConfigFiles)
if envFile != "" {
envFile = resolveFilePath(projectDir, envFile)
}

ctx, cancel := applyTimeout(ctx, timeout)
defer cancel()
Expand Down Expand Up @@ -224,6 +234,27 @@ func (c *ComposeProject) Close() error {
})
}

func resolveFilePath(base, file string) string {
if !filepath.IsAbs(file) {
// Adjust config file path based on specified directory.
// It is required because Compose CLI resolves file paths based on
// working directory of its process.
file = filepath.Join(base, file)
}
return file
}

func resolveConfigFilePaths(base string, configFiles []string) []string {
r := make([]string, 0, len(configFiles))
for _, f := range configFiles {
if f == "" || f == "-" {
continue // Ignore empty value and stdin.
}
r = append(r, resolveFilePath(base, f))
}
return r
}

func resolveGoModDir(ctx context.Context) (string, error) {
out, err := exec.CommandContext(ctx, "go", "env", "GOMOD").Output()
if err != nil {
Expand Down
16 changes: 15 additions & 1 deletion compose_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os/exec"
"sort"
"strings"
"sync"

"github.com/daichitakahashi/confort/compose"
Expand All @@ -25,6 +26,7 @@ type (
composer struct {
cli *client.Client
dockerCompose func(ctx context.Context, args ...string) *exec.Cmd
modifiedConfig []byte
proj projectConfig
resourcePolicy compose.ResourcePolicy
scalingPolicies map[string]compose.ScalingPolicy
Expand Down Expand Up @@ -77,10 +79,21 @@ func (b *composeBackend) Load(ctx context.Context, configFile string, opts compo
args = append(args, "config")

// Load canonical config.
canonicalConfig, err := exec.CommandContext(ctx, "docker", args...).Output()
var (
stdout bytes.Buffer
stderr strings.Builder
)
cmd := exec.CommandContext(ctx, "docker", args...)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
if errors.As(err, new(*exec.ExitError)) {
return nil, errors.New(stderr.String())
}
return nil, err
}
canonicalConfig := stdout.Bytes()

v := map[string]any{}
err = yaml.Unmarshal(canonicalConfig, &v)
Expand Down Expand Up @@ -119,6 +132,7 @@ func (b *composeBackend) Load(ctx context.Context, configFile string, opts compo
return &composer{
cli: b.cli,
dockerCompose: dockerCompose,
modifiedConfig: modifiedConfig,
proj: proj,
resourcePolicy: opts.ResourcePolicy,
scalingPolicies: scalingPolicies,
Expand Down
130 changes: 117 additions & 13 deletions compose_backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ package confort

import (
"context"
"path/filepath"
"strings"
"testing"

"github.com/daichitakahashi/confort/compose"
"github.com/daichitakahashi/confort/internal/beacon"
"github.com/docker/docker/client"
"gotest.tools/v3/golden"
)

// test against unified & modified configuration
func TestComposeBackend_Load(t *testing.T) {
t.Parallel()

ctx := context.Background()

cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
Expand All @@ -22,16 +26,116 @@ func TestComposeBackend_Load(t *testing.T) {
cli: cli,
}

be.Load(ctx, "", compose.LoadOptions{
ProjectDir: "./testdata/compose",
ProjectName: "",
OverrideConfigFiles: nil,
Profiles: nil,
EnvFile: "", // env of process
ResourcePolicy: compose.ResourcePolicy{},
})
}
type testCase struct {
configFile string
opts compose.LoadOptions
goldenFile string
}
runTest := func(t *testing.T, tc testCase) {
c, err := be.Load(ctx, tc.configFile, tc.opts)
if err != nil {
t.Fatal(err)
}
tc.goldenFile = strings.TrimPrefix(
filepath.Clean(tc.goldenFile), "testdata/")
golden.Assert(t, string(c.(*composer).modifiedConfig), tc.goldenFile)
}

// TODO: テストケース
// * 起動済みの
// * プロファイルで絞って、除外されたサービスの起動に失敗すること
testCases := map[string]testCase{
"normal": {
configFile: "./testdata/compose/simple/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/simple",
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/simple/modified.yaml",
},
"override-name": {
configFile: "./testdata/compose/simple/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/simple",
ProjectName: "new-name",
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/simple/modified-override-name.yaml",
},
"override": {
configFile: "./testdata/compose/override/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/override",
OverrideConfigFiles: []string{"./testdata/compose/override/compose.override.yaml"},
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/override/modified.yaml",
},
"profile-none": {
configFile: "./testdata/compose/profile/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/profile",
Profiles: nil,
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/profile/modified.yaml",
},
"profile-webapp": {
configFile: "./testdata/compose/profile/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/profile",
Profiles: []string{"webapp"},
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/profile/modified-webapp.yaml",
},
"profile-all": {
configFile: "./testdata/compose/profile/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/profile",
Profiles: []string{"webapp", "proxy"},
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/profile/modified-all.yaml",
},
"env-default": {
configFile: "./testdata/compose/env/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/env",
EnvFile: "",
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/env/modified.yaml",
},
"env-prod": {
configFile: "./testdata/compose/env/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/env",
EnvFile: "./testdata/compose/env/.env-prod",
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/env/modified-prod.yaml",
},
"project-dir": {
configFile: "./testdata/compose/simple/compose.yaml",
opts: compose.LoadOptions{
ProjectDir: "./testdata/compose/project-dir",
ResourceIdentifierLabel: beacon.LabelIdentifier,
ResourceIdentifier: beacon.Identifier("VALUE"),
},
goldenFile: "./testdata/compose/project-dir/modified.yaml",
},
}
for name, tc := range testCases {
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
runTest(t, tc)
})
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
golang.org/x/sync v0.1.0
google.golang.org/grpc v1.52.3
google.golang.org/protobuf v1.28.1
gotest.tools/v3 v3.4.0
)

require (
Expand Down
5 changes: 4 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down Expand Up @@ -315,6 +316,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4=
golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand All @@ -341,5 +343,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
7 changes: 0 additions & 7 deletions testdata/compose/compose.yaml

This file was deleted.

1 change: 1 addition & 0 deletions testdata/compose/env/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NGINX_VER=1.23.3-alpine
1 change: 1 addition & 0 deletions testdata/compose/env/.env-prod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NGINX_VER=1.23.3-alpine-slim
3 changes: 3 additions & 0 deletions testdata/compose/env/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
services:
server:
image: nginx:${NGINX_VER}
13 changes: 13 additions & 0 deletions testdata/compose/env/modified-prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: env
networks:
default:
labels:
daichitakahashi.confort.beacon.identifier: 8ec121c93e4a0de65f26e1500cb501e383531efb2c2ca9ec1d457478d6d3627b
name: env_default
services:
server:
image: nginx:1.23.3-alpine-slim
labels:
daichitakahashi.confort.beacon.identifier: 8ec121c93e4a0de65f26e1500cb501e383531efb2c2ca9ec1d457478d6d3627b
networks:
default: null
13 changes: 13 additions & 0 deletions testdata/compose/env/modified.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: env
networks:
default:
labels:
daichitakahashi.confort.beacon.identifier: 8ec121c93e4a0de65f26e1500cb501e383531efb2c2ca9ec1d457478d6d3627b
name: env_default
services:
server:
image: nginx:1.23.3-alpine
labels:
daichitakahashi.confort.beacon.identifier: 8ec121c93e4a0de65f26e1500cb501e383531efb2c2ca9ec1d457478d6d3627b
networks:
default: null
16 changes: 16 additions & 0 deletions testdata/compose/override/compose.override.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
server1:
image: alpine:3.16.2
ports:
- 8080/tcp
networks:
- default
- private-net
server2:
networks:
- default
- private-net

networks:
private-net:
external: true
16 changes: 16 additions & 0 deletions testdata/compose/override/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
server1:
image: alpine:3.16.2
ports:
- 80/tcp
server2:
image: alpine:3.16.2
volumes:
- internal:/var/internal
- external:/var/external

volumes:
internal:
external: false
external:
external: true

0 comments on commit c3354e8

Please sign in to comment.