diff --git a/cmd/drone-server/config/config.go b/cmd/drone-server/config/config.go index 94f52ad4..ab9fb920 100644 --- a/cmd/drone-server/config/config.go +++ b/cmd/drone-server/config/config.go @@ -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 diff --git a/cmd/drone-server/inject_plugin.go b/cmd/drone-server/inject_plugin.go index f982a622..a19eb050 100644 --- a/cmd/drone-server/inject_plugin.go +++ b/cmd/drone-server/inject_plugin.go @@ -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( diff --git a/plugin/converter/starlark.go b/plugin/converter/starlark.go index b5283ac3..8238a950 100644 --- a/plugin/converter/starlark.go +++ b/plugin/converter/starlark.go @@ -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 } diff --git a/plugin/converter/starlark/starlark.go b/plugin/converter/starlark/starlark.go index b15a99d2..3ad3239b 100644 --- a/plugin/converter/starlark/starlark.go +++ b/plugin/converter/starlark/starlark.go @@ -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) diff --git a/plugin/converter/starlark/starlark_test.go b/plugin/converter/starlark/starlark_test.go index 8ba84d77..6700fdd5 100644 --- a/plugin/converter/starlark/starlark_test.go +++ b/plugin/converter/starlark/starlark_test.go @@ -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 diff --git a/plugin/converter/starlark_test.go b/plugin/converter/starlark_test.go index 97310b9f..2846ac63 100644 --- a/plugin/converter/starlark_test.go +++ b/plugin/converter/starlark_test.go @@ -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) diff --git a/plugin/converter/template.go b/plugin/converter/template.go index aa72a82d..c89249cf 100644 --- a/plugin/converter/template.go +++ b/plugin/converter/template.go @@ -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 } diff --git a/plugin/converter/template_test.go b/plugin/converter/template_test.go index 820522ec..61f03764 100644 --- a/plugin/converter/template_test.go +++ b/plugin/converter/template_test.go @@ -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") } -} \ No newline at end of file +}