cloudos-cli 2.33.0__tar.gz → 2.35.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/PKG-INFO +50 -1
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/README.md +49 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/__main__.py +248 -2
- cloudos_cli-2.35.0/cloudos_cli/_version.py +1 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/datasets/datasets.py +85 -1
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/PKG-INFO +50 -1
- cloudos_cli-2.33.0/cloudos_cli/_version.py +0 -1
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/LICENSE +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/clos.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/configure/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/configure/configure.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/datasets/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/import_wf/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/import_wf/import_wf.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/jobs/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/jobs/job.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/queue/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/queue/queue.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/cloud.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/details.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/errors.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/requests.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/resources.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/SOURCES.txt +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/dependency_links.txt +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/entry_points.txt +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/requires.txt +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/top_level.txt +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/setup.cfg +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/setup.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/tests/__init__.py +0 -0
- {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/tests/functions_for_pytest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudos_cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.35.0
|
|
4
4
|
Summary: Python package for interacting with CloudOS
|
|
5
5
|
Home-page: https://github.com/lifebit-ai/cloudos-cli
|
|
6
6
|
Author: David Piñeyro
|
|
@@ -1007,6 +1007,55 @@ Please, be aware that renaming can only happen in files and folders that are pre
|
|
|
1007
1007
|
|
|
1008
1008
|
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
1009
1009
|
|
|
1010
|
+
```bash
|
|
1011
|
+
--cloudos-url $CLOUDOS \
|
|
1012
|
+
--apikey $MY_API_KEY \
|
|
1013
|
+
--workspace-id $WORKSPACE_ID \
|
|
1014
|
+
--project-name $PROJEC_NAME
|
|
1015
|
+
```
|
|
1016
|
+
#### Create a (virtual) folder
|
|
1017
|
+
|
|
1018
|
+
New folders can be created within the `Data` dataset and its subfolders using the following command
|
|
1019
|
+
|
|
1020
|
+
```
|
|
1021
|
+
cloudos datasets mkdir <new_folder_path>
|
|
1022
|
+
```
|
|
1023
|
+
where ` new_folder_path` is the path to the folder to be created.
|
|
1024
|
+
|
|
1025
|
+
Please, be aware that the folder creation can only happen in `Data` or its sub-folders.
|
|
1026
|
+
|
|
1027
|
+
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
1028
|
+
|
|
1029
|
+
```bash
|
|
1030
|
+
--cloudos-url $CLOUDOS \
|
|
1031
|
+
--apikey $MY_API_KEY \
|
|
1032
|
+
--workspace-id $WORKSPACE_ID \
|
|
1033
|
+
--project-name $PROJEC_NAME
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
#### Copying files and folders
|
|
1037
|
+
|
|
1038
|
+
Files and folders can be copied **from** anywhere in the project **to** `Data` or any of its subfolders programmatically (i.e `Data`, `Data/folder/file.txt`).
|
|
1039
|
+
|
|
1040
|
+
1. The copy can happen **within the same project** running the following command:
|
|
1041
|
+
```
|
|
1042
|
+
cloudos datasets cp <souce_path> <destination_path> --profile <profile name>
|
|
1043
|
+
```
|
|
1044
|
+
where the source project as well as the destination one is the one defined in the profile.
|
|
1045
|
+
|
|
1046
|
+
2. The move can also happen **across different projects** within the same workspace by running the following command
|
|
1047
|
+
```
|
|
1048
|
+
cloudos datasets cp <source_path> <destiantion_path> --profile <profile_name> --destination-project-name <project_name>
|
|
1049
|
+
```
|
|
1050
|
+
In this case, only the source project is the one specified in the profile.
|
|
1051
|
+
|
|
1052
|
+
Any of the `source_path` must be a full path; any `destination_path` must be a path starting with `Data` and finishing with the folder where to move the file/folder. An example of such command is:
|
|
1053
|
+
|
|
1054
|
+
```
|
|
1055
|
+
cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
1010
1059
|
```bash
|
|
1011
1060
|
--cloudos-url $CLOUDOS \
|
|
1012
1061
|
--apikey $MY_API_KEY \
|
|
@@ -972,6 +972,55 @@ Please, be aware that renaming can only happen in files and folders that are pre
|
|
|
972
972
|
|
|
973
973
|
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
974
974
|
|
|
975
|
+
```bash
|
|
976
|
+
--cloudos-url $CLOUDOS \
|
|
977
|
+
--apikey $MY_API_KEY \
|
|
978
|
+
--workspace-id $WORKSPACE_ID \
|
|
979
|
+
--project-name $PROJEC_NAME
|
|
980
|
+
```
|
|
981
|
+
#### Create a (virtual) folder
|
|
982
|
+
|
|
983
|
+
New folders can be created within the `Data` dataset and its subfolders using the following command
|
|
984
|
+
|
|
985
|
+
```
|
|
986
|
+
cloudos datasets mkdir <new_folder_path>
|
|
987
|
+
```
|
|
988
|
+
where ` new_folder_path` is the path to the folder to be created.
|
|
989
|
+
|
|
990
|
+
Please, be aware that the folder creation can only happen in `Data` or its sub-folders.
|
|
991
|
+
|
|
992
|
+
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
993
|
+
|
|
994
|
+
```bash
|
|
995
|
+
--cloudos-url $CLOUDOS \
|
|
996
|
+
--apikey $MY_API_KEY \
|
|
997
|
+
--workspace-id $WORKSPACE_ID \
|
|
998
|
+
--project-name $PROJEC_NAME
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
#### Copying files and folders
|
|
1002
|
+
|
|
1003
|
+
Files and folders can be copied **from** anywhere in the project **to** `Data` or any of its subfolders programmatically (i.e `Data`, `Data/folder/file.txt`).
|
|
1004
|
+
|
|
1005
|
+
1. The copy can happen **within the same project** running the following command:
|
|
1006
|
+
```
|
|
1007
|
+
cloudos datasets cp <souce_path> <destination_path> --profile <profile name>
|
|
1008
|
+
```
|
|
1009
|
+
where the source project as well as the destination one is the one defined in the profile.
|
|
1010
|
+
|
|
1011
|
+
2. The move can also happen **across different projects** within the same workspace by running the following command
|
|
1012
|
+
```
|
|
1013
|
+
cloudos datasets cp <source_path> <destiantion_path> --profile <profile_name> --destination-project-name <project_name>
|
|
1014
|
+
```
|
|
1015
|
+
In this case, only the source project is the one specified in the profile.
|
|
1016
|
+
|
|
1017
|
+
Any of the `source_path` must be a full path; any `destination_path` must be a path starting with `Data` and finishing with the folder where to move the file/folder. An example of such command is:
|
|
1018
|
+
|
|
1019
|
+
```
|
|
1020
|
+
cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
|
|
1021
|
+
```
|
|
1022
|
+
|
|
1023
|
+
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
975
1024
|
```bash
|
|
976
1025
|
--cloudos-url $CLOUDOS \
|
|
977
1026
|
--apikey $MY_API_KEY \
|
|
@@ -88,7 +88,9 @@ def run_cloudos_cli(ctx):
|
|
|
88
88
|
'datasets': {
|
|
89
89
|
'ls': shared_config,
|
|
90
90
|
'mv': shared_config,
|
|
91
|
-
'rename': shared_config
|
|
91
|
+
'rename': shared_config,
|
|
92
|
+
'cp': shared_config,
|
|
93
|
+
'mkdir': shared_config
|
|
92
94
|
}
|
|
93
95
|
})
|
|
94
96
|
else:
|
|
@@ -135,7 +137,9 @@ def run_cloudos_cli(ctx):
|
|
|
135
137
|
'datasets': {
|
|
136
138
|
'ls': shared_config,
|
|
137
139
|
'mv': shared_config,
|
|
138
|
-
'rename': shared_config
|
|
140
|
+
'rename': shared_config,
|
|
141
|
+
'cp': shared_config,
|
|
142
|
+
'mkdir': shared_config
|
|
139
143
|
}
|
|
140
144
|
})
|
|
141
145
|
|
|
@@ -2960,5 +2964,247 @@ def renaming_item(ctx, source_path, new_name, apikey, cloudos_url,
|
|
|
2960
2964
|
sys.exit(1)
|
|
2961
2965
|
|
|
2962
2966
|
|
|
2967
|
+
@datasets.command(name="cp")
|
|
2968
|
+
@click.argument("source_path", required=True)
|
|
2969
|
+
@click.argument("destination_path", required=True)
|
|
2970
|
+
@click.option('-k', '--apikey', required=True, help='Your CloudOS API key.')
|
|
2971
|
+
@click.option('-c', '--cloudos-url', default=CLOUDOS_URL, required=True, help='The CloudOS URL.')
|
|
2972
|
+
@click.option('--workspace-id', required=True, help='The CloudOS workspace ID.')
|
|
2973
|
+
@click.option('--project-name', required=True, help='The source project name.')
|
|
2974
|
+
@click.option('--destination-project-name', required=False, help='The destination project name. Defaults to the source project.')
|
|
2975
|
+
@click.option('--disable-ssl-verification', is_flag=True, help='Disable SSL certificate verification.')
|
|
2976
|
+
@click.option('--ssl-cert', help='Path to your SSL certificate file.')
|
|
2977
|
+
@click.option('--profile', default=None, help='Profile to use from the config file.')
|
|
2978
|
+
@click.pass_context
|
|
2979
|
+
def copy_item_cli(ctx, source_path, destination_path, apikey, cloudos_url,
|
|
2980
|
+
workspace_id, project_name, destination_project_name,
|
|
2981
|
+
disable_ssl_verification, ssl_cert, profile):
|
|
2982
|
+
"""
|
|
2983
|
+
Copy a file or folder (S3 or virtual) from SOURCE_PATH to DESTINATION_PATH.
|
|
2984
|
+
|
|
2985
|
+
SOURCE_PATH [path]: the full path to the file or folder to copy.
|
|
2986
|
+
E.g.: AnalysesResults/my_analysis/results/my_plot.png\n
|
|
2987
|
+
DESTINATION_PATH [path]: the full path to the destination folder. It must be a 'Data' folder path.
|
|
2988
|
+
E.g.: Data/plots
|
|
2989
|
+
"""
|
|
2990
|
+
click.echo("Loading configuration profile...")
|
|
2991
|
+
config_manager = ConfigurationProfile()
|
|
2992
|
+
required_dict = {
|
|
2993
|
+
'apikey': True,
|
|
2994
|
+
'workspace_id': True,
|
|
2995
|
+
'workflow_name': False,
|
|
2996
|
+
'project_name': True
|
|
2997
|
+
}
|
|
2998
|
+
apikey, cloudos_url, workspace_id, workflow_name, _, _, project_name = config_manager.load_profile_and_validate_data(
|
|
2999
|
+
ctx, INIT_PROFILE, CLOUDOS_URL, profile=profile,
|
|
3000
|
+
required_dict=required_dict,
|
|
3001
|
+
apikey=apikey,
|
|
3002
|
+
cloudos_url=cloudos_url,
|
|
3003
|
+
workspace_id=workspace_id,
|
|
3004
|
+
workflow_name=None,
|
|
3005
|
+
repository_platform=None,
|
|
3006
|
+
execution_platform=None,
|
|
3007
|
+
project_name=project_name
|
|
3008
|
+
)
|
|
3009
|
+
destination_project_name = destination_project_name or project_name
|
|
3010
|
+
verify_ssl = ssl_selector(disable_ssl_verification, ssl_cert)
|
|
3011
|
+
# Initialize clients
|
|
3012
|
+
source_client = Datasets(
|
|
3013
|
+
cloudos_url=cloudos_url,
|
|
3014
|
+
apikey=apikey,
|
|
3015
|
+
workspace_id=workspace_id,
|
|
3016
|
+
project_name=project_name,
|
|
3017
|
+
verify=verify_ssl,
|
|
3018
|
+
cromwell_token=None
|
|
3019
|
+
)
|
|
3020
|
+
dest_client = Datasets(
|
|
3021
|
+
cloudos_url=cloudos_url,
|
|
3022
|
+
apikey=apikey,
|
|
3023
|
+
workspace_id=workspace_id,
|
|
3024
|
+
project_name=destination_project_name,
|
|
3025
|
+
verify=verify_ssl,
|
|
3026
|
+
cromwell_token=None
|
|
3027
|
+
)
|
|
3028
|
+
# Validate paths
|
|
3029
|
+
dest_parts = destination_path.strip("/").split("/")
|
|
3030
|
+
if not dest_parts or dest_parts[0] != "Data":
|
|
3031
|
+
click.echo("[ERROR] DESTINATION_PATH must start with 'Data/'.", err=True)
|
|
3032
|
+
sys.exit(1)
|
|
3033
|
+
# Parse source and destination
|
|
3034
|
+
source_parts = source_path.strip("/").split("/")
|
|
3035
|
+
source_parent = "/".join(source_parts[:-1]) if len(source_parts) > 1 else ""
|
|
3036
|
+
source_name = source_parts[-1]
|
|
3037
|
+
dest_folder_name = dest_parts[-1]
|
|
3038
|
+
dest_parent = "/".join(dest_parts[:-1]) if len(dest_parts) > 1 else ""
|
|
3039
|
+
try:
|
|
3040
|
+
source_content = source_client.list_folder_content(source_parent)
|
|
3041
|
+
dest_content = dest_client.list_folder_content(dest_parent)
|
|
3042
|
+
except Exception as e:
|
|
3043
|
+
click.echo(f"[ERROR] Could not access paths: {str(e)}", err=True)
|
|
3044
|
+
sys.exit(1)
|
|
3045
|
+
# Find the source item
|
|
3046
|
+
source_item = None
|
|
3047
|
+
for item in source_content.get('files' or 'folders', {}):
|
|
3048
|
+
if item.get("name") == source_name:
|
|
3049
|
+
source_item = item
|
|
3050
|
+
break
|
|
3051
|
+
if not source_item:
|
|
3052
|
+
click.echo(f"[ERROR] Item '{source_name}' not found in '{source_parent or '[project root]'}'", err=True)
|
|
3053
|
+
sys.exit(1)
|
|
3054
|
+
# Find the destination folder
|
|
3055
|
+
destination_folder = None
|
|
3056
|
+
for folder in dest_content.get("folders", []):
|
|
3057
|
+
if folder.get("name") == dest_folder_name:
|
|
3058
|
+
destination_folder = folder
|
|
3059
|
+
break
|
|
3060
|
+
if not destination_folder:
|
|
3061
|
+
click.echo(f"[ERROR] Destination folder '{destination_path}' not found.", err=True)
|
|
3062
|
+
sys.exit(1)
|
|
3063
|
+
try:
|
|
3064
|
+
# Determine item type
|
|
3065
|
+
if "fileType" in source_item:
|
|
3066
|
+
item_type = "file"
|
|
3067
|
+
elif source_item.get("folderType") == "VirtualFolder":
|
|
3068
|
+
item_type = "virtual_folder"
|
|
3069
|
+
elif "s3BucketName" in source_item and source_item.get("folderType") == "S3Folder":
|
|
3070
|
+
item_type = "s3_folder"
|
|
3071
|
+
else:
|
|
3072
|
+
click.echo("[ERROR] Could not determine item type.", err=True)
|
|
3073
|
+
sys.exit(1)
|
|
3074
|
+
click.echo(f"Copying {item_type.replace('_', ' ')} '{source_name}' to '{destination_path}'...")
|
|
3075
|
+
if destination_folder.get("folderType") is True and destination_folder.get("kind") in ("Data", "Cohorts", "AnalysesResults"):
|
|
3076
|
+
destination_kind = "Dataset"
|
|
3077
|
+
else:
|
|
3078
|
+
destination_kind = "Folder"
|
|
3079
|
+
response = source_client.copy_item(
|
|
3080
|
+
item=source_item,
|
|
3081
|
+
destination_id=destination_folder["_id"],
|
|
3082
|
+
destination_kind=destination_kind
|
|
3083
|
+
)
|
|
3084
|
+
if response.ok:
|
|
3085
|
+
click.secho("[SUCCESS] Item copied successfully.", fg="green", bold=True)
|
|
3086
|
+
else:
|
|
3087
|
+
click.echo(f"[ERROR] Copy failed: {response.status_code} - {response.text}", err=True)
|
|
3088
|
+
sys.exit(1)
|
|
3089
|
+
except Exception as e:
|
|
3090
|
+
click.echo(f"[ERROR] Copy operation failed: {str(e)}", err=True)
|
|
3091
|
+
sys.exit(1)
|
|
3092
|
+
|
|
3093
|
+
|
|
3094
|
+
@datasets.command(name="mkdir")
|
|
3095
|
+
@click.argument("new_folder_path", required=True)
|
|
3096
|
+
@click.option('-k', '--apikey', required=True, help='Your CloudOS API key.')
|
|
3097
|
+
@click.option('-c', '--cloudos-url', default=CLOUDOS_URL, required=True, help='The CloudOS URL.')
|
|
3098
|
+
@click.option('--workspace-id', required=True, help='The CloudOS workspace ID.')
|
|
3099
|
+
@click.option('--project-name', required=True, help='The project name.')
|
|
3100
|
+
@click.option('--disable-ssl-verification', is_flag=True, help='Disable SSL certificate verification.')
|
|
3101
|
+
@click.option('--ssl-cert', help='Path to your SSL certificate file.')
|
|
3102
|
+
@click.option('--profile', default=None, help='Profile to use from the config file.')
|
|
3103
|
+
@click.pass_context
|
|
3104
|
+
def mkdir_item(ctx, new_folder_path, apikey, cloudos_url,
|
|
3105
|
+
workspace_id, project_name,
|
|
3106
|
+
disable_ssl_verification, ssl_cert, profile):
|
|
3107
|
+
"""
|
|
3108
|
+
Create a virtual folder in a CloudOS project.
|
|
3109
|
+
|
|
3110
|
+
NEW_FOLDER_PATH [path]: Full path to the new folder including its name. Must start with 'Data'.
|
|
3111
|
+
"""
|
|
3112
|
+
new_folder_path = new_folder_path.strip("/")
|
|
3113
|
+
if not new_folder_path.startswith("Data"):
|
|
3114
|
+
click.echo("[ERROR] NEW_FOLDER_PATH must start with 'Data'.", err=True)
|
|
3115
|
+
sys.exit(1)
|
|
3116
|
+
|
|
3117
|
+
path_parts = new_folder_path.split("/")
|
|
3118
|
+
if len(path_parts) < 2:
|
|
3119
|
+
click.echo("[ERROR] NEW_FOLDER_PATH must include at least a parent folder and the new folder name.", err=True)
|
|
3120
|
+
sys.exit(1)
|
|
3121
|
+
|
|
3122
|
+
parent_path = "/".join(path_parts[:-1])
|
|
3123
|
+
folder_name = path_parts[-1]
|
|
3124
|
+
|
|
3125
|
+
click.echo("Loading configuration profile...")
|
|
3126
|
+
config_manager = ConfigurationProfile()
|
|
3127
|
+
required_dict = {
|
|
3128
|
+
'apikey': True,
|
|
3129
|
+
'workspace_id': True,
|
|
3130
|
+
'workflow_name': False,
|
|
3131
|
+
'project_name': True
|
|
3132
|
+
}
|
|
3133
|
+
|
|
3134
|
+
apikey, cloudos_url, workspace_id, workflow_name, repository_platform, execution_platform, project_name = (
|
|
3135
|
+
config_manager.load_profile_and_validate_data(
|
|
3136
|
+
ctx,
|
|
3137
|
+
INIT_PROFILE,
|
|
3138
|
+
CLOUDOS_URL,
|
|
3139
|
+
profile=profile,
|
|
3140
|
+
required_dict=required_dict,
|
|
3141
|
+
apikey=apikey,
|
|
3142
|
+
cloudos_url=cloudos_url,
|
|
3143
|
+
workspace_id=workspace_id,
|
|
3144
|
+
workflow_name=None,
|
|
3145
|
+
repository_platform=None,
|
|
3146
|
+
execution_platform=None,
|
|
3147
|
+
project_name=project_name
|
|
3148
|
+
)
|
|
3149
|
+
)
|
|
3150
|
+
|
|
3151
|
+
verify_ssl = ssl_selector(disable_ssl_verification, ssl_cert)
|
|
3152
|
+
|
|
3153
|
+
client = Datasets(
|
|
3154
|
+
cloudos_url=cloudos_url,
|
|
3155
|
+
apikey=apikey,
|
|
3156
|
+
workspace_id=workspace_id,
|
|
3157
|
+
project_name=project_name,
|
|
3158
|
+
verify=verify_ssl,
|
|
3159
|
+
cromwell_token=None
|
|
3160
|
+
)
|
|
3161
|
+
|
|
3162
|
+
# Split parent path to get its parent + name
|
|
3163
|
+
parent_parts = parent_path.split("/")
|
|
3164
|
+
parent_name = parent_parts[-1]
|
|
3165
|
+
parent_of_parent_path = "/".join(parent_parts[:-1])
|
|
3166
|
+
|
|
3167
|
+
# List the parent of the parent
|
|
3168
|
+
try:
|
|
3169
|
+
contents = client.list_folder_content(parent_of_parent_path)
|
|
3170
|
+
except Exception as e:
|
|
3171
|
+
click.echo(f"[ERROR] Could not list contents at '{parent_of_parent_path}': {str(e)}", err=True)
|
|
3172
|
+
sys.exit(1)
|
|
3173
|
+
|
|
3174
|
+
# Find the parent folder in the contents
|
|
3175
|
+
folder_info = next(
|
|
3176
|
+
(f for f in contents.get("folders", []) if f.get("name") == parent_name),
|
|
3177
|
+
None
|
|
3178
|
+
)
|
|
3179
|
+
|
|
3180
|
+
if not folder_info:
|
|
3181
|
+
click.echo(f"[ERROR] Could not find folder '{parent_name}' in '{parent_of_parent_path}'.", err=True)
|
|
3182
|
+
sys.exit(1)
|
|
3183
|
+
|
|
3184
|
+
parent_id = folder_info.get("_id")
|
|
3185
|
+
folder_type = folder_info.get("folderType")
|
|
3186
|
+
|
|
3187
|
+
if folder_type is True:
|
|
3188
|
+
parent_kind = "Dataset"
|
|
3189
|
+
elif isinstance(folder_type, str):
|
|
3190
|
+
parent_kind = "Folder"
|
|
3191
|
+
else:
|
|
3192
|
+
click.echo(f"[ERROR] Unrecognized folderType for '{parent_path}'.", err=True)
|
|
3193
|
+
sys.exit(1)
|
|
3194
|
+
|
|
3195
|
+
# Create the folder
|
|
3196
|
+
click.echo(f"Creating folder '{folder_name}' under '{parent_path}' ({parent_kind})...")
|
|
3197
|
+
try:
|
|
3198
|
+
response = client.create_virtual_folder(name=folder_name, parent_id=parent_id, parent_kind=parent_kind)
|
|
3199
|
+
if response.ok:
|
|
3200
|
+
click.secho(f"[SUCCESS] Folder '{folder_name}' created under '{parent_path}'", fg="green", bold=True)
|
|
3201
|
+
else:
|
|
3202
|
+
click.echo(f"[ERROR] Folder creation failed: {response.status_code} - {response.text}", err=True)
|
|
3203
|
+
sys.exit(1)
|
|
3204
|
+
except Exception as e:
|
|
3205
|
+
click.echo(f"[ERROR] Folder creation failed: {str(e)}", err=True)
|
|
3206
|
+
sys.exit(1)
|
|
3207
|
+
|
|
3208
|
+
|
|
2963
3209
|
if __name__ == "__main__":
|
|
2964
3210
|
run_cloudos_cli()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.35.0'
|
|
@@ -5,7 +5,7 @@ This is the main class for file explorer (datasets).
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from typing import Union
|
|
7
7
|
from cloudos_cli.clos import Cloudos
|
|
8
|
-
from cloudos_cli.utils.requests import retry_requests_get, retry_requests_put
|
|
8
|
+
from cloudos_cli.utils.requests import retry_requests_get, retry_requests_put, retry_requests_post
|
|
9
9
|
import json
|
|
10
10
|
|
|
11
11
|
@dataclass
|
|
@@ -403,4 +403,88 @@ class Datasets(Cloudos):
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
response = retry_requests_put(url, headers=headers, data=json.dumps(payload), verify=self.verify)
|
|
406
|
+
return response
|
|
407
|
+
|
|
408
|
+
def copy_item(self, item, destination_id, destination_kind):
|
|
409
|
+
"""Copy a file or folder (S3 or Virtual) to a destination in CloudOS."""
|
|
410
|
+
headers = {
|
|
411
|
+
"accept": "application/json",
|
|
412
|
+
"content-type": "application/json",
|
|
413
|
+
"ApiKey": self.apikey
|
|
414
|
+
}
|
|
415
|
+
parent = {"kind": destination_kind, "id": destination_id}
|
|
416
|
+
|
|
417
|
+
# Virtual folder
|
|
418
|
+
if item.get("folderType") == "VirtualFolder":
|
|
419
|
+
payload = {
|
|
420
|
+
"copyContentsFrom": item["_id"],
|
|
421
|
+
"name": item["name"],
|
|
422
|
+
"parent": parent
|
|
423
|
+
}
|
|
424
|
+
url = f"{self.cloudos_url}/api/v1/folders/virtual?teamId={self.workspace_id}"
|
|
425
|
+
# S3 folder
|
|
426
|
+
elif item.get("folderType") == "S3Folder":
|
|
427
|
+
payload = {
|
|
428
|
+
"s3BucketName": item["s3BucketName"],
|
|
429
|
+
"s3ObjectKey": item.get("s3ObjectKey") or item.get("s3Prefix"),
|
|
430
|
+
"name": item["name"],
|
|
431
|
+
"parent": parent,
|
|
432
|
+
"isManagedByLifebit": item.get("isManagedByLifebit", False)
|
|
433
|
+
}
|
|
434
|
+
url = f"{self.cloudos_url}/api/v1/folders/s3?teamId={self.workspace_id}"
|
|
435
|
+
# S3 file
|
|
436
|
+
elif item.get("fileType") == "S3File":
|
|
437
|
+
payload = {
|
|
438
|
+
"s3BucketName": item["s3BucketName"],
|
|
439
|
+
"s3ObjectKey": item["s3ObjectKey"],
|
|
440
|
+
"name": item["name"],
|
|
441
|
+
"parent": parent,
|
|
442
|
+
"isManagedByLifebit": item.get("isManagedByLifebit", False),
|
|
443
|
+
"sizeInBytes": item.get("sizeInBytes", 0)
|
|
444
|
+
}
|
|
445
|
+
url = f"{self.cloudos_url}/api/v1/files/s3?teamId={self.workspace_id}"
|
|
446
|
+
else:
|
|
447
|
+
raise ValueError(f"Unknown item type for copy: {item.get('name')}")
|
|
448
|
+
response = retry_requests_post(url, headers=headers, json=payload)
|
|
449
|
+
|
|
450
|
+
return response
|
|
451
|
+
|
|
452
|
+
def create_virtual_folder(self, name: str, parent_id: str, parent_kind: str):
|
|
453
|
+
"""
|
|
454
|
+
Create a new virtual folder in CloudOS under a given parent.
|
|
455
|
+
|
|
456
|
+
Parameters
|
|
457
|
+
----------
|
|
458
|
+
name : str
|
|
459
|
+
The name of the new folder.
|
|
460
|
+
parent_id : str
|
|
461
|
+
The ID of the parent (can be a Dataset or a Folder).
|
|
462
|
+
parent_kind : str
|
|
463
|
+
The type of the parent: either "Dataset" or "Folder".
|
|
464
|
+
|
|
465
|
+
Returns
|
|
466
|
+
-------
|
|
467
|
+
response : requests.Response
|
|
468
|
+
The response object from the CloudOS API.
|
|
469
|
+
"""
|
|
470
|
+
if parent_kind not in ("Dataset", "Folder"):
|
|
471
|
+
raise ValueError("Invalid parent_kind. Must be 'Dataset' or 'Folder'.")
|
|
472
|
+
|
|
473
|
+
url = f"{self.cloudos_url}/api/v1/folders/virtual?teamId={self.workspace_id}"
|
|
474
|
+
|
|
475
|
+
headers = {
|
|
476
|
+
"accept": "application/json",
|
|
477
|
+
"content-type": "application/json",
|
|
478
|
+
"ApiKey": self.apikey
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
payload = {
|
|
482
|
+
"name": name,
|
|
483
|
+
"parent": {
|
|
484
|
+
"kind": parent_kind,
|
|
485
|
+
"id": parent_id
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
response = retry_requests_post(url, headers=headers, json=payload, verify=self.verify)
|
|
406
490
|
return response
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudos_cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.35.0
|
|
4
4
|
Summary: Python package for interacting with CloudOS
|
|
5
5
|
Home-page: https://github.com/lifebit-ai/cloudos-cli
|
|
6
6
|
Author: David Piñeyro
|
|
@@ -1007,6 +1007,55 @@ Please, be aware that renaming can only happen in files and folders that are pre
|
|
|
1007
1007
|
|
|
1008
1008
|
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
1009
1009
|
|
|
1010
|
+
```bash
|
|
1011
|
+
--cloudos-url $CLOUDOS \
|
|
1012
|
+
--apikey $MY_API_KEY \
|
|
1013
|
+
--workspace-id $WORKSPACE_ID \
|
|
1014
|
+
--project-name $PROJEC_NAME
|
|
1015
|
+
```
|
|
1016
|
+
#### Create a (virtual) folder
|
|
1017
|
+
|
|
1018
|
+
New folders can be created within the `Data` dataset and its subfolders using the following command
|
|
1019
|
+
|
|
1020
|
+
```
|
|
1021
|
+
cloudos datasets mkdir <new_folder_path>
|
|
1022
|
+
```
|
|
1023
|
+
where ` new_folder_path` is the path to the folder to be created.
|
|
1024
|
+
|
|
1025
|
+
Please, be aware that the folder creation can only happen in `Data` or its sub-folders.
|
|
1026
|
+
|
|
1027
|
+
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
1028
|
+
|
|
1029
|
+
```bash
|
|
1030
|
+
--cloudos-url $CLOUDOS \
|
|
1031
|
+
--apikey $MY_API_KEY \
|
|
1032
|
+
--workspace-id $WORKSPACE_ID \
|
|
1033
|
+
--project-name $PROJEC_NAME
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
#### Copying files and folders
|
|
1037
|
+
|
|
1038
|
+
Files and folders can be copied **from** anywhere in the project **to** `Data` or any of its subfolders programmatically (i.e `Data`, `Data/folder/file.txt`).
|
|
1039
|
+
|
|
1040
|
+
1. The copy can happen **within the same project** running the following command:
|
|
1041
|
+
```
|
|
1042
|
+
cloudos datasets cp <souce_path> <destination_path> --profile <profile name>
|
|
1043
|
+
```
|
|
1044
|
+
where the source project as well as the destination one is the one defined in the profile.
|
|
1045
|
+
|
|
1046
|
+
2. The move can also happen **across different projects** within the same workspace by running the following command
|
|
1047
|
+
```
|
|
1048
|
+
cloudos datasets cp <source_path> <destiantion_path> --profile <profile_name> --destination-project-name <project_name>
|
|
1049
|
+
```
|
|
1050
|
+
In this case, only the source project is the one specified in the profile.
|
|
1051
|
+
|
|
1052
|
+
Any of the `source_path` must be a full path; any `destination_path` must be a path starting with `Data` and finishing with the folder where to move the file/folder. An example of such command is:
|
|
1053
|
+
|
|
1054
|
+
```
|
|
1055
|
+
cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
|
|
1010
1059
|
```bash
|
|
1011
1060
|
--cloudos-url $CLOUDOS \
|
|
1012
1061
|
--apikey $MY_API_KEY \
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.33.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|