Merge pull request #3120 from drone/feature/yaml-templates
Feature/ add yaml templates
This commit is contained in:
commit
730f7596d5
7 changed files with 145 additions and 25 deletions
1
go.mod
1
go.mod
|
@ -18,6 +18,7 @@ require (
|
||||||
github.com/drone/drone-ui v2.0.1+incompatible
|
github.com/drone/drone-ui v2.0.1+incompatible
|
||||||
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4
|
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4
|
||||||
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629
|
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629
|
||||||
|
github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056 // indirect
|
||||||
github.com/drone/go-license v1.0.2
|
github.com/drone/go-license v1.0.2
|
||||||
github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2
|
github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2
|
||||||
github.com/drone/go-scm v1.15.2
|
github.com/drone/go-scm v1.15.2
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -86,6 +86,10 @@ github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4 h1:XsstoCeXC2t8
|
||||||
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
|
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
|
||||||
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw=
|
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw=
|
||||||
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||||
|
github.com/drone/funcmap v0.0.0-20190918184546-d4ef6e88376d h1:/IO7UVVu191Jc0DajV4cDVoO+91cuppvgxg2MZl+AXI=
|
||||||
|
github.com/drone/funcmap v0.0.0-20190918184546-d4ef6e88376d/go.mod h1:Hph0/pT6ZxbujnE1Z6/08p5I0XXuOsppqF6NQlGOK0E=
|
||||||
|
github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056 h1:SCJwMR0FMA0aKwAntCBh02YmtHEnU40zaDzeeCvIRug=
|
||||||
|
github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056/go.mod h1:Hph0/pT6ZxbujnE1Z6/08p5I0XXuOsppqF6NQlGOK0E=
|
||||||
github.com/drone/go-license v1.0.2 h1:7OwndfYk+Lp/cGHkxe4HUn/Ysrrw3WYH2pnd99yrkok=
|
github.com/drone/go-license v1.0.2 h1:7OwndfYk+Lp/cGHkxe4HUn/Ysrrw3WYH2pnd99yrkok=
|
||||||
github.com/drone/go-license v1.0.2/go.mod h1:fGRHf+F1cEaw3YVYiJ6js3G3dVhcxyS617RnNRUMsms=
|
github.com/drone/go-license v1.0.2/go.mod h1:fGRHf+F1cEaw3YVYiJ6js3G3dVhcxyS617RnNRUMsms=
|
||||||
github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2 h1:RGpgNkowJc5LAVn/ZONx70qmnaTA0z/3hHPzTBdAEO8=
|
github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2 h1:RGpgNkowJc5LAVn/ZONx70qmnaTA0z/3hHPzTBdAEO8=
|
||||||
|
|
|
@ -17,22 +17,26 @@
|
||||||
package converter
|
package converter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
templating "text/template"
|
||||||
|
|
||||||
"github.com/drone/drone/core"
|
"github.com/drone/drone/core"
|
||||||
"github.com/drone/drone/plugin/converter/jsonnet"
|
"github.com/drone/drone/plugin/converter/jsonnet"
|
||||||
"github.com/drone/drone/plugin/converter/starlark"
|
"github.com/drone/drone/plugin/converter/starlark"
|
||||||
|
"github.com/drone/funcmap"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// templateFileRE regex to verifying kind is template.
|
// TemplateFileRE regex to verifying kind is template.
|
||||||
templateFileRE = regexp.MustCompile("^kind:\\s+template+\\n")
|
TemplateFileRE = regexp.MustCompile("^kind:\\s+template+\\n")
|
||||||
ErrTemplateNotFound = errors.New("template converter: template name given not found")
|
ErrTemplateNotFound = errors.New("template converter: template name given not found")
|
||||||
ErrTemplateSyntaxErrors = errors.New("template converter: there is a problem with the yaml file provided")
|
ErrTemplateSyntaxErrors = errors.New("template converter: there is a problem with the yaml file provided")
|
||||||
)
|
)
|
||||||
|
@ -52,8 +56,9 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
if strings.HasSuffix(req.Repo.Config, ".yml") == false {
|
if strings.HasSuffix(req.Repo.Config, ".yml") == false {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// check kind is template
|
// check kind is template
|
||||||
if templateFileRE.MatchString(req.Config.Data) == false {
|
if TemplateFileRE.MatchString(req.Config.Data) == false {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
// map to templateArgs
|
// map to templateArgs
|
||||||
|
@ -71,21 +76,40 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if file is of type Starlark
|
switch filepath.Ext(templateArgs.Load) {
|
||||||
if strings.HasSuffix(templateArgs.Load, ".script") ||
|
case ".yml", ".yaml":
|
||||||
strings.HasSuffix(templateArgs.Load, ".star") ||
|
return parseYaml(req, template, templateArgs)
|
||||||
strings.HasSuffix(templateArgs.Load, ".starlark") {
|
case ".star", ".starlark", ".script":
|
||||||
|
return parseStarlark(req, template, templateArgs)
|
||||||
|
case ".jsonnet":
|
||||||
|
return parseJsonnet(req, template, templateArgs)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
file, err := starlark.Parse(req, template, templateArgs.Data)
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseYaml(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs) (*core.Config, error) {
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"build": toBuild(req.Build),
|
||||||
|
"repo": toRepo(req.Repo),
|
||||||
|
"input": templateArgs.Data,
|
||||||
|
}
|
||||||
|
tmpl, err := templating.New(template.Name).Funcs(funcmap.SafeFuncs).Parse(template.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out bytes.Buffer
|
||||||
|
err = tmpl.Execute(&out, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &core.Config{
|
return &core.Config{
|
||||||
Data: file,
|
Data: out.String(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
// Check if the file is of type Jsonnet
|
|
||||||
if strings.HasSuffix(templateArgs.Load, ".jsonnet") {
|
func parseJsonnet(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs) (*core.Config, error) {
|
||||||
file, err := jsonnet.Parse(req, template, templateArgs.Data)
|
file, err := jsonnet.Parse(req, template, templateArgs.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -95,5 +119,12 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
func parseStarlark(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs) (*core.Config, error) {
|
||||||
|
file, err := starlark.Parse(req, template, templateArgs.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &core.Config{
|
||||||
|
Data: file,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,3 +326,65 @@ func TestTemplateNestedValuesPluginConvertStarlark(t *testing.T) {
|
||||||
t.Errorf("Want %q got %q", want, got)
|
t.Errorf("Want %q got %q", want, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplatePluginConvertYaml(t *testing.T) {
|
||||||
|
templateArgs, err := ioutil.ReadFile("testdata/yaml.template.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &core.ConvertArgs{
|
||||||
|
Build: &core.Build{
|
||||||
|
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
|
||||||
|
},
|
||||||
|
Repo: &core.Repository{
|
||||||
|
Slug: "octocat/hello-world",
|
||||||
|
Config: ".drone.yml",
|
||||||
|
Namespace: "octocat",
|
||||||
|
},
|
||||||
|
Config: &core.Config{
|
||||||
|
Data: string(templateArgs),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeInput, err := ioutil.ReadFile("testdata/yaml.input.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
after, err := ioutil.ReadFile("testdata/yaml.input.golden")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
template := &core.Template{
|
||||||
|
Name: "plugin.yaml",
|
||||||
|
Data: string(beforeInput),
|
||||||
|
Namespace: "octocat",
|
||||||
|
}
|
||||||
|
|
||||||
|
controller := gomock.NewController(t)
|
||||||
|
defer controller.Finish()
|
||||||
|
|
||||||
|
templates := mock.NewMockTemplateStore(controller)
|
||||||
|
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
|
||||||
|
|
||||||
|
plugin := Template(templates)
|
||||||
|
config, err := plugin.Convert(noContext, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if config == nil {
|
||||||
|
t.Error("Want non-nil configuration")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if want, got := config.Data, string(after); want != got {
|
||||||
|
t.Errorf("Want %q got %q", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
8
plugin/converter/testdata/yaml.input.golden
vendored
Normal file
8
plugin/converter/testdata/yaml.input.golden
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: defaults
|
||||||
|
steps:
|
||||||
|
- name: MY_STEP
|
||||||
|
image: my_image
|
||||||
|
commands:
|
||||||
|
- my_command
|
8
plugin/converter/testdata/yaml.input.yml
vendored
Normal file
8
plugin/converter/testdata/yaml.input.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: defaults
|
||||||
|
steps:
|
||||||
|
- name: {{ upper .input.stepName }}
|
||||||
|
image: {{ .input.image }}
|
||||||
|
commands:
|
||||||
|
- {{ .input.commands }}
|
6
plugin/converter/testdata/yaml.template.yml
vendored
Normal file
6
plugin/converter/testdata/yaml.template.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
kind: template
|
||||||
|
load: plugin.yaml
|
||||||
|
data:
|
||||||
|
stepName: my_step
|
||||||
|
image: my_image
|
||||||
|
commands: my_command
|
Loading…
Reference in a new issue