132 lines
3.7 KiB
Go
132 lines
3.7 KiB
Go
// Copyright 2019 Drone IO, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// +build !oss
|
|
|
|
package converter
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
templating "text/template"
|
|
|
|
"github.com/drone/drone/core"
|
|
"github.com/drone/drone/plugin/converter/jsonnet"
|
|
"github.com/drone/drone/plugin/converter/starlark"
|
|
"github.com/drone/funcmap"
|
|
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
var (
|
|
// templateFileRE regex to verifying kind is template.
|
|
templateFileRE = regexp.MustCompilePOSIX("^kind:[[:space:]]+template[[:space:]]?+$")
|
|
errTemplateNotFound = errors.New("template converter: template name given not found")
|
|
errTemplateSyntaxErrors = errors.New("template converter: there is a problem with the yaml file provided")
|
|
errTemplateExtensionInvalid = errors.New("template extension invalid. must be yaml, starlark or jsonnet")
|
|
)
|
|
|
|
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) {
|
|
// check type is yaml
|
|
if strings.HasSuffix(req.Repo.Config, ".yml") == false {
|
|
return nil, nil
|
|
}
|
|
|
|
// check kind is template
|
|
if templateFileRE.MatchString(req.Config.Data) == false {
|
|
return nil, nil
|
|
}
|
|
// map to templateArgs
|
|
var templateArgs core.TemplateArgs
|
|
err := yaml.Unmarshal([]byte(req.Config.Data), &templateArgs)
|
|
if err != nil {
|
|
return nil, errTemplateSyntaxErrors
|
|
}
|
|
// get template from db
|
|
template, err := p.templateStore.FindName(ctx, templateArgs.Load, req.Repo.Namespace)
|
|
if err == sql.ErrNoRows {
|
|
return nil, errTemplateNotFound
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch filepath.Ext(templateArgs.Load) {
|
|
case ".yml", ".yaml":
|
|
return parseYaml(req, template, templateArgs)
|
|
case ".star", ".starlark", ".script":
|
|
return parseStarlark(req, template, templateArgs, p.stepLimit)
|
|
case ".jsonnet":
|
|
return parseJsonnet(req, template, templateArgs)
|
|
default:
|
|
return nil, errTemplateExtensionInvalid
|
|
}
|
|
}
|
|
|
|
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 {
|
|
return nil, err
|
|
}
|
|
return &core.Config{
|
|
Data: out.String(),
|
|
}, nil
|
|
}
|
|
|
|
func parseJsonnet(req *core.ConvertArgs, template *core.Template, templateArgs core.TemplateArgs) (*core.Config, error) {
|
|
file, err := jsonnet.Parse(req, nil, 0, template, templateArgs.Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &core.Config{
|
|
Data: file,
|
|
}, nil
|
|
}
|
|
|
|
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
|
|
}
|
|
return &core.Config{
|
|
Data: file,
|
|
}, nil
|
|
}
|