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#681
  • Loading branch information
DaanRosendal committed Mar 13, 2024
1 parent 3b90a67 commit 98994a7
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 1 deletion.
3 changes: 2 additions & 1 deletion docs/cmd_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ Workflow execution commands:
validate Validate workflow specification file.

Workflow sharing commands:
share-add Share a workflow with other users (read-only).
share-add Share a workflow with other users (read-only).
share-remove Unshare a workflow.

Workspace interactive commands:
close Close an interactive session.
Expand Down
38 changes: 38 additions & 0 deletions reana_client/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1327,3 +1327,41 @@ def share_workflow(
f"Message: {e.response.json()['message']}"
)
raise Exception(e.response.json()["message"])


def unshare_workflow(workflow, user_email_to_unshare_with, access_token):
"""Unshare a workflow with a user.
:param workflow: name or id of the workflow.
:param user_email_to_unshare_with: user to unshare the workflow with.
:param access_token: access token of the current user.
:return: a dictionary containing the ``workflow_id``, ``workflow_name``, and
a ``message`` key with the result of the operation.
"""
try:
unshare_params = {
"workflow_id_or_name": workflow,
"user_email_to_unshare_with": user_email_to_unshare_with,
"access_token": access_token,
}

(response, http_response) = current_rs_api_client.api.unshare_workflow(
**unshare_params
).result()

if http_response.status_code == 200:
return response
else:
raise Exception(
"Expected status code 200 but replied with "
f"{http_response.status_code}"
)

except HTTPError as e:
logging.debug(
"Workflow could not be unshared: "
f"\nStatus: {e.response.status_code}\nReason: {e.response.reason}\n"
f"Message: {e.response.json()['message']}"
)
raise Exception(e.response.json()["message"])
61 changes: 61 additions & 0 deletions reana_client/cli/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1544,3 +1544,64 @@ def share_workflow_add(

else:
display_message(f"Cannot find workflow {workflow}", msg_type="error")


@workflow_sharing_group.command("share-remove")
@check_connection
@add_workflow_option
@add_access_token_options
@click.option(
"-u",
"--user",
"users",
multiple=True,
help="Users to unshare the workflow with.",
required=True,
)
@click.pass_context
def share_workflow_remove(ctx, workflow, access_token, users): # noqa D412
"""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
"""
from reana_client.api.client import unshare_workflow

unshare_errors = []
unshared_users = []

if workflow:
try:
for user in users:
try:
logging.info(f"Unsharing workflow {workflow} with user {user}")
unshare_workflow(workflow, user, access_token)
unshared_users.append(user)
except Exception as e:
unshare_errors.append(
f"Failed to unshare {workflow} with {user}: {str(e)}"
)
logging.debug(traceback.format_exc())
except Exception as e:
logging.debug(traceback.format_exc())
logging.debug(str(e))
display_message(
"An error occurred while unsharing workflow:\n{}".format(str(e)),
msg_type="error",
)

if unshared_users:
display_message(
f"{workflow} is no longer shared with {', '.join(unshared_users)}",
msg_type="success",
)
if unshare_errors:
for error in unshare_errors:
display_message(error, msg_type="error")

else:
display_message(f"Cannot find workflow {workflow}", msg_type="error")
35 changes: 35 additions & 0 deletions tests/test_cli_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -1049,3 +1049,38 @@ def test_share_add_workflow():
)
assert result.exit_code == 0
assert response["message"] in result.output


def test_share_remove_workflow():
"""Test share-remove workflows."""
status_code = 200
response = {
"message": "is no longer shared with",
"workflow_id": "string",
"workflow_name": "string",
}
env = {"REANA_SERVER_URL": "localhost"}
mock_http_response, mock_response = Mock(), Mock()
mock_http_response.status_code = status_code
mock_response = response
reana_token = "000000"
runner = CliRunner(env=env)
with runner.isolation():
with patch(
"reana_client.api.client.current_rs_api_client",
make_mock_api_client("reana-server")(mock_response, mock_http_response),
):
result = runner.invoke(
cli,
[
"share-remove",
"-t",
reana_token,
"--workflow",
"test-workflow.1",
"--user",
"bob@.cern.ch",
],
)
assert result.exit_code == 0
assert response["message"] in result.output

0 comments on commit 98994a7

Please sign in to comment.