Skip to content

Commit

Permalink
cli: implement share-remove command
Browse files Browse the repository at this point in the history
Adds a new command to the CLI to unshare a workflow.

Closes reanahub/reana-client#681
  • Loading branch information
DaanRosendal committed Nov 8, 2023
1 parent e96dbf9 commit bd6a677
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ func NewRootCmd() *cobra.Command {
Message: "Workflow sharing commands:",
Commands: []*cobra.Command{
newShareAddCmd(),
newShareRemoveCmd(),
},
},
{
Expand Down
119 changes: 119 additions & 0 deletions cmd/share_remove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
This file is part of REANA.
Copyright (C) 2023 CERN.
REANA is free software; you can redistribute it and/or modify it
under the terms of the MIT License; see LICENSE file for more details.
*/

package cmd

import (
"fmt"
"reanahub/reana-client-go/client"
"reanahub/reana-client-go/client/operations"
"reanahub/reana-client-go/pkg/displayer"
"reanahub/reana-client-go/pkg/errorhandler"
"strings"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

const shareRemoveDesc = `Unshare a workflow.
The ` + `share-remove` + ` command allows for unsharing a workflow. The workflow
will no longer be visible to the users with whom it was shared.
Example:
$ reana-client share-remove -w myanalysis.42 --user bob@example.org
`

type shareRemoveOptions struct {
token string
workflow string
users []string
}

// newShareRemoveCmd creates a command to unshare a workflow.
func newShareRemoveCmd() *cobra.Command {
o := &shareRemoveOptions{}

cmd := &cobra.Command{
Use: "share-remove",
Short: "Unshare a workflow.",
Long: shareRemoveDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return o.run(cmd)
},
}

f := cmd.Flags()
f.StringVarP(
&o.workflow,
"workflow",
"w",
"",
`Name or UUID of the workflow. Overrides value of
REANA_WORKON environment variable.`,
)
f.StringVarP(&o.token, "access-token", "t", "", "Access token of the current user.")
f.StringSliceVarP(&o.users, "user", "u", []string{}, `Users to unshare the workflow with.`)
// Remove -h shorthand
cmd.PersistentFlags().BoolP("help", "h", false, "Help for share-remove")

return cmd
}

func (o *shareRemoveOptions) run(cmd *cobra.Command) error {
shareRemoveParams := operations.NewUnshareWorkflowParams()
shareRemoveParams.SetAccessToken(&o.token)
shareRemoveParams.SetWorkflowIDOrName(o.workflow)

api, err := client.ApiClient()
if err != nil {
return err
}

shareErrors := []string{}
sharedUsers := []string{}

for _, user := range o.users {
log.Infof("Unsharing workflow %s with user %s", o.workflow, user)

shareRemoveParams.SetUserEmailToUnshareWith(user)
_, err := api.Operations.UnshareWorkflow(shareRemoveParams)

if err != nil {
err := errorhandler.HandleApiError(err)
shareErrors = append(
shareErrors,
fmt.Sprintf("Failed to unshare %s with %s: %s", o.workflow, user, err.Error()),
)
} else {
sharedUsers = append(sharedUsers, user)
}
}

if len(sharedUsers) > 0 {
displayer.DisplayMessage(
fmt.Sprintf(
"%s is no longer shared with %s",
o.workflow,
strings.Join(sharedUsers, ", "),
),
displayer.Success,
false,
cmd.OutOrStdout(),
)
}
if len(shareErrors) > 0 {
for _, err := range shareErrors {
displayer.DisplayMessage(err, displayer.Error, false, cmd.OutOrStdout())
}
}

return nil
}
56 changes: 56 additions & 0 deletions cmd/share_remove_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
This file is part of REANA.
Copyright (C) 2023 CERN.
REANA is free software; you can redistribute it and/or modify it under the terms
of the MIT License; see LICENSE file for more details.
*/

package cmd

import (
"fmt"
"net/http"
"testing"
)

var shareRemovePathTemplate = "/api/workflows/%s/unshare"

func TestShareRemove(t *testing.T) {
workflowName := "my_workflow"
tests := map[string]TestCmdParams{
"default": {
serverResponses: map[string]ServerResponse{
fmt.Sprintf(shareRemovePathTemplate, workflowName): {
statusCode: http.StatusOK,
},
},
args: []string{"-w", workflowName, "--user", "bob@cern.ch"},
expected: []string{
"my_workflow is no longer shared with bob@cern.ch",
},
},
"invalid workflow": {
serverResponses: map[string]ServerResponse{
fmt.Sprintf(shareRemovePathTemplate, "invalid"): {
statusCode: http.StatusNotFound,
responseFile: "common_invalid_workflow.json",
},
},
args: []string{
"-w", "invalid",
"--user", "bob@cern.ch",
},
expected: []string{
"REANA_WORKON is set to invalid, but that workflow does not exist.",
},
},
}

for name, params := range tests {
t.Run(name, func(t *testing.T) {
params.cmd = "share-remove"
testCmdRun(t, params)
})
}
}

0 comments on commit bd6a677

Please sign in to comment.