enable secret short and long form

This commit is contained in:
Brad Rydzewski 2019-02-21 14:29:06 -08:00
parent 5e77906fc4
commit 6d6664de36
9 changed files with 85 additions and 40 deletions

View File

@ -10,6 +10,7 @@ steps:
- name: test - name: test
image: golang:1.11 image: golang:1.11
commands: commands:
- go vet ./...
- go test ./... - go test ./...
... ...

View File

@ -2,13 +2,13 @@ Copyright 2019 Drone.IO, Inc.
Source code in this repository is variously licensed under the Source code in this repository is variously licensed under the
Apache License Version 2.0, an Apache compatible license, or the Apache License Version 2.0, an Apache compatible license, or the
Drone Community License. Source code in a given file is licensed Drone Non-Commercial License. Source code in a given file is
under the Drone Community License unless otherwise noted at the licensed under the Drone Non-Commercial License unless otherwise
beginning of the file. noted at the beginning of the file.
----------------------------------------------------------------- -----------------------------------------------------------------
Drone Community License Drone Non-Commercial License
Contributor: Drone.IO, Inc. Contributor: Drone.IO, Inc.

View File

@ -86,9 +86,9 @@ func createStep(spec *engine.Spec, src *yaml.Container) *engine.Step {
// appends the environment variables to the // appends the environment variables to the
// container definition. // container definition.
for key, value := range src.Environment { for key, value := range src.Environment {
if value.Secret != "" { if value.Secret.Name != "" {
sec := &engine.SecretVar{ sec := &engine.SecretVar{
Name: value.Secret, Name: value.Secret.Name,
Env: key, Env: key,
} }
dst.Secrets = append(dst.Secrets, sec) dst.Secrets = append(dst.Secrets, sec)
@ -106,9 +106,9 @@ func createStep(spec *engine.Spec, src *yaml.Container) *engine.Step {
// if the setting parameter is sources from the // if the setting parameter is sources from the
// secret we create a secret enviornment variable. // secret we create a secret enviornment variable.
if value.Secret != "" { if value.Secret.Name != "" {
sec := &engine.SecretVar{ sec := &engine.SecretVar{
Name: value.Secret, Name: value.Secret.Name,
Env: key, Env: key,
} }
dst.Secrets = append(dst.Secrets, sec) dst.Secrets = append(dst.Secrets, sec)

View File

@ -195,7 +195,7 @@ func toEnvironment(from *Container) map[string]*droneyaml.Variable {
for _, val := range from.Secrets.Secrets { for _, val := range from.Secrets.Secrets {
name := strings.ToUpper(val.Target) name := strings.ToUpper(val.Target)
envs[name] = &droneyaml.Variable{ envs[name] = &droneyaml.Variable{
Secret: val.Source, Secret: droneyaml.FromSecret{Name: val.Source},
} }
} }
return envs return envs

View File

@ -19,26 +19,27 @@ type (
// can be defined as a string literal or as a reference // can be defined as a string literal or as a reference
// to a secret. // to a secret.
Variable struct { Variable struct {
Value string `json:"value,omitempty"` Value string `json:"value,omitempty"`
Secret string `json:"from_secret,omitempty" yaml:"from_secret"` Secret FromSecret `json:"from_secret,omitempty" yaml:"from_secret"`
} }
// variable is a tempoary type used to unmarshal // variable is a tempoary type used to unmarshal
// variables with references to secrets. // variables with references to secrets.
variable struct { variable struct {
Value string FromSecret FromSecret `yaml:"from_secret"`
Secret string `yaml:"from_secret"`
} }
) )
// UnmarshalYAML implements yaml unmarshalling. // UnmarshalYAML implements yaml unmarshalling.
func (v *Variable) UnmarshalYAML(unmarshal func(interface{}) error) error { func (v *Variable) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(variable) d := new(variable)
err := unmarshal(&d.Value) err := unmarshal(d)
if err != nil { if err == nil && (d.FromSecret.Name != "" || d.FromSecret.Path != "") {
err = unmarshal(d) v.Secret = d.FromSecret
return nil
} }
v.Value = d.Value var s string
v.Secret = d.Secret err = unmarshal(&s)
v.Value = s
return err return err
} }

View File

@ -14,7 +14,8 @@ func TestEnv(t *testing.T) {
tests := []struct { tests := []struct {
yaml string yaml string
value string value string
from string name string
path string
}{ }{
{ {
yaml: "bar", yaml: "bar",
@ -22,7 +23,12 @@ func TestEnv(t *testing.T) {
}, },
{ {
yaml: "from_secret: username", yaml: "from_secret: username",
from: "username", name: "username",
},
{
yaml: "from_secret: { name: username, path: secret/data/docker }",
name: "username",
path: "secret/data/docker",
}, },
} }
for _, test := range tests { for _, test := range tests {
@ -36,8 +42,11 @@ func TestEnv(t *testing.T) {
if got, want := out.Value, test.value; got != want { if got, want := out.Value, test.value; got != want {
t.Errorf("Want variable value %q, got %q", want, got) t.Errorf("Want variable value %q, got %q", want, got)
} }
if got, want := out.Secret, test.from; got != want { if got, want := out.Secret.Name, test.name; got != want {
t.Errorf("Want variable from_secret %q, got %q", want, got) t.Errorf("Want variable from_secret.name %q, got %q", want, got)
}
if got, want := out.Secret.Path, test.path; got != want {
t.Errorf("Want variable from_secret.path %q, got %q", want, got)
} }
} }
} }

View File

@ -1,11 +1,11 @@
// Copyright 2019 Drone IO, Inc. // Copyright 2019 Drone IO, Inc.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -20,13 +20,13 @@ type (
// to a secret. // to a secret.
Parameter struct { Parameter struct {
Value interface{} `json:"value,omitempty"` Value interface{} `json:"value,omitempty"`
Secret string `json:"from_secret,omitempty" yaml:"from_secret"` Secret FromSecret `json:"from_secret,omitempty" yaml:"from_secret"`
} }
// parameter is a tempoary type used to unmarshal // parameter is a tempoary type used to unmarshal
// parameters with references to secrets. // parameters with references to secrets.
parameter struct { parameter struct {
Secret string `yaml:"from_secret"` FromSecret FromSecret `yaml:"from_secret"`
} }
) )
@ -34,8 +34,8 @@ type (
func (p *Parameter) UnmarshalYAML(unmarshal func(interface{}) error) error { func (p *Parameter) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(parameter) d := new(parameter)
err := unmarshal(d) err := unmarshal(d)
if err == nil && d.Secret != ""{ if err == nil && (d.FromSecret.Name != "" || d.FromSecret.Path != "") {
p.Secret = d.Secret p.Secret = d.FromSecret
return nil return nil
} }
var i interface{} var i interface{}

View File

@ -5,6 +5,7 @@
package yaml package yaml
import ( import (
"reflect"
"testing" "testing"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -14,15 +15,32 @@ func TestParam(t *testing.T) {
tests := []struct { tests := []struct {
yaml string yaml string
value interface{} value interface{}
from string name string
path string
}{ }{
{ {
yaml: "bar", yaml: "bar",
value: "bar", value: "bar",
name: "",
path: "",
}, },
{ {
yaml: "from_secret: username", yaml: "[ bar ]",
from: "username", value: []interface{}{"bar"},
name: "",
path: "",
},
{
yaml: "from_secret: username",
value: nil,
name: "username",
path: "",
},
{
yaml: "from_secret: { path: secret/data/docker, name: username }",
value: nil,
name: "username",
path: "secret/data/docker",
}, },
} }
for _, test := range tests { for _, test := range tests {
@ -33,11 +51,14 @@ func TestParam(t *testing.T) {
t.Error(err) t.Error(err)
return return
} }
if got, want := out.Value, test.value; got != want { if got, want := out.Value, test.value; !reflect.DeepEqual(got, want) {
t.Errorf("Want value %q, got %q", want, got) t.Errorf("Want value %q of type %T, got %q of type %T", want, want, got, got)
} }
if got, want := out.Secret, test.from; got != want { if got, want := out.Secret.Name, test.name; got != want {
t.Errorf("Want from_secret %q, got %q", want, got) t.Errorf("Want from_secret.name %q, got %q", want, got)
}
if got, want := out.Secret.Path, test.path; got != want {
t.Errorf("Want from_secret.path %q, got %q", want, got)
} }
} }
} }

View File

@ -114,12 +114,12 @@ func printEnviron(w writer, v map[string]*yaml.Variable) {
w.IndentIncrease() w.IndentIncrease()
for _, k := range keys { for _, k := range keys {
v := v[k] v := v[k]
if v.Secret == "" { if v.Secret.Name == "" && v.Secret.Path == "" {
w.WriteTagValue(k, v.Value) w.WriteTagValue(k, v.Value)
} else { } else {
w.WriteTag(k) w.WriteTag(k)
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("from_secret", v.Secret) printFromSecret(w, v.Secret)
w.IndentDecrease() w.IndentDecrease()
} }
} }
@ -183,12 +183,12 @@ func printSettings(w writer, v map[string]*yaml.Parameter) {
w.IndentIncrease() w.IndentIncrease()
for _, k := range keys { for _, k := range keys {
v := v[k] v := v[k]
if v.Secret == "" { if v.Secret.Name == "" && v.Secret.Path == "" {
w.WriteTagValue(k, v.Value) w.WriteTagValue(k, v.Value)
} else { } else {
w.WriteTag(k) w.WriteTag(k)
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("from_secret", v.Secret) printFromSecret(w, v.Secret)
w.IndentDecrease() w.IndentDecrease()
} }
} }
@ -208,6 +208,19 @@ func printVolumeMounts(w writer, v []*yaml.VolumeMount) {
} }
} }
// helper function pretty prints the from_secret sequence.
func printFromSecret(w writer, v yaml.FromSecret) {
if v.Path == "" {
w.WriteTagValue("from_secret", v.Name)
} else {
w.WriteTag("from_secret")
w.IndentIncrease()
w.WriteTagValue("path", v.Path)
w.WriteTagValue("name", v.Name)
w.IndentDecrease()
}
}
// helper function returns true if the Build block should // helper function returns true if the Build block should
// be printed in short form. // be printed in short form.
func shortBuild(b *yaml.Build) bool { func shortBuild(b *yaml.Build) bool {