Make starlark step limit configurable (#3134)

Define environment variable DRONE_STARLARK_STEP_LIMIT to some number to
override the default value.
This commit is contained in:
Phil Davis 2021-09-03 16:20:44 +05:45 committed by GitHub
parent 4ea914d779
commit 8c24225240
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 33 additions and 23 deletions

View file

@ -145,6 +145,7 @@ type (
// Starlark configures the starlark plugin
Starlark struct {
Enabled bool `envconfig:"DRONE_STARLARK_ENABLED"`
StepLimit uint64 `envconfig:"DRONE_STARLARK_STEP_LIMIT"`
}
// License provides license configuration

View file

@ -81,12 +81,14 @@ func provideConvertPlugin(client *scm.Client, conf spec.Config, templateStore co
converter.Legacy(false),
converter.Starlark(
conf.Starlark.Enabled,
conf.Starlark.StepLimit,
),
converter.Jsonnet(
conf.Jsonnet.Enabled,
),
converter.Template(
templateStore,
conf.Starlark.StepLimit,
),
converter.Memoize(
converter.Remote(

View file

@ -26,14 +26,16 @@ import (
// Starlark returns a conversion service that converts the
// starlark file to a yaml file.
func Starlark(enabled bool) core.ConvertService {
func Starlark(enabled bool, stepLimit uint64) core.ConvertService {
return &starlarkPlugin{
enabled: enabled,
stepLimit: stepLimit,
}
}
type starlarkPlugin struct {
enabled bool
stepLimit uint64
}
func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
@ -51,7 +53,7 @@ func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
return nil, nil
}
file, err := starlark.Parse(req, nil, nil)
file, err := starlark.Parse(req, nil, nil, p.stepLimit)
if err != nil {
return nil, err
}

View file

@ -54,7 +54,7 @@ var (
ErrCannotLoad = errors.New("starlark: cannot load external scripts")
)
func Parse(req *core.ConvertArgs, template *core.Template, templateData map[string]interface{}) (string, error) {
func Parse(req *core.ConvertArgs, template *core.Template, templateData map[string]interface{}, stepLimit uint64) (string, error) {
thread := &starlark.Thread{
Name: "drone",
Load: noLoad,
@ -101,7 +101,10 @@ func Parse(req *core.ConvertArgs, template *core.Template, templateData map[stri
// set the maximum number of operations in the script. this
// mitigates long running scripts.
thread.SetMaxExecutionSteps(50000)
if stepLimit == 0 {
stepLimit = 50000
}
thread.SetMaxExecutionSteps(stepLimit)
// execute the main method in the script.
mainVal, err = starlark.Call(thread, main, args, nil)

View file

@ -57,7 +57,7 @@ func TestParseStarlark(t *testing.T) {
req.Config.Data = string(before)
parsedFile, err := Parse(req, template, templateData)
parsedFile, err := Parse(req, template, templateData, 0)
if err != nil {
t.Error(err)
return
@ -95,7 +95,7 @@ func TestParseStarlarkNotTemplateFile(t *testing.T) {
req.Repo.Config = "plugin.starlark.star"
req.Config.Data = string(before)
parsedFile, err := Parse(req, nil, nil)
parsedFile, err := Parse(req, nil, nil, 0)
if err != nil {
t.Error(err)
return

View file

@ -22,7 +22,7 @@ import (
)
func TestStarlarkConvert(t *testing.T) {
plugin := Starlark(true)
plugin := Starlark(true, 0)
req := &core.ConvertArgs{
Build: &core.Build{
@ -100,7 +100,7 @@ func TestConvert_Multi(t *testing.T) {
},
}
plugin := Starlark(true)
plugin := Starlark(true, 0)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)
@ -125,7 +125,7 @@ func TestConvert_Multi(t *testing.T) {
// this test verifies the plugin is skipped when it has
// not been explicitly enabled.
func TestConvert_Skip(t *testing.T) {
plugin := Starlark(false)
plugin := Starlark(false, 0)
config, err := plugin.Convert(noContext, nil)
if err != nil {
t.Error(err)
@ -145,7 +145,7 @@ func TestConvert_SkipYaml(t *testing.T) {
},
}
plugin := Starlark(true)
plugin := Starlark(true, 0)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)

View file

@ -42,14 +42,16 @@ var (
errTemplateExtensionInvalid = errors.New("template extension invalid. must be yaml, starlark or jsonnet")
)
func Template(templateStore core.TemplateStore) core.ConvertService {
func Template(templateStore core.TemplateStore, stepLimit uint64) core.ConvertService {
return &templatePlugin{
templateStore: templateStore,
stepLimit: stepLimit,
}
}
type templatePlugin struct {
templateStore core.TemplateStore
stepLimit uint64
}
func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
@ -81,7 +83,7 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
case ".yml", ".yaml":
return parseYaml(req, template, templateArgs)
case ".star", ".starlark", ".script":
return parseStarlark(req, template, templateArgs)
return parseStarlark(req, template, templateArgs, p.stepLimit)
case ".jsonnet":
return parseJsonnet(req, template, templateArgs)
default:
@ -119,8 +121,8 @@ func parseJsonnet(req *core.ConvertArgs, template *core.Template, templateArgs c
}, nil
}
func parseStarlark(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs) (*core.Config, error) {
file, err := starlark.Parse(req, template, templateArgs.Data)
func parseStarlark(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs, stepLimit uint64) (*core.Config, error) {
file, err := starlark.Parse(req, template, templateArgs.Data, stepLimit)
if err != nil {
return nil, err
}

View file

@ -70,7 +70,7 @@ func TestTemplatePluginConvertStarlark(t *testing.T) {
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
plugin := Template(templates)
plugin := Template(templates, 0)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)
@ -89,7 +89,7 @@ func TestTemplatePluginConvertStarlark(t *testing.T) {
func TestTemplatePluginConvertNotYamlFile(t *testing.T) {
plugin := Template(nil)
plugin := Template(nil, 0)
req := &core.ConvertArgs{
Build: &core.Build{
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
@ -117,7 +117,7 @@ func TestTemplatePluginConvertDroneFileTypePipeline(t *testing.T) {
t.Error(err)
return
}
plugin := Template(nil)
plugin := Template(nil, 0)
req := &core.ConvertArgs{
Build: &core.Build{
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
@ -169,7 +169,7 @@ func TestTemplatePluginConvertTemplateNotFound(t *testing.T) {
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(nil, nil)
plugin := Template(templates)
plugin := Template(templates, 0)
config, err := plugin.Convert(noContext, req)
if config != nil {
@ -222,7 +222,7 @@ func TestTemplatePluginConvertJsonnet(t *testing.T) {
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
plugin := Template(templates)
plugin := Template(templates, 0)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)
@ -294,7 +294,7 @@ func TestTemplateNestedValuesPluginConvertStarlark(t *testing.T) {
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
plugin := Template(templates)
plugin := Template(templates, 0)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)
@ -372,7 +372,7 @@ func TestTemplatePluginConvertYaml(t *testing.T) {
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
plugin := Template(templates)
plugin := Template(templates, 0)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)
@ -430,9 +430,9 @@ func TestTemplatePluginConvertInvalidTemplateExtension(t *testing.T) {
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
plugin := Template(templates)
plugin := Template(templates, 0)
config, err := plugin.Convert(noContext, req)
if config != nil {
t.Errorf("template extension invalid. must be yaml, starlark or jsonnet")
}
}
}