1
0
mirror of https://github.com/drone/drone-cli.git synced 2026-02-09 03:03:35 +01:00

bump drone-yaml

This commit is contained in:
Brad Rydzewski 2018-10-18 15:44:27 -07:00
parent 2f5aa0ae26
commit 884a46fdba
11 changed files with 171 additions and 16 deletions

2
Gopkg.lock generated

@ -113,7 +113,7 @@
"yaml/pretty",
"yaml/signer"
]
revision = "a71f44ace1bdab086904cde2fe4534406376ae0b"
revision = "dfd798e3ae5589567f2a9e4e052c7eb6372e9367"
[[projects]]
name = "github.com/drone/envsubst"

@ -3,6 +3,7 @@ package compiler
import (
"github.com/drone/drone-runtime/engine"
"github.com/drone/drone-yaml/yaml"
"github.com/drone/drone-yaml/yaml/compiler/image"
"github.com/dchest/uniuri"
)
@ -132,6 +133,7 @@ func (c *Compiler) Compile(from *yaml.Pipeline) *engine.Spec {
if !from.Clone.Disable {
src := createClone(from)
dst := createStep(spec, src)
dst.Docker.PullPolicy = engine.PullIfNotExists
setupCloneDepth(from, dst)
setupCloneCredentials(spec, dst, c.gitCredentials())
setupWorkingDir(src, dst, workspace)
@ -164,11 +166,22 @@ func (c *Compiler) Compile(from *yaml.Pipeline) *engine.Spec {
spec.Steps = append(spec.Steps, step)
}
// rename will store a list of container names
// that should be mapped to their temporary alias.
rename := map[string]string{}
// for each pipeline step defined in the yaml
// configuration file, convert to a runtime step
// and append to the specification.
for _, container := range from.Steps {
step := createStep(spec, container)
var step *engine.Step
switch {
case container.Build != nil:
step = createBuildStep(spec, container)
rename[container.Build.Image] = step.Metadata.UID
default:
step = createStep(spec, container)
}
setupWorkingDir(container, step, workspace)
setupWorkingDirMount(step, base)
setupWorkspaceEnv(step, base, dir, workspace)
@ -185,6 +198,36 @@ func (c *Compiler) Compile(from *yaml.Pipeline) *engine.Spec {
spec.Steps = append(spec.Steps, step)
}
// if the pipeline includes any build and publish
// steps we should create an entry for the host
// machine docker socket.
if spec.Docker != nil && len(rename) > 0 {
v := &engine.Volume{
Metadata: engine.Metadata{
UID: c.random(),
Name: "_docker_socket",
Namespace: namespace,
Labels: map[string]string{},
},
HostPath: &engine.VolumeHostPath{
Path: "/var/run/docker.sock",
},
}
spec.Docker.Volumes = append(spec.Docker.Volumes, v)
}
// images created during the pipeline are assigned a
// random alias. All references to the origin image
// name must be changed to the alias.
for _, step := range spec.Steps {
for k, v := range rename {
if image.MatchTag(step.Docker.Image, k) {
img := image.Trim(step.Docker.Image) + ":" + v
step.Docker.Image = image.Expand(img)
}
}
}
// executes user-defined transformations before the
// final specification is returned.
if c.TransformFunc != nil {

@ -43,6 +43,12 @@ func Match(from string, to ...string) bool {
return false
}
// MatchTag returns true if the image name matches
// an image in the list, including the tag.
func MatchTag(a, b string) bool {
return Expand(a) == Expand(b)
}
// MatchHostname returns true if the image hostname
// matches the specified hostname.
func MatchHostname(image, hostname string) bool {

@ -54,6 +54,13 @@ func createStep(spec *engine.Spec, src *yaml.Container) *engine.Step {
// appends the volumes to the container def.
for _, vol := range src.Volumes {
// the user should never be able to directly
// mount the docker socket. This should be
// restricted by the linter, but we place this
// check here just to be safe.
if vol.Name == "_docker_socket" {
continue
}
mount := &engine.VolumeMount{
Name: vol.Name,
Path: vol.MountPath,
@ -113,3 +120,60 @@ func createStep(spec *engine.Spec, src *yaml.Container) *engine.Step {
return dst
}
func createBuildStep(spec *engine.Spec, src *yaml.Container) *engine.Step {
dst := &engine.Step{
Metadata: engine.Metadata{
UID: random(),
Name: src.Name,
Namespace: spec.Metadata.Namespace,
Labels: map[string]string{
"io.drone.step.name": src.Name,
},
},
Detach: src.Detach,
DependsOn: src.DependsOn,
Devices: nil,
Docker: &engine.DockerStep{
Args: []string{"--build"},
DNS: src.DNS,
Image: "drone/docker",
PullPolicy: engine.PullIfNotExists,
},
Envs: map[string]string{},
IgnoreErr: toIgnoreErr(src),
IgnoreStderr: false,
IgnoreStdout: false,
Resources: toResources(src),
RunPolicy: toRunPolicy(src),
}
// if v := src.Build.Args; len(v) > 0 {
// dst.Envs["DOCKER_BUILD_ARGS"] = strings.Join(v, ",")
// }
if v := src.Build.CacheFrom; len(v) > 0 {
dst.Envs["DOCKER_BUILD_CACHE_FROM"] = strings.Join(v, ",")
}
// if len(src.Build.Labels) > 0 {
// dst.Envs["DOCKER_BUILD_LABELS"] = strings.Join(v, ",")
// }
if v := src.Build.Dockerfile; v != "" {
dst.Envs["DOCKER_BUILD_DOCKERFILE"] = v
}
if v := src.Build.Context; v != "" {
dst.Envs["DOCKER_BUILD_CONTEXT"] = v
}
if v := src.Build.Image; v != "" {
alias := image.Trim(v) + ":" + dst.Metadata.UID
dst.Envs["DOCKER_BUILD_IMAGE"] = image.Expand(v)
dst.Envs["DOCKER_BUILD_IMAGE_ALIAS"] = image.Expand(alias)
}
dst.Volumes = append(dst.Volumes, &engine.VolumeMount{
Name: "_docker_socket",
Path: "/var/run/docker.sock",
})
return dst
}

@ -6,14 +6,14 @@ type (
// to a secret.
Variable struct {
Value string `json:"value,omitempty"`
Secret string `json:"$secret,omitempty" yaml:"$secret"`
Secret string `json:"from_secret,omitempty" yaml:"from_secret"`
}
// variable is a tempoary type used to unmarshal
// variables with references to secrets.
variable struct {
Value string
Secret string `yaml:"$secret"`
Secret string `yaml:"from_secret"`
}
)

@ -2,6 +2,7 @@ package linter
import (
"errors"
"fmt"
"github.com/drone/drone-yaml/yaml"
)
@ -49,9 +50,12 @@ func checkContainer(container *yaml.Container, trusted bool) error {
if err != nil {
return err
}
if container.Image == "" {
if container.Build == nil && container.Image == "" {
return errors.New("linter: invalid or missing image")
}
if container.Build != nil && container.Build.Image == "" {
return errors.New("linter: invalid or missing build image")
}
if container.Name == "" {
return errors.New("linter: invalid or missing name")
}
@ -70,6 +74,12 @@ func checkContainer(container *yaml.Container, trusted bool) error {
if trusted == false && len(container.ExtraHosts) > 0 {
return errors.New("linter: untrusted repositories cannot configure extra_hosts")
}
for _, mount := range container.Volumes {
switch mount.Name {
case "workspace", "_workspace", "_docker_socket":
return fmt.Errorf("linter: invalid volume name: %s", mount.Name)
}
}
return nil
}
@ -104,6 +114,10 @@ func checkVolumes(pipeline *yaml.Pipeline, trusted bool) error {
return err
}
}
switch volume.Name {
case "workspace", "_workspace", "_docker_socket":
return fmt.Errorf("linter: invalid volume name: %s", volume.Name)
}
}
return nil
}

@ -2,8 +2,7 @@ package yaml
import (
"encoding/json"
"gopkg.in/yaml.v2"
"errors"
)
// Resource enums.
@ -88,5 +87,5 @@ func (m *Manifest) MarshalJSON() ([]byte, error) {
// MarshalYAML implement the yaml.Marshaler.
func (m *Manifest) MarshalYAML() (interface{}, error) {
return yaml.Marshal(m.Resources)
return nil, errors.New("yaml: marshal not implemented")
}

@ -6,13 +6,13 @@ type (
// to a secret.
Parameter struct {
Value interface{} `json:"value,omitempty"`
Secret string `json:"$secret,omitempty" yaml:"$secret"`
Secret string `json:"from_secret,omitempty" yaml:"from_secret"`
}
// parameter is a tempoary type used to unmarshal
// parameters with references to secrets.
parameter struct {
Secret string `yaml:"$secret"`
Secret string `yaml:"from_secret"`
}
)

@ -113,7 +113,7 @@ func printEnviron(w writer, v map[string]*yaml.Variable) {
} else {
w.WriteTag(k)
w.IndentIncrease()
w.WriteTagValue("$secret", v.Secret)
w.WriteTagValue("from_secret", v.Secret)
w.IndentDecrease()
}
}
@ -182,7 +182,7 @@ func printSettings(w writer, v map[string]*yaml.Parameter) {
} else {
w.WriteTag(k)
w.IndentIncrease()
w.WriteTagValue("$secret", v.Secret)
w.WriteTagValue("from_secret", v.Secret)
w.IndentDecrease()
}
}

@ -15,15 +15,36 @@ func printSecret(w writer, v *yaml.Secret) {
w.WriteTagValue("version", v.Version)
w.WriteTagValue("kind", v.Kind)
w.WriteTagValue("type", v.Type)
if v.Type == "encrypted" {
if v.Type == "encrypted" || v.Type == "opaque" {
printData(w, v.Data)
} else {
w.WriteTagValue("data", v.Data)
printExternalData(w, v.External)
}
w.WriteByte('\n')
w.WriteByte('\n')
}
// helper function prints the external data.
func printExternalData(w writer, d map[string]yaml.ExternalData) {
var keys []string
for k := range d {
keys = append(keys, k)
}
sort.Strings(keys)
w.WriteTag("external_data")
w.IndentIncrease()
for _, k := range keys {
v := d[k]
w.WriteTag(k)
w.IndentIncrease()
w.WriteTagValue("path", v.Path)
w.WriteTagValue("name", v.Name)
w.IndentDecrease()
}
w.IndentDecrease()
}
func printData(w writer, d map[string]string) {
var keys []string
for k := range d {

@ -10,7 +10,15 @@ type (
Kind string `json:"kind,omitempty"`
Type string `json:"type,omitempty"`
Data map[string]string `json:"data,omitempty"`
Data map[string]string `json:"data,omitempty"`
External map[string]ExternalData `json:"external_data,omitempty" yaml:"external_data"`
}
// ExternalData defines the path and name of external
// data located in an external or remote storage system.
ExternalData struct {
Path string `json:"path,omitempty"`
Name string `json:"name,omitempty"`
}
)
@ -22,7 +30,7 @@ func (s *Secret) GetKind() string { return s.Kind }
// Validate returns an error if the secret is invalid.
func (s *Secret) Validate() error {
if len(s.Data) == 0 {
if len(s.Data) == 0 && len(s.External) == 0 {
return errors.New("yaml: invalid secret resource")
}
return nil