diff --git a/cmd/drone-server/config/config.go b/cmd/drone-server/config/config.go index 76d1ffea2..0f37b5e23 100644 --- a/cmd/drone-server/config/config.go +++ b/cmd/drone-server/config/config.go @@ -54,6 +54,7 @@ type ( Datadog Datadog Docker Docker HTTP HTTP + Jsonnet Jsonnet Logging Logging // Prometheus Prometheus Proxy Proxy @@ -116,6 +117,11 @@ type ( Token string `envconfig:"DRONE_DATADOG_TOKEN"` } + // Jsonnet configures the jsonnet plugin + Jsonnet struct { + Enabled bool `envconfig:"DRONE_JSONNET_ENABLED"` + } + // Kubernetes provides kubernetes configuration Kubernetes struct { Enabled bool `envconfig:"DRONE_KUBERNETES_ENABLED"` diff --git a/cmd/drone-server/inject_plugin.go b/cmd/drone-server/inject_plugin.go index 010335787..53c936dbc 100644 --- a/cmd/drone-server/inject_plugin.go +++ b/cmd/drone-server/inject_plugin.go @@ -57,6 +57,7 @@ func provideConfigPlugin(client *scm.Client, contents core.FileService, conf spe conf.Yaml.Secret, conf.Yaml.SkipVerify, ), + config.Jsonnet(contents, conf.Jsonnet.Enabled), config.Repository(contents), ) } diff --git a/go.mod b/go.mod index 86cf0a24e..367514435 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/golang/protobuf v1.2.0 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c github.com/google/go-cmp v0.2.0 + github.com/google/go-jsonnet v0.12.1 github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf github.com/google/wire v0.2.1 github.com/googleapis/gnostic v0.2.0 diff --git a/go.sum b/go.sum index 6057df0a0..a1b0c1301 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCy github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-jsonnet v0.12.1 h1:v0iUm/b4SBz7lR/diMoz9tLAz8lqtnNRKIwMrmU2HEU= +github.com/google/go-jsonnet v0.12.1/go.mod h1:gVu3UVSfOt5fRFq+dh9duBqXa5905QY8S1QvMNcEIVs= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/wire v0.2.1 h1:TYj4Z2qjqxa2ufb34UJqVeO9aznL+i0fLO6TqThKZ7Y= @@ -112,6 +114,8 @@ github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6 h1:qCv4319q2q7XKn0MQbi8p37hsJ+9Xo8e6yojA73JVxk= github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM= +github.com/hashicorp/go-rootcerts v1.0.0 h1:ueI78wUjYExhCvMLow4icJnayNNFRgy0d9EGs/a1T44= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/nomad v0.0.0-20190125003214-134391155854 h1:L7WhLZt2ory/kQWxqkMwOiBpIoa4BWoadN7yx8LHEtk= diff --git a/plugin/config/jsonnet.go b/plugin/config/jsonnet.go new file mode 100644 index 000000000..b55cf835a --- /dev/null +++ b/plugin/config/jsonnet.go @@ -0,0 +1,77 @@ +// Copyright 2019 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by the Drone Non-Commercial License +// that can be found in the LICENSE file. + +// +build !oss + +package config + +import ( + "bytes" + "context" + "strings" + + "github.com/drone/drone/core" + + "github.com/google/go-jsonnet" +) + +// Jsonnet returns a configuration service that fetches the +// jsonnet file directly from the source code management (scm) +// system and converts to a yaml file. +func Jsonnet(service core.FileService, enabled bool) core.ConfigService { + return &jsonnetPlugin{ + enabled: enabled, + repos: &repo{files: service}, + } +} + +type jsonnetPlugin struct { + enabled bool + repos *repo +} + +func (p *jsonnetPlugin) Find(ctx context.Context, req *core.ConfigArgs) (*core.Config, error) { + if p.enabled == false { + return nil, nil + } + + // if the file extension is not jsonnet we can + // skip this plugin by returning zero values. + if strings.HasSuffix(req.Repo.Config, ".jsonnet") == false { + return nil, nil + } + + // get the file contents. + config, err := p.repos.Find(ctx, req) + if err != nil { + return nil, err + } + + // TODO(bradrydzewski) temporarily disable file imports + // TODO(bradrydzewski) handle object vs array output + + // create the jsonnet vm + vm := jsonnet.MakeVM() + vm.MaxStack = 500 + vm.StringOutput = false + vm.ErrorFormatter.SetMaxStackTraceSize(20) + + // convert the jsonnet file to yaml + buf := new(bytes.Buffer) + docs, err := vm.EvaluateSnippetStream(req.Repo.Config, config.Data) + if err != nil { + return nil, err + } + + // the jsonnet vm returns a stream of yaml documents + // that need to be combined into a single yaml file. + for _, doc := range docs { + buf.WriteString("---") + buf.WriteString("\n") + buf.WriteString(doc) + } + + config.Data = buf.String() + return config, nil +} diff --git a/plugin/config/jsonnet_oss.go b/plugin/config/jsonnet_oss.go new file mode 100644 index 000000000..dc38165de --- /dev/null +++ b/plugin/config/jsonnet_oss.go @@ -0,0 +1,24 @@ +// 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 config + +import "github.com/drone/drone/core" + +// Jsonnet returns a no-op configuration service. +func Jsonnet(service core.FileService, enabled bool) core.ConfigService { + return new(noop) +} diff --git a/plugin/config/jsonnet_test.go b/plugin/config/jsonnet_test.go new file mode 100644 index 000000000..9d26a590c --- /dev/null +++ b/plugin/config/jsonnet_test.go @@ -0,0 +1,7 @@ +// Copyright 2019 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by the Drone Non-Commercial License +// that can be found in the LICENSE file. + +// +build !oss + +package config