support environment masking

pull/3/head
Brad Rydzewski 4 years ago
parent 6f725b3b9f
commit a238edf7e8

@ -4,11 +4,7 @@
package provider
import (
"context"
"github.com/drone/runner-go/environ"
)
import "context"
// Combine returns a new combined environment provider,
// capable of sourcing environment variables from multiple
@ -21,16 +17,14 @@ type combined struct {
sources []Provider
}
func (p *combined) List(ctx context.Context, in *Request) (map[string]string, error) {
out := map[string]string{}
func (p *combined) List(ctx context.Context, in *Request) ([]*Variable, error) {
var out []*Variable
for _, source := range p.sources {
got, err := source.List(ctx, in)
if err != nil {
return nil, err
}
if got != nil {
out = environ.Combine(got, out)
}
out = append(out, got...)
}
return out, nil
}

@ -7,6 +7,8 @@ package provider
import (
"errors"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestCombine(t *testing.T) {
@ -15,20 +17,29 @@ func TestCombine(t *testing.T) {
aa := Static(a)
bb := Static(b)
p := Combine(aa, bb)
out, err := p.List(noContext, nil)
got, err := p.List(noContext, nil)
if err != nil {
t.Error(err)
return
}
if len(out) != 2 {
if len(got) != 2 {
t.Errorf("Expect combined variable output")
return
}
if out["a"] != "b" {
t.Errorf("Missing variable")
want := []*Variable{
{
Name: "a",
Data: "b",
Mask: false,
},
{
Name: "c",
Data: "d",
Mask: false,
},
}
if out["c"] != "d" {
t.Errorf("Missing variable")
if diff := cmp.Diff(got, want); diff != "" {
t.Errorf(diff)
}
}

@ -40,7 +40,7 @@ type external struct {
client environ.Plugin
}
func (p *external) List(ctx context.Context, in *Request) (map[string]string, error) {
func (p *external) List(ctx context.Context, in *Request) ([]*Variable, error) {
if p.client == nil {
return nil, nil
}
@ -74,5 +74,13 @@ func (p *external) List(ctx context.Context, in *Request) (map[string]string, er
logger.Trace("environment: external: environment variable list returned")
return res, nil
var out []*Variable
for _, v := range res {
out = append(out, &Variable{
Name: v.Name,
Data: v.Data,
Mask: v.Mask,
})
}
return out, nil
}

@ -19,9 +19,17 @@ func TestExternal(t *testing.T) {
Build: &drone.Build{Event: drone.EventPush},
Repo: &drone.Repo{Private: false},
}
want := map[string]string{"a": "b"}
res := []*environ.Variable{
{
Name: "a",
Data: "b",
Mask: true,
},
}
want := []*Variable{{Name: "a", Data: "b", Mask: true}}
provider := External("http://localhost", "secret", false)
provider.(*external).client = &mockPlugin{out: want}
provider.(*external).client = &mockPlugin{out: res}
got, err := provider.List(noContext, req)
if err != nil {
t.Error(err)
@ -91,10 +99,10 @@ func TestMultiExternal(t *testing.T) {
}
type mockPlugin struct {
out map[string]string
out []*environ.Variable
err error
}
func (m *mockPlugin) List(context.Context, *environ.Request) (map[string]string, error) {
func (m *mockPlugin) List(context.Context, *environ.Request) ([]*environ.Variable, error) {
return m.out, m.err
}

@ -19,9 +19,16 @@ type Request struct {
Build *drone.Build
}
// Variable defines an environment variable.
type Variable struct {
Name string
Data string
Mask bool
}
// Provider is the interface that must be implemented by an
// environment provider.
type Provider interface {
// List returns a list of environment variables.
List(context.Context, *Request) (map[string]string, error)
List(context.Context, *Request) ([]*Variable, error)
}

@ -11,10 +11,10 @@ import (
var noContext = context.Background()
type mockProvider struct {
out map[string]string
out []*Variable
err error
}
func (p *mockProvider) List(context.Context, *Request) (map[string]string, error) {
func (p *mockProvider) List(context.Context, *Request) ([]*Variable, error) {
return p.out, p.err
}

@ -17,6 +17,6 @@ type static struct {
params map[string]string
}
func (p *static) List(context.Context, *Request) (map[string]string, error) {
return p.params, nil
func (p *static) List(context.Context, *Request) ([]*Variable, error) {
return ToSlice(p.params), nil
}

@ -5,19 +5,28 @@
package provider
import (
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestStatic(t *testing.T) {
a := map[string]string{"a": "b"}
p := Static(a)
b, err := p.List(noContext, nil)
in := map[string]string{"a": "b"}
got, err := Static(in).List(noContext, nil)
if err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(a, b) {
t.Errorf("Unexpected environment variable output")
want := []*Variable{
{
Name: "a",
Data: "b",
},
}
if diff := cmp.Diff(got, want); diff != "" {
t.Errorf(diff)
}
}

@ -0,0 +1,52 @@
// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Polyform License
// that can be found in the LICENSE file.
package provider
// ToMap is a helper function that converts a list of
// variables to a map.
func ToMap(src []*Variable) map[string]string {
dst := map[string]string{}
for _, v := range src {
dst[v.Name] = v.Data
}
return dst
}
// ToSlice is a helper function that converts a map of
// environment variables to a slice.
func ToSlice(src map[string]string) []*Variable {
var dst []*Variable
for k, v := range src {
dst = append(dst, &Variable{
Name: k,
Data: v,
})
}
return dst
}
// FilterMasked is a helper function that filters a list of
// variable to return a list of masked variables only.
func FilterMasked(v []*Variable) []*Variable {
var filtered []*Variable
for _, vv := range v {
if vv.Mask {
filtered = append(filtered, vv)
}
}
return filtered
}
// FilterUnmasked is a helper function that filters a list of
// variable to return a list of masked variables only.
func FilterUnmasked(v []*Variable) []*Variable {
var filtered []*Variable
for _, vv := range v {
if vv.Mask == false {
filtered = append(filtered, vv)
}
}
return filtered
}

@ -0,0 +1,87 @@
// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Polyform License
// that can be found in the LICENSE file.
package provider
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestToMap(t *testing.T) {
in := []*Variable{
{
Name: "foo",
Data: "bar",
},
}
want := map[string]string{
"foo": "bar",
}
got := ToMap(in)
if diff := cmp.Diff(want, got); diff != "" {
t.Log(diff)
t.Errorf("Unexpected map value")
}
}
func TestFromMap(t *testing.T) {
in := map[string]string{
"foo": "bar",
}
want := []*Variable{
{
Name: "foo",
Data: "bar",
},
}
got := ToSlice(in)
if diff := cmp.Diff(want, got); diff != "" {
t.Log(diff)
t.Errorf("Unexpected variable list")
}
}
func TestFilterMasked(t *testing.T) {
in := []*Variable{
{
Name: "foo",
Data: "bar",
Mask: false,
},
{
Name: "baz",
Data: "qux",
Mask: true,
},
}
want := in[1:]
got := FilterMasked(in)
if diff := cmp.Diff(want, got); diff != "" {
t.Log(diff)
t.Errorf("Unexpected variable list")
}
}
func TestFilterUnmasked(t *testing.T) {
in := []*Variable{
{
Name: "foo",
Data: "bar",
Mask: true,
},
{
Name: "baz",
Data: "qux",
Mask: false,
},
}
want := in[1:]
got := FilterUnmasked(in)
if diff := cmp.Diff(want, got); diff != "" {
t.Log(diff)
t.Errorf("Unexpected variable list")
}
}

@ -8,7 +8,7 @@ require (
github.com/buildkite/yaml v2.1.0+incompatible
github.com/coreos/go-semver v0.3.0
github.com/docker/go-units v0.4.0
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79
github.com/drone/drone-go v1.2.1-0.20200326064413-195394da1018
github.com/drone/envsubst v1.0.2
github.com/google/go-cmp v0.3.0
github.com/hashicorp/go-multierror v1.0.0

@ -13,6 +13,11 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79 h1:jW+dJ8HrZ1CbazlsYoriOOCQnVJ2NkfNczLHs6UMU6I=
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
github.com/drone/drone-go v1.2.1-0.20200326061744-0158580ce4ea h1:bMFm53oPjGvjpdO7+mfK6Qak4+O5ri5UlmlvN6J/qvo=
github.com/drone/drone-go v1.2.1-0.20200326061744-0158580ce4ea/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
github.com/drone/drone-go v1.2.1-0.20200326064413-195394da1018 h1:aHRv4GohqzHXZEGks/Qyrd8kI7hkCdLhJO1QoYtQMjU=
github.com/drone/drone-go v1.2.1-0.20200326064413-195394da1018/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
github.com/drone/drone-go v1.3.1 h1:D4KXbauJtbT/zXk19TcMpu36F8GPOUcndIw7pOWsX6k=
github.com/drone/envsubst v1.0.2 h1:dpYLMAspQHW0a8dZpLRKe9jCNvIGZPhCPrycZzIHdqo=
github.com/drone/envsubst v1.0.2/go.mod h1:bkZbnc/2vh1M12Ecn7EYScpI4YGYU0etwLJICOWi8Z0=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=

Loading…
Cancel
Save