mirror of https://github.com/harness/drone.git
Make starlark size limit configurable (#3291)
parent
326df61dfa
commit
7a8c7e1d24
|
@ -148,6 +148,7 @@ type (
|
||||||
Starlark struct {
|
Starlark struct {
|
||||||
Enabled bool `envconfig:"DRONE_STARLARK_ENABLED"`
|
Enabled bool `envconfig:"DRONE_STARLARK_ENABLED"`
|
||||||
StepLimit uint64 `envconfig:"DRONE_STARLARK_STEP_LIMIT"`
|
StepLimit uint64 `envconfig:"DRONE_STARLARK_STEP_LIMIT"`
|
||||||
|
SizeLimit uint64 `envconfig:"DRONE_STARLARK_SIZE_LIMIT" default:"0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// License provides license configuration
|
// License provides license configuration
|
||||||
|
|
|
@ -83,6 +83,7 @@ func provideConvertPlugin(client *scm.Client, fileService core.FileService, conf
|
||||||
converter.Starlark(
|
converter.Starlark(
|
||||||
conf.Starlark.Enabled,
|
conf.Starlark.Enabled,
|
||||||
conf.Starlark.StepLimit,
|
conf.Starlark.StepLimit,
|
||||||
|
conf.Starlark.SizeLimit,
|
||||||
),
|
),
|
||||||
converter.Jsonnet(
|
converter.Jsonnet(
|
||||||
conf.Jsonnet.Enabled,
|
conf.Jsonnet.Enabled,
|
||||||
|
@ -92,6 +93,7 @@ func provideConvertPlugin(client *scm.Client, fileService core.FileService, conf
|
||||||
converter.Template(
|
converter.Template(
|
||||||
templateStore,
|
templateStore,
|
||||||
conf.Starlark.StepLimit,
|
conf.Starlark.StepLimit,
|
||||||
|
conf.Starlark.SizeLimit,
|
||||||
),
|
),
|
||||||
converter.Memoize(
|
converter.Memoize(
|
||||||
converter.Remote(
|
converter.Remote(
|
||||||
|
|
|
@ -26,16 +26,18 @@ import (
|
||||||
|
|
||||||
// Starlark returns a conversion service that converts the
|
// Starlark returns a conversion service that converts the
|
||||||
// starlark file to a yaml file.
|
// starlark file to a yaml file.
|
||||||
func Starlark(enabled bool, stepLimit uint64) core.ConvertService {
|
func Starlark(enabled bool, stepLimit uint64, sizeLimit uint64) core.ConvertService {
|
||||||
return &starlarkPlugin{
|
return &starlarkPlugin{
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
stepLimit: stepLimit,
|
stepLimit: stepLimit,
|
||||||
|
sizeLimit: sizeLimit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type starlarkPlugin struct {
|
type starlarkPlugin struct {
|
||||||
enabled bool
|
enabled bool
|
||||||
stepLimit uint64
|
stepLimit uint64
|
||||||
|
sizeLimit uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||||
|
@ -53,7 +55,7 @@ func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := starlark.Parse(req, nil, nil, p.stepLimit)
|
file, err := starlark.Parse(req, nil, nil, p.stepLimit, p.sizeLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@ const (
|
||||||
newline = "\n"
|
newline = "\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// limits generated configuration file size.
|
// default limit for generated configuration file size.
|
||||||
const limit = 1000000
|
const defaultSizeLimit = 1000000
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrMainMissing indicates the starlark script is missing
|
// ErrMainMissing indicates the starlark script is missing
|
||||||
|
@ -54,7 +54,7 @@ var (
|
||||||
ErrCannotLoad = errors.New("starlark: cannot load external scripts")
|
ErrCannotLoad = errors.New("starlark: cannot load external scripts")
|
||||||
)
|
)
|
||||||
|
|
||||||
func Parse(req *core.ConvertArgs, template *core.Template, templateData map[string]interface{}, stepLimit uint64) (string, error) {
|
func Parse(req *core.ConvertArgs, template *core.Template, templateData map[string]interface{}, stepLimit uint64, sizeLimit uint64) (string, error) {
|
||||||
thread := &starlark.Thread{
|
thread := &starlark.Thread{
|
||||||
Name: "drone",
|
Name: "drone",
|
||||||
Load: noLoad,
|
Load: noLoad,
|
||||||
|
@ -132,9 +132,13 @@ func Parse(req *core.ConvertArgs, template *core.Template, templateData map[stri
|
||||||
return "", ErrMainReturn
|
return "", ErrMainReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sizeLimit == 0 {
|
||||||
|
sizeLimit = defaultSizeLimit
|
||||||
|
}
|
||||||
|
|
||||||
// this is a temporary workaround until we
|
// this is a temporary workaround until we
|
||||||
// implement a LimitWriter.
|
// implement a LimitWriter.
|
||||||
if b := buf.Bytes(); len(b) > limit {
|
if b := buf.Bytes(); uint64(len(b)) > sizeLimit {
|
||||||
return "", ErrMaximumSize
|
return "", ErrMaximumSize
|
||||||
}
|
}
|
||||||
return buf.String(), nil
|
return buf.String(), nil
|
||||||
|
|
|
@ -57,7 +57,7 @@ func TestParseStarlark(t *testing.T) {
|
||||||
|
|
||||||
req.Config.Data = string(before)
|
req.Config.Data = string(before)
|
||||||
|
|
||||||
parsedFile, err := Parse(req, template, templateData, 0)
|
parsedFile, err := Parse(req, template, templateData, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -95,7 +95,7 @@ func TestParseStarlarkNotTemplateFile(t *testing.T) {
|
||||||
req.Repo.Config = "plugin.starlark.star"
|
req.Repo.Config = "plugin.starlark.star"
|
||||||
req.Config.Data = string(before)
|
req.Config.Data = string(before)
|
||||||
|
|
||||||
parsedFile, err := Parse(req, nil, nil, 0)
|
parsedFile, err := Parse(req, nil, nil, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -18,6 +18,6 @@ package converter
|
||||||
|
|
||||||
import "github.com/drone/drone/core"
|
import "github.com/drone/drone/core"
|
||||||
|
|
||||||
func Starlark(enabled bool, stepLimit uint64) core.ConvertService {
|
func Starlark(enabled bool, stepLimit uint64, sizeLimit uint64) core.ConvertService {
|
||||||
return new(noop)
|
return new(noop)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStarlarkConvert(t *testing.T) {
|
func TestStarlarkConvert(t *testing.T) {
|
||||||
plugin := Starlark(true, 0)
|
plugin := Starlark(true, 0, 0)
|
||||||
|
|
||||||
req := &core.ConvertArgs{
|
req := &core.ConvertArgs{
|
||||||
Build: &core.Build{
|
Build: &core.Build{
|
||||||
|
@ -102,7 +102,7 @@ func TestConvert_Multi(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin := Starlark(true, 0)
|
plugin := Starlark(true, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -134,7 +134,7 @@ func TestConvert_Multi(t *testing.T) {
|
||||||
// this test verifies the plugin is skipped when it has
|
// this test verifies the plugin is skipped when it has
|
||||||
// not been explicitly enabled.
|
// not been explicitly enabled.
|
||||||
func TestConvert_Skip(t *testing.T) {
|
func TestConvert_Skip(t *testing.T) {
|
||||||
plugin := Starlark(false, 0)
|
plugin := Starlark(false, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, nil)
|
config, err := plugin.Convert(noContext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -154,7 +154,7 @@ func TestConvert_SkipYaml(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin := Starlark(true, 0)
|
plugin := Starlark(true, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -164,3 +164,35 @@ func TestConvert_SkipYaml(t *testing.T) {
|
||||||
t.Errorf("Expect nil config returned for non-starlark files")
|
t.Errorf("Expect nil config returned for non-starlark files")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this test verifies the plugin returns error
|
||||||
|
// if the generated file size is exceeded.
|
||||||
|
func TestConvert_SizeLimit(t *testing.T) {
|
||||||
|
smallFileSizeLimit := uint64(1)
|
||||||
|
plugin := Starlark(true, 0, smallFileSizeLimit)
|
||||||
|
|
||||||
|
req := &core.ConvertArgs{
|
||||||
|
Build: &core.Build{
|
||||||
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
},
|
||||||
|
Repo: &core.Repository{
|
||||||
|
Slug: "octocat/hello-world",
|
||||||
|
Config: ".drone.yml",
|
||||||
|
},
|
||||||
|
Config: &core.Config{},
|
||||||
|
}
|
||||||
|
|
||||||
|
before, err := ioutil.ReadFile("testdata/single.star")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Repo.Config = "single.star"
|
||||||
|
req.Config.Data = string(before)
|
||||||
|
_, expectedError := plugin.Convert(noContext, req)
|
||||||
|
if expectedError == nil {
|
||||||
|
t.Error("Expected 'starlark: maximum file size exceeded' error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,16 +41,18 @@ var (
|
||||||
errTemplateExtensionInvalid = errors.New("template extension invalid. must be yaml, starlark or jsonnet")
|
errTemplateExtensionInvalid = errors.New("template extension invalid. must be yaml, starlark or jsonnet")
|
||||||
)
|
)
|
||||||
|
|
||||||
func Template(templateStore core.TemplateStore, stepLimit uint64) core.ConvertService {
|
func Template(templateStore core.TemplateStore, stepLimit uint64, sizeLimit uint64) core.ConvertService {
|
||||||
return &templatePlugin{
|
return &templatePlugin{
|
||||||
templateStore: templateStore,
|
templateStore: templateStore,
|
||||||
stepLimit: stepLimit,
|
stepLimit: stepLimit,
|
||||||
|
sizeLimit: sizeLimit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type templatePlugin struct {
|
type templatePlugin struct {
|
||||||
templateStore core.TemplateStore
|
templateStore core.TemplateStore
|
||||||
stepLimit uint64
|
stepLimit uint64
|
||||||
|
sizeLimit uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||||
|
@ -84,7 +86,7 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
case ".yml", ".yaml":
|
case ".yml", ".yaml":
|
||||||
return parseYaml(req, template, templateArgs)
|
return parseYaml(req, template, templateArgs)
|
||||||
case ".star", ".starlark", ".script":
|
case ".star", ".starlark", ".script":
|
||||||
return parseStarlark(req, template, templateArgs, p.stepLimit)
|
return parseStarlark(req, template, templateArgs, p.stepLimit, p.sizeLimit)
|
||||||
case ".jsonnet":
|
case ".jsonnet":
|
||||||
return parseJsonnet(req, template, templateArgs)
|
return parseJsonnet(req, template, templateArgs)
|
||||||
default:
|
default:
|
||||||
|
@ -122,8 +124,8 @@ func parseJsonnet(req *core.ConvertArgs, template *core.Template, templateArgs c
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStarlark(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs, stepLimit uint64) (*core.Config, error) {
|
func parseStarlark(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs, stepLimit uint64, sizeLimit uint64) (*core.Config, error) {
|
||||||
file, err := starlark.Parse(req, template, templateArgs.Data, stepLimit)
|
file, err := starlark.Parse(req, template, templateArgs.Data, stepLimit, sizeLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Template(templateStore core.TemplateStore, stepLimit uint64) core.ConvertService {
|
func Template(templateStore core.TemplateStore, stepLimit uint64, sizeLimit uint64) core.ConvertService {
|
||||||
return &templatePlugin{
|
return &templatePlugin{
|
||||||
templateStore: templateStore,
|
templateStore: templateStore,
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ func TestTemplatePluginConvertStarlark(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -92,7 +92,7 @@ func TestTemplatePluginConvertStarlark(t *testing.T) {
|
||||||
|
|
||||||
func TestTemplatePluginConvertNotYamlFile(t *testing.T) {
|
func TestTemplatePluginConvertNotYamlFile(t *testing.T) {
|
||||||
|
|
||||||
plugin := Template(nil, 0)
|
plugin := Template(nil, 0, 0)
|
||||||
req := &core.ConvertArgs{
|
req := &core.ConvertArgs{
|
||||||
Build: &core.Build{
|
Build: &core.Build{
|
||||||
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
@ -120,7 +120,7 @@ func TestTemplatePluginConvertDroneFileTypePipeline(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
plugin := Template(nil, 0)
|
plugin := Template(nil, 0, 0)
|
||||||
req := &core.ConvertArgs{
|
req := &core.ConvertArgs{
|
||||||
Build: &core.Build{
|
Build: &core.Build{
|
||||||
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
@ -161,7 +161,7 @@ func TestTemplatePluginConvertDroneFileYamlExtensions(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, dummyErr)
|
templates.EXPECT().FindName(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, dummyErr)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
req := &core.ConvertArgs{
|
req := &core.ConvertArgs{
|
||||||
Build: &core.Build{
|
Build: &core.Build{
|
||||||
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
@ -214,7 +214,7 @@ func TestTemplatePluginConvertTemplateNotFound(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(nil, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(nil, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
|
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if config != nil {
|
if config != nil {
|
||||||
|
@ -267,7 +267,7 @@ func TestTemplatePluginConvertJsonnet(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -346,7 +346,7 @@ func TestTemplateNestedValuesPluginConvertStarlark(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -424,7 +424,7 @@ func TestTemplatePluginConvertYaml(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -483,7 +483,7 @@ func TestTemplatePluginConvertInvalidTemplateExtension(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if config != nil {
|
if config != nil {
|
||||||
t.Errorf("template extension invalid. must be yaml, starlark or jsonnet")
|
t.Errorf("template extension invalid. must be yaml, starlark or jsonnet")
|
||||||
|
@ -535,7 +535,7 @@ func TestTemplatePluginConvertYamlWithComment(t *testing.T) {
|
||||||
templates := mock.NewMockTemplateStore(controller)
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
plugin := Template(templates, 0)
|
plugin := Template(templates, 0, 0)
|
||||||
config, err := plugin.Convert(noContext, req)
|
config, err := plugin.Convert(noContext, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|
Loading…
Reference in New Issue