Skip to content

Commit

Permalink
fix(deployments): support commas in values for deploy parameters (#526)
Browse files Browse the repository at this point in the history
Co-authored-by: David May <[email protected]>
  • Loading branch information
ecrupper and wass3rw3rk authored Feb 7, 2024
1 parent b39b30a commit 05b0d75
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 80 deletions.
32 changes: 1 addition & 31 deletions action/deployment/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,15 @@
package deployment

import (
"fmt"
"strings"

"github.com/go-vela/cli/internal/output"

"github.com/go-vela/sdk-go/vela"

"github.com/go-vela/types/library"
"github.com/go-vela/types/raw"

"github.com/sirupsen/logrus"
)

// parseKeyValue converts the slice of key=value into a map.
func parseKeyValue(input []string) (raw.StringSliceMap, error) {
payload := raw.StringSliceMap{}

for _, i := range input {
parts := strings.SplitN(i, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("%s is not in key=value format", i)
}

payload[parts[0]] = parts[1]
}

return payload, nil
}

// Add creates a deployment based off the provided configuration.
func (c *Config) Add(client *vela.Client) error {
logrus.Debug("executing add for deployment configuration")
Expand All @@ -44,17 +24,7 @@ func (c *Config) Add(client *vela.Client) error {
Task: &c.Task,
Target: &c.Target,
Description: &c.Description,
}

// check if the user provided any parameters
if len(c.Parameters) != 0 {
// convert the parameters into map[string]string format
payload, err := parseKeyValue(c.Parameters)
if err != nil {
return err
}

d.SetPayload(payload)
Payload: &c.Parameters,
}

logrus.Tracef("adding deployment for repo %s/%s", c.Org, c.Repo)
Expand Down
50 changes: 4 additions & 46 deletions action/deployment/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package deployment

import (
"net/http/httptest"
"reflect"
"testing"

"github.com/go-vela/sdk-go/vela"
Expand Down Expand Up @@ -90,21 +89,10 @@ func TestDeployment_Config_Add(t *testing.T) {
Target: "production",
Task: "deploy:vela",
Output: "yaml",
Parameters: []string{"foo=test1", "bar=test2"},
},
},
{
failure: true,
config: &Config{
Action: "add",
Org: "github",
Repo: "octocat",
Description: "Deployment request from Vela",
Ref: "refs/heads/main",
Target: "production",
Task: "deploy:vela",
Output: "yaml",
Parameters: []string{"badinput"},
Parameters: raw.StringSliceMap{
"foo": "bar",
"faz": "baz",
},
},
},
}
Expand All @@ -126,33 +114,3 @@ func TestDeployment_Config_Add(t *testing.T) {
}
}
}

func Test_parseKeyValue(t *testing.T) {
type args struct {
input []string
}

tests := []struct {
name string
args args
want raw.StringSliceMap
wantErr bool
}{
{"valid input", args{input: []string{"foo=test1", "bar=test2"}}, raw.StringSliceMap{"foo": "test1", "bar": "test2"}, false},
{"invalid input", args{input: []string{"foo=test1", "badinput"}}, nil, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseKeyValue(tt.args.input)
if (err != nil) != tt.wantErr {
t.Errorf("parseKeyValue() error = %v, wantErr %v", err, tt.wantErr)
return
}

if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseKeyValue() = %v, want %v", got, tt.want)
}
})
}
}
4 changes: 3 additions & 1 deletion action/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

package deployment

import "github.com/go-vela/types/raw"

// Config represents the configuration necessary
// to perform deployment related quests with Vela.
type Config struct {
Expand All @@ -16,5 +18,5 @@ type Config struct {
Page int
PerPage int
Output string
Parameters []string
Parameters raw.StringSliceMap
}
77 changes: 75 additions & 2 deletions command/deployment/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ package deployment

import (
"fmt"
"os"
"strings"

"github.com/go-vela/cli/action"
"github.com/go-vela/cli/action/deployment"
"github.com/go-vela/cli/internal"
"github.com/go-vela/cli/internal/client"
"github.com/go-vela/types/raw"
"github.com/joho/godotenv"

"github.com/urfave/cli/v2"
)
Expand Down Expand Up @@ -69,6 +73,12 @@ var CommandAdd = &cli.Command{
Aliases: []string{"p"},
Usage: "provide the parameter(s) within `key=value` format for the deployment",
},
&cli.StringFlag{
EnvVars: []string{"VELA_PARAMETERS_FILE", "DEPLOYMENT_PARAMETERS_FILE"},
Name: "parameters-file",
Aliases: []string{"pf", "parameter-file"},
Usage: "provide deployment parameters via a JSON or env file",
},

// Output Flags

Expand All @@ -95,7 +105,9 @@ EXAMPLES:
$ {{.HelpName}} --org MyOrg --repo MyRepo --description 'my custom message'
7. Add a deployment for a repository with two parameters.
$ {{.HelpName}} --org MyOrg --repo MyRepo --parameter 'key=value' --parameter 'foo=bar'
8. Add a deployment for a repository when config or environment variables are set.
8. Add a deployment for a repository with a parameters JSON file.
$ {{.HelpName}} --org MyOrg --repo MyRepo --parameters-file params.json
9. Add a deployment for a repository when config or environment variables are set.
$ {{.HelpName}}
DOCUMENTATION:
Expand All @@ -114,6 +126,26 @@ func add(c *cli.Context) error {
return err
}

var parameters raw.StringSliceMap

pFile := c.String("parameters-file")
pInput := c.StringSlice("parameter")

if len(pFile) > 0 {
parameters, err = parseParamFile(pFile)
if err != nil {
return err
}
}

if len(pInput) > 0 {
// convert the parameters into map[string]string format
parameters, err = parseKeyValue(pInput)
if err != nil {
return err
}
}

// parse the Vela client from the context
//
// https://pkg.go.dev/github.com/go-vela/cli/internal/client?tab=doc#Parse
Expand All @@ -134,7 +166,7 @@ func add(c *cli.Context) error {
Target: c.String("target"),
Task: c.String("task"),
Output: c.String(internal.FlagOutput),
Parameters: c.StringSlice("parameter"),
Parameters: parameters,
}

// validate deployment configuration
Expand All @@ -150,3 +182,44 @@ func add(c *cli.Context) error {
// https://pkg.go.dev/github.com/go-vela/cli/action/deployment?tab=doc#Config.Add
return d.Add(client)
}

// parseKeyValue converts the slice of key=value into a map.
func parseKeyValue(input []string) (raw.StringSliceMap, error) {
payload := raw.StringSliceMap{}

for _, i := range input {
parts := strings.SplitN(i, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("%s is not in key=value format", i)
}

payload[parts[0]] = parts[1]
}

return payload, nil
}

// parseParamFile is a helper function that populates a slice map with values from a file.
func parseParamFile(pFile string) (raw.StringSliceMap, error) {
payload := raw.StringSliceMap{}

data, err := os.ReadFile(pFile)
if err != nil {
return nil, err
}

switch {
case strings.HasSuffix(pFile, ".json"), strings.HasSuffix(pFile, ".JSON"):
err = payload.UnmarshalJSON(data)
if err != nil {
return nil, err
}
default:
payload, err = godotenv.Read(pFile)
if err != nil {
return nil, err
}
}

return payload, nil
}
97 changes: 97 additions & 0 deletions command/deployment/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ package deployment
import (
"flag"
"net/http/httptest"
"reflect"
"testing"

"github.com/go-vela/cli/test"
"github.com/go-vela/server/mock/server"
"github.com/go-vela/types/raw"

"github.com/urfave/cli/v2"
)
Expand Down Expand Up @@ -69,3 +71,98 @@ func TestDeployment_Add(t *testing.T) {
}
}
}

func Test_parseKeyValue(t *testing.T) {
type args struct {
input []string
}

tests := []struct {
name string
args args
want raw.StringSliceMap
wantErr bool
}{
{"valid input", args{input: []string{"foo=test1", "bar=test2"}}, raw.StringSliceMap{"foo": "test1", "bar": "test2"}, false},
{"invalid input", args{input: []string{"foo=test1", "badinput"}}, nil, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseKeyValue(tt.args.input)
if (err != nil) != tt.wantErr {
t.Errorf("parseKeyValue() error = %v, wantErr %v", err, tt.wantErr)
return
}

if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseKeyValue() = %v, want %v", got, tt.want)
}
})
}
}

func Test_parseParamFile(t *testing.T) {
tests := []struct {
name string
file string
want raw.StringSliceMap
wantErr bool
}{
{
name: "valid simple input JSON",
file: "testdata/deploy-params-simple.json",
want: raw.StringSliceMap{
"one": "two",
"three": "four",
"five": "six",
},
},
{
name: "valid comma input JSON",
file: "testdata/deploy-params-comma.json",
want: raw.StringSliceMap{
"greeting": "hello, there!",
"farewell": "so long, partner!",
},
},
{
name: "valid input ENV",
file: "testdata/deploy-params-env.env",
want: raw.StringSliceMap{
"USER": "VELA",
"REPO": "CLI",
"ORG": "GO-VELA",
},
},
{
name: "invalid input JSON bad type",
file: "testdata/deploy-params-bad-type.json",
wantErr: true,
},
{
name: "invalid input JSON bad structure",
file: "testdata/deploy-params-bad-struct.json",
wantErr: true,
},
{
name: "invalid input nonexistent file",
file: "testdata/does-not-exist.json",
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseParamFile(tt.file)
if (err != nil) != tt.wantErr {
t.Errorf("parseParamFile() error = %v, wantErr %v", err, tt.wantErr)
return
}

if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseParamFile() = %v, want %v", got, tt.want)
}
})
}
}
6 changes: 6 additions & 0 deletions command/deployment/testdata/deploy-params-bad-struct.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"nested": {
"foo": "bar"
},
"faz": "baz"
}
4 changes: 4 additions & 0 deletions command/deployment/testdata/deploy-params-bad-type.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"integer": 2,
"string": "foo"
}
4 changes: 4 additions & 0 deletions command/deployment/testdata/deploy-params-comma.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"greeting": "hello, there!",
"farewell": "so long, partner!"
}
3 changes: 3 additions & 0 deletions command/deployment/testdata/deploy-params-env.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
USER=VELA
REPO=CLI
ORG=GO-VELA
Loading

0 comments on commit 05b0d75

Please sign in to comment.