Skip to content

Commit

Permalink
Update deployment parameters to handle database and web connections.
Browse files Browse the repository at this point in the history
  • Loading branch information
garnold54 committed Mar 19, 2024
1 parent f88e5cc commit d3d110c
Show file tree
Hide file tree
Showing 7 changed files with 489 additions and 42 deletions.
49 changes: 49 additions & 0 deletions cmd/deploymentparameterTypeFlag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cmd

import (
"errors"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

type deploymentParameterTypeFlag string

const (
deploymentParameterTypeFlagText deploymentParameterTypeFlag = "text"
deploymentParameterTypeFlagDatabase deploymentParameterTypeFlag = "database"
deploymentParameterTypeFlagWeb deploymentParameterTypeFlag = "web"
)

// String is used both by fmt.Print and by Cobra in help text
func (e *deploymentParameterTypeFlag) String() string {
return string(*e)
}

// Set must have pointer receiver so it doesn't change the value of a copy
func (e *deploymentParameterTypeFlag) Set(v string) error {
switch v {
case "text", "database", "web":
*e = deploymentParameterTypeFlag(v)
return nil
default:
return errors.New(`must be one of "text" or "database" or "web"`)
}
}

// Type is only used in help text
func (e *deploymentParameterTypeFlag) Type() string {
return "string"
}

// https://github.com/uber-go/guide/blob/master/style.md#verify-interface-compliance
var _ pflag.Value = (*apiVersionFlag)(nil)

// enable tab completion
func deploymentParameterTypeFlagCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{
"text\ttext deployment parameter type",
"database\tdatabase connection deployment parameter type",
"web\tweb connection deployment parameter type",
}, cobra.ShellCompDirectiveDefault
}
17 changes: 12 additions & 5 deletions cmd/deploymentparameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ type DeploymentParameters struct {
}

type DeploymentParameter struct {
Name string `json:"name"`
Owner string `json:"owner"`
Type string `json:"type"`
Updated time.Time `json:"updated"`
Value string `json:"value"`
Name string `json:"name"`
Owner string `json:"owner"`
Type string `json:"type"`
Updated time.Time `json:"updated"`
Value string `json:"value"`
ResourceMissing bool `json:"resourceMissing"`
ChoiceSettings struct {
ChoiceSet string `json:"choiceSet"`
Services []string `json:"services"`
ExcludedServices []string `json:"excludedServices"`
Family string `json:"family"`
} `json:"choiceSettings,omitempty"`
}

type deploymentparametersFlags struct {
Expand Down
65 changes: 53 additions & 12 deletions cmd/deploymentparameters_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,24 @@ import (
)

type NewDeplymentParameter struct {
Type string `json:"type"`
Name string `json:"name"`
Value string `json:"value"`
Name string `json:"name"`
Type string `json:"type"`
Value string `json:"value"`
ChoiceSettings struct {
ChoiceSet string `json:"choiceSet"`
Services []string `json:"services,omitempty"`
ExcludedServices []string `json:"excludedServices,omitempty"`
Family string `json:"family,omitempty"`
} `json:"choiceSettings,omitempty"`
}

type deploymentParameterCreateFlags struct {
dpType string
value string
name string
dpType deploymentParameterTypeFlag
value string
name string
dbType string
includedServices []string
excludedServices []string
}

func newDeploymentParameterCreateCmd() *cobra.Command {
Expand All @@ -39,26 +48,58 @@ func newDeploymentParameterCreateCmd() *cobra.Command {
RunE: deploymentParametersCreateRun(&f),
}

cmd.Flags().StringVar(&f.dpType, "type", "text", "Type of parameter")
cmd.Flags().Var(&f.dpType, "type", "Type of parameter to create. Must be one of text, database, or web. Default is text.")
cmd.Flags().StringVar(&f.name, "name", "", "Name of the deployment parameter to create.")
cmd.Flags().StringVar(&f.value, "value", "", "The value to set the deployment parameter to.")
// currently type can only be set to "text". But in the future maybe there will be more options?
cmd.Flags().MarkHidden("type")
cmd.Flags().StringVar(&f.value, "value", "", "The value to set the deployment parameter to. (Optional)")
cmd.Flags().StringArrayVar(&f.includedServices, "included-service", []string{}, "Service to include in the deployment parameter. Can be passed in multiple times if there are multiple Web services to include.")
cmd.Flags().StringArrayVar(&f.excludedServices, "excluded-service", []string{}, "Service to exclude in the deployment parameter. Can be passed in multiple times if there are multiple Web services to exclude.")
cmd.Flags().StringVar(&f.dbType, "database-type", "", "The type of the database to use for the database deployment parameter. (Optional)")
cmd.RegisterFlagCompletionFunc("type", deploymentParameterTypeFlagCompletion)
cmd.MarkFlagRequired("name")
cmd.MarkFlagRequired("value")
return cmd
}

func deploymentParametersCreateRun(f *deploymentParameterCreateFlags) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {

if f.dpType == "" {
f.dpType = deploymentParameterTypeFlagText
}

// if type isnot web and includeServices or excludedServices is set, then error
if f.dpType != deploymentParameterTypeFlagWeb && (len(f.includedServices) > 0 || len(f.excludedServices) > 0) {
return errors.New("cannot include or exclude services for a non-web connection deployment parameter")
}

// if the type is not database and dbType is set, then error
if f.dpType != deploymentParameterTypeFlagDatabase && f.dbType != "" {
return errors.New("cannot set a database family for a non-database deployment parameter")
}

// set up http
client := &http.Client{}

var newDepParam NewDeplymentParameter
newDepParam.Name = f.name
newDepParam.Value = f.value
newDepParam.Type = f.dpType

// set type specific settings
if f.dpType == deploymentParameterTypeFlagDatabase {
newDepParam.Type = "dropdown"
newDepParam.ChoiceSettings.ChoiceSet = "dbConnections"
if f.dbType != "" {
newDepParam.ChoiceSettings.Family = f.dbType
}
} else if f.dpType == deploymentParameterTypeFlagWeb {
newDepParam.Type = "dropdown"
newDepParam.ChoiceSettings.ChoiceSet = "webConnections"
newDepParam.ChoiceSettings.Services = f.includedServices
newDepParam.ChoiceSettings.ExcludedServices = f.excludedServices
} else {
// text type just sets type and nothing else
newDepParam.Type = f.dpType.String()
}

jsonData, err := json.Marshal(newDepParam)
if err != nil {
return err
Expand Down
54 changes: 48 additions & 6 deletions cmd/deploymentparameters_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,9 @@ func TestDeploymentParametersCreate(t *testing.T) {
},
{
name: "missing name flag",
wantErrText: "required flag(s) \"name\", \"value\" not set",
wantErrText: "required flag(s) \"name\" not set",
args: []string{"deploymentparameters", "create"},
},
{
name: "missing value flag",
wantErrText: "required flag(s) \"value\" not set",
args: []string{"deploymentparameters", "create", "--name", "myDep"},
},
{
name: "create parameter",
statusCode: http.StatusCreated,
Expand All @@ -45,6 +40,53 @@ func TestDeploymentParametersCreate(t *testing.T) {
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue"},
wantErrText: "A deployment parameter with name \"myDep\" already exists.",
},
{
name: "create parameter with invalid type",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "invalid"},
wantErrOutputRegex: "invalid argument \"invalid\" for \"--type\" flag: must be one of \"text\" or \"database\" or \"web\"",
},
{
name: "create parameter with text type",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "text"},
wantOutputRegex: "^Deployment Parameter successfully created.[\\s]*$",
},
{
name: "create parameter with web type",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "web"},
wantBodyRegEx: `{"name":"myDep","type":"dropdown","value":"myValue","choiceSettings":{"choiceSet":"webConnections"}}`,
wantOutputRegex: "^Deployment Parameter successfully created.[\\s]*$",
},
{
name: "create parameter with web type and included services",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "web", "--included-service", "service1", "--included-service", "service2"},
wantBodyRegEx: `{"name":"myDep","type":"dropdown","value":"myValue","choiceSettings":{"choiceSet":"webConnections","services":\["service1","service2"\]}}`,
wantOutputRegex: "^Deployment Parameter successfully created.[\\s]*$",
},
{
name: "create parameter with web type and excluded services",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "web", "--excluded-service", "service1", "--excluded-service", "service2"},
wantBodyRegEx: `{"name":"myDep","type":"dropdown","value":"myValue","choiceSettings":{"choiceSet":"webConnections","excludedServices":\["service1","service2"\]}}`,
wantOutputRegex: "^Deployment Parameter successfully created.[\\s]*$",
},
{
name: "create parameter with db type",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "database"},
wantBodyRegEx: `{"name":"myDep","type":"dropdown","value":"myValue","choiceSettings":{"choiceSet":"dbConnections"}}`,
wantOutputRegex: "^Deployment Parameter successfully created.[\\s]*$",
},
{
name: "create parameter with db type and dbType flag",
statusCode: http.StatusCreated,
args: []string{"deploymentparameters", "create", "--name", "myDep", "--value", "myValue", "--type", "database", "--database-type", "dbType"},
wantBodyRegEx: `{"name":"myDep","type":"dropdown","value":"myValue","choiceSettings":{"choiceSet":"dbConnections","family":"dbType"}}`,
wantOutputRegex: "^Deployment Parameter successfully created.[\\s]*$",
},
}

runTests(cases, t)
Expand Down
50 changes: 40 additions & 10 deletions cmd/deploymentparameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,45 @@ func TestDeploymentParameters(t *testing.T) {
"value": "myVal",
"type": "text",
"owner": "admin",
"resourceMissing": false,
"updated": "2023-01-18T23:04:25.764Z"
},
{
"name": "test",
"value": "test value",
"type": "text",
"type": "dropdown",
"name": "testdb",
"value": "db",
"type": "dropdown",
"owner": "admin",
"updated": "2024-03-12T20:39:12.149Z",
"resourceMissing": false,
"choiceSettings": {
"choiceSet": "dbConnections",
"family": "PostgreSQL"
}
},
{
"type": "dropdown",
"name": "testweb",
"value": "aaa",
"type": "dropdown",
"owner": "admin",
"updated": "2023-01-19T17:56:54.472Z"
}
"updated": "2024-03-15T17:42:56.752Z",
"resourceMissing": true,
"choiceSettings": {
"choiceSet": "webConnections",
"services": [
"Slack"
]
}
}
],
"totalCount": 2,
"totalCount": 3,
"limit": 100,
"offset": 0
}`

responseSingle := `{
responseSingleText := `{
"name": "myDep",
"value": "myVal",
"type": "text",
Expand All @@ -54,7 +77,7 @@ func TestDeploymentParameters(t *testing.T) {
statusCode: http.StatusOK,
args: []string{"deploymentparameters"},
body: response,
wantOutputRegex: "^[\\s]*NAME[\\s]*OWNER[\\s]*TYPE[\\s]*VALUE[\\s]*LAST UPDATED[\\s]*myDep[\\s]*admin[\\s]*text[\\s]*myVal[\\s]*2023-01-18 23:04:25.764 \\+0000 UTC[\\s]*test[\\s]*admin[\\s]*text[\\s]*test[\\s]*value[\\s]*2023-01-19 17:56:54.472 \\+0000 UTC[\\s]*$",
wantOutputRegex: "^[\\s]*NAME[\\s]*OWNER[\\s]*TYPE[\\s]*VALUE[\\s]*LAST UPDATED[\\s]*myDep[\\s]*admin[\\s]*text[\\s]*myVal[\\s]*2023-01-18 23:04:25.764 \\+0000 UTC[\\s]*testdb[\\s]*admin[\\s]*dropdown[\\s]*db[\\s]*2024-03-12 20:39:12.149 \\+0000 UTC[\\s]*testweb[\\s]*admin[\\s]*dropdown[\\s]*aaa[\\s]*2024-03-15 17:42:56.752 \\+0000 UTC[\\s]*$",
},
{
name: "get deployment parameters json output",
Expand All @@ -66,7 +89,7 @@ func TestDeploymentParameters(t *testing.T) {
{
name: "get single parameter",
statusCode: http.StatusOK,
body: responseSingle,
body: responseSingleText,
args: []string{"deploymentparameters", "--name", "myDep"},
wantOutputRegex: "^[\\s]*NAME[\\s]*OWNER[\\s]*TYPE[\\s]*VALUE[\\s]*LAST UPDATED[\\s]*myDep[\\s]*admin[\\s]*text[\\s]*myVal[\\s]*2023-01-18 23:04:25.764 \\+0000 UTC[\\s]*$",
},
Expand All @@ -75,7 +98,14 @@ func TestDeploymentParameters(t *testing.T) {
statusCode: http.StatusOK,
args: []string{"repositories", "--output=custom-columns=NAME:.name"},
body: response,
wantOutputRegex: "^[\\s]*NAME[\\s]*myDep[\\s]*test[\\s]*$",
wantOutputRegex: "^[\\s]*NAME[\\s]*myDep[\\s]*testdb[\\s]*testweb[\\s]*$",
},
{
name: "get deployment parameters custom columns no headers V4",
statusCode: http.StatusOK,
args: []string{"repositories", "--output=custom-columns=NAME:.name", "--no-headers"},
body: response,
wantOutputRegex: "^[\\s]*myDep[\\s]*testdb[\\s]*testweb[\\s]*$",
},
}

Expand Down
Loading

0 comments on commit d3d110c

Please sign in to comment.