Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): delete env locks #1901

Merged
merged 11 commits into from
Aug 22, 2024
2 changes: 2 additions & 0 deletions cli/pkg/cmd/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func RunCLI() ReturnCode {
return handleCreateTeamLock(*kpClientParams, subflags)
case "create-group-lock":
return handleCreateGroupLock(*kpClientParams, subflags)
case "delete-env-lock":
return handleDeleteEnvLock(*kpClientParams, subflags)
default:
log.Printf("unknown subcommand %s\n", subcommand)
return ReturnCodeInvalidArguments
Expand Down
22 changes: 16 additions & 6 deletions cli/pkg/cmd/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,24 @@ func handleRelease(kpClientParams kuberpultClientParameters, args []string) Retu
return ReturnCodeSuccess
}

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

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

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

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

func handleCreateAppLock(kpClientParams kuberpultClientParameters, args []string) ReturnCode {
Expand All @@ -70,7 +80,7 @@ func handleCreateAppLock(kpClientParams kuberpultClientParameters, args []string
log.Printf("error while parsing command line args, error: %v", err)
return ReturnCodeInvalidArguments
}
return handleCreateLock(kpClientParams, parsedArgs)
return handleLockRequest(kpClientParams, parsedArgs)
}

func handleCreateTeamLock(kpClientParams kuberpultClientParameters, args []string) ReturnCode {
Expand All @@ -80,7 +90,7 @@ func handleCreateTeamLock(kpClientParams kuberpultClientParameters, args []strin
log.Printf("error while parsing command line args, error: %v", err)
return ReturnCodeInvalidArguments
}
return handleCreateLock(kpClientParams, parsedArgs)
return handleLockRequest(kpClientParams, parsedArgs)
}

func handleCreateGroupLock(kpClientParams kuberpultClientParameters, args []string) ReturnCode {
Expand All @@ -90,10 +100,10 @@ func handleCreateGroupLock(kpClientParams kuberpultClientParameters, args []stri
log.Printf("error while parsing command line args, error: %v", err)
return ReturnCodeInvalidArguments
}
return handleCreateLock(kpClientParams, parsedArgs)
return handleLockRequest(kpClientParams, parsedArgs)
}

func handleCreateLock(kpClientParams kuberpultClientParameters, parsedArgs locks.LockParameters) ReturnCode {
func handleLockRequest(kpClientParams kuberpultClientParameters, parsedArgs locks.LockParameters) ReturnCode {
authParams := kutil.AuthenticationParameters{
IapToken: kpClientParams.iapToken,
DexToken: kpClientParams.dexToken,
Expand All @@ -107,7 +117,7 @@ func handleCreateLock(kpClientParams kuberpultClientParameters, parsedArgs locks
HttpTimeout: cli_utils.HttpDefaultTimeout,
}

if err := locks.CreateLock(requestParameters, authParams, parsedArgs); err != nil {
if err := locks.HandleLockRequest(requestParameters, authParams, parsedArgs); err != nil {
log.Printf("error creating lock, error: %v", err)
return ReturnCodeFailure
}
Expand Down
67 changes: 66 additions & 1 deletion cli/pkg/locks/env_lock_parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func convertToCreateEnvironmentLockParams(cmdArgs CreateEnvLockCommandLineArgume
return nil, fmt.Errorf("the provided command line arguments structure is invalid, cause: %s", msg)
}

rp := EnvironmentLockParameters{
rp := CreateEnvironmentLockParameters{
LockId: cmdArgs.lockId.Values[0],
Environment: cmdArgs.environment.Values[0],
UseDexAuthentication: false, //For now there is no ambiguity as to which endpoint to use
Expand All @@ -99,3 +99,68 @@ func ParseArgsCreateEnvironmentLock(args []string) (LockParameters, error) {

return rp, nil
}

type DeleteEnvLockCommandLineArguments struct {
environment cli_utils.RepeatedString
lockId cli_utils.RepeatedString
}

func argsValidDeleteEnvLock(cmdArgs *DeleteEnvLockCommandLineArguments) (result bool, errorMessage string) {
if len(cmdArgs.lockId.Values) != 1 {
return false, "the --lockID arg must be set exactly once"
}
if len(cmdArgs.environment.Values) != 1 {
return false, "the --environment 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 readDeleteEnvLockArgs(args []string) (*DeleteEnvLockCommandLineArguments, error) {
cmdArgs := DeleteEnvLockCommandLineArguments{} //exhaustruct:ignore

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

fs.Var(&cmdArgs.environment, "environment", "the environment to delete the lock for")
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 := argsValidDeleteEnvLock(&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 convertToDeleteEnvironmentLockParams(cmdArgs DeleteEnvLockCommandLineArguments) (LockParameters, error) {
if ok, msg := argsValidDeleteEnvLock(&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)
}
return &DeleteEnvironmentLockParameters{
LockId: cmdArgs.lockId.Values[0],
Environment: cmdArgs.environment.Values[0],
UseDexAuthentication: false,
}, nil
}

func ParseArgsDeleteEnvironmentLock(args []string) (LockParameters, error) {
cmdArgs, err := readDeleteEnvLockArgs(args)
if err != nil {
return nil, fmt.Errorf("error while reading command line arguments for deleting env locks, error: %w", err)
}
rp, err := convertToDeleteEnvironmentLockParams(*cmdArgs)
if err != nil {
return nil, fmt.Errorf("error while creating parameters for deleting an environment lock, error: %w", err)
}
return rp, nil
}
132 changes: 129 additions & 3 deletions cli/pkg/locks/env_lock_parsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,93 @@ func TestReadArgs(t *testing.T) {
}
}

func TestReadDeleteEnvLockArgs(t *testing.T) {
type testCase struct {
name string
args []string
expectedCmdArgs *DeleteEnvLockCommandLineArguments
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", "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 is properly provided but without --lockID",
args: []string{"--environment", "potato"},
expectedError: errMatcher{
msg: "the --lockID arg must be set exactly once",
},
},
{
name: "only --lockID is properly provided but without --environment",
args: []string{"--lockID", "potato"},
expectedError: errMatcher{
msg: "the --environment arg must be set exactly once",
},
},
{
name: "--message is not accepted",
args: []string{"--environment", "development", "--lockID", "my-lock", "--message", "\"my message\""},
expectedError: errMatcher{
msg: "error while parsing command line arguments, error: flag provided but not defined: -message",
},
},
{
name: "--environment, lockID are are specified, but not the message",
args: []string{"--environment", "development", "--lockID", "my-lock"},
expectedCmdArgs: &DeleteEnvLockCommandLineArguments{
environment: 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 := readDeleteEnvLockArgs(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(DeleteEnvLockCommandLineArguments{})); diff != "" {
t.Fatalf("expected args:\n %v\n, got:\n %v, diff:\n %s\n", tc.expectedCmdArgs, cmdArgs, diff)
}
})
}
}

func TestParseArgs(t *testing.T) {
type testCase struct {
name string
Expand All @@ -152,7 +239,7 @@ func TestParseArgs(t *testing.T) {
{
name: "with environment and lockID and message",
cmdArgs: []string{"--environment", "development", "--lockID", "my-lock", "--message", "message"},
expectedParams: &EnvironmentLockParameters{
expectedParams: &CreateEnvironmentLockParameters{
Environment: "development",
LockId: "my-lock",
Message: "message",
Expand All @@ -161,7 +248,7 @@ func TestParseArgs(t *testing.T) {
{
name: "with environment and lockID and no message",
cmdArgs: []string{"--environment", "development", "--lockID", "my-lock"},
expectedParams: &EnvironmentLockParameters{
expectedParams: &CreateEnvironmentLockParameters{
Environment: "development",
LockId: "my-lock",
Message: "",
Expand All @@ -171,7 +258,7 @@ func TestParseArgs(t *testing.T) {
{
name: "with environment and lockID and multi word message message",
cmdArgs: []string{"--environment", "development", "--lockID", "my-lock", "--message", "this is a very long message"},
expectedParams: &EnvironmentLockParameters{
expectedParams: &CreateEnvironmentLockParameters{
Environment: "development",
LockId: "my-lock",
Message: "this is a very long message",
Expand All @@ -197,3 +284,42 @@ func TestParseArgs(t *testing.T) {
})
}
}

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

tcs := []testCase{
{
name: "with environment and lockID and message",
cmdArgs: []string{"--environment", "development", "--lockID", "my-lock"},
expectedParams: &DeleteEnvironmentLockParameters{
Environment: "development",
LockId: "my-lock",
UseDexAuthentication: false,
},
},
}

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

params, err := ParseArgsDeleteEnvironmentLock(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)
}
})
}
}
Loading
Loading