Skip to content

Commit

Permalink
feat(cli): delete group locks (#1904)
Browse files Browse the repository at this point in the history
Ref: SRX-BUU4S5
  • Loading branch information
miguel-crespo-fdc authored Aug 23, 2024
1 parent c9cf7e5 commit f9fa0cd
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 8 deletions.
2 changes: 2 additions & 0 deletions cli/pkg/cmd/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ func RunCLI() ReturnCode {
return handleDeleteAppLock(*kpClientParams, subflags)
case "delete-team-lock":
return handleDeleteTeamLock(*kpClientParams, subflags)
case "delete-group-lock":
return handleDeleteGroupLock(*kpClientParams, subflags)
default:
log.Printf("unknown subcommand %s\n", subcommand)
return ReturnCodeInvalidArguments
Expand Down
10 changes: 10 additions & 0 deletions cli/pkg/cmd/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ func handleCreateGroupLock(kpClientParams kuberpultClientParameters, args []stri
return handleLockRequest(kpClientParams, parsedArgs)
}

func handleDeleteGroupLock(kpClientParams kuberpultClientParameters, args []string) ReturnCode {
parsedArgs, err := locks.ParseArgsDeleteGroupLock(args)

if err != nil {
log.Printf("error while parsing command line args, error: %v", err)
return ReturnCodeInvalidArguments
}
return handleLockRequest(kpClientParams, parsedArgs)
}

func handleLockRequest(kpClientParams kuberpultClientParameters, parsedArgs locks.LockParameters) ReturnCode {
authParams := kutil.AuthenticationParameters{
IapToken: kpClientParams.iapToken,
Expand Down
70 changes: 69 additions & 1 deletion cli/pkg/locks/group_lock_parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func convertToCreateGroupLockParams(cmdArgs CreateEnvGroupLockCommandLineArgumen
return nil, fmt.Errorf("the provided command line arguments structure is invalid, cause: %s", msg)
}

rp := EnvironmentGroupLockParameters{
rp := CreateEnvironmentGroupLockParameters{
LockId: cmdArgs.lockId.Values[0],
EnvironmentGroup: cmdArgs.environmentGroup.Values[0],
UseDexAuthentication: false, //For now there is no ambiguity as to which endpoint to use
Expand All @@ -99,3 +99,71 @@ func ParseArgsCreateGroupLock(args []string) (LockParameters, error) {

return rp, nil
}

type DeleteEnvGroupLockCommandLineArguments struct {
environmentGroup cli_utils.RepeatedString
lockId cli_utils.RepeatedString
}

func argsValidDeleteEnvGroupLock(cmdArgs *DeleteEnvGroupLockCommandLineArguments) (result bool, errorMessage string) {
if len(cmdArgs.lockId.Values) != 1 {
return false, "the --lockID arg must be set exactly once"
}
if len(cmdArgs.environmentGroup.Values) != 1 {
return false, "the --environment-group arg must be set exactly once"
}

return true, ""
}

// takes the raw command line flags and converts them to an intermediate represnetations for easy validation
func readDeleteGroupLockArgs(args []string) (*DeleteEnvGroupLockCommandLineArguments, error) {
cmdArgs := DeleteEnvGroupLockCommandLineArguments{} //exhaustruct:ignore

fs := flag.NewFlagSet("flag set", flag.ContinueOnError)

fs.Var(&cmdArgs.environmentGroup, "environment-group", "the environment-group of the lock you are trying to delete")
fs.Var(&cmdArgs.lockId, "lockID", "the ID of the lock you are trying to delete")

if err := fs.Parse(args); err != nil {
return nil, fmt.Errorf("error while parsing command line arguments, error: %w", err)
}

if len(fs.Args()) != 0 { // kuberpult-cli release does not accept any positional arguments, so this is an error
return nil, fmt.Errorf("these arguments are not recognized: \"%v\"", strings.Join(fs.Args(), " "))
}

if ok, msg := argsValidDeleteEnvGroupLock(&cmdArgs); !ok {
return nil, fmt.Errorf(msg)
}

return &cmdArgs, nil
}

// converts the intermediate representation of the command line flags into the final structure containing parameters for the create lock endpoint
func convertToDeleteGroupLockParams(cmdArgs DeleteEnvGroupLockCommandLineArguments) (LockParameters, error) {
if ok, msg := argsValidDeleteEnvGroupLock(&cmdArgs); !ok {
// this should never happen, as the validation is already performed by the readArgs function
return nil, fmt.Errorf("the provided command line arguments structure is invalid, cause: %s", msg)
}

rp := DeleteEnvironmentGroupLockParameters{
LockId: cmdArgs.lockId.Values[0],
EnvironmentGroup: cmdArgs.environmentGroup.Values[0],
UseDexAuthentication: false, //For now there is no ambiguity as to which endpoint to use
}
return &rp, nil
}

func ParseArgsDeleteGroupLock(args []string) (LockParameters, error) {
cmdArgs, err := readDeleteGroupLockArgs(args)
if err != nil {
return nil, fmt.Errorf("error while reading command line arguments for deleting an environment group lock, error: %w", err)
}
rp, err := convertToDeleteGroupLockParams(*cmdArgs)
if err != nil {
return nil, fmt.Errorf("error while creating parameters for deleting an environment group lock, error: %w", err)
}

return rp, nil
}
124 changes: 121 additions & 3 deletions cli/pkg/locks/group_lock_parsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,86 @@ func TestReadGroupLockArgs(t *testing.T) {
}
}

func TestReadDeleteGroupLockArgs(t *testing.T) {
type testCase struct {
name string
args []string
expectedCmdArgs *DeleteEnvGroupLockCommandLineArguments
expectedError error
}

tcs := []testCase{
{
name: "some unrecognized positional arguments",
args: []string{"potato", "tomato"},
expectedError: errMatcher{
msg: "these arguments are not recognized: \"potato tomato\"",
},
},
{
name: "some flags that don't exist",
args: []string{"--environment-group", "development", "--potato", "tomato"},
expectedError: errMatcher{
msg: "error while parsing command line arguments, error: flag provided but not defined: -potato",
},
},
{
name: "nothing provided",
args: []string{},
expectedError: errMatcher{
msg: "the --lockID arg must be set exactly once",
},
},
{
name: "only --environment-group is properly provided but without --lockID",
args: []string{"--environment-group", "potato"},
expectedError: errMatcher{
msg: "the --lockID arg must be set exactly once",
},
},
{
name: "only --lockID is properly provided but without --environment-group",
args: []string{"--lockID", "potato"},
expectedError: errMatcher{
msg: "the --environment-group arg must be set exactly once",
},
},
{
name: "--environment-group and lockID",
args: []string{"--environment-group", "development", "--lockID", "my-lock"},
expectedCmdArgs: &DeleteEnvGroupLockCommandLineArguments{
environmentGroup: cli_utils.RepeatedString{
Values: []string{
"development",
},
},
lockId: cli_utils.RepeatedString{
Values: []string{
"my-lock",
},
},
},
},
}

for _, tc := range tcs {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

cmdArgs, err := readDeleteGroupLockArgs(tc.args)
// check errors
if diff := cmp.Diff(tc.expectedError, err, cmpopts.EquateErrors()); diff != "" {
t.Fatalf("error mismatch (-want, +got):\n%s", diff)
}

if diff := cmp.Diff(cmdArgs, tc.expectedCmdArgs, cmp.AllowUnexported(DeleteEnvGroupLockCommandLineArguments{})); diff != "" {
t.Fatalf("expected args:\n %v\n, got:\n %v, diff:\n %s\n", tc.expectedCmdArgs, cmdArgs, diff)
}
})
}
}

func TestParseEnvGroupArgs(t *testing.T) {
type testCase struct {
name string
Expand All @@ -139,7 +219,7 @@ func TestParseEnvGroupArgs(t *testing.T) {
{
name: "with environment and lockID and message",
cmdArgs: []string{"--environment-group", "development", "--lockID", "my-lock", "--message", "message"},
expectedParams: &EnvironmentGroupLockParameters{
expectedParams: &CreateEnvironmentGroupLockParameters{
EnvironmentGroup: "development",
LockId: "my-lock",
Message: "message",
Expand All @@ -148,7 +228,7 @@ func TestParseEnvGroupArgs(t *testing.T) {
{
name: "with environment and lockID and no message",
cmdArgs: []string{"--environment-group", "development", "--lockID", "my-lock"},
expectedParams: &EnvironmentGroupLockParameters{
expectedParams: &CreateEnvironmentGroupLockParameters{
EnvironmentGroup: "development",
LockId: "my-lock",
Message: "",
Expand All @@ -158,7 +238,7 @@ func TestParseEnvGroupArgs(t *testing.T) {
{
name: "with environment and lockID and multi word message message",
cmdArgs: []string{"--environment-group", "development", "--lockID", "my-lock", "--message", "this is a very long message"},
expectedParams: &EnvironmentGroupLockParameters{
expectedParams: &CreateEnvironmentGroupLockParameters{
EnvironmentGroup: "development",
LockId: "my-lock",
Message: "this is a very long message",
Expand All @@ -184,3 +264,41 @@ func TestParseEnvGroupArgs(t *testing.T) {
})
}
}

func TestParseDeleteEnvGroupArgs(t *testing.T) {
type testCase struct {
name string
cmdArgs []string
expectedParams LockParameters
expectedError error
}

tcs := []testCase{
{
name: "with environment groups and lockID",
cmdArgs: []string{"--environment-group", "development", "--lockID", "my-lock"},
expectedParams: &DeleteEnvironmentGroupLockParameters{
EnvironmentGroup: "development",
LockId: "my-lock",
},
},
}

for _, tc := range tcs {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

params, err := ParseArgsDeleteGroupLock(tc.cmdArgs)
// check errors
if diff := cmp.Diff(tc.expectedError, err, cmpopts.EquateErrors()); diff != "" {
t.Fatalf("error mismatch (-want, +got):\n%s", diff)
}

// check result
if diff := cmp.Diff(tc.expectedParams, params); diff != "" {
t.Fatalf("expected args:\n %v\n, got:\n %v\n, diff:\n %s\n", tc.expectedParams, params, diff)
}
})
}
}
26 changes: 22 additions & 4 deletions cli/pkg/locks/lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,17 @@ type DeleteTeamLockParameters struct {
UseDexAuthentication bool
}

type EnvironmentGroupLockParameters struct {
type CreateEnvironmentGroupLockParameters struct {
EnvironmentGroup string
LockId string
Message string
UseDexAuthentication bool
}
type DeleteEnvironmentGroupLockParameters struct {
EnvironmentGroup string
LockId string
UseDexAuthentication bool
}

type LockJsonData struct {
Message string `json:"message"`
Expand Down Expand Up @@ -111,11 +116,11 @@ func (e *CreateEnvironmentLockParameters) FillHttpInfo() (*HttpInfo, error) {
d := LockJsonData{
Message: e.Message,
}

var jsonData, err = json.Marshal(d)
if err != nil {
return nil, fmt.Errorf("Could not EnvironmentLockParameters data to json: %w\n", err)
}

prefix := "environments"
if e.UseDexAuthentication {
prefix = "api/environments"
Expand Down Expand Up @@ -207,13 +212,13 @@ func (e *DeleteTeamLockParameters) FillHttpInfo() (*HttpInfo, error) {
}, nil
}

func (e *EnvironmentGroupLockParameters) FillHttpInfo() (*HttpInfo, error) {
func (e *CreateEnvironmentGroupLockParameters) FillHttpInfo() (*HttpInfo, error) {
d := LockJsonData{
Message: e.Message,
}
var jsonData, err = json.Marshal(d)
if err != nil {
return nil, fmt.Errorf("Could not marshal EnvironmentGroupLockParameters data to json: %w\n", err)
return nil, fmt.Errorf("Could not marshal CreateEnvironmentGroupLockParameters data to json: %w\n", err)
}
prefix := "environment-groups"
if e.UseDexAuthentication {
Expand All @@ -227,6 +232,19 @@ func (e *EnvironmentGroupLockParameters) FillHttpInfo() (*HttpInfo, error) {
}, nil
}

func (e *DeleteEnvironmentGroupLockParameters) FillHttpInfo() (*HttpInfo, error) {
prefix := "environment-groups"
if e.UseDexAuthentication {
prefix = "api/environment-groups"
}
return &HttpInfo{
jsonData: []byte{},
ContentType: "application/json",
HttpMethod: http.MethodDelete,
RestPath: fmt.Sprintf("%s/%s/locks/%s", prefix, e.EnvironmentGroup, e.LockId),
}, nil
}

func createHttpRequest(url string, authParams kutil.AuthenticationParameters, requestInfo *HttpInfo) (*http.Request, error) {
urlStruct, err := urllib.Parse(url)
if err != nil {
Expand Down

0 comments on commit f9fa0cd

Please sign in to comment.