Add support for glob syntax when checking volumes (#64)
Follow #60 Reviewed-on: https://gitea.com/gitea/act/pulls/64 Reviewed-by: Jason Song <i@wolfogre.com> Co-authored-by: Zettat123 <zettat123@gmail.com> Co-committed-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
parent
56e103b4ba
commit
a165e17878
1
go.mod
1
go.mod
@ -14,6 +14,7 @@ require (
|
|||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/go-git/go-billy/v5 v5.4.1
|
github.com/go-git/go-billy/v5 v5.4.1
|
||||||
github.com/go-git/go-git/v5 v5.7.0
|
github.com/go-git/go-git/v5 v5.7.0
|
||||||
|
github.com/gobwas/glob v0.2.3
|
||||||
github.com/imdario/mergo v0.3.15
|
github.com/imdario/mergo v0.3.15
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
|
2
go.sum
2
go.sum
@ -68,6 +68,8 @@ github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw4
|
|||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
|
||||||
github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE=
|
github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE=
|
||||||
github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
|
github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
|
||||||
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
networktypes "github.com/docker/docker/api/types/network"
|
networktypes "github.com/docker/docker/api/types/network"
|
||||||
|
"github.com/gobwas/glob"
|
||||||
|
|
||||||
"github.com/go-git/go-billy/v5/helper/polyfill"
|
"github.com/go-git/go-billy/v5/helper/polyfill"
|
||||||
"github.com/go-git/go-billy/v5/osfs"
|
"github.com/go-git/go-billy/v5/osfs"
|
||||||
@ -883,13 +884,27 @@ func (cr *containerReference) wait() common.Executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For Gitea
|
||||||
|
// sanitizeConfig remove the invalid configurations from `config` and `hostConfig`
|
||||||
func (cr *containerReference) sanitizeConfig(ctx context.Context, config *container.Config, hostConfig *container.HostConfig) (*container.Config, *container.HostConfig) {
|
func (cr *containerReference) sanitizeConfig(ctx context.Context, config *container.Config, hostConfig *container.HostConfig) (*container.Config, *container.HostConfig) {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
|
|
||||||
if len(cr.input.ValidVolumes) > 0 {
|
if len(cr.input.ValidVolumes) > 0 {
|
||||||
vv := make(map[string]struct{}, len(cr.input.ValidVolumes))
|
globs := make([]glob.Glob, 0, len(cr.input.ValidVolumes))
|
||||||
for _, volume := range cr.input.ValidVolumes {
|
for _, v := range cr.input.ValidVolumes {
|
||||||
vv[volume] = struct{}{}
|
if g, err := glob.Compile(v); err != nil {
|
||||||
|
logger.Errorf("create glob from %s error: %v", v, err)
|
||||||
|
} else {
|
||||||
|
globs = append(globs, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isValid := func(v string) bool {
|
||||||
|
for _, g := range globs {
|
||||||
|
if g.Match(v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
// sanitize binds
|
// sanitize binds
|
||||||
sanitizedBinds := make([]string, 0, len(hostConfig.Binds))
|
sanitizedBinds := make([]string, 0, len(hostConfig.Binds))
|
||||||
@ -904,23 +919,26 @@ func (cr *containerReference) sanitizeConfig(ctx context.Context, config *contai
|
|||||||
sanitizedBinds = append(sanitizedBinds, bind)
|
sanitizedBinds = append(sanitizedBinds, bind)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := vv[parsed.Source]; ok {
|
if isValid(parsed.Source) {
|
||||||
sanitizedBinds = append(sanitizedBinds, bind)
|
sanitizedBinds = append(sanitizedBinds, bind)
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("[%s] is not a valid volume, will be ignored", bind)
|
logger.Warnf("[%s] is not a valid volume, will be ignored", parsed.Source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hostConfig.Binds = sanitizedBinds
|
hostConfig.Binds = sanitizedBinds
|
||||||
// sanitize mounts
|
// sanitize mounts
|
||||||
sanitizedMounts := make([]mount.Mount, 0, len(hostConfig.Mounts))
|
sanitizedMounts := make([]mount.Mount, 0, len(hostConfig.Mounts))
|
||||||
for _, mt := range hostConfig.Mounts {
|
for _, mt := range hostConfig.Mounts {
|
||||||
if _, ok := vv[mt.Source]; ok {
|
if isValid(mt.Source) {
|
||||||
sanitizedMounts = append(sanitizedMounts, mt)
|
sanitizedMounts = append(sanitizedMounts, mt)
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("[%s] is not a valid volume, will be ignored", mt.Source)
|
logger.Warnf("[%s] is not a valid volume, will be ignored", mt.Source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hostConfig.Mounts = sanitizedMounts
|
hostConfig.Mounts = sanitizedMounts
|
||||||
|
} else {
|
||||||
|
hostConfig.Binds = []string{}
|
||||||
|
hostConfig.Mounts = []mount.Mount{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return config, hostConfig
|
return config, hostConfig
|
||||||
|
@ -9,8 +9,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/nektos/act/pkg/common"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/sirupsen/logrus/hooks/test"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
@ -166,3 +170,76 @@ func TestDockerExecFailure(t *testing.T) {
|
|||||||
|
|
||||||
// Type assert containerReference implements ExecutionsEnvironment
|
// Type assert containerReference implements ExecutionsEnvironment
|
||||||
var _ ExecutionsEnvironment = &containerReference{}
|
var _ ExecutionsEnvironment = &containerReference{}
|
||||||
|
|
||||||
|
func TestCheckVolumes(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
validVolumes []string
|
||||||
|
binds []string
|
||||||
|
expectedBinds []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "match all volumes",
|
||||||
|
validVolumes: []string{"**"},
|
||||||
|
binds: []string{
|
||||||
|
"shared_volume:/shared_volume",
|
||||||
|
"/home/test/data:/test_data",
|
||||||
|
"/etc/conf.d/base.json:/config/base.json",
|
||||||
|
"sql_data:/sql_data",
|
||||||
|
"/secrets/keys:/keys",
|
||||||
|
},
|
||||||
|
expectedBinds: []string{
|
||||||
|
"shared_volume:/shared_volume",
|
||||||
|
"/home/test/data:/test_data",
|
||||||
|
"/etc/conf.d/base.json:/config/base.json",
|
||||||
|
"sql_data:/sql_data",
|
||||||
|
"/secrets/keys:/keys",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "no volumes can be matched",
|
||||||
|
validVolumes: []string{},
|
||||||
|
binds: []string{
|
||||||
|
"shared_volume:/shared_volume",
|
||||||
|
"/home/test/data:/test_data",
|
||||||
|
"/etc/conf.d/base.json:/config/base.json",
|
||||||
|
"sql_data:/sql_data",
|
||||||
|
"/secrets/keys:/keys",
|
||||||
|
},
|
||||||
|
expectedBinds: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "only allowed volumes can be matched",
|
||||||
|
validVolumes: []string{
|
||||||
|
"shared_volume",
|
||||||
|
"/home/test/data",
|
||||||
|
"/etc/conf.d/*.json",
|
||||||
|
},
|
||||||
|
binds: []string{
|
||||||
|
"shared_volume:/shared_volume",
|
||||||
|
"/home/test/data:/test_data",
|
||||||
|
"/etc/conf.d/base.json:/config/base.json",
|
||||||
|
"sql_data:/sql_data",
|
||||||
|
"/secrets/keys:/keys",
|
||||||
|
},
|
||||||
|
expectedBinds: []string{
|
||||||
|
"shared_volume:/shared_volume",
|
||||||
|
"/home/test/data:/test_data",
|
||||||
|
"/etc/conf.d/base.json:/config/base.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
logger, _ := test.NewNullLogger()
|
||||||
|
ctx := common.WithLogger(context.Background(), logger)
|
||||||
|
cr := &containerReference{
|
||||||
|
input: &NewContainerInput{
|
||||||
|
ValidVolumes: tc.validVolumes,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, hostConf := cr.sanitizeConfig(ctx, &container.Config{}, &container.HostConfig{Binds: tc.binds})
|
||||||
|
assert.Equal(t, tc.expectedBinds, hostConf.Binds)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user