mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-08-22 19:49:08 +08:00
Compare commits
10 Commits
v0.7.0-rc1
...
v0.7.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
05846896d1 | ||
![]() |
906948782e | ||
![]() |
1e1cc940df | ||
![]() |
e89ed1bcb6 | ||
![]() |
f0026081a7 | ||
![]() |
a18829f837 | ||
![]() |
da0eb138d0 | ||
![]() |
a2c7d43e46 | ||
![]() |
f7cba04f5e | ||
![]() |
12b5db70e2 |
@@ -24,12 +24,13 @@ RUN --mount=target=. \
|
|||||||
|
|
||||||
FROM gobase AS buildx-build
|
FROM gobase AS buildx-build
|
||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
|
ARG LDFLAGS="-w -s"
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
RUN --mount=type=bind,target=. \
|
RUN --mount=type=bind,target=. \
|
||||||
--mount=type=cache,target=/root/.cache \
|
--mount=type=cache,target=/root/.cache \
|
||||||
--mount=type=cache,target=/go/pkg/mod \
|
--mount=type=cache,target=/go/pkg/mod \
|
||||||
--mount=type=bind,source=/tmp/.ldflags,target=/tmp/.ldflags,from=buildx-version \
|
--mount=type=bind,source=/tmp/.ldflags,target=/tmp/.ldflags,from=buildx-version \
|
||||||
set -x; xx-go build -ldflags "$(cat /tmp/.ldflags)" -o /usr/bin/buildx ./cmd/buildx && \
|
set -x; xx-go build -ldflags "$(cat /tmp/.ldflags) ${LDFLAGS}" -o /usr/bin/buildx ./cmd/buildx && \
|
||||||
xx-verify --static /usr/bin/buildx
|
xx-verify --static /usr/bin/buildx
|
||||||
|
|
||||||
FROM buildx-build AS test
|
FROM buildx-build AS test
|
||||||
|
15
bake/bake.go
15
bake/bake.go
@@ -89,7 +89,20 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m, c.Groups, nil
|
|
||||||
|
var g []*Group
|
||||||
|
if len(targets) == 0 || (len(targets) == 1 && targets[0] == "default") {
|
||||||
|
for _, group := range c.Groups {
|
||||||
|
if group.Name != "default" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g = []*Group{{Targets: group.Targets}}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g = []*Group{{Targets: targets}}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseFiles(files []File, defaults map[string]string) (_ *Config, err error) {
|
func ParseFiles(files []File, defaults map[string]string) (_ *Config, err error) {
|
||||||
|
@@ -3,6 +3,7 @@ package bake
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -34,7 +35,7 @@ target "webapp" {
|
|||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
t.Run("NoOverrides", func(t *testing.T) {
|
t.Run("NoOverrides", func(t *testing.T) {
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, nil, nil)
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, nil, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 1, len(m))
|
require.Equal(t, 1, len(m))
|
||||||
|
|
||||||
@@ -43,6 +44,9 @@ target "webapp" {
|
|||||||
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"])
|
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"])
|
||||||
require.Equal(t, true, *m["webapp"].NoCache)
|
require.Equal(t, true, *m["webapp"].NoCache)
|
||||||
require.Nil(t, m["webapp"].Pull)
|
require.Nil(t, m["webapp"].Pull)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("InvalidTargetOverrides", func(t *testing.T) {
|
t.Run("InvalidTargetOverrides", func(t *testing.T) {
|
||||||
@@ -56,7 +60,7 @@ target "webapp" {
|
|||||||
os.Setenv("VAR_FROMENV"+t.Name(), "fromEnv")
|
os.Setenv("VAR_FROMENV"+t.Name(), "fromEnv")
|
||||||
defer os.Unsetenv("VAR_FROM_ENV" + t.Name())
|
defer os.Unsetenv("VAR_FROM_ENV" + t.Name())
|
||||||
|
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{
|
||||||
"webapp.args.VAR_UNSET",
|
"webapp.args.VAR_UNSET",
|
||||||
"webapp.args.VAR_EMPTY=",
|
"webapp.args.VAR_EMPTY=",
|
||||||
"webapp.args.VAR_SET=bananas",
|
"webapp.args.VAR_SET=bananas",
|
||||||
@@ -81,17 +85,23 @@ target "webapp" {
|
|||||||
|
|
||||||
require.Equal(t, m["webapp"].Args["VAR_BOTH"], "webapp")
|
require.Equal(t, m["webapp"].Args["VAR_BOTH"], "webapp")
|
||||||
require.Equal(t, m["webapp"].Args["VAR_INHERITED"], "override")
|
require.Equal(t, m["webapp"].Args["VAR_INHERITED"], "override")
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
// building leaf but overriding parent fields
|
// building leaf but overriding parent fields
|
||||||
t.Run("parent", func(t *testing.T) {
|
t.Run("parent", func(t *testing.T) {
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{
|
||||||
"webDEP.args.VAR_INHERITED=override",
|
"webDEP.args.VAR_INHERITED=override",
|
||||||
"webDEP.args.VAR_BOTH=override",
|
"webDEP.args.VAR_BOTH=override",
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, m["webapp"].Args["VAR_INHERITED"], "override")
|
require.Equal(t, m["webapp"].Args["VAR_INHERITED"], "override")
|
||||||
require.Equal(t, m["webapp"].Args["VAR_BOTH"], "webapp")
|
require.Equal(t, m["webapp"].Args["VAR_BOTH"], "webapp")
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -99,40 +109,48 @@ target "webapp" {
|
|||||||
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil)
|
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil)
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
|
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context=foo"}, nil)
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context=foo"}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, "foo", *m["webapp"].Context)
|
require.Equal(t, "foo", *m["webapp"].Context)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("NoCacheOverride", func(t *testing.T) {
|
t.Run("NoCacheOverride", func(t *testing.T) {
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.no-cache=false"}, nil)
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.no-cache=false"}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, false, *m["webapp"].NoCache)
|
require.Equal(t, false, *m["webapp"].NoCache)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PullOverride", func(t *testing.T) {
|
t.Run("PullOverride", func(t *testing.T) {
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil)
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, false, *m["webapp"].Pull)
|
require.Equal(t, false, *m["webapp"].Pull)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PatternOverride", func(t *testing.T) {
|
t.Run("PatternOverride", func(t *testing.T) {
|
||||||
// same check for two cases
|
// same check for two cases
|
||||||
multiTargetCheck := func(t *testing.T, m map[string]*Target, err error) {
|
multiTargetCheck := func(t *testing.T, m map[string]*Target, g []*Group, err error) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 2, len(m))
|
require.Equal(t, 2, len(m))
|
||||||
require.Equal(t, "foo", *m["webapp"].Dockerfile)
|
require.Equal(t, "foo", *m["webapp"].Dockerfile)
|
||||||
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"])
|
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"])
|
||||||
require.Equal(t, "foo", *m["webDEP"].Dockerfile)
|
require.Equal(t, "foo", *m["webDEP"].Dockerfile)
|
||||||
require.Equal(t, "webDEP", m["webDEP"].Args["VAR_INHERITED"])
|
require.Equal(t, "webDEP", m["webDEP"].Args["VAR_INHERITED"])
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
sort.Strings(g[0].Targets)
|
||||||
|
require.Equal(t, []string{"webDEP", "webapp"}, g[0].Targets)
|
||||||
}
|
}
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
targets []string
|
targets []string
|
||||||
overrides []string
|
overrides []string
|
||||||
check func(*testing.T, map[string]*Target, error)
|
check func(*testing.T, map[string]*Target, []*Group, error)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "multi target single pattern",
|
name: "multi target single pattern",
|
||||||
@@ -150,18 +168,20 @@ target "webapp" {
|
|||||||
name: "single target",
|
name: "single target",
|
||||||
targets: []string{"webapp"},
|
targets: []string{"webapp"},
|
||||||
overrides: []string{"web*.dockerfile=foo"},
|
overrides: []string{"web*.dockerfile=foo"},
|
||||||
check: func(t *testing.T, m map[string]*Target, err error) {
|
check: func(t *testing.T, m map[string]*Target, g []*Group, err error) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 1, len(m))
|
require.Equal(t, 1, len(m))
|
||||||
require.Equal(t, "foo", *m["webapp"].Dockerfile)
|
require.Equal(t, "foo", *m["webapp"].Dockerfile)
|
||||||
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"])
|
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"])
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"webapp"}, g[0].Targets)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nomatch",
|
name: "nomatch",
|
||||||
targets: []string{"webapp"},
|
targets: []string{"webapp"},
|
||||||
overrides: []string{"nomatch*.dockerfile=foo"},
|
overrides: []string{"nomatch*.dockerfile=foo"},
|
||||||
check: func(t *testing.T, m map[string]*Target, err error) {
|
check: func(t *testing.T, m map[string]*Target, g []*Group, err error) {
|
||||||
// NOTE: I am unsure whether failing to match should always error out
|
// NOTE: I am unsure whether failing to match should always error out
|
||||||
// instead of simply skipping that override.
|
// instead of simply skipping that override.
|
||||||
// Let's enforce the error and we can relax it later if users complain.
|
// Let's enforce the error and we can relax it later if users complain.
|
||||||
@@ -172,8 +192,8 @@ target "webapp" {
|
|||||||
}
|
}
|
||||||
for _, test := range cases {
|
for _, test := range cases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, test.targets, test.overrides, nil)
|
m, g, err := ReadTargets(ctx, []File{fp}, test.targets, test.overrides, nil)
|
||||||
test.check(t, m, err)
|
test.check(t, m, g, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -260,16 +280,21 @@ services:
|
|||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
m, _, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil)
|
m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 3, len(m))
|
require.Equal(t, 3, len(m))
|
||||||
_, ok := m["newservice"]
|
_, ok := m["newservice"]
|
||||||
|
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile)
|
require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile)
|
||||||
require.Equal(t, ".", *m["webapp"].Context)
|
require.Equal(t, ".", *m["webapp"].Context)
|
||||||
require.Equal(t, "1", m["webapp"].Args["buildno"])
|
require.Equal(t, "1", m["webapp"].Args["buildno"])
|
||||||
require.Equal(t, "12", m["webapp"].Args["buildno2"])
|
require.Equal(t, "12", m["webapp"].Args["buildno2"])
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
sort.Strings(g[0].Targets)
|
||||||
|
require.Equal(t, []string{"db", "newservice", "webapp"}, g[0].Targets)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHCLCwdPrefix(t *testing.T) {
|
func TestHCLCwdPrefix(t *testing.T) {
|
||||||
@@ -282,7 +307,7 @@ func TestHCLCwdPrefix(t *testing.T) {
|
|||||||
}`),
|
}`),
|
||||||
}
|
}
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil)
|
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 1, len(m))
|
require.Equal(t, 1, len(m))
|
||||||
@@ -294,6 +319,9 @@ func TestHCLCwdPrefix(t *testing.T) {
|
|||||||
|
|
||||||
require.Equal(t, "test", *m["app"].Dockerfile)
|
require.Equal(t, "test", *m["app"].Dockerfile)
|
||||||
require.Equal(t, "foo", *m["app"].Context)
|
require.Equal(t, "foo", *m["app"].Context)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"app"}, g[0].Targets)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverrideMerge(t *testing.T) {
|
func TestOverrideMerge(t *testing.T) {
|
||||||
@@ -324,3 +352,177 @@ func TestOverrideMerge(t *testing.T) {
|
|||||||
require.Equal(t, 1, len(m["app"].Outputs))
|
require.Equal(t, 1, len(m["app"].Outputs))
|
||||||
require.Equal(t, "type=registry", m["app"].Outputs[0])
|
require.Equal(t, "type=registry", m["app"].Outputs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadTargetsMixed(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
fTargetDefault := File{
|
||||||
|
Name: "docker-bake2.hcl",
|
||||||
|
Data: []byte(`
|
||||||
|
target "default" {
|
||||||
|
dockerfile = "test"
|
||||||
|
}`)}
|
||||||
|
|
||||||
|
fTargetImage := File{
|
||||||
|
Name: "docker-bake3.hcl",
|
||||||
|
Data: []byte(`
|
||||||
|
target "image" {
|
||||||
|
dockerfile = "test"
|
||||||
|
}`)}
|
||||||
|
|
||||||
|
fpHCL := File{
|
||||||
|
Name: "docker-bake.hcl",
|
||||||
|
Data: []byte(`
|
||||||
|
group "default" {
|
||||||
|
targets = ["image"]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "nocache" {
|
||||||
|
no-cache = true
|
||||||
|
}
|
||||||
|
|
||||||
|
group "release" {
|
||||||
|
targets = ["image-release"]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "image" {
|
||||||
|
inherits = ["nocache"]
|
||||||
|
output = ["type=docker"]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "image-release" {
|
||||||
|
inherits = ["image"]
|
||||||
|
output = ["type=image,push=true"]
|
||||||
|
tags = ["user/app:latest"]
|
||||||
|
}`)}
|
||||||
|
|
||||||
|
fpYML := File{
|
||||||
|
Name: "docker-compose.yml",
|
||||||
|
Data: []byte(`
|
||||||
|
services:
|
||||||
|
addon:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
args:
|
||||||
|
CT_ECR: foo
|
||||||
|
CT_TAG: bar
|
||||||
|
image: ct-addon:bar
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=test
|
||||||
|
- AWS_ACCESS_KEY_ID=dummy
|
||||||
|
- AWS_SECRET_ACCESS_KEY=dummy
|
||||||
|
|
||||||
|
aws:
|
||||||
|
build:
|
||||||
|
dockerfile: ./aws.Dockerfile
|
||||||
|
args:
|
||||||
|
CT_ECR: foo
|
||||||
|
CT_TAG: bar
|
||||||
|
image: ct-fake-aws:bar`)}
|
||||||
|
|
||||||
|
fpJSON := File{
|
||||||
|
Name: "docker-bake.json",
|
||||||
|
Data: []byte(`{
|
||||||
|
"group": {
|
||||||
|
"default": {
|
||||||
|
"targets": [
|
||||||
|
"image"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"image": {
|
||||||
|
"context": ".",
|
||||||
|
"dockerfile": "Dockerfile",
|
||||||
|
"output": [
|
||||||
|
"type=docker"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`)}
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
m, g, err := ReadTargets(ctx, []File{fTargetDefault}, []string{"default"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, len(g))
|
||||||
|
require.Equal(t, 1, len(m))
|
||||||
|
require.Equal(t, "test", *m["default"].Dockerfile)
|
||||||
|
|
||||||
|
_, _, err = ReadTargets(ctx, []File{fTargetImage}, []string{"default"}, nil, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fTargetImage}, []string{"image"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"image"}, g[0].Targets)
|
||||||
|
require.Equal(t, 1, len(m))
|
||||||
|
require.Equal(t, "test", *m["image"].Dockerfile)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fTargetImage}, []string{"image"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"image"}, g[0].Targets)
|
||||||
|
require.Equal(t, 1, len(m))
|
||||||
|
require.Equal(t, "test", *m["image"].Dockerfile)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpHCL}, []string{"image-release"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"image-release"}, g[0].Targets)
|
||||||
|
require.Equal(t, 1, len(m))
|
||||||
|
require.Equal(t, 1, len(m["image-release"].Outputs))
|
||||||
|
require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0])
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpHCL}, []string{"image", "image-release"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"image", "image-release"}, g[0].Targets)
|
||||||
|
require.Equal(t, 2, len(m))
|
||||||
|
require.Equal(t, ".", *m["image"].Context)
|
||||||
|
require.Equal(t, 1, len(m["image-release"].Outputs))
|
||||||
|
require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0])
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpYML, fpHCL}, []string{"default"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"image"}, g[0].Targets)
|
||||||
|
require.Equal(t, 1, len(m))
|
||||||
|
require.Equal(t, ".", *m["image"].Context)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpJSON}, []string{"default"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
require.Equal(t, []string{"image"}, g[0].Targets)
|
||||||
|
require.Equal(t, 1, len(m))
|
||||||
|
require.Equal(t, ".", *m["image"].Context)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpYML}, []string{"default"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
sort.Strings(g[0].Targets)
|
||||||
|
require.Equal(t, []string{"addon", "aws"}, g[0].Targets)
|
||||||
|
require.Equal(t, 2, len(m))
|
||||||
|
require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile)
|
||||||
|
require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpYML, fpHCL}, []string{"addon", "aws"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
sort.Strings(g[0].Targets)
|
||||||
|
require.Equal(t, []string{"addon", "aws"}, g[0].Targets)
|
||||||
|
require.Equal(t, 2, len(m))
|
||||||
|
require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile)
|
||||||
|
require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile)
|
||||||
|
|
||||||
|
m, g, err = ReadTargets(ctx, []File{fpYML, fpHCL}, []string{"addon", "aws", "image"}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(g))
|
||||||
|
sort.Strings(g[0].Targets)
|
||||||
|
require.Equal(t, []string{"addon", "aws", "image"}, g[0].Targets)
|
||||||
|
require.Equal(t, 3, len(m))
|
||||||
|
require.Equal(t, ".", *m["image"].Context)
|
||||||
|
require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile)
|
||||||
|
require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile)
|
||||||
|
}
|
||||||
|
@@ -38,7 +38,6 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var url string
|
var url string
|
||||||
var noTarget bool
|
|
||||||
cmdContext := "cwd://"
|
cmdContext := "cwd://"
|
||||||
|
|
||||||
if len(targets) > 0 {
|
if len(targets) > 0 {
|
||||||
@@ -49,7 +48,6 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
|
|||||||
if bake.IsRemoteURL(targets[0]) {
|
if bake.IsRemoteURL(targets[0]) {
|
||||||
cmdContext = targets[0]
|
cmdContext = targets[0]
|
||||||
targets = targets[1:]
|
targets = targets[1:]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +55,6 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
|
|||||||
|
|
||||||
if len(targets) == 0 {
|
if len(targets) == 0 {
|
||||||
targets = []string{"default"}
|
targets = []string{"default"}
|
||||||
noTarget = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
overrides := in.overrides
|
overrides := in.overrides
|
||||||
@@ -107,7 +104,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
t, g, err := bake.ReadTargets(ctx, files, targets, overrides, map[string]string{
|
tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, map[string]string{
|
||||||
// Don't forget to update documentation if you add a new
|
// Don't forget to update documentation if you add a new
|
||||||
// built-in variable: docs/reference/buildx_bake.md#built-in-variables
|
// built-in variable: docs/reference/buildx_bake.md#built-in-variables
|
||||||
"BAKE_CMD_CONTEXT": cmdContext,
|
"BAKE_CMD_CONTEXT": cmdContext,
|
||||||
@@ -118,31 +115,24 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this function can update target context string from the input so call before printOnly check
|
// this function can update target context string from the input so call before printOnly check
|
||||||
bo, err := bake.TargetsToBuildOpt(t, inp)
|
bo, err := bake.TargetsToBuildOpt(tgts, inp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.printOnly {
|
if in.printOnly {
|
||||||
defGroup := map[string][]string{
|
var defg map[string]*bake.Group
|
||||||
"default": targets,
|
if len(grps) == 1 {
|
||||||
}
|
defg = map[string]*bake.Group{
|
||||||
if noTarget {
|
"default": grps[0],
|
||||||
for _, group := range g {
|
|
||||||
if group.Name != "default" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defGroup = map[string][]string{
|
|
||||||
"default": group.Targets,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dt, err := json.MarshalIndent(struct {
|
dt, err := json.MarshalIndent(struct {
|
||||||
Group map[string][]string `json:"group,omitempty"`
|
Group map[string]*bake.Group `json:"group,omitempty"`
|
||||||
Target map[string]*bake.Target `json:"target"`
|
Target map[string]*bake.Target `json:"target"`
|
||||||
}{
|
}{
|
||||||
defGroup,
|
defg,
|
||||||
t,
|
tgts,
|
||||||
}, "", " ")
|
}, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -99,19 +99,23 @@ $ docker buildx bake -f docker-compose.dev.yaml backend database
|
|||||||
You can also use a remote `git` bake definition:
|
You can also use a remote `git` bake definition:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ docker buildx bake "git://github.com/docker/cli#master" --print
|
$ docker buildx bake "git://github.com/docker/cli#v20.10.11" --print
|
||||||
#1 [internal] load git source git://github.com/docker/cli#master
|
#1 [internal] load git source git://github.com/docker/cli#v20.10.11
|
||||||
#1 0.686 2776a6d694f988c0c1df61cad4bfac0f54e481c8 refs/heads/master
|
#1 0.745 e8f1871b077b64bcb4a13334b7146492773769f7 refs/tags/v20.10.11
|
||||||
#1 CACHED
|
#1 2.022 From git://github.com/docker/cli
|
||||||
|
#1 2.022 * [new tag] v20.10.11 -> v20.10.11
|
||||||
|
#1 DONE 2.9s
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"binary"
|
"binary"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"binary": {
|
"binary": {
|
||||||
"context": "git://github.com/docker/cli#master",
|
"context": "git://github.com/docker/cli#v20.10.11",
|
||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
"args": {
|
"args": {
|
||||||
"BASE_VARIANT": "alpine",
|
"BASE_VARIANT": "alpine",
|
||||||
@@ -153,11 +157,6 @@ EOT
|
|||||||
```console
|
```console
|
||||||
$ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" --print
|
$ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" --print
|
||||||
{
|
{
|
||||||
"group": {
|
|
||||||
"default": [
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"target": {
|
"target": {
|
||||||
"default": {
|
"default": {
|
||||||
"context": ".",
|
"context": ".",
|
||||||
@@ -180,19 +179,14 @@ $ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test"
|
|||||||
```
|
```
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" "git://github.com/docker/cli#master" --print
|
$ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" "git://github.com/docker/cli#v20.10.11" --print
|
||||||
#1 [internal] load git source git://github.com/tonistiigi/buildx#remote-test
|
#1 [internal] load git source git://github.com/tonistiigi/buildx#remote-test
|
||||||
#1 0.401 577303add004dd7efeb13434d69ea030d35f7888 refs/heads/remote-test
|
#1 0.429 577303add004dd7efeb13434d69ea030d35f7888 refs/heads/remote-test
|
||||||
#1 CACHED
|
#1 CACHED
|
||||||
{
|
{
|
||||||
"group": {
|
|
||||||
"default": [
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"target": {
|
"target": {
|
||||||
"default": {
|
"default": {
|
||||||
"context": "git://github.com/docker/cli#master",
|
"context": "git://github.com/docker/cli#v20.10.11",
|
||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
"dockerfile-inline": "FROM alpine\nWORKDIR /src\nCOPY . .\nRUN ls -l \u0026\u0026 stop\n"
|
"dockerfile-inline": "FROM alpine\nWORKDIR /src\nCOPY . .\nRUN ls -l \u0026\u0026 stop\n"
|
||||||
}
|
}
|
||||||
@@ -201,7 +195,7 @@ $ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" "git://git
|
|||||||
```
|
```
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" "git://github.com/docker/cli#master"
|
$ docker buildx bake "git://github.com/tonistiigi/buildx#remote-test" "git://github.com/docker/cli#v20.10.11"
|
||||||
...
|
...
|
||||||
> [4/4] RUN ls -l && stop:
|
> [4/4] RUN ls -l && stop:
|
||||||
#8 0.136 drwxrwxrwx 5 root root 4096 Jul 27 18:31 kubernetes
|
#8 0.136 drwxrwxrwx 5 root root 4096 Jul 27 18:31 kubernetes
|
||||||
@@ -229,9 +223,11 @@ format, without starting a build.
|
|||||||
$ docker buildx bake -f docker-bake.hcl --print db
|
$ docker buildx bake -f docker-bake.hcl --print db
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"db"
|
"db"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"db": {
|
"db": {
|
||||||
@@ -372,9 +368,11 @@ You can use this file directly:
|
|||||||
$ docker buildx bake --print app
|
$ docker buildx bake --print app
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"app"
|
"app"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"app": {
|
"app": {
|
||||||
@@ -402,9 +400,11 @@ And invoke bake together with both of the files:
|
|||||||
$ docker buildx bake -f docker-bake.hcl -f env.hcl --print app
|
$ docker buildx bake -f docker-bake.hcl -f env.hcl --print app
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"app"
|
"app"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"app": {
|
"app": {
|
||||||
@@ -454,9 +454,11 @@ target "webapp" {
|
|||||||
$ docker buildx bake --print webapp
|
$ docker buildx bake --print webapp
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"webapp"
|
"webapp"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"webapp": {
|
"webapp": {
|
||||||
@@ -474,9 +476,11 @@ $ docker buildx bake --print webapp
|
|||||||
$ TAG=$(git rev-parse --short HEAD) docker buildx bake --print webapp
|
$ TAG=$(git rev-parse --short HEAD) docker buildx bake --print webapp
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"webapp"
|
"webapp"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"webapp": {
|
"webapp": {
|
||||||
@@ -492,7 +496,7 @@ $ TAG=$(git rev-parse --short HEAD) docker buildx bake --print webapp
|
|||||||
|
|
||||||
#### Using the `add` function
|
#### Using the `add` function
|
||||||
|
|
||||||
You can use [`go-cty` stdlib functions]([go-cty](https://github.com/zclconf/go-cty/tree/main/cty/function/stdlib)).
|
You can use [`go-cty` stdlib functions](https://github.com/zclconf/go-cty/tree/main/cty/function/stdlib).
|
||||||
Here we are using the `add` function.
|
Here we are using the `add` function.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
@@ -516,9 +520,11 @@ target "webapp" {
|
|||||||
$ docker buildx bake --print webapp
|
$ docker buildx bake --print webapp
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"webapp"
|
"webapp"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"webapp": {
|
"webapp": {
|
||||||
@@ -559,9 +565,11 @@ target "webapp" {
|
|||||||
$ docker buildx bake --print webapp
|
$ docker buildx bake --print webapp
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"webapp"
|
"webapp"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"webapp": {
|
"webapp": {
|
||||||
@@ -604,9 +612,11 @@ target "webapp" {
|
|||||||
$ docker buildx bake --print webapp
|
$ docker buildx bake --print webapp
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"webapp"
|
"webapp"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"webapp": {
|
"webapp": {
|
||||||
@@ -645,9 +655,11 @@ target "webapp" {
|
|||||||
$ docker buildx bake --print webapp
|
$ docker buildx bake --print webapp
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"webapp"
|
"webapp"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"webapp": {
|
"webapp": {
|
||||||
@@ -700,9 +712,11 @@ target "app" {
|
|||||||
$ docker buildx bake -f docker-bake1.hcl -f docker-bake2.hcl --print app
|
$ docker buildx bake -f docker-bake1.hcl -f docker-bake2.hcl --print app
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"app"
|
"app"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"app": {
|
"app": {
|
||||||
@@ -744,9 +758,11 @@ target "app" {
|
|||||||
$ docker buildx bake --print app
|
$ docker buildx bake --print app
|
||||||
{
|
{
|
||||||
"group": {
|
"group": {
|
||||||
"default": [
|
"default": {
|
||||||
|
"targets": [
|
||||||
"app"
|
"app"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"app": {
|
"app": {
|
||||||
@@ -810,6 +826,14 @@ services:
|
|||||||
```console
|
```console
|
||||||
$ docker buildx bake --print
|
$ docker buildx bake --print
|
||||||
{
|
{
|
||||||
|
"group": {
|
||||||
|
"default": {
|
||||||
|
"targets": [
|
||||||
|
"aws",
|
||||||
|
"addon"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"addon": {
|
"addon": {
|
||||||
"context": ".",
|
"context": ".",
|
||||||
|
5
go.mod
5
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/bugsnag/panicwrap v1.2.0 // indirect
|
github.com/bugsnag/panicwrap v1.2.0 // indirect
|
||||||
github.com/cenkalti/backoff v2.1.1+incompatible // indirect
|
github.com/cenkalti/backoff v2.1.1+incompatible // indirect
|
||||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect
|
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect
|
||||||
github.com/compose-spec/compose-go v0.0.0-20210729195839-de56f4f0cb3c
|
github.com/compose-spec/compose-go v1.0.5
|
||||||
github.com/containerd/console v1.0.3
|
github.com/containerd/console v1.0.3
|
||||||
github.com/containerd/containerd v1.5.5
|
github.com/containerd/containerd v1.5.5
|
||||||
github.com/docker/cli v20.10.8+incompatible
|
github.com/docker/cli v20.10.8+incompatible
|
||||||
@@ -57,7 +57,8 @@ require (
|
|||||||
|
|
||||||
replace (
|
replace (
|
||||||
github.com/docker/cli => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
|
github.com/docker/cli => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
|
||||||
github.com/docker/docker => github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible
|
github.com/docker/docker => github.com/tonistiigi/docker v0.10.1-0.20211122204227-65a6f25dbca2
|
||||||
|
github.com/tonistiigi/fsutil => github.com/tonistiigi/fsutil v0.0.0-20211122210416-da5201e0b3af
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939
|
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939
|
||||||
|
22
go.sum
22
go.sum
@@ -262,8 +262,10 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
|
|||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||||
github.com/compose-spec/compose-go v0.0.0-20210729195839-de56f4f0cb3c h1:lSR4wokZlq+Q8uJpgZuFMs3VoLaYVV07cJOZHa1zRBg=
|
github.com/compose-spec/compose-go v1.0.5 h1:WtfK7tJsk5C8h12iggum7p28kTxeXH7Xi5c/pLfnBwk=
|
||||||
github.com/compose-spec/compose-go v0.0.0-20210729195839-de56f4f0cb3c/go.mod h1:5V65rPnTvvQagtoMxTneJ2QicLq6ZRQQ7fOgPN226fo=
|
github.com/compose-spec/compose-go v1.0.5/go.mod h1:LQ/JAjSIyh8bTu4RV6nkyf0Ow/Yf3qpvzrdEigxduiw=
|
||||||
|
github.com/compose-spec/godotenv v1.1.0 h1:wzShe5P6L/Aw3wsV357eWlZdMcPaOe2V2+3+qGwMEL4=
|
||||||
|
github.com/compose-spec/godotenv v1.1.0/go.mod h1:zF/3BOa18Z24tts5qnO/E9YURQanJTBUf7nlcCTNsyc=
|
||||||
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
||||||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||||
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
|
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
|
||||||
@@ -419,8 +421,6 @@ github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompa
|
|||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible h1:tSd7TeZCH0j9m4P14bfe/eO1KYawrt3DztHI8gZAmLM=
|
|
||||||
github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
|
||||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||||
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
|
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
|
||||||
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
|
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
|
||||||
@@ -794,7 +794,6 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
|||||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||||
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||||
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
|
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
|
||||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||||
@@ -903,8 +902,9 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
|||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
|
github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
|
||||||
github.com/moby/buildkit v0.9.1-0.20211019185819-8778943ac3da h1:DJ6zT0cdxXgUf17GmYAWqCGv47cJXx7nZ1CTHojZ3A4=
|
github.com/moby/buildkit v0.9.1-0.20211019185819-8778943ac3da h1:DJ6zT0cdxXgUf17GmYAWqCGv47cJXx7nZ1CTHojZ3A4=
|
||||||
@@ -913,7 +913,6 @@ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
|||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
|
||||||
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
||||||
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
||||||
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
|
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
|
||||||
@@ -988,7 +987,6 @@ github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 h1:TVz
|
|||||||
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE=
|
github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE=
|
||||||
@@ -1201,9 +1199,10 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
|
github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
|
||||||
github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
|
github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
|
||||||
github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN64dG941IOXfhJhlH0qB92hxJ9A1ewrdUmJ6xo=
|
github.com/tonistiigi/docker v0.10.1-0.20211122204227-65a6f25dbca2 h1:e6PyP4Gi3HZ9hSH9gGGGSaBh3EI+HZj5E4fgEV43ZCI=
|
||||||
github.com/tonistiigi/fsutil v0.0.0-20210818161904-4442383b5028 h1:uEkkUFMCPtzz1HVOa42u15OHems1ugiRt172tSRTWSk=
|
github.com/tonistiigi/docker v0.10.1-0.20211122204227-65a6f25dbca2/go.mod h1:v9W/4hjeg+54O4ffkt1Dnh7nOIE9uHi9F0W9clN3nTQ=
|
||||||
github.com/tonistiigi/fsutil v0.0.0-20210818161904-4442383b5028/go.mod h1:E6osHKls9ix67jofYQ61RQKwlJhqJOZM2hintp+49iI=
|
github.com/tonistiigi/fsutil v0.0.0-20211122210416-da5201e0b3af h1:G5OoRy5gm3D9uLT0JIlgjB0aJPyTM48GFDqS9ESQPW4=
|
||||||
|
github.com/tonistiigi/fsutil v0.0.0-20211122210416-da5201e0b3af/go.mod h1:WnebnONB1EcTV5BdGlPLPlCX+FVMKhTnGZP2BvmyhgE=
|
||||||
github.com/tonistiigi/go-actions-cache v0.0.0-20211002214948-4d48f2ff622a/go.mod h1:YiIBjH5gP7mao3t0dBrNNBGuKYdeJmcAJjYLXr43k6A=
|
github.com/tonistiigi/go-actions-cache v0.0.0-20211002214948-4d48f2ff622a/go.mod h1:YiIBjH5gP7mao3t0dBrNNBGuKYdeJmcAJjYLXr43k6A=
|
||||||
github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939 h1:s6wDMZYNyWt8KvkjhrMpOthFPgI3JB8ipJS+eCV/psg=
|
github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939 h1:s6wDMZYNyWt8KvkjhrMpOthFPgI3JB8ipJS+eCV/psg=
|
||||||
github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939/go.mod h1:Vm5u/mtkj1OMhtao0v+BGo2LUoLCgHYXvRmj0jWITlE=
|
github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939/go.mod h1:Vm5u/mtkj1OMhtao0v+BGo2LUoLCgHYXvRmj0jWITlE=
|
||||||
@@ -1561,7 +1560,6 @@ golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201013081832-0aaa2718063a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201013081832-0aaa2718063a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
64
vendor/github.com/compose-spec/compose-go/loader/interpolate.go
generated
vendored
64
vendor/github.com/compose-spec/compose-go/loader/interpolate.go
generated
vendored
@@ -21,14 +21,21 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
interp "github.com/compose-spec/compose-go/interpolation"
|
interp "github.com/compose-spec/compose-go/interpolation"
|
||||||
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var interpolateTypeCastMapping = map[interp.Path]interp.Cast{
|
var interpolateTypeCastMapping = map[interp.Path]interp.Cast{
|
||||||
servicePath("configs", interp.PathMatchList, "mode"): toInt,
|
servicePath("configs", interp.PathMatchList, "mode"): toInt,
|
||||||
servicePath("secrets", interp.PathMatchList, "mode"): toInt,
|
servicePath("cpu_count"): toInt64,
|
||||||
servicePath("healthcheck", "retries"): toInt,
|
servicePath("cpu_percent"): toFloat,
|
||||||
servicePath("healthcheck", "disable"): toBoolean,
|
servicePath("cpu_period"): toInt64,
|
||||||
|
servicePath("cpu_quota"): toInt64,
|
||||||
|
servicePath("cpu_rt_period"): toInt64,
|
||||||
|
servicePath("cpu_rt_runtime"): toInt64,
|
||||||
|
servicePath("cpus"): toFloat32,
|
||||||
|
servicePath("cpu_shares"): toInt64,
|
||||||
|
servicePath("init"): toBoolean,
|
||||||
servicePath("deploy", "replicas"): toInt,
|
servicePath("deploy", "replicas"): toInt,
|
||||||
servicePath("deploy", "update_config", "parallelism"): toInt,
|
servicePath("deploy", "update_config", "parallelism"): toInt,
|
||||||
servicePath("deploy", "update_config", "max_failure_ratio"): toFloat,
|
servicePath("deploy", "update_config", "max_failure_ratio"): toFloat,
|
||||||
@@ -36,20 +43,35 @@ var interpolateTypeCastMapping = map[interp.Path]interp.Cast{
|
|||||||
servicePath("deploy", "rollback_config", "max_failure_ratio"): toFloat,
|
servicePath("deploy", "rollback_config", "max_failure_ratio"): toFloat,
|
||||||
servicePath("deploy", "restart_policy", "max_attempts"): toInt,
|
servicePath("deploy", "restart_policy", "max_attempts"): toInt,
|
||||||
servicePath("deploy", "placement", "max_replicas_per_node"): toInt,
|
servicePath("deploy", "placement", "max_replicas_per_node"): toInt,
|
||||||
|
servicePath("healthcheck", "retries"): toInt,
|
||||||
|
servicePath("healthcheck", "disable"): toBoolean,
|
||||||
|
servicePath("mem_limit"): toUnitBytes,
|
||||||
|
servicePath("mem_reservation"): toUnitBytes,
|
||||||
|
servicePath("memswap_limit"): toUnitBytes,
|
||||||
|
servicePath("mem_swappiness"): toUnitBytes,
|
||||||
|
servicePath("oom_kill_disable"): toBoolean,
|
||||||
|
servicePath("oom_score_adj"): toInt64,
|
||||||
|
servicePath("pids_limit"): toInt64,
|
||||||
servicePath("ports", interp.PathMatchList, "target"): toInt,
|
servicePath("ports", interp.PathMatchList, "target"): toInt,
|
||||||
servicePath("ports", interp.PathMatchList, "published"): toInt,
|
servicePath("ports", interp.PathMatchList, "published"): toInt,
|
||||||
|
servicePath("privileged"): toBoolean,
|
||||||
|
servicePath("read_only"): toBoolean,
|
||||||
|
servicePath("scale"): toInt,
|
||||||
|
servicePath("secrets", interp.PathMatchList, "mode"): toInt,
|
||||||
|
servicePath("shm_size"): toUnitBytes,
|
||||||
|
servicePath("stdin_open"): toBoolean,
|
||||||
|
servicePath("stop_grace_period"): toDuration,
|
||||||
|
servicePath("tty"): toBoolean,
|
||||||
servicePath("ulimits", interp.PathMatchAll): toInt,
|
servicePath("ulimits", interp.PathMatchAll): toInt,
|
||||||
servicePath("ulimits", interp.PathMatchAll, "hard"): toInt,
|
servicePath("ulimits", interp.PathMatchAll, "hard"): toInt,
|
||||||
servicePath("ulimits", interp.PathMatchAll, "soft"): toInt,
|
servicePath("ulimits", interp.PathMatchAll, "soft"): toInt,
|
||||||
servicePath("privileged"): toBoolean,
|
|
||||||
servicePath("read_only"): toBoolean,
|
|
||||||
servicePath("stdin_open"): toBoolean,
|
|
||||||
servicePath("tty"): toBoolean,
|
|
||||||
servicePath("volumes", interp.PathMatchList, "read_only"): toBoolean,
|
servicePath("volumes", interp.PathMatchList, "read_only"): toBoolean,
|
||||||
servicePath("volumes", interp.PathMatchList, "volume", "nocopy"): toBoolean,
|
servicePath("volumes", interp.PathMatchList, "volume", "nocopy"): toBoolean,
|
||||||
|
servicePath("volumes", interp.PathMatchList, "tmpfs", "size"): toUnitBytes,
|
||||||
iPath("networks", interp.PathMatchAll, "external"): toBoolean,
|
iPath("networks", interp.PathMatchAll, "external"): toBoolean,
|
||||||
iPath("networks", interp.PathMatchAll, "internal"): toBoolean,
|
iPath("networks", interp.PathMatchAll, "internal"): toBoolean,
|
||||||
iPath("networks", interp.PathMatchAll, "attachable"): toBoolean,
|
iPath("networks", interp.PathMatchAll, "attachable"): toBoolean,
|
||||||
|
iPath("networks", interp.PathMatchAll, "enable_ipv6"): toBoolean,
|
||||||
iPath("volumes", interp.PathMatchAll, "external"): toBoolean,
|
iPath("volumes", interp.PathMatchAll, "external"): toBoolean,
|
||||||
iPath("secrets", interp.PathMatchAll, "external"): toBoolean,
|
iPath("secrets", interp.PathMatchAll, "external"): toBoolean,
|
||||||
iPath("configs", interp.PathMatchAll, "external"): toBoolean,
|
iPath("configs", interp.PathMatchAll, "external"): toBoolean,
|
||||||
@@ -67,10 +89,38 @@ func toInt(value string) (interface{}, error) {
|
|||||||
return strconv.Atoi(value)
|
return strconv.Atoi(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toInt64(value string) (interface{}, error) {
|
||||||
|
return strconv.ParseInt(value, 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toUnitBytes(value string) (interface{}, error) {
|
||||||
|
i, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return types.UnitBytes(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toDuration(value string) (interface{}, error) {
|
||||||
|
i, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return types.Duration(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
func toFloat(value string) (interface{}, error) {
|
func toFloat(value string) (interface{}, error) {
|
||||||
return strconv.ParseFloat(value, 64)
|
return strconv.ParseFloat(value, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toFloat32(value string) (interface{}, error) {
|
||||||
|
f, err := strconv.ParseFloat(value, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return float32(f), nil
|
||||||
|
}
|
||||||
|
|
||||||
// should match http://yaml.org/type/bool.html
|
// should match http://yaml.org/type/bool.html
|
||||||
func toBoolean(value string) (interface{}, error) {
|
func toBoolean(value string) (interface{}, error) {
|
||||||
switch strings.ToLower(value) {
|
switch strings.ToLower(value) {
|
||||||
|
141
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
141
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
@@ -31,14 +31,13 @@ import (
|
|||||||
"github.com/compose-spec/compose-go/schema"
|
"github.com/compose-spec/compose-go/schema"
|
||||||
"github.com/compose-spec/compose-go/template"
|
"github.com/compose-spec/compose-go/template"
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
units "github.com/docker/go-units"
|
"github.com/compose-spec/godotenv"
|
||||||
"github.com/imdario/mergo"
|
"github.com/docker/go-units"
|
||||||
"github.com/joho/godotenv"
|
"github.com/mattn/go-shellwords"
|
||||||
shellwords "github.com/mattn/go-shellwords"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
yaml "gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options supported by Load
|
// Options supported by Load
|
||||||
@@ -49,6 +48,8 @@ type Options struct {
|
|||||||
SkipInterpolation bool
|
SkipInterpolation bool
|
||||||
// Skip normalization
|
// Skip normalization
|
||||||
SkipNormalization bool
|
SkipNormalization bool
|
||||||
|
// Resolve paths
|
||||||
|
ResolvePaths bool
|
||||||
// Skip consistency check
|
// Skip consistency check
|
||||||
SkipConsistencyCheck bool
|
SkipConsistencyCheck bool
|
||||||
// Skip extends
|
// Skip extends
|
||||||
@@ -103,6 +104,11 @@ func WithDiscardEnvFiles(opts *Options) {
|
|||||||
opts.discardEnvFiles = true
|
opts.discardEnvFiles = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSkipValidation sets the Options to skip validation when loading sections
|
||||||
|
func WithSkipValidation(opts *Options) {
|
||||||
|
opts.SkipValidation = true
|
||||||
|
}
|
||||||
|
|
||||||
// ParseYAML reads the bytes from a file, parses the bytes into a mapping
|
// ParseYAML reads the bytes from a file, parses the bytes into a mapping
|
||||||
// structure, and returns it.
|
// structure, and returns it.
|
||||||
func ParseYAML(source []byte) (map[string]interface{}, error) {
|
func ParseYAML(source []byte) (map[string]interface{}, error) {
|
||||||
@@ -199,7 +205,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !opts.SkipNormalization {
|
if !opts.SkipNormalization {
|
||||||
err = normalize(project)
|
err = normalize(project, opts.ResolvePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -216,34 +222,14 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseConfig(b []byte, opts *Options) (map[string]interface{}, error) {
|
func parseConfig(b []byte, opts *Options) (map[string]interface{}, error) {
|
||||||
|
yaml, err := ParseYAML(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if !opts.SkipInterpolation {
|
if !opts.SkipInterpolation {
|
||||||
withoutComments, err := removeYamlComments(b)
|
return interp.Interpolate(yaml, *opts.Interpolate)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
return yaml, err
|
||||||
substituted, err := opts.Interpolate.Substitute(string(withoutComments), template.Mapping(opts.Interpolate.LookupValue))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
b = []byte(substituted)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ParseYAML(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeYamlComments drop all comments from the yaml file, so we don't try to apply string substitutions on irrelevant places
|
|
||||||
func removeYamlComments(b []byte) ([]byte, error) {
|
|
||||||
var cfg interface{}
|
|
||||||
err := yaml.Unmarshal(b, &cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
b, err = yaml.Marshal(cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func groupXFieldsIntoExtensions(dict map[string]interface{}) map[string]interface{} {
|
func groupXFieldsIntoExtensions(dict map[string]interface{}) map[string]interface{} {
|
||||||
@@ -274,7 +260,7 @@ func loadSections(filename string, config map[string]interface{}, configDetails
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Networks, err = LoadNetworks(getSection(config, "networks"), configDetails.Version)
|
cfg.Networks, err = LoadNetworks(getSection(config, "networks"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -282,11 +268,11 @@ func loadSections(filename string, config map[string]interface{}, configDetails
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cfg.Secrets, err = LoadSecrets(getSection(config, "secrets"), configDetails)
|
cfg.Secrets, err = LoadSecrets(getSection(config, "secrets"), configDetails, opts.ResolvePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cfg.Configs, err = LoadConfigObjs(getSection(config, "configs"), configDetails)
|
cfg.Configs, err = LoadConfigObjs(getSection(config, "configs"), configDetails, opts.ResolvePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -439,6 +425,14 @@ func formatInvalidKeyError(keyPrefix string, key interface{}) error {
|
|||||||
func LoadServices(filename string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options) ([]types.ServiceConfig, error) {
|
func LoadServices(filename string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options) ([]types.ServiceConfig, error) {
|
||||||
var services []types.ServiceConfig
|
var services []types.ServiceConfig
|
||||||
|
|
||||||
|
x, ok := servicesDict["extensions"]
|
||||||
|
if ok {
|
||||||
|
// as a top-level attribute, "services" doesn't support extensions, and a service can be named `x-foo`
|
||||||
|
for k, v := range x.(map[string]interface{}) {
|
||||||
|
servicesDict[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for name := range servicesDict {
|
for name := range servicesDict {
|
||||||
serviceConfig, err := loadServiceWithExtends(filename, name, servicesDict, workingDir, lookupEnv, opts, &cycleTracker{})
|
serviceConfig, err := loadServiceWithExtends(filename, name, servicesDict, workingDir, lookupEnv, opts, &cycleTracker{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -456,7 +450,12 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceConfig, err := LoadService(name, servicesDict[name].(map[string]interface{}), workingDir, lookupEnv)
|
target, ok := servicesDict[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("cannot extend service %q in %s: service not found", name, filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceConfig, err := LoadService(name, target.(map[string]interface{}), workingDir, lookupEnv, opts.ResolvePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -478,15 +477,7 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !opts.SkipInterpolation {
|
baseFile, err := parseConfig(bytes, opts)
|
||||||
substitute, err := opts.Interpolate.Substitute(string(bytes), template.Mapping(opts.Interpolate.LookupValue))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bytes = []byte(substitute)
|
|
||||||
}
|
|
||||||
|
|
||||||
baseFile, err := ParseYAML(bytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -516,10 +507,10 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mergo.Merge(baseService, serviceConfig, mergo.WithAppendSlice, mergo.WithOverride, mergo.WithTransformers(serviceSpecials)); err != nil {
|
serviceConfig, err = _merge(baseService, serviceConfig)
|
||||||
return nil, errors.Wrapf(err, "cannot merge service %s", name)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
serviceConfig = baseService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceConfig, nil
|
return serviceConfig, nil
|
||||||
@@ -527,8 +518,10 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
|||||||
|
|
||||||
// LoadService produces a single ServiceConfig from a compose file Dict
|
// LoadService produces a single ServiceConfig from a compose file Dict
|
||||||
// the serviceDict is not validated if directly used. Use Load() to enable validation
|
// the serviceDict is not validated if directly used. Use Load() to enable validation
|
||||||
func LoadService(name string, serviceDict map[string]interface{}, workingDir string, lookupEnv template.Mapping) (*types.ServiceConfig, error) {
|
func LoadService(name string, serviceDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, resolvePaths bool) (*types.ServiceConfig, error) {
|
||||||
serviceConfig := &types.ServiceConfig{}
|
serviceConfig := &types.ServiceConfig{
|
||||||
|
Scale: 1,
|
||||||
|
}
|
||||||
if err := Transform(serviceDict, serviceConfig); err != nil {
|
if err := Transform(serviceDict, serviceConfig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -538,8 +531,18 @@ func LoadService(name string, serviceDict map[string]interface{}, workingDir str
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := resolveVolumePaths(serviceConfig.Volumes, workingDir, lookupEnv); err != nil {
|
for i, volume := range serviceConfig.Volumes {
|
||||||
return nil, err
|
if volume.Type != "bind" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if volume.Source == "" {
|
||||||
|
return nil, errors.New(`invalid mount config for type "bind": field Source must not be empty`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolvePaths {
|
||||||
|
serviceConfig.Volumes[i] = resolveVolumePath(volume, workingDir, lookupEnv)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceConfig, nil
|
return serviceConfig, nil
|
||||||
@@ -574,16 +577,7 @@ func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string, l
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) error {
|
func resolveVolumePath(volume types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) types.ServiceVolumeConfig {
|
||||||
for i, volume := range volumes {
|
|
||||||
if volume.Type != "bind" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if volume.Source == "" {
|
|
||||||
return errors.New(`invalid mount config for type "bind": field Source must not be empty`)
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath := expandUser(volume.Source, lookupEnv)
|
filePath := expandUser(volume.Source, lookupEnv)
|
||||||
// Check if source is an absolute path (either Unix or Windows), to
|
// Check if source is an absolute path (either Unix or Windows), to
|
||||||
// handle a Windows client with a Unix daemon or vice-versa.
|
// handle a Windows client with a Unix daemon or vice-versa.
|
||||||
@@ -595,9 +589,7 @@ func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string,
|
|||||||
filePath = absPath(workingDir, filePath)
|
filePath = absPath(workingDir, filePath)
|
||||||
}
|
}
|
||||||
volume.Source = filePath
|
volume.Source = filePath
|
||||||
volumes[i] = volume
|
return volume
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this more robust
|
// TODO: make this more robust
|
||||||
@@ -633,7 +625,7 @@ func transformUlimits(data interface{}) (interface{}, error) {
|
|||||||
|
|
||||||
// LoadNetworks produces a NetworkConfig map from a compose file Dict
|
// LoadNetworks produces a NetworkConfig map from a compose file Dict
|
||||||
// the source Dict is not validated if directly used. Use Load() to enable validation
|
// the source Dict is not validated if directly used. Use Load() to enable validation
|
||||||
func LoadNetworks(source map[string]interface{}, version string) (map[string]types.NetworkConfig, error) {
|
func LoadNetworks(source map[string]interface{}) (map[string]types.NetworkConfig, error) {
|
||||||
networks := make(map[string]types.NetworkConfig)
|
networks := make(map[string]types.NetworkConfig)
|
||||||
err := Transform(source, &networks)
|
err := Transform(source, &networks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -701,13 +693,13 @@ func LoadVolumes(source map[string]interface{}) (map[string]types.VolumeConfig,
|
|||||||
|
|
||||||
// LoadSecrets produces a SecretConfig map from a compose file Dict
|
// LoadSecrets produces a SecretConfig map from a compose file Dict
|
||||||
// the source Dict is not validated if directly used. Use Load() to enable validation
|
// the source Dict is not validated if directly used. Use Load() to enable validation
|
||||||
func LoadSecrets(source map[string]interface{}, details types.ConfigDetails) (map[string]types.SecretConfig, error) {
|
func LoadSecrets(source map[string]interface{}, details types.ConfigDetails, resolvePaths bool) (map[string]types.SecretConfig, error) {
|
||||||
secrets := make(map[string]types.SecretConfig)
|
secrets := make(map[string]types.SecretConfig)
|
||||||
if err := Transform(source, &secrets); err != nil {
|
if err := Transform(source, &secrets); err != nil {
|
||||||
return secrets, err
|
return secrets, err
|
||||||
}
|
}
|
||||||
for name, secret := range secrets {
|
for name, secret := range secrets {
|
||||||
obj, err := loadFileObjectConfig(name, "secret", types.FileObjectConfig(secret), details)
|
obj, err := loadFileObjectConfig(name, "secret", types.FileObjectConfig(secret), details, resolvePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -719,13 +711,13 @@ func LoadSecrets(source map[string]interface{}, details types.ConfigDetails) (ma
|
|||||||
|
|
||||||
// LoadConfigObjs produces a ConfigObjConfig map from a compose file Dict
|
// LoadConfigObjs produces a ConfigObjConfig map from a compose file Dict
|
||||||
// the source Dict is not validated if directly used. Use Load() to enable validation
|
// the source Dict is not validated if directly used. Use Load() to enable validation
|
||||||
func LoadConfigObjs(source map[string]interface{}, details types.ConfigDetails) (map[string]types.ConfigObjConfig, error) {
|
func LoadConfigObjs(source map[string]interface{}, details types.ConfigDetails, resolvePaths bool) (map[string]types.ConfigObjConfig, error) {
|
||||||
configs := make(map[string]types.ConfigObjConfig)
|
configs := make(map[string]types.ConfigObjConfig)
|
||||||
if err := Transform(source, &configs); err != nil {
|
if err := Transform(source, &configs); err != nil {
|
||||||
return configs, err
|
return configs, err
|
||||||
}
|
}
|
||||||
for name, config := range configs {
|
for name, config := range configs {
|
||||||
obj, err := loadFileObjectConfig(name, "config", types.FileObjectConfig(config), details)
|
obj, err := loadFileObjectConfig(name, "config", types.FileObjectConfig(config), details, resolvePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -735,7 +727,7 @@ func LoadConfigObjs(source map[string]interface{}, details types.ConfigDetails)
|
|||||||
return configs, nil
|
return configs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfig, details types.ConfigDetails) (types.FileObjectConfig, error) {
|
func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfig, details types.ConfigDetails, resolvePaths bool) (types.FileObjectConfig, error) {
|
||||||
// if "external: true"
|
// if "external: true"
|
||||||
switch {
|
switch {
|
||||||
case obj.External.External:
|
case obj.External.External:
|
||||||
@@ -758,8 +750,10 @@ func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfi
|
|||||||
return obj, errors.Errorf("%[1]s %[2]s: %[1]s.driver and %[1]s.file conflict; only use %[1]s.driver", objType, name)
|
return obj, errors.Errorf("%[1]s %[2]s: %[1]s.driver and %[1]s.file conflict; only use %[1]s.driver", objType, name)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
if resolvePaths {
|
||||||
obj.File = absPath(details.WorkingDir, obj.File)
|
obj.File = absPath(details.WorkingDir, obj.File)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
@@ -1018,10 +1012,13 @@ var transformSize TransformerFunc = func(value interface{}) (interface{}, error)
|
|||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case int:
|
case int:
|
||||||
return int64(value), nil
|
return int64(value), nil
|
||||||
|
case int64, types.UnitBytes:
|
||||||
|
return value, nil
|
||||||
case string:
|
case string:
|
||||||
return units.RAMInBytes(value)
|
return units.RAMInBytes(value)
|
||||||
|
default:
|
||||||
|
return value, errors.Errorf("invalid type for size %T", value)
|
||||||
}
|
}
|
||||||
panic(errors.Errorf("invalid type for size %T", value))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var transformStringToDuration TransformerFunc = func(value interface{}) (interface{}, error) {
|
var transformStringToDuration TransformerFunc = func(value interface{}) (interface{}, error) {
|
||||||
|
74
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
74
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
@@ -33,6 +33,7 @@ var serviceSpecials = &specials{
|
|||||||
m: map[reflect.Type]func(dst, src reflect.Value) error{
|
m: map[reflect.Type]func(dst, src reflect.Value) error{
|
||||||
reflect.TypeOf(&types.LoggingConfig{}): safelyMerge(mergeLoggingConfig),
|
reflect.TypeOf(&types.LoggingConfig{}): safelyMerge(mergeLoggingConfig),
|
||||||
reflect.TypeOf(&types.UlimitsConfig{}): safelyMerge(mergeUlimitsConfig),
|
reflect.TypeOf(&types.UlimitsConfig{}): safelyMerge(mergeUlimitsConfig),
|
||||||
|
reflect.TypeOf([]types.ServiceVolumeConfig{}): mergeSlice(toServiceVolumeConfigsMap, toServiceVolumeConfigsSlice),
|
||||||
reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice),
|
reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice),
|
||||||
reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice),
|
reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice),
|
||||||
reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice),
|
reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice),
|
||||||
@@ -86,13 +87,11 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig,
|
|||||||
for name, overrideService := range overrideServices {
|
for name, overrideService := range overrideServices {
|
||||||
overrideService := overrideService
|
overrideService := overrideService
|
||||||
if baseService, ok := baseServices[name]; ok {
|
if baseService, ok := baseServices[name]; ok {
|
||||||
if err := mergo.Merge(&baseService, &overrideService, mergo.WithAppendSlice, mergo.WithOverride, mergo.WithTransformers(serviceSpecials)); err != nil {
|
merged, err := _merge(&baseService, &overrideService)
|
||||||
return base, errors.Wrapf(err, "cannot merge service %s", name)
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "cannot merge service %s", name)
|
||||||
}
|
}
|
||||||
if len(overrideService.Command) > 0 {
|
baseServices[name] = *merged
|
||||||
baseService.Command = overrideService.Command
|
|
||||||
}
|
|
||||||
baseServices[name] = baseService
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
baseServices[name] = overrideService
|
baseServices[name] = overrideService
|
||||||
@@ -105,6 +104,19 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig,
|
|||||||
return services, nil
|
return services, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _merge(baseService *types.ServiceConfig, overrideService *types.ServiceConfig) (*types.ServiceConfig, error) {
|
||||||
|
if err := mergo.Merge(baseService, overrideService, mergo.WithAppendSlice, mergo.WithOverride, mergo.WithTransformers(serviceSpecials)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if overrideService.Command != nil {
|
||||||
|
baseService.Command = overrideService.Command
|
||||||
|
}
|
||||||
|
if overrideService.Entrypoint != nil {
|
||||||
|
baseService.Entrypoint = overrideService.Entrypoint
|
||||||
|
}
|
||||||
|
return baseService, nil
|
||||||
|
}
|
||||||
|
|
||||||
func toServiceSecretConfigsMap(s interface{}) (map[interface{}]interface{}, error) {
|
func toServiceSecretConfigsMap(s interface{}) (map[interface{}]interface{}, error) {
|
||||||
secrets, ok := s.([]types.ServiceSecretConfig)
|
secrets, ok := s.([]types.ServiceSecretConfig)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -135,8 +147,33 @@ func toServicePortConfigsMap(s interface{}) (map[interface{}]interface{}, error)
|
|||||||
return nil, errors.Errorf("not a servicePortConfig slice: %v", s)
|
return nil, errors.Errorf("not a servicePortConfig slice: %v", s)
|
||||||
}
|
}
|
||||||
m := map[interface{}]interface{}{}
|
m := map[interface{}]interface{}{}
|
||||||
|
type port struct {
|
||||||
|
target uint32
|
||||||
|
published uint32
|
||||||
|
ip string
|
||||||
|
protocol string
|
||||||
|
}
|
||||||
|
|
||||||
for _, p := range ports {
|
for _, p := range ports {
|
||||||
m[p.Published] = p
|
mergeKey := port{
|
||||||
|
target: p.Target,
|
||||||
|
published: p.Published,
|
||||||
|
ip: p.HostIP,
|
||||||
|
protocol: p.Protocol,
|
||||||
|
}
|
||||||
|
m[mergeKey] = p
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toServiceVolumeConfigsMap(s interface{}) (map[interface{}]interface{}, error) {
|
||||||
|
volumes, ok := s.([]types.ServiceVolumeConfig)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("not a ServiceVolumeConfig slice: %v", s)
|
||||||
|
}
|
||||||
|
m := map[interface{}]interface{}{}
|
||||||
|
for _, v := range volumes {
|
||||||
|
m[v.Target] = v
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@@ -166,7 +203,28 @@ func toServicePortConfigsSlice(dst reflect.Value, m map[interface{}]interface{})
|
|||||||
for _, v := range m {
|
for _, v := range m {
|
||||||
s = append(s, v.(types.ServicePortConfig))
|
s = append(s, v.(types.ServicePortConfig))
|
||||||
}
|
}
|
||||||
sort.Slice(s, func(i, j int) bool { return s[i].Published < s[j].Published })
|
sort.Slice(s, func(i, j int) bool {
|
||||||
|
if s[i].Target != s[j].Target {
|
||||||
|
return s[i].Target < s[j].Target
|
||||||
|
}
|
||||||
|
if s[i].Published != s[j].Published {
|
||||||
|
return s[i].Published < s[j].Published
|
||||||
|
}
|
||||||
|
if s[i].HostIP != s[j].HostIP {
|
||||||
|
return s[i].HostIP < s[j].HostIP
|
||||||
|
}
|
||||||
|
return s[i].Protocol < s[j].Protocol
|
||||||
|
})
|
||||||
|
dst.Set(reflect.ValueOf(s))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toServiceVolumeConfigsSlice(dst reflect.Value, m map[interface{}]interface{}) error {
|
||||||
|
s := []types.ServiceVolumeConfig{}
|
||||||
|
for _, v := range m {
|
||||||
|
s = append(s, v.(types.ServiceVolumeConfig))
|
||||||
|
}
|
||||||
|
sort.Slice(s, func(i, j int) bool { return s[i].Target < s[j].Target })
|
||||||
dst.Set(reflect.ValueOf(s))
|
dst.Set(reflect.ValueOf(s))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
41
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
41
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
@@ -28,7 +28,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
|
// normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
|
||||||
func normalize(project *types.Project) error {
|
func normalize(project *types.Project, resolvePaths bool) error {
|
||||||
absWorkingDir, err := filepath.Abs(project.WorkingDir)
|
absWorkingDir, err := filepath.Abs(project.WorkingDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -41,6 +41,10 @@ func normalize(project *types.Project) error {
|
|||||||
}
|
}
|
||||||
project.ComposeFiles = absComposeFiles
|
project.ComposeFiles = absComposeFiles
|
||||||
|
|
||||||
|
if project.Networks == nil {
|
||||||
|
project.Networks = make(map[string]types.NetworkConfig)
|
||||||
|
}
|
||||||
|
|
||||||
// If not declared explicitly, Compose model involves an implicit "default" network
|
// If not declared explicitly, Compose model involves an implicit "default" network
|
||||||
if _, ok := project.Networks["default"]; !ok {
|
if _, ok := project.Networks["default"]; !ok {
|
||||||
project.Networks["default"] = types.NetworkConfig{}
|
project.Networks["default"] = types.NetworkConfig{}
|
||||||
@@ -72,8 +76,9 @@ func normalize(project *types.Project) error {
|
|||||||
}
|
}
|
||||||
localContext := absPath(project.WorkingDir, s.Build.Context)
|
localContext := absPath(project.WorkingDir, s.Build.Context)
|
||||||
if _, err := os.Stat(localContext); err == nil {
|
if _, err := os.Stat(localContext); err == nil {
|
||||||
|
if resolvePaths {
|
||||||
s.Build.Context = localContext
|
s.Build.Context = localContext
|
||||||
s.Build.Dockerfile = absPath(localContext, s.Build.Dockerfile)
|
}
|
||||||
} else {
|
} else {
|
||||||
// might be a remote http/git context. Unfortunately supported "remote" syntax is highly ambiguous
|
// might be a remote http/git context. Unfortunately supported "remote" syntax is highly ambiguous
|
||||||
// in moby/moby and not defined by compose-spec, so let's assume runtime will check
|
// in moby/moby and not defined by compose-spec, so let's assume runtime will check
|
||||||
@@ -82,17 +87,22 @@ func normalize(project *types.Project) error {
|
|||||||
}
|
}
|
||||||
s.Environment = s.Environment.Resolve(fn)
|
s.Environment = s.Environment.Resolve(fn)
|
||||||
|
|
||||||
err := relocateLogDriver(s)
|
err := relocateLogDriver(&s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = relocateLogOpt(s)
|
err = relocateLogOpt(&s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = relocateDockerfile(s)
|
err = relocateDockerfile(&s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = relocateScale(&s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -105,6 +115,21 @@ func normalize(project *types.Project) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func relocateScale(s *types.ServiceConfig) error {
|
||||||
|
scale := uint64(s.Scale)
|
||||||
|
if scale != 1 {
|
||||||
|
logrus.Warn("`scale` is deprecated. Use the `deploy.replicas` element")
|
||||||
|
if s.Deploy == nil {
|
||||||
|
s.Deploy = &types.DeployConfig{}
|
||||||
|
}
|
||||||
|
if s.Deploy.Replicas != nil && *s.Deploy.Replicas != scale {
|
||||||
|
return errors.Wrap(errdefs.ErrInvalid, "can't use both 'scale' (deprecated) and 'deploy.replicas'")
|
||||||
|
}
|
||||||
|
s.Deploy.Replicas = &scale
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func absComposeFiles(composeFiles []string) ([]string, error) {
|
func absComposeFiles(composeFiles []string) ([]string, error) {
|
||||||
absComposeFiles := make([]string, len(composeFiles))
|
absComposeFiles := make([]string, len(composeFiles))
|
||||||
for i, composeFile := range composeFiles {
|
for i, composeFile := range composeFiles {
|
||||||
@@ -191,7 +216,7 @@ func relocateExternalName(project *types.Project) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func relocateLogOpt(s types.ServiceConfig) error {
|
func relocateLogOpt(s *types.ServiceConfig) error {
|
||||||
if len(s.LogOpt) != 0 {
|
if len(s.LogOpt) != 0 {
|
||||||
logrus.Warn("`log_opts` is deprecated. Use the `logging` element")
|
logrus.Warn("`log_opts` is deprecated. Use the `logging` element")
|
||||||
if s.Logging == nil {
|
if s.Logging == nil {
|
||||||
@@ -208,7 +233,7 @@ func relocateLogOpt(s types.ServiceConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func relocateLogDriver(s types.ServiceConfig) error {
|
func relocateLogDriver(s *types.ServiceConfig) error {
|
||||||
if s.LogDriver != "" {
|
if s.LogDriver != "" {
|
||||||
logrus.Warn("`log_driver` is deprecated. Use the `logging` element")
|
logrus.Warn("`log_driver` is deprecated. Use the `logging` element")
|
||||||
if s.Logging == nil {
|
if s.Logging == nil {
|
||||||
@@ -223,7 +248,7 @@ func relocateLogDriver(s types.ServiceConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func relocateDockerfile(s types.ServiceConfig) error {
|
func relocateDockerfile(s *types.ServiceConfig) error {
|
||||||
if s.Dockerfile != "" {
|
if s.Dockerfile != "" {
|
||||||
logrus.Warn("`dockerfile` is deprecated. Use the `build` element")
|
logrus.Warn("`dockerfile` is deprecated. Use the `build` element")
|
||||||
if s.Build == nil {
|
if s.Build == nil {
|
||||||
|
11
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
11
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
@@ -38,20 +38,13 @@ func checkConsistency(project *types.Project) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(s.NetworkMode, types.NetworkModeServicePrefix) {
|
if strings.HasPrefix(s.NetworkMode, types.ServicePrefix) {
|
||||||
serviceName := s.NetworkMode[len(types.NetworkModeServicePrefix):]
|
serviceName := s.NetworkMode[len(types.ServicePrefix):]
|
||||||
if _, err := project.GetServices(serviceName); err != nil {
|
if _, err := project.GetServices(serviceName); err != nil {
|
||||||
return fmt.Errorf("service %q not found for network_mode 'service:%s'", serviceName, serviceName)
|
return fmt.Errorf("service %q not found for network_mode 'service:%s'", serviceName, serviceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(s.NetworkMode, types.NetworkModeContainerPrefix) {
|
|
||||||
containerName := s.NetworkMode[len(types.NetworkModeContainerPrefix):]
|
|
||||||
if _, err := project.GetByContainerName(containerName); err != nil {
|
|
||||||
return fmt.Errorf("service with container_name %q not found for network_mode 'container:%s'", containerName, containerName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, volume := range s.Volumes {
|
for _, volume := range s.Volumes {
|
||||||
switch volume.Type {
|
switch volume.Type {
|
||||||
case types.VolumeTypeVolume:
|
case types.VolumeTypeVolume:
|
||||||
|
11
vendor/github.com/compose-spec/compose-go/schema/compose-spec.json
generated
vendored
11
vendor/github.com/compose-spec/compose-go/schema/compose-spec.json
generated
vendored
@@ -331,7 +331,7 @@
|
|||||||
"privileged": {"type": "boolean"},
|
"privileged": {"type": "boolean"},
|
||||||
"profiles": {"$ref": "#/definitions/list_of_strings"},
|
"profiles": {"$ref": "#/definitions/list_of_strings"},
|
||||||
"pull_policy": {"type": "string", "enum": [
|
"pull_policy": {"type": "string", "enum": [
|
||||||
"always", "never", "if_not_present", "build"
|
"always", "never", "if_not_present", "build", "missing"
|
||||||
]},
|
]},
|
||||||
"read_only": {"type": "boolean"},
|
"read_only": {"type": "boolean"},
|
||||||
"restart": {"type": "string"},
|
"restart": {"type": "string"},
|
||||||
@@ -367,6 +367,7 @@
|
|||||||
"stdin_open": {"type": "boolean"},
|
"stdin_open": {"type": "boolean"},
|
||||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||||
"stop_signal": {"type": "string"},
|
"stop_signal": {"type": "string"},
|
||||||
|
"storage_opt": {"type": "object"},
|
||||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||||
"tty": {"type": "boolean"},
|
"tty": {"type": "boolean"},
|
||||||
"ulimits": {
|
"ulimits": {
|
||||||
@@ -426,8 +427,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"size": {
|
"size": {
|
||||||
"type": "integer",
|
"oneOf": [
|
||||||
"minimum": 0
|
{"type": "integer", "minimum": 0},
|
||||||
|
{"type": "string"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@@ -769,7 +772,7 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"patternProperties": {
|
"patternProperties": {
|
||||||
".+": {
|
".+": {
|
||||||
"type": ["string", "number", "null"]
|
"type": ["string", "number", "boolean", "null"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
9
vendor/github.com/compose-spec/compose-go/template/template.go
generated
vendored
9
vendor/github.com/compose-spec/compose-go/template/template.go
generated
vendored
@@ -25,11 +25,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var delimiter = "\\$"
|
var delimiter = "\\$"
|
||||||
var substitution = "[_a-z][_a-z0-9]*(?::?[-?][^}]*)?"
|
var substitutionNamed = "[_a-z][_a-z0-9]*"
|
||||||
|
var substitutionBraced = "[_a-z][_a-z0-9]*(?::?[-?][^}]*)?"
|
||||||
|
|
||||||
var patternString = fmt.Sprintf(
|
var patternString = fmt.Sprintf(
|
||||||
"%s(?i:(?P<escaped>%s)|(?P<named>%s)|{(?P<braced>%s)}|(?P<invalid>))",
|
"%s(?i:(?P<escaped>%s)|(?P<named>%s)|{(?P<braced>%s)}|(?P<invalid>))",
|
||||||
delimiter, delimiter, substitution, substitution,
|
delimiter, delimiter, substitutionNamed, substitutionBraced,
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultPattern = regexp.MustCompile(patternString)
|
var defaultPattern = regexp.MustCompile(patternString)
|
||||||
@@ -74,9 +75,11 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su
|
|||||||
return escaped
|
return escaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
braced := false
|
||||||
substitution := groups["named"]
|
substitution := groups["named"]
|
||||||
if substitution == "" {
|
if substitution == "" {
|
||||||
substitution = groups["braced"]
|
substitution = groups["braced"]
|
||||||
|
braced = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if substitution == "" {
|
if substitution == "" {
|
||||||
@@ -84,6 +87,7 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if braced {
|
||||||
for _, f := range subsFuncs {
|
for _, f := range subsFuncs {
|
||||||
var (
|
var (
|
||||||
value string
|
value string
|
||||||
@@ -98,6 +102,7 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
value, ok := mapping(substitution)
|
value, ok := mapping(substitution)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
23
vendor/github.com/compose-spec/compose-go/types/project.go
generated
vendored
23
vendor/github.com/compose-spec/compose-go/types/project.go
generated
vendored
@@ -94,24 +94,6 @@ func (p Project) ConfigNames() []string {
|
|||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Project) GetByContainerName(names ...string) (Services, error) {
|
|
||||||
if len(names) == 0 {
|
|
||||||
return p.Services, nil
|
|
||||||
}
|
|
||||||
services := Services{}
|
|
||||||
outLoop:
|
|
||||||
for _, name := range names {
|
|
||||||
for _, s := range p.Services {
|
|
||||||
if name == s.ContainerName {
|
|
||||||
services = append(services, s)
|
|
||||||
continue outLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("service with container_name %q could not be found", name)
|
|
||||||
}
|
|
||||||
return services, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetServices retrieve services by names, or return all services if no name specified
|
// GetServices retrieve services by names, or return all services if no name specified
|
||||||
func (p Project) GetServices(names ...string) (Services, error) {
|
func (p Project) GetServices(names ...string) (Services, error) {
|
||||||
if len(names) == 0 {
|
if len(names) == 0 {
|
||||||
@@ -228,6 +210,11 @@ func (s Services) GetProfiles() []string {
|
|||||||
|
|
||||||
// ApplyProfiles disables service which don't match selected profiles
|
// ApplyProfiles disables service which don't match selected profiles
|
||||||
func (p *Project) ApplyProfiles(profiles []string) {
|
func (p *Project) ApplyProfiles(profiles []string) {
|
||||||
|
for _, p := range profiles {
|
||||||
|
if p == "*" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
var enabled, disabled Services
|
var enabled, disabled Services
|
||||||
for _, service := range p.Services {
|
for _, service := range p.Services {
|
||||||
if service.HasProfile(profiles) {
|
if service.HasProfile(profiles) {
|
||||||
|
38
vendor/github.com/compose-spec/compose-go/types/types.go
generated
vendored
38
vendor/github.com/compose-spec/compose-go/types/types.go
generated
vendored
@@ -89,7 +89,7 @@ type ServiceConfig struct {
|
|||||||
Profiles []string `mapstructure:"profiles" yaml:"profiles,omitempty" json:"profiles,omitempty"`
|
Profiles []string `mapstructure:"profiles" yaml:"profiles,omitempty" json:"profiles,omitempty"`
|
||||||
|
|
||||||
Build *BuildConfig `yaml:",omitempty" json:"build,omitempty"`
|
Build *BuildConfig `yaml:",omitempty" json:"build,omitempty"`
|
||||||
BlkioConfig *BlkioConfig `yaml:",omitempty" json:"blkio_config,omitempty"`
|
BlkioConfig *BlkioConfig `mapstructure:"blkio_config" yaml:",omitempty" json:"blkio_config,omitempty"`
|
||||||
CapAdd []string `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"`
|
CapAdd []string `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"`
|
||||||
CapDrop []string `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"`
|
CapDrop []string `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"`
|
||||||
CgroupParent string `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"`
|
CgroupParent string `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"`
|
||||||
@@ -152,7 +152,7 @@ type ServiceConfig struct {
|
|||||||
ReadOnly bool `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
|
ReadOnly bool `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
|
||||||
Restart string `yaml:",omitempty" json:"restart,omitempty"`
|
Restart string `yaml:",omitempty" json:"restart,omitempty"`
|
||||||
Runtime string `yaml:",omitempty" json:"runtime,omitempty"`
|
Runtime string `yaml:",omitempty" json:"runtime,omitempty"`
|
||||||
Scale int `yaml:",omitempty" json:"scale,omitempty"`
|
Scale int `yaml:"-" json:"-"`
|
||||||
Secrets []ServiceSecretConfig `yaml:",omitempty" json:"secrets,omitempty"`
|
Secrets []ServiceSecretConfig `yaml:",omitempty" json:"secrets,omitempty"`
|
||||||
SecurityOpt []string `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"`
|
SecurityOpt []string `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"`
|
||||||
ShmSize UnitBytes `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"`
|
ShmSize UnitBytes `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"`
|
||||||
@@ -226,10 +226,17 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ServicePrefix is the prefix for references pointing to a service
|
||||||
|
ServicePrefix = "service:"
|
||||||
|
// ContainerPrefix is the prefix for references pointing to a container
|
||||||
|
ContainerPrefix = "container:"
|
||||||
|
|
||||||
// NetworkModeServicePrefix is the prefix for network_mode pointing to a service
|
// NetworkModeServicePrefix is the prefix for network_mode pointing to a service
|
||||||
NetworkModeServicePrefix = "service:"
|
// Deprecated prefer ServicePrefix
|
||||||
|
NetworkModeServicePrefix = ServicePrefix
|
||||||
// NetworkModeContainerPrefix is the prefix for network_mode pointing to a container
|
// NetworkModeContainerPrefix is the prefix for network_mode pointing to a container
|
||||||
NetworkModeContainerPrefix = "container:"
|
// Deprecated prefer ContainerPrefix
|
||||||
|
NetworkModeContainerPrefix = ContainerPrefix
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetDependencies retrieve all services this service depends on
|
// GetDependencies retrieve all services this service depends on
|
||||||
@@ -246,9 +253,21 @@ func (s ServiceConfig) GetDependencies() []string {
|
|||||||
dependencies.append(link)
|
dependencies.append(link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(s.NetworkMode, NetworkModeServicePrefix) {
|
if strings.HasPrefix(s.NetworkMode, ServicePrefix) {
|
||||||
dependencies.append(s.NetworkMode[len(NetworkModeServicePrefix):])
|
dependencies.append(s.NetworkMode[len(ServicePrefix):])
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(s.Ipc, ServicePrefix) {
|
||||||
|
dependencies.append(s.Ipc[len(ServicePrefix):])
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(s.Pid, ServicePrefix) {
|
||||||
|
dependencies.append(s.Pid[len(ServicePrefix):])
|
||||||
|
}
|
||||||
|
for _, vol := range s.VolumesFrom {
|
||||||
|
if !strings.HasPrefix(s.Pid, ContainerPrefix) {
|
||||||
|
dependencies.append(vol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dependencies.toSlice()
|
return dependencies.toSlice()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +371,7 @@ func (e MappingWithEquals) OverrideBy(other MappingWithEquals) MappingWithEquals
|
|||||||
// Resolve update a MappingWithEquals for keys without value (`key`, but not `key=`)
|
// Resolve update a MappingWithEquals for keys without value (`key`, but not `key=`)
|
||||||
func (e MappingWithEquals) Resolve(lookupFn func(string) (string, bool)) MappingWithEquals {
|
func (e MappingWithEquals) Resolve(lookupFn func(string) (string, bool)) MappingWithEquals {
|
||||||
for k, v := range e {
|
for k, v := range e {
|
||||||
if v == nil || *v == "" {
|
if v == nil {
|
||||||
if value, ok := lookupFn(k); ok {
|
if value, ok := lookupFn(k); ok {
|
||||||
e[k] = &value
|
e[k] = &value
|
||||||
}
|
}
|
||||||
@@ -558,7 +577,7 @@ type ServiceNetworkConfig struct {
|
|||||||
// ServicePortConfig is the port configuration for a service
|
// ServicePortConfig is the port configuration for a service
|
||||||
type ServicePortConfig struct {
|
type ServicePortConfig struct {
|
||||||
Mode string `yaml:",omitempty" json:"mode,omitempty"`
|
Mode string `yaml:",omitempty" json:"mode,omitempty"`
|
||||||
HostIP string `yaml:"host_ip,omitempty" json:"host_ip,omitempty"`
|
HostIP string `mapstructure:"host_ip" yaml:"host_ip,omitempty" json:"host_ip,omitempty"`
|
||||||
Target uint32 `yaml:",omitempty" json:"target,omitempty"`
|
Target uint32 `yaml:",omitempty" json:"target,omitempty"`
|
||||||
Published uint32 `yaml:",omitempty" json:"published,omitempty"`
|
Published uint32 `yaml:",omitempty" json:"published,omitempty"`
|
||||||
Protocol string `yaml:",omitempty" json:"protocol,omitempty"`
|
Protocol string `yaml:",omitempty" json:"protocol,omitempty"`
|
||||||
@@ -671,7 +690,7 @@ type ServiceVolumeVolume struct {
|
|||||||
|
|
||||||
// ServiceVolumeTmpfs are options for a service volume of type tmpfs
|
// ServiceVolumeTmpfs are options for a service volume of type tmpfs
|
||||||
type ServiceVolumeTmpfs struct {
|
type ServiceVolumeTmpfs struct {
|
||||||
Size int64 `yaml:",omitempty" json:"size,omitempty"`
|
Size UnitBytes `yaml:",omitempty" json:"size,omitempty"`
|
||||||
|
|
||||||
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
||||||
}
|
}
|
||||||
@@ -729,6 +748,7 @@ type NetworkConfig struct {
|
|||||||
Internal bool `yaml:",omitempty" json:"internal,omitempty"`
|
Internal bool `yaml:",omitempty" json:"internal,omitempty"`
|
||||||
Attachable bool `yaml:",omitempty" json:"attachable,omitempty"`
|
Attachable bool `yaml:",omitempty" json:"attachable,omitempty"`
|
||||||
Labels Labels `yaml:",omitempty" json:"labels,omitempty"`
|
Labels Labels `yaml:",omitempty" json:"labels,omitempty"`
|
||||||
|
EnableIPv6 bool `mapstructure:"enable_ipv6" yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"`
|
||||||
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
vendor/github.com/compose-spec/godotenv/Earthfile
generated
vendored
Normal file
27
vendor/github.com/compose-spec/godotenv/Earthfile
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
ARG GOLANG_VERSION=1.17.1
|
||||||
|
ARG ALPINE_VERSION=3.14
|
||||||
|
|
||||||
|
FROM golang:${GOLANG_VERSION}-alpine${ALPINE_VERSION}
|
||||||
|
WORKDIR /code
|
||||||
|
|
||||||
|
code:
|
||||||
|
FROM +base
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
golangci:
|
||||||
|
ARG GOLANGCI_VERSION=v1.40.1
|
||||||
|
FROM golangci/golangci-lint:${GOLANGCI_VERSION}-alpine
|
||||||
|
SAVE ARTIFACT /usr/bin/golangci-lint
|
||||||
|
|
||||||
|
lint:
|
||||||
|
FROM +code
|
||||||
|
COPY +golangci/golangci-lint /usr/bin/golangci-lint
|
||||||
|
RUN golangci-lint run --timeout 5m ./...
|
||||||
|
|
||||||
|
test:
|
||||||
|
FROM +code
|
||||||
|
RUN go test ./...
|
||||||
|
|
||||||
|
all:
|
||||||
|
BUILD +lint
|
||||||
|
BUILD +test
|
18
vendor/github.com/compose-spec/godotenv/README.md
generated
vendored
Normal file
18
vendor/github.com/compose-spec/godotenv/README.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# GoDotEnv
|
||||||
|
|
||||||
|
A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file)
|
||||||
|
|
||||||
|
From the original Library:
|
||||||
|
|
||||||
|
> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables.
|
||||||
|
>
|
||||||
|
> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped.
|
||||||
|
|
||||||
|
This is a fork of [joho/godotenv](https://github.com/joho/godotenv) focussing on `.env` file support by the compose specification
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
To run linter and tests, please install [Earthly](https://earthly.dev/get-earthly) and run:
|
||||||
|
```sh
|
||||||
|
earthly +all
|
||||||
|
```
|
3
vendor/github.com/compose-spec/godotenv/go.mod
generated
vendored
Normal file
3
vendor/github.com/compose-spec/godotenv/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/compose-spec/godotenv
|
||||||
|
|
||||||
|
go 1.16
|
0
vendor/github.com/compose-spec/godotenv/go.sum
generated
vendored
Normal file
0
vendor/github.com/compose-spec/godotenv/go.sum
generated
vendored
Normal file
@@ -14,19 +14,42 @@
|
|||||||
package godotenv
|
package godotenv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const doubleQuoteSpecialChars = "\\\n\r\"!$`"
|
const doubleQuoteSpecialChars = "\\\n\r\"!$`"
|
||||||
|
|
||||||
|
// LookupFn represents a lookup function to resolve variables from
|
||||||
|
type LookupFn func(string) (string, bool)
|
||||||
|
|
||||||
|
var noLookupFn = func(s string) (string, bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse reads an env file from io.Reader, returning a map of keys and values.
|
||||||
|
func Parse(r io.Reader) (map[string]string, error) {
|
||||||
|
return ParseWithLookup(r, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseWithLookup reads an env file from io.Reader, returning a map of keys and values.
|
||||||
|
func ParseWithLookup(r io.Reader, lookupFn LookupFn) (map[string]string, error) {
|
||||||
|
data, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return UnmarshalBytesWithLookup(data, lookupFn)
|
||||||
|
}
|
||||||
|
|
||||||
// Load will read your env file(s) and load them into ENV for this process.
|
// Load will read your env file(s) and load them into ENV for this process.
|
||||||
//
|
//
|
||||||
// Call this function as close as possible to the start of your program (ideally in main)
|
// Call this function as close as possible to the start of your program (ideally in main)
|
||||||
@@ -39,15 +62,7 @@ const doubleQuoteSpecialChars = "\\\n\r\"!$`"
|
|||||||
//
|
//
|
||||||
// It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults
|
// It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults
|
||||||
func Load(filenames ...string) (err error) {
|
func Load(filenames ...string) (err error) {
|
||||||
filenames = filenamesOrDefault(filenames)
|
return load(false, filenames...)
|
||||||
|
|
||||||
for _, filename := range filenames {
|
|
||||||
err = loadFile(filename, false)
|
|
||||||
if err != nil {
|
|
||||||
return // return early on a spazout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overload will read your env file(s) and load them into ENV for this process.
|
// Overload will read your env file(s) and load them into ENV for this process.
|
||||||
@@ -62,10 +77,14 @@ func Load(filenames ...string) (err error) {
|
|||||||
//
|
//
|
||||||
// It's important to note this WILL OVERRIDE an env variable that already exists - consider the .env file to forcefilly set all vars.
|
// It's important to note this WILL OVERRIDE an env variable that already exists - consider the .env file to forcefilly set all vars.
|
||||||
func Overload(filenames ...string) (err error) {
|
func Overload(filenames ...string) (err error) {
|
||||||
|
return load(true, filenames...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func load(overload bool, filenames ...string) (err error) {
|
||||||
filenames = filenamesOrDefault(filenames)
|
filenames = filenamesOrDefault(filenames)
|
||||||
|
|
||||||
for _, filename := range filenames {
|
for _, filename := range filenames {
|
||||||
err = loadFile(filename, true)
|
err = loadFile(filename, overload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return // return early on a spazout
|
return // return early on a spazout
|
||||||
}
|
}
|
||||||
@@ -73,14 +92,14 @@ func Overload(filenames ...string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read all env (with same file loading semantics as Load) but return values as
|
// ReadWithLookup gets all env vars from the files and/or lookup function and return values as
|
||||||
// a map rather than automatically writing values into env
|
// a map rather than automatically writing values into env
|
||||||
func Read(filenames ...string) (envMap map[string]string, err error) {
|
func ReadWithLookup(lookupFn LookupFn, filenames ...string) (envMap map[string]string, err error) {
|
||||||
filenames = filenamesOrDefault(filenames)
|
filenames = filenamesOrDefault(filenames)
|
||||||
envMap = make(map[string]string)
|
envMap = make(map[string]string)
|
||||||
|
|
||||||
for _, filename := range filenames {
|
for _, filename := range filenames {
|
||||||
individualEnvMap, individualErr := readFile(filename)
|
individualEnvMap, individualErr := readFile(filename, lookupFn)
|
||||||
|
|
||||||
if individualErr != nil {
|
if individualErr != nil {
|
||||||
err = individualErr
|
err = individualErr
|
||||||
@@ -95,37 +114,27 @@ func Read(filenames ...string) (envMap map[string]string, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse reads an env file from io.Reader, returning a map of keys and values.
|
// Read all env (with same file loading semantics as Load) but return values as
|
||||||
func Parse(r io.Reader) (envMap map[string]string, err error) {
|
// a map rather than automatically writing values into env
|
||||||
envMap = make(map[string]string)
|
func Read(filenames ...string) (envMap map[string]string, err error) {
|
||||||
|
return ReadWithLookup(nil, filenames...)
|
||||||
var lines []string
|
|
||||||
scanner := bufio.NewScanner(r)
|
|
||||||
for scanner.Scan() {
|
|
||||||
lines = append(lines, scanner.Text())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = scanner.Err(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fullLine := range lines {
|
|
||||||
if !isIgnoredLine(fullLine) {
|
|
||||||
var key, value string
|
|
||||||
key, value, err = parseLine(fullLine, envMap)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
envMap[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal reads an env file from a string, returning a map of keys and values.
|
// Unmarshal reads an env file from a string, returning a map of keys and values.
|
||||||
func Unmarshal(str string) (envMap map[string]string, err error) {
|
func Unmarshal(str string) (envMap map[string]string, err error) {
|
||||||
return Parse(strings.NewReader(str))
|
return UnmarshalBytes([]byte(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBytes parses env file from byte slice of chars, returning a map of keys and values.
|
||||||
|
func UnmarshalBytes(src []byte) (map[string]string, error) {
|
||||||
|
return UnmarshalBytesWithLookup(src, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBytesWithLookup parses env file from byte slice of chars, returning a map of keys and values.
|
||||||
|
func UnmarshalBytesWithLookup(src []byte, lookupFn LookupFn) (map[string]string, error) {
|
||||||
|
out := make(map[string]string)
|
||||||
|
err := parseBytes(src, out, lookupFn)
|
||||||
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec loads env vars from the specified filenames (empty map falls back to default)
|
// Exec loads env vars from the specified filenames (empty map falls back to default)
|
||||||
@@ -136,7 +145,9 @@ func Unmarshal(str string) (envMap map[string]string, err error) {
|
|||||||
// If you want more fine grained control over your command it's recommended
|
// If you want more fine grained control over your command it's recommended
|
||||||
// that you use `Load()` or `Read()` and the `os/exec` package yourself.
|
// that you use `Load()` or `Read()` and the `os/exec` package yourself.
|
||||||
func Exec(filenames []string, cmd string, cmdArgs []string) error {
|
func Exec(filenames []string, cmd string, cmdArgs []string) error {
|
||||||
Load(filenames...)
|
if err := Load(filenames...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
command := exec.Command(cmd, cmdArgs...)
|
command := exec.Command(cmd, cmdArgs...)
|
||||||
command.Stdin = os.Stdin
|
command.Stdin = os.Stdin
|
||||||
@@ -147,25 +158,33 @@ func Exec(filenames []string, cmd string, cmdArgs []string) error {
|
|||||||
|
|
||||||
// Write serializes the given environment and writes it to a file
|
// Write serializes the given environment and writes it to a file
|
||||||
func Write(envMap map[string]string, filename string) error {
|
func Write(envMap map[string]string, filename string) error {
|
||||||
content, error := Marshal(envMap)
|
content, err := Marshal(envMap)
|
||||||
if error != nil {
|
if err != nil {
|
||||||
return error
|
|
||||||
}
|
|
||||||
file, error := os.Create(filename)
|
|
||||||
if error != nil {
|
|
||||||
return error
|
|
||||||
}
|
|
||||||
_, err := file.WriteString(content)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
_, err = file.WriteString(content + "\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return file.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
// Marshal outputs the given environment as a dotenv-formatted environment file.
|
// Marshal outputs the given environment as a dotenv-formatted environment file.
|
||||||
// Each line is in the format: KEY="VALUE" where VALUE is backslash-escaped.
|
// Each line is in the format: KEY="VALUE" where VALUE is backslash-escaped.
|
||||||
func Marshal(envMap map[string]string) (string, error) {
|
func Marshal(envMap map[string]string) (string, error) {
|
||||||
lines := make([]string, 0, len(envMap))
|
lines := make([]string, 0, len(envMap))
|
||||||
for k, v := range envMap {
|
for k, v := range envMap {
|
||||||
|
if d, err := strconv.Atoi(v); err == nil {
|
||||||
|
lines = append(lines, fmt.Sprintf(`%s=%d`, k, d))
|
||||||
|
} else {
|
||||||
lines = append(lines, fmt.Sprintf(`%s="%s"`, k, doubleQuoteEscape(v)))
|
lines = append(lines, fmt.Sprintf(`%s="%s"`, k, doubleQuoteEscape(v)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sort.Strings(lines)
|
sort.Strings(lines)
|
||||||
return strings.Join(lines, "\n"), nil
|
return strings.Join(lines, "\n"), nil
|
||||||
}
|
}
|
||||||
@@ -178,7 +197,7 @@ func filenamesOrDefault(filenames []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadFile(filename string, overload bool) error {
|
func loadFile(filename string, overload bool) error {
|
||||||
envMap, err := readFile(filename)
|
envMap, err := readFile(filename, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -192,24 +211,29 @@ func loadFile(filename string, overload bool) error {
|
|||||||
|
|
||||||
for key, value := range envMap {
|
for key, value := range envMap {
|
||||||
if !currentEnv[key] || overload {
|
if !currentEnv[key] || overload {
|
||||||
os.Setenv(key, value)
|
_ = os.Setenv(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFile(filename string) (envMap map[string]string, err error) {
|
func readFile(filename string, lookupFn LookupFn) (envMap map[string]string, err error) {
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
return Parse(file)
|
return ParseWithLookup(file, lookupFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var exportRegex = regexp.MustCompile(`^\s*(?:export\s+)?(.*?)\s*$`)
|
||||||
|
|
||||||
func parseLine(line string, envMap map[string]string) (key string, value string, err error) {
|
func parseLine(line string, envMap map[string]string) (key string, value string, err error) {
|
||||||
|
return parseLineWithLookup(line, envMap, nil)
|
||||||
|
}
|
||||||
|
func parseLineWithLookup(line string, envMap map[string]string, lookupFn LookupFn) (key string, value string, err error) {
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
err = errors.New("zero length string")
|
err = errors.New("zero length string")
|
||||||
return
|
return
|
||||||
@@ -250,31 +274,30 @@ func parseLine(line string, envMap map[string]string) (key string, value string,
|
|||||||
err = errors.New("Can't separate key from value")
|
err = errors.New("Can't separate key from value")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
key = exportRegex.ReplaceAllString(splitString[0], "$1")
|
||||||
// Parse the key
|
|
||||||
key = splitString[0]
|
|
||||||
if strings.HasPrefix(key, "export") {
|
|
||||||
key = strings.TrimPrefix(key, "export")
|
|
||||||
}
|
|
||||||
key = strings.Trim(key, " ")
|
|
||||||
|
|
||||||
// Parse the value
|
// Parse the value
|
||||||
value = parseValue(splitString[1], envMap)
|
value = parseValue(splitString[1], envMap, lookupFn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseValue(value string, envMap map[string]string) string {
|
var (
|
||||||
|
singleQuotesRegex = regexp.MustCompile(`\A'(.*)'\z`)
|
||||||
|
doubleQuotesRegex = regexp.MustCompile(`\A"(.*)"\z`)
|
||||||
|
escapeRegex = regexp.MustCompile(`\\.`)
|
||||||
|
unescapeCharsRegex = regexp.MustCompile(`\\([^$])`)
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseValue(value string, envMap map[string]string, lookupFn LookupFn) string {
|
||||||
|
|
||||||
// trim
|
// trim
|
||||||
value = strings.Trim(value, " ")
|
value = strings.Trim(value, " ")
|
||||||
|
|
||||||
// check if we've got quoted values or possible escapes
|
// check if we've got quoted values or possible escapes
|
||||||
if len(value) > 1 {
|
if len(value) > 1 {
|
||||||
rs := regexp.MustCompile(`\A'(.*)'\z`)
|
singleQuotes := singleQuotesRegex.FindStringSubmatch(value)
|
||||||
singleQuotes := rs.FindStringSubmatch(value)
|
|
||||||
|
|
||||||
rd := regexp.MustCompile(`\A"(.*)"\z`)
|
doubleQuotes := doubleQuotesRegex.FindStringSubmatch(value)
|
||||||
doubleQuotes := rd.FindStringSubmatch(value)
|
|
||||||
|
|
||||||
if singleQuotes != nil || doubleQuotes != nil {
|
if singleQuotes != nil || doubleQuotes != nil {
|
||||||
// pull the quotes off the edges
|
// pull the quotes off the edges
|
||||||
@@ -283,7 +306,6 @@ func parseValue(value string, envMap map[string]string) string {
|
|||||||
|
|
||||||
if doubleQuotes != nil {
|
if doubleQuotes != nil {
|
||||||
// expand newlines
|
// expand newlines
|
||||||
escapeRegex := regexp.MustCompile(`\\.`)
|
|
||||||
value = escapeRegex.ReplaceAllStringFunc(value, func(match string) string {
|
value = escapeRegex.ReplaceAllStringFunc(value, func(match string) string {
|
||||||
c := strings.TrimPrefix(match, `\`)
|
c := strings.TrimPrefix(match, `\`)
|
||||||
switch c {
|
switch c {
|
||||||
@@ -296,23 +318,22 @@ func parseValue(value string, envMap map[string]string) string {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// unescape characters
|
// unescape characters
|
||||||
e := regexp.MustCompile(`\\([^$])`)
|
value = unescapeCharsRegex.ReplaceAllString(value, "$1")
|
||||||
value = e.ReplaceAllString(value, "$1")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if singleQuotes == nil {
|
if singleQuotes == nil {
|
||||||
value = expandVariables(value, envMap)
|
value = expandVariables(value, envMap, lookupFn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandVariables(v string, m map[string]string) string {
|
var expandVarRegex = regexp.MustCompile(`(\\)?(\$)(\()?\{?([A-Z0-9_]+)?\}?`)
|
||||||
r := regexp.MustCompile(`(\\)?(\$)(\()?\{?([A-Z0-9_]+)?\}?`)
|
|
||||||
|
|
||||||
return r.ReplaceAllStringFunc(v, func(s string) string {
|
func expandVariables(v string, envMap map[string]string, lookupFn LookupFn) string {
|
||||||
submatch := r.FindStringSubmatch(s)
|
return expandVarRegex.ReplaceAllStringFunc(v, func(s string) string {
|
||||||
|
submatch := expandVarRegex.FindStringSubmatch(s)
|
||||||
|
|
||||||
if submatch == nil {
|
if submatch == nil {
|
||||||
return s
|
return s
|
||||||
@@ -320,17 +341,25 @@ func expandVariables(v string, m map[string]string) string {
|
|||||||
if submatch[1] == "\\" || submatch[2] == "(" {
|
if submatch[1] == "\\" || submatch[2] == "(" {
|
||||||
return submatch[0][1:]
|
return submatch[0][1:]
|
||||||
} else if submatch[4] != "" {
|
} else if submatch[4] != "" {
|
||||||
return m[submatch[4]]
|
//first check if we have defined this already earlier
|
||||||
|
if envMap[submatch[4]] != "" {
|
||||||
|
return envMap[submatch[4]]
|
||||||
|
}
|
||||||
|
if lookupFn == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
//if we have not defined it, check the lookup function provided
|
||||||
|
//by the user
|
||||||
|
s2, ok := lookupFn(submatch[4])
|
||||||
|
if ok {
|
||||||
|
return s2
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func isIgnoredLine(line string) bool {
|
|
||||||
trimmedLine := strings.Trim(line, " \n\t")
|
|
||||||
return len(trimmedLine) == 0 || strings.HasPrefix(trimmedLine, "#")
|
|
||||||
}
|
|
||||||
|
|
||||||
func doubleQuoteEscape(line string) string {
|
func doubleQuoteEscape(line string) string {
|
||||||
for _, c := range doubleQuoteSpecialChars {
|
for _, c := range doubleQuoteSpecialChars {
|
||||||
toReplace := "\\" + string(c)
|
toReplace := "\\" + string(c)
|
223
vendor/github.com/compose-spec/godotenv/parser.go
generated
vendored
Normal file
223
vendor/github.com/compose-spec/godotenv/parser.go
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
package godotenv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
charComment = '#'
|
||||||
|
prefixSingleQuote = '\''
|
||||||
|
prefixDoubleQuote = '"'
|
||||||
|
|
||||||
|
exportPrefix = "export"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseBytes(src []byte, out map[string]string, lookupFn LookupFn) error {
|
||||||
|
cutset := src
|
||||||
|
for {
|
||||||
|
cutset = getStatementStart(cutset)
|
||||||
|
if cutset == nil {
|
||||||
|
// reached end of file
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
key, left, inherited, err := locateKeyName(cutset)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if strings.Contains(key, " ") {
|
||||||
|
return errors.New("key cannot contain a space")
|
||||||
|
}
|
||||||
|
|
||||||
|
if inherited {
|
||||||
|
if lookupFn == nil {
|
||||||
|
lookupFn = noLookupFn
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := lookupFn(key)
|
||||||
|
if ok {
|
||||||
|
out[key] = value
|
||||||
|
cutset = left
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value, left, err := extractVarValue(left, out, lookupFn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out[key] = value
|
||||||
|
cutset = left
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getStatementPosition returns position of statement begin.
|
||||||
|
//
|
||||||
|
// It skips any comment line or non-whitespace character.
|
||||||
|
func getStatementStart(src []byte) []byte {
|
||||||
|
pos := indexOfNonSpaceChar(src)
|
||||||
|
if pos == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
src = src[pos:]
|
||||||
|
if src[0] != charComment {
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip comment section
|
||||||
|
pos = bytes.IndexFunc(src, isCharFunc('\n'))
|
||||||
|
if pos == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return getStatementStart(src[pos:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// locateKeyName locates and parses key name and returns rest of slice
|
||||||
|
func locateKeyName(src []byte) (key string, cutset []byte, inherited bool, err error) {
|
||||||
|
// trim "export" and space at beginning
|
||||||
|
src = bytes.TrimLeftFunc(bytes.TrimPrefix(src, []byte(exportPrefix)), isSpace)
|
||||||
|
|
||||||
|
// locate key name end and validate it in single loop
|
||||||
|
offset := 0
|
||||||
|
loop:
|
||||||
|
for i, char := range src {
|
||||||
|
rchar := rune(char)
|
||||||
|
if isSpace(rchar) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch char {
|
||||||
|
case '=', ':', '\n':
|
||||||
|
// library also supports yaml-style value declaration
|
||||||
|
key = string(src[0:i])
|
||||||
|
offset = i + 1
|
||||||
|
inherited = char == '\n'
|
||||||
|
break loop
|
||||||
|
case '_':
|
||||||
|
default:
|
||||||
|
// variable name should match [A-Za-z0-9_]
|
||||||
|
if unicode.IsLetter(rchar) || unicode.IsNumber(rchar) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil, inherited, fmt.Errorf(
|
||||||
|
`unexpected character %q in variable name near %q`,
|
||||||
|
string(char), string(src))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(src) == 0 {
|
||||||
|
return "", nil, inherited, errors.New("zero length string")
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim whitespace
|
||||||
|
key = strings.TrimRightFunc(key, unicode.IsSpace)
|
||||||
|
cutset = bytes.TrimLeftFunc(src[offset:], isSpace)
|
||||||
|
return key, cutset, inherited, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractVarValue extracts variable value and returns rest of slice
|
||||||
|
func extractVarValue(src []byte, envMap map[string]string, lookupFn LookupFn) (value string, rest []byte, err error) {
|
||||||
|
quote, hasPrefix := hasQuotePrefix(src)
|
||||||
|
if !hasPrefix {
|
||||||
|
// unquoted value - read until whitespace
|
||||||
|
end := bytes.IndexFunc(src, unicode.IsSpace)
|
||||||
|
if end == -1 {
|
||||||
|
return expandVariables(string(src), envMap, lookupFn), nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return expandVariables(string(src[0:end]), envMap, lookupFn), src[end:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup quoted string terminator
|
||||||
|
for i := 1; i < len(src); i++ {
|
||||||
|
if char := src[i]; char != quote {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip escaped quote symbol (\" or \', depends on quote)
|
||||||
|
if prevChar := src[i-1]; prevChar == '\\' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim quotes
|
||||||
|
trimFunc := isCharFunc(rune(quote))
|
||||||
|
value = string(bytes.TrimLeftFunc(bytes.TrimRightFunc(src[0:i], trimFunc), trimFunc))
|
||||||
|
if quote == prefixDoubleQuote {
|
||||||
|
// unescape newlines for double quote (this is compat feature)
|
||||||
|
// and expand environment variables
|
||||||
|
value = expandVariables(expandEscapes(value), envMap, lookupFn)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, src[i+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// return formatted error if quoted string is not terminated
|
||||||
|
valEndIndex := bytes.IndexFunc(src, isCharFunc('\n'))
|
||||||
|
if valEndIndex == -1 {
|
||||||
|
valEndIndex = len(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil, fmt.Errorf("unterminated quoted value %s", src[:valEndIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandEscapes(str string) string {
|
||||||
|
out := escapeRegex.ReplaceAllStringFunc(str, func(match string) string {
|
||||||
|
c := strings.TrimPrefix(match, `\`)
|
||||||
|
switch c {
|
||||||
|
case "n":
|
||||||
|
return "\n"
|
||||||
|
case "r":
|
||||||
|
return "\r"
|
||||||
|
default:
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return unescapeCharsRegex.ReplaceAllString(out, "$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func indexOfNonSpaceChar(src []byte) int {
|
||||||
|
return bytes.IndexFunc(src, func(r rune) bool {
|
||||||
|
return !unicode.IsSpace(r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasQuotePrefix reports whether charset starts with single or double quote and returns quote character
|
||||||
|
func hasQuotePrefix(src []byte) (prefix byte, isQuored bool) {
|
||||||
|
if len(src) == 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch prefix := src[0]; prefix {
|
||||||
|
case prefixDoubleQuote, prefixSingleQuote:
|
||||||
|
return prefix, true
|
||||||
|
default:
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCharFunc(char rune) func(rune) bool {
|
||||||
|
return func(v rune) bool {
|
||||||
|
return v == char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isSpace reports whether the rune is a space character but not line break character
|
||||||
|
//
|
||||||
|
// this differs from unicode.IsSpace, which also applies line break as space
|
||||||
|
func isSpace(r rune) bool {
|
||||||
|
switch r {
|
||||||
|
case '\t', '\v', '\f', '\r', ' ', 0x85, 0xA0:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
13
vendor/github.com/docker/docker/pkg/archive/archive.go
generated
vendored
13
vendor/github.com/docker/docker/pkg/archive/archive.go
generated
vendored
@@ -809,7 +809,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||||||
rebaseName := options.RebaseNames[include]
|
rebaseName := options.RebaseNames[include]
|
||||||
|
|
||||||
var (
|
var (
|
||||||
parentMatched []bool
|
parentMatchInfo []fileutils.MatchInfo
|
||||||
parentDirs []string
|
parentDirs []string
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -845,13 +845,14 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
parentDirs = parentDirs[:len(parentDirs)-1]
|
parentDirs = parentDirs[:len(parentDirs)-1]
|
||||||
parentMatched = parentMatched[:len(parentMatched)-1]
|
parentMatchInfo = parentMatchInfo[:len(parentMatchInfo)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(parentMatched) != 0 {
|
var matchInfo fileutils.MatchInfo
|
||||||
skip, err = pm.MatchesUsingParentResult(relFilePath, parentMatched[len(parentMatched)-1])
|
if len(parentMatchInfo) != 0 {
|
||||||
|
skip, matchInfo, err = pm.MatchesUsingParentResults(relFilePath, parentMatchInfo[len(parentMatchInfo)-1])
|
||||||
} else {
|
} else {
|
||||||
skip, err = pm.MatchesOrParentMatches(relFilePath)
|
skip, matchInfo, err = pm.MatchesUsingParentResults(relFilePath, fileutils.MatchInfo{})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error matching %s: %v", relFilePath, err)
|
logrus.Errorf("Error matching %s: %v", relFilePath, err)
|
||||||
@@ -860,7 +861,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||||||
|
|
||||||
if f.IsDir() {
|
if f.IsDir() {
|
||||||
parentDirs = append(parentDirs, relFilePath)
|
parentDirs = append(parentDirs, relFilePath)
|
||||||
parentMatched = append(parentMatched, skip)
|
parentMatchInfo = append(parentMatchInfo, matchInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
83
vendor/github.com/docker/docker/pkg/fileutils/fileutils.go
generated
vendored
83
vendor/github.com/docker/docker/pkg/fileutils/fileutils.go
generated
vendored
@@ -62,9 +62,9 @@ func NewPatternMatcher(patterns []string) (*PatternMatcher, error) {
|
|||||||
//
|
//
|
||||||
// Matches is not safe to call concurrently.
|
// Matches is not safe to call concurrently.
|
||||||
//
|
//
|
||||||
// This implementation is buggy (it only checks a single parent dir against the
|
// Depercated: This implementation is buggy (it only checks a single parent dir
|
||||||
// pattern) and will be removed soon. Use either MatchesOrParentMatches or
|
// against the pattern) and will be removed soon. Use either
|
||||||
// MatchesUsingParentResult instead.
|
// MatchesOrParentMatches or MatchesUsingParentResults instead.
|
||||||
func (pm *PatternMatcher) Matches(file string) (bool, error) {
|
func (pm *PatternMatcher) Matches(file string) (bool, error) {
|
||||||
matched := false
|
matched := false
|
||||||
file = filepath.FromSlash(file)
|
file = filepath.FromSlash(file)
|
||||||
@@ -150,6 +150,11 @@ func (pm *PatternMatcher) MatchesOrParentMatches(file string) (bool, error) {
|
|||||||
// The "file" argument should be a slash-delimited path.
|
// The "file" argument should be a slash-delimited path.
|
||||||
//
|
//
|
||||||
// MatchesUsingParentResult is not safe to call concurrently.
|
// MatchesUsingParentResult is not safe to call concurrently.
|
||||||
|
//
|
||||||
|
// Deprecated: this function does behave correctly in some cases (see
|
||||||
|
// https://github.com/docker/buildx/issues/850).
|
||||||
|
//
|
||||||
|
// Use MatchesUsingParentResults instead.
|
||||||
func (pm *PatternMatcher) MatchesUsingParentResult(file string, parentMatched bool) (bool, error) {
|
func (pm *PatternMatcher) MatchesUsingParentResult(file string, parentMatched bool) (bool, error) {
|
||||||
matched := parentMatched
|
matched := parentMatched
|
||||||
file = filepath.FromSlash(file)
|
file = filepath.FromSlash(file)
|
||||||
@@ -174,6 +179,78 @@ func (pm *PatternMatcher) MatchesUsingParentResult(file string, parentMatched bo
|
|||||||
return matched, nil
|
return matched, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchInfo tracks information about parent dir matches while traversing a
|
||||||
|
// filesystem.
|
||||||
|
type MatchInfo struct {
|
||||||
|
parentMatched []bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchesUsingParentResults returns true if "file" matches any of the patterns
|
||||||
|
// and isn't excluded by any of the subsequent patterns. The functionality is
|
||||||
|
// the same as Matches, but as an optimization, the caller passes in
|
||||||
|
// intermediate results from matching the parent directory.
|
||||||
|
//
|
||||||
|
// The "file" argument should be a slash-delimited path.
|
||||||
|
//
|
||||||
|
// MatchesUsingParentResults is not safe to call concurrently.
|
||||||
|
func (pm *PatternMatcher) MatchesUsingParentResults(file string, parentMatchInfo MatchInfo) (bool, MatchInfo, error) {
|
||||||
|
parentMatched := parentMatchInfo.parentMatched
|
||||||
|
if len(parentMatched) != 0 && len(parentMatched) != len(pm.patterns) {
|
||||||
|
return false, MatchInfo{}, errors.New("wrong number of values in parentMatched")
|
||||||
|
}
|
||||||
|
|
||||||
|
file = filepath.FromSlash(file)
|
||||||
|
matched := false
|
||||||
|
|
||||||
|
matchInfo := MatchInfo{
|
||||||
|
parentMatched: make([]bool, len(pm.patterns)),
|
||||||
|
}
|
||||||
|
for i, pattern := range pm.patterns {
|
||||||
|
match := false
|
||||||
|
// If the parent matched this pattern, we don't need to recheck.
|
||||||
|
if len(parentMatched) != 0 {
|
||||||
|
match = parentMatched[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
if !match {
|
||||||
|
// Skip evaluation if this is an inclusion and the filename
|
||||||
|
// already matched the pattern, or it's an exclusion and it has
|
||||||
|
// not matched the pattern yet.
|
||||||
|
if pattern.exclusion != matched {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
match, err = pattern.match(file)
|
||||||
|
if err != nil {
|
||||||
|
return false, matchInfo, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the zero value of MatchInfo was passed in, we don't have
|
||||||
|
// any information about the parent dir's match results, and we
|
||||||
|
// apply the same logic as MatchesOrParentMatches.
|
||||||
|
if len(parentMatched) == 0 {
|
||||||
|
if parentPath := filepath.Dir(file); parentPath != "." {
|
||||||
|
parentPathDirs := strings.Split(parentPath, string(os.PathSeparator))
|
||||||
|
// Check to see if the pattern matches one of our parent dirs.
|
||||||
|
for i := range parentPathDirs {
|
||||||
|
match, _ = pattern.match(strings.Join(parentPathDirs[:i+1], string(os.PathSeparator)))
|
||||||
|
if match {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matchInfo.parentMatched[i] = match
|
||||||
|
|
||||||
|
if match {
|
||||||
|
matched = !pattern.exclusion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matched, matchInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Exclusions returns true if any of the patterns define exclusions
|
// Exclusions returns true if any of the patterns define exclusions
|
||||||
func (pm *PatternMatcher) Exclusions() bool {
|
func (pm *PatternMatcher) Exclusions() bool {
|
||||||
return pm.exclusions
|
return pm.exclusions
|
||||||
|
8
vendor/github.com/joho/godotenv/.travis.yml
generated
vendored
8
vendor/github.com/joho/godotenv/.travis.yml
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.x
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
163
vendor/github.com/joho/godotenv/README.md
generated
vendored
163
vendor/github.com/joho/godotenv/README.md
generated
vendored
@@ -1,163 +0,0 @@
|
|||||||
# GoDotEnv [](https://travis-ci.org/joho/godotenv) [](https://ci.appveyor.com/project/joho/godotenv) [](https://goreportcard.com/report/github.com/joho/godotenv)
|
|
||||||
|
|
||||||
A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file)
|
|
||||||
|
|
||||||
From the original Library:
|
|
||||||
|
|
||||||
> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables.
|
|
||||||
>
|
|
||||||
> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped.
|
|
||||||
|
|
||||||
It can be used as a library (for loading in env for your own daemons etc) or as a bin command.
|
|
||||||
|
|
||||||
There is test coverage and CI for both linuxish and windows environments, but I make no guarantees about the bin version working on windows.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
As a library
|
|
||||||
|
|
||||||
```shell
|
|
||||||
go get github.com/joho/godotenv
|
|
||||||
```
|
|
||||||
|
|
||||||
or if you want to use it as a bin command
|
|
||||||
```shell
|
|
||||||
go get github.com/joho/godotenv/cmd/godotenv
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Add your application configuration to your `.env` file in the root of your project:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
S3_BUCKET=YOURS3BUCKET
|
|
||||||
SECRET_KEY=YOURSECRETKEYGOESHERE
|
|
||||||
```
|
|
||||||
|
|
||||||
Then in your Go app you can do something like
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/joho/godotenv"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
err := godotenv.Load()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Error loading .env file")
|
|
||||||
}
|
|
||||||
|
|
||||||
s3Bucket := os.Getenv("S3_BUCKET")
|
|
||||||
secretKey := os.Getenv("SECRET_KEY")
|
|
||||||
|
|
||||||
// now do something with s3 or whatever
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import
|
|
||||||
|
|
||||||
```go
|
|
||||||
import _ "github.com/joho/godotenv/autoload"
|
|
||||||
```
|
|
||||||
|
|
||||||
While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit
|
|
||||||
|
|
||||||
```go
|
|
||||||
_ = godotenv.Load("somerandomfile")
|
|
||||||
_ = godotenv.Load("filenumberone.env", "filenumbertwo.env")
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to be really fancy with your env file you can do comments and exports (below is a valid env file)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# I am a comment and that is OK
|
|
||||||
SOME_VAR=someval
|
|
||||||
FOO=BAR # comments at line end are OK too
|
|
||||||
export BAR=BAZ
|
|
||||||
```
|
|
||||||
|
|
||||||
Or finally you can do YAML(ish) style
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
FOO: bar
|
|
||||||
BAR: baz
|
|
||||||
```
|
|
||||||
|
|
||||||
as a final aside, if you don't want godotenv munging your env you can just get a map back instead
|
|
||||||
|
|
||||||
```go
|
|
||||||
var myEnv map[string]string
|
|
||||||
myEnv, err := godotenv.Read()
|
|
||||||
|
|
||||||
s3Bucket := myEnv["S3_BUCKET"]
|
|
||||||
```
|
|
||||||
|
|
||||||
... or from an `io.Reader` instead of a local file
|
|
||||||
|
|
||||||
```go
|
|
||||||
reader := getRemoteFile()
|
|
||||||
myEnv, err := godotenv.Parse(reader)
|
|
||||||
```
|
|
||||||
|
|
||||||
... or from a `string` if you so desire
|
|
||||||
|
|
||||||
```go
|
|
||||||
content := getRemoteFileContent()
|
|
||||||
myEnv, err := godotenv.Unmarshal(content)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Mode
|
|
||||||
|
|
||||||
Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH`
|
|
||||||
|
|
||||||
```
|
|
||||||
godotenv -f /some/path/to/.env some_command with some args
|
|
||||||
```
|
|
||||||
|
|
||||||
If you don't specify `-f` it will fall back on the default of loading `.env` in `PWD`
|
|
||||||
|
|
||||||
### Writing Env Files
|
|
||||||
|
|
||||||
Godotenv can also write a map representing the environment to a correctly-formatted and escaped file
|
|
||||||
|
|
||||||
```go
|
|
||||||
env, err := godotenv.Unmarshal("KEY=value")
|
|
||||||
err := godotenv.Write(env, "./.env")
|
|
||||||
```
|
|
||||||
|
|
||||||
... or to a string
|
|
||||||
|
|
||||||
```go
|
|
||||||
env, err := godotenv.Unmarshal("KEY=value")
|
|
||||||
content, err := godotenv.Marshal(env)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Contributions are most welcome! The parser itself is pretty stupidly naive and I wouldn't be surprised if it breaks with edge cases.
|
|
||||||
|
|
||||||
*code changes without tests will not be accepted*
|
|
||||||
|
|
||||||
1. Fork it
|
|
||||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
||||||
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
||||||
4. Push to the branch (`git push origin my-new-feature`)
|
|
||||||
5. Create new Pull Request
|
|
||||||
|
|
||||||
## Releases
|
|
||||||
|
|
||||||
Releases should follow [Semver](http://semver.org/) though the first couple of releases are `v1` and `v1.1`.
|
|
||||||
|
|
||||||
Use [annotated tags for all releases](https://github.com/joho/godotenv/issues/30). Example `git tag -a v1.2.1`
|
|
||||||
|
|
||||||
## CI
|
|
||||||
|
|
||||||
Linux: [](https://travis-ci.org/joho/godotenv) Windows: [](https://ci.appveyor.com/project/joho/godotenv)
|
|
||||||
|
|
||||||
## Who?
|
|
||||||
|
|
||||||
The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](https://johnbarton.co/) based off the tests/fixtures in the original library.
|
|
8
vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
generated
vendored
8
vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
generated
vendored
@@ -1,4 +1,10 @@
|
|||||||
## unreleased
|
## 1.4.2
|
||||||
|
|
||||||
|
* Custom name matchers to support any sort of casing, formatting, etc. for
|
||||||
|
field names. [GH-250]
|
||||||
|
* Fix possible panic in ComposeDecodeHookFunc [GH-251]
|
||||||
|
|
||||||
|
## 1.4.1
|
||||||
|
|
||||||
* Fix regression where `*time.Time` value would be set to empty and not be sent
|
* Fix regression where `*time.Time` value would be set to empty and not be sent
|
||||||
to decode hooks properly [GH-232]
|
to decode hooks properly [GH-232]
|
||||||
|
3
vendor/github.com/mitchellh/mapstructure/decode_hooks.go
generated
vendored
3
vendor/github.com/mitchellh/mapstructure/decode_hooks.go
generated
vendored
@@ -62,7 +62,8 @@ func DecodeHookExec(
|
|||||||
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
var data interface{}
|
data := f.Interface()
|
||||||
|
|
||||||
newFrom := f
|
newFrom := f
|
||||||
for _, f1 := range fs {
|
for _, f1 := range fs {
|
||||||
data, err = DecodeHookExec(f1, newFrom, t)
|
data, err = DecodeHookExec(f1, newFrom, t)
|
||||||
|
13
vendor/github.com/mitchellh/mapstructure/mapstructure.go
generated
vendored
13
vendor/github.com/mitchellh/mapstructure/mapstructure.go
generated
vendored
@@ -192,7 +192,7 @@ type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface
|
|||||||
// source and target types.
|
// source and target types.
|
||||||
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
|
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
|
||||||
|
|
||||||
// DecodeHookFuncRaw is a DecodeHookFunc which has complete access to both the source and target
|
// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
|
||||||
// values.
|
// values.
|
||||||
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
|
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
|
||||||
|
|
||||||
@@ -258,6 +258,11 @@ type DecoderConfig struct {
|
|||||||
// The tag name that mapstructure reads for field names. This
|
// The tag name that mapstructure reads for field names. This
|
||||||
// defaults to "mapstructure"
|
// defaults to "mapstructure"
|
||||||
TagName string
|
TagName string
|
||||||
|
|
||||||
|
// MatchName is the function used to match the map key to the struct
|
||||||
|
// field name or tag. Defaults to `strings.EqualFold`. This can be used
|
||||||
|
// to implement case-sensitive tag values, support snake casing, etc.
|
||||||
|
MatchName func(mapKey, fieldName string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Decoder takes a raw interface value and turns it into structured
|
// A Decoder takes a raw interface value and turns it into structured
|
||||||
@@ -376,6 +381,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
|
|||||||
config.TagName = "mapstructure"
|
config.TagName = "mapstructure"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.MatchName == nil {
|
||||||
|
config.MatchName = strings.EqualFold
|
||||||
|
}
|
||||||
|
|
||||||
result := &Decoder{
|
result := &Decoder{
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
@@ -1340,7 +1349,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.EqualFold(mK, fieldName) {
|
if d.config.MatchName(mK, fieldName) {
|
||||||
rawMapKey = dataValKey
|
rawMapKey = dataValKey
|
||||||
rawMapVal = dataVal.MapIndex(dataValKey)
|
rawMapVal = dataVal.MapIndex(dataValKey)
|
||||||
break
|
break
|
||||||
|
13
vendor/github.com/tonistiigi/fsutil/diff_containerd.go
generated
vendored
13
vendor/github.com/tonistiigi/fsutil/diff_containerd.go
generated
vendored
@@ -33,6 +33,19 @@ const (
|
|||||||
ChangeKindDelete
|
ChangeKindDelete
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (k ChangeKind) String() string {
|
||||||
|
switch k {
|
||||||
|
case ChangeKindAdd:
|
||||||
|
return "add"
|
||||||
|
case ChangeKindModify:
|
||||||
|
return "modify"
|
||||||
|
case ChangeKindDelete:
|
||||||
|
return "delete"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ChangeFunc is the type of function called for each change
|
// ChangeFunc is the type of function called for each change
|
||||||
// computed during a directory changes calculation.
|
// computed during a directory changes calculation.
|
||||||
type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
|
type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
|
||||||
|
14
vendor/github.com/tonistiigi/fsutil/diskwriter_freebsd.go
generated
vendored
Normal file
14
vendor/github.com/tonistiigi/fsutil/diskwriter_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package fsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tonistiigi/fsutil/types"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createSpecialFile(path string, mode uint32, stat *types.Stat) error {
|
||||||
|
dev := unix.Mkdev(uint32(stat.Devmajor), uint32(stat.Devminor))
|
||||||
|
|
||||||
|
return unix.Mknod(path, mode, dev)
|
||||||
|
}
|
2
vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
generated
vendored
2
vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
generated
vendored
@@ -45,7 +45,7 @@ func handleTarTypeBlockCharFifo(path string, stat *types.Stat) error {
|
|||||||
mode |= syscall.S_IFBLK
|
mode |= syscall.S_IFBLK
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor))); err != nil {
|
if err := createSpecialFile(path, mode, stat); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
13
vendor/github.com/tonistiigi/fsutil/diskwriter_unixnobsd.go
generated
vendored
Normal file
13
vendor/github.com/tonistiigi/fsutil/diskwriter_unixnobsd.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// +build !windows,!freebsd
|
||||||
|
|
||||||
|
package fsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/tonistiigi/fsutil/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createSpecialFile(path string, mode uint32, stat *types.Stat) error {
|
||||||
|
return syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor)))
|
||||||
|
}
|
2
vendor/github.com/tonistiigi/fsutil/docker-bake.hcl
generated
vendored
2
vendor/github.com/tonistiigi/fsutil/docker-bake.hcl
generated
vendored
@@ -63,5 +63,5 @@ target "shfmt" {
|
|||||||
|
|
||||||
target "cross" {
|
target "cross" {
|
||||||
inherits = ["build"]
|
inherits = ["build"]
|
||||||
platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x"]
|
platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x", "darwin/amd64", "darwin/arm64", "windows/amd64", "freebsd/amd64", "freebsd/arm64"]
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/tonistiigi/fsutil/go.mod
generated
vendored
2
vendor/github.com/tonistiigi/fsutil/go.mod
generated
vendored
@@ -18,3 +18,5 @@ require (
|
|||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gotest.tools/v3 v3.0.3 // indirect
|
gotest.tools/v3 v3.0.3 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/docker/docker => github.com/aaronlehmann/docker v1.4.2-0.20211119215941-554d44fa45a2
|
||||||
|
4
vendor/github.com/tonistiigi/fsutil/go.sum
generated
vendored
4
vendor/github.com/tonistiigi/fsutil/go.sum
generated
vendored
@@ -2,6 +2,8 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/aaronlehmann/docker v1.4.2-0.20211119215941-554d44fa45a2 h1:W1DM5Z2Yym6DVr1Qcx+HCECYYjoAGWfYfgS1prcqoc4=
|
||||||
|
github.com/aaronlehmann/docker v1.4.2-0.20211119215941-554d44fa45a2/go.mod h1:fLQH6hJxU6jTc+JFQWNyw/nl0i9+jjwDmugekrLew18=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
@@ -23,8 +25,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible h1:tSd7TeZCH0j9m4P14bfe/eO1KYawrt3DztHI8gZAmLM=
|
|
||||||
github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
45
vendor/github.com/tonistiigi/fsutil/prefix/match.go
generated
vendored
45
vendor/github.com/tonistiigi/fsutil/prefix/match.go
generated
vendored
@@ -1,45 +0,0 @@
|
|||||||
package prefix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Match matches a path against a pattern. It returns m = true if the path
|
|
||||||
// matches the pattern, and partial = true if the pattern has more separators
|
|
||||||
// than the path and the common components match (for example, name = foo and
|
|
||||||
// pattern = foo/bar/*). slashSeparator determines whether the path and pattern
|
|
||||||
// are '/' delimited (true) or use the native path separator (false).
|
|
||||||
func Match(pattern, name string, slashSeparator bool) (m bool, partial bool) {
|
|
||||||
separator := filepath.Separator
|
|
||||||
if slashSeparator {
|
|
||||||
separator = '/'
|
|
||||||
}
|
|
||||||
count := strings.Count(name, string(separator))
|
|
||||||
if strings.Count(pattern, string(separator)) > count {
|
|
||||||
pattern = trimUntilIndex(pattern, string(separator), count)
|
|
||||||
partial = true
|
|
||||||
}
|
|
||||||
if slashSeparator {
|
|
||||||
m, _ = path.Match(pattern, name)
|
|
||||||
} else {
|
|
||||||
m, _ = filepath.Match(pattern, name)
|
|
||||||
}
|
|
||||||
return m, partial
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimUntilIndex(str, sep string, count int) string {
|
|
||||||
s := str
|
|
||||||
i := 0
|
|
||||||
c := 0
|
|
||||||
for {
|
|
||||||
idx := strings.Index(s, sep)
|
|
||||||
s = s[idx+len(sep):]
|
|
||||||
i += idx + len(sep)
|
|
||||||
c++
|
|
||||||
if c > count {
|
|
||||||
return str[:i-len(sep)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
189
vendor/github.com/tonistiigi/fsutil/walker.go
generated
vendored
189
vendor/github.com/tonistiigi/fsutil/walker.go
generated
vendored
@@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/docker/pkg/fileutils"
|
"github.com/docker/docker/pkg/fileutils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tonistiigi/fsutil/prefix"
|
|
||||||
"github.com/tonistiigi/fsutil/types"
|
"github.com/tonistiigi/fsutil/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,20 +35,15 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
|
|||||||
return errors.WithStack(&os.PathError{Op: "walk", Path: root, Err: syscall.ENOTDIR})
|
return errors.WithStack(&os.PathError{Op: "walk", Path: root, Err: syscall.ENOTDIR})
|
||||||
}
|
}
|
||||||
|
|
||||||
var pm *fileutils.PatternMatcher
|
var (
|
||||||
if opt != nil && opt.ExcludePatterns != nil {
|
includePatterns []string
|
||||||
pm, err = fileutils.NewPatternMatcher(opt.ExcludePatterns)
|
includeMatcher *fileutils.PatternMatcher
|
||||||
if err != nil {
|
excludeMatcher *fileutils.PatternMatcher
|
||||||
return errors.Wrapf(err, "invalid excludepatterns: %s", opt.ExcludePatterns)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var includePatterns []string
|
|
||||||
if opt != nil && opt.IncludePatterns != nil {
|
if opt != nil && opt.IncludePatterns != nil {
|
||||||
includePatterns = make([]string, len(opt.IncludePatterns))
|
includePatterns = make([]string, len(opt.IncludePatterns))
|
||||||
for k := range opt.IncludePatterns {
|
copy(includePatterns, opt.IncludePatterns)
|
||||||
includePatterns[k] = filepath.Clean(opt.IncludePatterns[k])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if opt != nil && opt.FollowPaths != nil {
|
if opt != nil && opt.FollowPaths != nil {
|
||||||
targets, err := FollowLinks(p, opt.FollowPaths)
|
targets, err := FollowLinks(p, opt.FollowPaths)
|
||||||
@@ -61,13 +55,32 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
|
|||||||
includePatterns = dedupePaths(includePatterns)
|
includePatterns = dedupePaths(includePatterns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(includePatterns) != 0 {
|
||||||
|
includeMatcher, err = fileutils.NewPatternMatcher(includePatterns)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "invalid includepatterns: %s", opt.IncludePatterns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
if opt != nil && opt.ExcludePatterns != nil {
|
||||||
lastIncludedDir string
|
excludeMatcher, err = fileutils.NewPatternMatcher(opt.ExcludePatterns)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "invalid excludepatterns: %s", opt.ExcludePatterns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parentDirs []string // used only for exclude handling
|
type visitedDir struct {
|
||||||
parentMatchedExclude []bool
|
fi os.FileInfo
|
||||||
)
|
path string
|
||||||
|
origpath string
|
||||||
|
pathWithSep string
|
||||||
|
includeMatchInfo fileutils.MatchInfo
|
||||||
|
excludeMatchInfo fileutils.MatchInfo
|
||||||
|
calledFn bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// used only for include/exclude handling
|
||||||
|
var parentDirs []visitedDir
|
||||||
|
|
||||||
seenFiles := make(map[uint64]string)
|
seenFiles := make(map[uint64]string)
|
||||||
return filepath.Walk(root, func(path string, fi os.FileInfo, err error) (retErr error) {
|
return filepath.Walk(root, func(path string, fi os.FileInfo, err error) (retErr error) {
|
||||||
@@ -90,87 +103,84 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt != nil {
|
var dir visitedDir
|
||||||
if includePatterns != nil {
|
|
||||||
skip := false
|
|
||||||
if lastIncludedDir != "" {
|
|
||||||
if strings.HasPrefix(path, lastIncludedDir+string(filepath.Separator)) {
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !skip {
|
if includeMatcher != nil || excludeMatcher != nil {
|
||||||
matched := false
|
for len(parentDirs) != 0 {
|
||||||
partial := true
|
lastParentDir := parentDirs[len(parentDirs)-1].pathWithSep
|
||||||
for _, pattern := range includePatterns {
|
|
||||||
if ok, p := prefix.Match(pattern, path, false); ok {
|
|
||||||
matched = true
|
|
||||||
if !p {
|
|
||||||
partial = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !matched {
|
|
||||||
if fi.IsDir() {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if !partial && fi.IsDir() {
|
|
||||||
lastIncludedDir = path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pm != nil {
|
|
||||||
for len(parentMatchedExclude) != 0 {
|
|
||||||
lastParentDir := parentDirs[len(parentDirs)-1]
|
|
||||||
if strings.HasPrefix(path, lastParentDir) {
|
if strings.HasPrefix(path, lastParentDir) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
parentDirs = parentDirs[:len(parentDirs)-1]
|
parentDirs = parentDirs[:len(parentDirs)-1]
|
||||||
parentMatchedExclude = parentMatchedExclude[:len(parentMatchedExclude)-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var m bool
|
if fi.IsDir() {
|
||||||
if len(parentMatchedExclude) != 0 {
|
dir = visitedDir{
|
||||||
m, err = pm.MatchesUsingParentResult(path, parentMatchedExclude[len(parentMatchedExclude)-1])
|
fi: fi,
|
||||||
} else {
|
path: path,
|
||||||
m, err = pm.MatchesOrParentMatches(path)
|
origpath: origpath,
|
||||||
|
pathWithSep: path + string(filepath.Separator),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
skip := false
|
||||||
|
|
||||||
|
if includeMatcher != nil {
|
||||||
|
var parentIncludeMatchInfo fileutils.MatchInfo
|
||||||
|
if len(parentDirs) != 0 {
|
||||||
|
parentIncludeMatchInfo = parentDirs[len(parentDirs)-1].includeMatchInfo
|
||||||
|
}
|
||||||
|
m, matchInfo, err := includeMatcher.MatchesUsingParentResults(path, parentIncludeMatchInfo)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to match includepatterns")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.IsDir() {
|
||||||
|
dir.includeMatchInfo = matchInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m {
|
||||||
|
skip = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if excludeMatcher != nil {
|
||||||
|
var parentExcludeMatchInfo fileutils.MatchInfo
|
||||||
|
if len(parentDirs) != 0 {
|
||||||
|
parentExcludeMatchInfo = parentDirs[len(parentDirs)-1].excludeMatchInfo
|
||||||
|
}
|
||||||
|
m, matchInfo, err := excludeMatcher.MatchesUsingParentResults(path, parentExcludeMatchInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to match excludepatterns")
|
return errors.Wrap(err, "failed to match excludepatterns")
|
||||||
}
|
}
|
||||||
|
|
||||||
var dirSlash string
|
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
dirSlash = path + string(filepath.Separator)
|
dir.excludeMatchInfo = matchInfo
|
||||||
parentDirs = append(parentDirs, dirSlash)
|
|
||||||
parentMatchedExclude = append(parentMatchedExclude, m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if m {
|
if m {
|
||||||
if fi.IsDir() {
|
if fi.IsDir() && !excludeMatcher.Exclusions() {
|
||||||
if !pm.Exclusions() {
|
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
for _, pat := range pm.Patterns() {
|
skip = true
|
||||||
if !pat.Exclusion() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
patStr := pat.String() + string(filepath.Separator)
|
|
||||||
if strings.HasPrefix(patStr, dirSlash) {
|
|
||||||
goto passedFilter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
passedFilter:
|
if includeMatcher != nil || excludeMatcher != nil {
|
||||||
|
defer func() {
|
||||||
|
if fi.IsDir() {
|
||||||
|
parentDirs = append(parentDirs, dir)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if skip {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dir.calledFn = true
|
||||||
|
|
||||||
stat, err := mkstat(origpath, path, fi, seenFiles)
|
stat, err := mkstat(origpath, path, fi, seenFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -185,6 +195,31 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for i, parentDir := range parentDirs {
|
||||||
|
if parentDir.calledFn {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parentStat, err := mkstat(parentDir.origpath, parentDir.path, parentDir.fi, seenFiles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if opt != nil && opt.Map != nil {
|
||||||
|
if allowed := opt.Map(parentStat.Path, parentStat); !allowed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := fn(parentStat.Path, &StatInfo{parentStat}, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
parentDirs[i].calledFn = true
|
||||||
|
}
|
||||||
if err := fn(stat.Path, &StatInfo{stat}, nil); err != nil {
|
if err := fn(stat.Path, &StatInfo{stat}, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
16
vendor/modules.txt
vendored
16
vendor/modules.txt
vendored
@@ -30,7 +30,7 @@ github.com/cenkalti/backoff/v4
|
|||||||
github.com/cespare/xxhash/v2
|
github.com/cespare/xxhash/v2
|
||||||
# github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e
|
# github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e
|
||||||
## explicit
|
## explicit
|
||||||
# github.com/compose-spec/compose-go v0.0.0-20210729195839-de56f4f0cb3c
|
# github.com/compose-spec/compose-go v1.0.5
|
||||||
## explicit
|
## explicit
|
||||||
github.com/compose-spec/compose-go/errdefs
|
github.com/compose-spec/compose-go/errdefs
|
||||||
github.com/compose-spec/compose-go/interpolation
|
github.com/compose-spec/compose-go/interpolation
|
||||||
@@ -38,6 +38,8 @@ github.com/compose-spec/compose-go/loader
|
|||||||
github.com/compose-spec/compose-go/schema
|
github.com/compose-spec/compose-go/schema
|
||||||
github.com/compose-spec/compose-go/template
|
github.com/compose-spec/compose-go/template
|
||||||
github.com/compose-spec/compose-go/types
|
github.com/compose-spec/compose-go/types
|
||||||
|
# github.com/compose-spec/godotenv v1.1.0
|
||||||
|
github.com/compose-spec/godotenv
|
||||||
# github.com/containerd/console v1.0.3
|
# github.com/containerd/console v1.0.3
|
||||||
## explicit
|
## explicit
|
||||||
github.com/containerd/console
|
github.com/containerd/console
|
||||||
@@ -124,7 +126,7 @@ github.com/docker/distribution/registry/client/transport
|
|||||||
github.com/docker/distribution/registry/storage/cache
|
github.com/docker/distribution/registry/storage/cache
|
||||||
github.com/docker/distribution/registry/storage/cache/memory
|
github.com/docker/distribution/registry/storage/cache/memory
|
||||||
github.com/docker/distribution/uuid
|
github.com/docker/distribution/uuid
|
||||||
# github.com/docker/docker v20.10.7+incompatible => github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible
|
# github.com/docker/docker v20.10.7+incompatible => github.com/tonistiigi/docker v0.10.1-0.20211122204227-65a6f25dbca2
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/docker/api
|
github.com/docker/docker/api
|
||||||
github.com/docker/docker/api/types
|
github.com/docker/docker/api/types
|
||||||
@@ -263,8 +265,6 @@ github.com/inconshreveable/mousetrap
|
|||||||
## explicit
|
## explicit
|
||||||
# github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a
|
# github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a
|
||||||
## explicit
|
## explicit
|
||||||
# github.com/joho/godotenv v1.3.0
|
|
||||||
github.com/joho/godotenv
|
|
||||||
# github.com/json-iterator/go v1.1.11
|
# github.com/json-iterator/go v1.1.11
|
||||||
github.com/json-iterator/go
|
github.com/json-iterator/go
|
||||||
# github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
# github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
||||||
@@ -284,7 +284,7 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
|
|||||||
github.com/miekg/pkcs11
|
github.com/miekg/pkcs11
|
||||||
# github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
|
# github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
|
||||||
github.com/mitchellh/go-wordwrap
|
github.com/mitchellh/go-wordwrap
|
||||||
# github.com/mitchellh/mapstructure v1.4.1
|
# github.com/mitchellh/mapstructure v1.4.2
|
||||||
github.com/mitchellh/mapstructure
|
github.com/mitchellh/mapstructure
|
||||||
# github.com/moby/buildkit v0.9.1-0.20211019185819-8778943ac3da
|
# github.com/moby/buildkit v0.9.1-0.20211019185819-8778943ac3da
|
||||||
## explicit
|
## explicit
|
||||||
@@ -416,9 +416,8 @@ github.com/theupdateframework/notary/tuf/data
|
|||||||
github.com/theupdateframework/notary/tuf/signed
|
github.com/theupdateframework/notary/tuf/signed
|
||||||
github.com/theupdateframework/notary/tuf/utils
|
github.com/theupdateframework/notary/tuf/utils
|
||||||
github.com/theupdateframework/notary/tuf/validation
|
github.com/theupdateframework/notary/tuf/validation
|
||||||
# github.com/tonistiigi/fsutil v0.0.0-20210818161904-4442383b5028
|
# github.com/tonistiigi/fsutil v0.0.0-20210818161904-4442383b5028 => github.com/tonistiigi/fsutil v0.0.0-20211122210416-da5201e0b3af
|
||||||
github.com/tonistiigi/fsutil
|
github.com/tonistiigi/fsutil
|
||||||
github.com/tonistiigi/fsutil/prefix
|
|
||||||
github.com/tonistiigi/fsutil/types
|
github.com/tonistiigi/fsutil/types
|
||||||
# github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
|
# github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
|
||||||
## explicit
|
## explicit
|
||||||
@@ -872,7 +871,8 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
|||||||
# sigs.k8s.io/yaml v1.2.0
|
# sigs.k8s.io/yaml v1.2.0
|
||||||
sigs.k8s.io/yaml
|
sigs.k8s.io/yaml
|
||||||
# github.com/docker/cli => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
|
# github.com/docker/cli => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
|
||||||
# github.com/docker/docker => github.com/docker/docker v20.10.3-0.20210817025855-ba2adeebdb8d+incompatible
|
# github.com/docker/docker => github.com/tonistiigi/docker v0.10.1-0.20211122204227-65a6f25dbca2
|
||||||
|
# github.com/tonistiigi/fsutil => github.com/tonistiigi/fsutil v0.0.0-20211122210416-da5201e0b3af
|
||||||
# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939
|
# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939
|
||||||
# go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939
|
# go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939
|
||||||
# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939
|
# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939
|
||||||
|
Reference in New Issue
Block a user