-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implementing pflag.Value interface to represent corev1.EnvVar used in both Build and BuildRun.
- Loading branch information
Showing
11 changed files
with
211 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package flags | ||
|
||
import ( | ||
"fmt" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
) | ||
|
||
// CoreEnvVarSliceValue implements pflag.Value interface, in order to store corev1.EnvVar key-value | ||
// pairs, used on Shipwright's BuildSpec. | ||
type CoreEnvVarSliceValue struct { | ||
envs *[]corev1.EnvVar // pointer to the slice of EnvVar | ||
} | ||
|
||
// String prints out the string representation of the slice of EnvVar objects. | ||
func (c *CoreEnvVarSliceValue) String() string { | ||
s := []string{} | ||
for _, e := range *c.envs { | ||
s = append(s, fmt.Sprintf("%s=%s", e.Name, e.Value)) | ||
} | ||
return fmt.Sprintf("[%s]", s) | ||
} | ||
|
||
// setEnvVar populates the local slice of EnvVar, making sure the entry is not repeated. | ||
func (c *CoreEnvVarSliceValue) setEnvVar(value string) error { | ||
k, v, err := splitKV(value) | ||
if err != nil { | ||
return err | ||
} | ||
for _, e := range *c.envs { | ||
if k == e.Name { | ||
return fmt.Errorf("environment variable '%s' is already set!", k) | ||
} | ||
} | ||
*c.envs = append(*c.envs, corev1.EnvVar{Name: k, Value: v}) | ||
return nil | ||
} | ||
|
||
// Set receives a string with key-value pairs comma separated. | ||
func (c *CoreEnvVarSliceValue) Set(value string) error { | ||
values, err := readAsCSV(value) | ||
if err != nil { | ||
return err | ||
} | ||
for _, v := range values { | ||
if err = c.setEnvVar(v); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// Type analogous to the pflag "stringSlice". | ||
func (c *CoreEnvVarSliceValue) Type() string { | ||
return "stringSlice" | ||
} | ||
|
||
// NewCoreEnvVarSliceValue instantiate a CoreEnvVarSliceValue sharing the EnvVar pointer. | ||
func NewCoreEnvVarSliceValue(envs *[]corev1.EnvVar) *CoreEnvVarSliceValue { | ||
return &CoreEnvVarSliceValue{envs: envs} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package flags | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/onsi/gomega" | ||
o "github.com/onsi/gomega" | ||
buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1" | ||
corev1 "k8s.io/api/core/v1" | ||
) | ||
|
||
func TestCoreEnvVarSliceValue(t *testing.T) { | ||
g := gomega.NewGomegaWithT(t) | ||
|
||
spec := &buildv1alpha1.BuildSpec{Env: []corev1.EnvVar{}} | ||
c := NewCoreEnvVarSliceValue(&spec.Env) | ||
|
||
// expect error when key-value is not split by equal sign | ||
err := c.Set("a") | ||
g.Expect(err).NotTo(o.BeNil()) | ||
|
||
// setting two key-value pairs, error is not expected | ||
err = c.Set("a=b,c=d") | ||
g.Expect(err).To(o.BeNil()) | ||
g.Expect(len(spec.Env)).To(o.Equal(2)) | ||
g.Expect(spec.Env[0].Name).To(o.Equal("a")) | ||
g.Expect(spec.Env[0].Value).To(o.Equal("b")) | ||
|
||
// on trying to insert a repeated value, it should error | ||
err = c.Set("a=b") | ||
g.Expect(err).NotTo(o.BeNil()) | ||
|
||
s := c.String() | ||
g.Expect(s).To(o.Equal("[[a=b c=d]]")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package flags | ||
|
||
import ( | ||
"bytes" | ||
"encoding/csv" | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// splitKV splits a key-value pair, and returns error for malformed pairs. | ||
func splitKV(value string) (string, string, error) { | ||
s := strings.Split(value, "=") | ||
if len(s) != 2 || s[0] == "" { | ||
return "", "", fmt.Errorf("informed value '%s' is not in key=value format!", value) | ||
} | ||
return s[0], s[1], nil | ||
} | ||
|
||
// readAsCSV splits the value by comma into a slice of string. | ||
func readAsCSV(value string) ([]string, error) { | ||
if value == "" { | ||
return []string{}, nil | ||
} | ||
|
||
r := strings.NewReader(value) | ||
cr := csv.NewReader(r) | ||
return cr.Read() | ||
} | ||
|
||
// writeAsCSV joins with comma the values informed. | ||
func writeAsCSV(values []string) (string, error) { | ||
b := &bytes.Buffer{} | ||
w := csv.NewWriter(b) | ||
if err := w.Write(values); err != nil { | ||
return "", err | ||
} | ||
w.Flush() | ||
return strings.TrimSuffix(b.String(), "\n"), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package flags | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/onsi/gomega" | ||
o "github.com/onsi/gomega" | ||
) | ||
|
||
func Test_splitKV(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
value string | ||
k string | ||
v string | ||
wantErr bool | ||
}{{ | ||
"error when no value is informed", | ||
"k", | ||
"", | ||
"", | ||
true, | ||
}, { | ||
"error when only value is informed", | ||
"=v", | ||
"", | ||
"", | ||
true, | ||
}, { | ||
"success on spliting key=value", | ||
"k=v", | ||
"k", | ||
"v", | ||
false, | ||
}} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, got1, err := splitKV(tt.value) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("splitKV() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
if got != tt.k { | ||
t.Errorf("splitKV() got = %v, want %v", got, tt.k) | ||
} | ||
if got1 != tt.v { | ||
t.Errorf("splitKV() got1 = %v, want %v", got1, tt.v) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func Test_readAsCSV(t *testing.T) { | ||
g := gomega.NewGomegaWithT(t) | ||
|
||
emptySlice, err := readAsCSV("") | ||
g.Expect(err).To(o.BeNil()) | ||
g.Expect(emptySlice).To(o.Equal([]string{})) | ||
|
||
slice, err := readAsCSV("a,b,c") | ||
g.Expect(err).To(o.BeNil()) | ||
g.Expect(slice).To(o.Equal([]string{"a", "b", "c"})) | ||
} | ||
|
||
func Test_writeAsCSV(t *testing.T) { | ||
g := gomega.NewGomegaWithT(t) | ||
|
||
s, err := writeAsCSV([]string{"a", "b", "c"}) | ||
g.Expect(err).To(o.BeNil()) | ||
g.Expect(s).To(o.Equal("a,b,c")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.