|
1 | 1 | from click import command, option, style, argument |
2 | 2 | from cloudinary_cli.utils.utils import normalize_list_params, print_help_and_exit |
3 | 3 | import cloudinary |
| 4 | +from cloudinary_cli.utils.clone.metadata import clone_metadata |
4 | 5 | from cloudinary.auth_token import _digest |
5 | 6 | from cloudinary_cli.utils.utils import run_tasks_concurrently |
6 | | -from cloudinary_cli.utils.api_utils import upload_file, handle_api_command |
| 7 | +from cloudinary_cli.utils.api_utils import upload_file |
7 | 8 | from cloudinary_cli.utils.json_utils import print_json |
8 | | -from cloudinary_cli.utils.config_utils import get_cloudinary_config, config_to_dict, config_to_tuple_list |
| 9 | +from cloudinary_cli.utils.config_utils import get_cloudinary_config, config_to_dict |
9 | 10 | from cloudinary_cli.defaults import logger |
10 | 11 | from cloudinary_cli.core.search import execute_single_request, handle_auto_pagination |
11 | 12 | import time |
@@ -55,27 +56,19 @@ def clone(target, force, overwrite, concurrent_workers, fields, |
55 | 56 | target_config, auth_token = _validate_clone_inputs(target) |
56 | 57 | if not target_config: |
57 | 58 | return False |
58 | | - |
| 59 | + if 'metadata' in normalize_list_params(fields): |
| 60 | + metadata_clone = clone_metadata(target_config) |
| 61 | + if not metadata_clone: |
| 62 | + logger.error(style(f"The operation has been aborted due to your answer.", fg="red")) |
| 63 | + return False |
| 64 | + else: |
| 65 | + logger.info(style(f"Metadata cloned successfully from {cloudinary.config().cloud_name} to {target_config.cloud_name}. We will now proceed with cloning the assets.", fg="green")) |
59 | 66 | source_assets = search_assets(search_exp, force) |
60 | 67 | if not source_assets: |
61 | 68 | return False |
62 | 69 | if not isinstance(source_assets, dict) or not source_assets.get('resources'): |
63 | 70 | logger.error(style(f"No asset(s) found in {cloudinary.config().cloud_name}", fg="red")) |
64 | 71 | return False |
65 | | - |
66 | | - if 'metadata' in normalize_list_params(fields): |
67 | | - source_metadata = list_metadata_items("metadata_fields") |
68 | | - if source_metadata.get('metadata_fields'): |
69 | | - target_metadata = list_metadata_items("metadata_fields", config_to_tuple_list(target_config)) |
70 | | - fields_compare = compare_create_metadata_items(source_metadata, target_metadata, config_to_tuple_list(target_config), key="metadata_fields") |
71 | | - source_metadata_rules = list_metadata_items("metadata_rules") |
72 | | - if source_metadata_rules.get('metadata_rules'): |
73 | | - target_metadata_rules = list_metadata_items("metadata_rules", config_to_tuple_list(target_config)) |
74 | | - rules_compare = compare_create_metadata_items(source_metadata_rules,target_metadata_rules, config_to_tuple_list(target_config), key="metadata_rules", id_field="name") |
75 | | - else: |
76 | | - logger.info(style(f"No metadata rules found in {cloudinary.config().cloud_name}", fg="yellow")) |
77 | | - else: |
78 | | - logger.info(style(f"No metadata found in {cloudinary.config().cloud_name}", fg="yellow")) |
79 | 72 |
|
80 | 73 | upload_list = _prepare_upload_list( |
81 | 74 | source_assets, target_config, overwrite, async_, |
@@ -150,79 +143,6 @@ def search_assets(search_exp, force): |
150 | 143 |
|
151 | 144 | return res |
152 | 145 |
|
153 | | -def list_metadata_items(method_key, *options): |
154 | | - api_method_name = 'list_' + method_key |
155 | | - params = [api_method_name] |
156 | | - if options: |
157 | | - options = options[0] |
158 | | - res = handle_api_command(params, (), options, None, None, None, |
159 | | - doc_url="", api_instance=cloudinary.api, |
160 | | - api_name="admin", |
161 | | - auto_paginate=True, |
162 | | - force=True, return_data=True) |
163 | | - res.get(method_key).sort(key=lambda x: x["external_id"]) |
164 | | - |
165 | | - return res |
166 | | - |
167 | | - |
168 | | -def create_metadata_item(api_method_name, item, *options): |
169 | | - params = (api_method_name, item) |
170 | | - if options: |
171 | | - options = options[0] |
172 | | - res = handle_api_command(params, (), options, None, None, None, |
173 | | - doc_url="", api_instance=cloudinary.api, |
174 | | - api_name="admin", |
175 | | - return_data=True) |
176 | | - |
177 | | - return res |
178 | | - |
179 | | - |
180 | | -def deep_diff(obj_source, obj_target): |
181 | | - diffs = {} |
182 | | - for k in set(obj_source.keys()).union(obj_target.keys()): |
183 | | - if obj_source.get(k) != obj_target.get(k): |
184 | | - diffs[k] = {"json_source": obj_source.get(k), "json_target": obj_target.get(k)} |
185 | | - |
186 | | - return diffs |
187 | | - |
188 | | - |
189 | | -def compare_create_metadata_items(json_source, json_target, target_config, key, id_field = "external_id"): |
190 | | - list_source = {item[id_field]: item for item in json_source.get(key, [])} |
191 | | - list_target = {item[id_field]: item for item in json_target.get(key, [])} |
192 | | - |
193 | | - only_in_source = list(list_source.keys() - list_target.keys()) |
194 | | - common = list_source.keys() & list_target.keys() |
195 | | - |
196 | | - if not len(only_in_source): |
197 | | - logger.info(style(f"{(' '.join(key.split('_')))} in {dict(target_config)['cloud_name']} and in {cloudinary.config().cloud_name} are identical. No {(' '.join(key.split('_')))} will be cloned", fg="yellow")) |
198 | | - else: |
199 | | - logger.info(style(f"Copying {len(only_in_source)} {(' '.join(key.split('_')))} from {cloudinary.config().cloud_name} to {dict(target_config)['cloud_name']}", fg="blue")) |
200 | | - |
201 | | - for key_field in only_in_source: |
202 | | - if key == 'metadata_fields': |
203 | | - try: |
204 | | - res = create_metadata_item('add_metadata_field', list_source[key_field],target_config) |
205 | | - logger.info(style(f"Successfully created {(' '.join(key.split('_')))} {key_field} to {dict(target_config)['cloud_name']}", fg="green")) |
206 | | - except Exception as e: |
207 | | - logger.error(style(f"Error when creating {(' '.join(key.split('_')))} {key_field} to {dict(target_config)['cloud_name']}", fg="red")) |
208 | | - else: |
209 | | - try: |
210 | | - res = create_metadata_item('add_metadata_rule', list_source[key_field],target_config) |
211 | | - logger.info(style(f"Successfully created {(' '.join(key.split('_')))} {key_field} to {dict(target_config)['cloud_name']}", fg="green")) |
212 | | - except Exception as e: |
213 | | - logger.error(style(f"Error when creating {(' '.join(key.split('_')))} {key_field} to {dict(target_config)['cloud_name']}", fg="red")) |
214 | | - |
215 | | - |
216 | | - diffs = {} |
217 | | - for id_ in common: |
218 | | - if list_source[id_] != list_target[id_]: |
219 | | - diffs[id_] = deep_diff(list_source[id_], list_target[id_]) |
220 | | - |
221 | | - return { |
222 | | - "only_in_json_source": only_in_source, |
223 | | - "differences": diffs |
224 | | - } |
225 | | - |
226 | 146 | def _normalize_search_expression(search_exp): |
227 | 147 | """ |
228 | 148 | Ensures the search expression has a valid 'type' filter. |
|
0 commit comments