Skip to content

Commit 3c16e66

Browse files
sajaganalhercot
authored andcommitted
[ignore] Updated the ND rest, backup and restore module logic and documentation
1 parent b576721 commit 3c16e66

File tree

7 files changed

+71
-39
lines changed

7 files changed

+71
-39
lines changed

plugins/httpapi/nd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def send_file_request(self, method, path, file=None, data=None, remote_path=None
352352

353353
mp_encoder = MultipartEncoder(fields=fields)
354354
multiheader = {"Content-Type": mp_encoder.content_type, "Accept": "*/*", "Accept-Encoding": "gzip, deflate, br"}
355-
self.connection.queue_message("info", "send_file_request() - connection.send({0}, {1}, {2}, {3})".format(path, method, fields, multiheader))
355+
self.connection.queue_message("debug", "send_file_request() - connection.send({0}, {1}, {2}, {3})".format(path, method, fields, multiheader))
356356
response, rdata = self.connection.send(path, mp_encoder.to_string(), method=method, headers=multiheader)
357357
except Exception as e:
358358
self.error = dict(code=self.status, message="ND HTTPAPI MultipartEncoder Exception: {0} - {1} ".format(e, traceback.format_exc()))

plugins/module_utils/nd.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,21 +224,20 @@ def __init__(self, module):
224224
self.url = None
225225
self.httpapi_logs = list()
226226
self.connection = None
227-
self.version = None
227+
self._version = None
228228

229229
# Set Connection plugin
230230
self.set_connection()
231231

232-
# Set ND version
233-
self.set_version()
234-
235232
if self.module._debug:
236233
self.module.warn("Enable debug output because ANSIBLE_DEBUG was set.")
237234
self.params["output_level"] = "debug"
238235

239-
def set_version(self):
240-
if self.version is None and self.connection:
241-
self.version = self.connection.get_version("nd")
236+
@property
237+
def version(self):
238+
if self._version is None and self.connection:
239+
self._version = self.connection.get_version("nd")
240+
return self._version
242241

243242
def set_connection(self):
244243
if self.connection is None:

plugins/modules/nd_backup.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
file_location:
3636
description:
3737
- The download path and file name for a backup.
38-
- When O(file_location) is specified, the backup will be created and automatically downloaded to the local machine at the designated path.
39-
- Automatic download is not supported for the ND versions 3.2.1 and later. Use a following task with O(state=download) to download the backup.
38+
- When O(file_location) is specified, the backup will be created and automatically downloaded to the designated path.
4039
aliases: [ local_path, path ]
4140
type: str
4241
backup_key:
@@ -58,18 +57,18 @@
5857
remote_location:
5958
description:
6059
- The name of the remote storage location.
61-
- Use O(remote_location="") to create local backup.
60+
- Use O(remote_location="") to create ND local backup.
6261
- This parameter is only supported on ND v3.2.1 and later.
6362
default: ""
6463
type: str
6564
state:
6665
description:
67-
- Use O(state=backup) for creating and downloading a backup of the cluster config for the ND versions less than 3.2.1.
68-
- Use O(state=backup) to create a cluster configuration backup. Automatic download is not supported for the ND versions 3.2.1 and later.
69-
- After creation, use O(state=download) to download the backup file.
70-
- Use O(state=download) downloading a backup to the local machine, the O(state=download) is only supported on ND v3.2.1 and later.
7166
- Use O(state=query) for listing all the backed up files.
7267
- Use O(state=absent) for deleting a backup job.
68+
- For ND versions earlier than v3.2.1, use O(state=backup) for creating and automatically downloading a backup of the cluster config.
69+
- For ND versions later than v3.2.1, use O(state=backup) for creating a cluster configuration backup,
70+
use O(state=download) for downloading a backup to the designated path.
71+
- O(state=download) is only supported on ND v3.2.1 and later.
7372
type: str
7473
choices: [ backup, download, query, absent ]
7574
default: backup
@@ -79,7 +78,7 @@
7978
"""
8079

8180
EXAMPLES = r"""
82-
- name: Create a backup for ND versions < 3.2.1
81+
- name: Create a backup and automatically download it to file_location for ND versions < 3.2.1
8382
cisco.nd.nd_backup:
8483
name: nexus
8584
encryption_key: testtest
@@ -93,20 +92,20 @@
9392
remote_location: remote_machine
9493
state: backup
9594
96-
- name: Create a local backup for ND versions >= 3.2.1
95+
- name: Create a ND local backup for ND versions >= 3.2.1
9796
cisco.nd.nd_backup:
9897
name: nexus
9998
encryption_key: testtest1
10099
state: backup
101100
102-
- name: Create a backup and download it to the local machine for ND versions >= 3.2.1
101+
- name: Create a backup and download it to the designated path for ND versions >= 3.2.1
103102
cisco.nd.nd_backup:
104103
name: nexus
105104
file_location: ./nexus.tgz
106105
encryption_key: testtest1
107106
state: backup
108107
109-
- name: Download a local/remote backup for ND versions >= 3.2.1
108+
- name: Download an existing backup for ND versions >= 3.2.1
110109
cisco.nd.nd_backup:
111110
name: nexus
112111
state: download
@@ -174,8 +173,8 @@ def main():
174173
backups = nd.query_obj("/api/config/class/exports") if nd.version < "3.2.1" else nd.query_obj(path)
175174

176175
if nd.version < "3.2.1":
177-
if not file_location and state in ["backup", "download"]:
178-
nd.fail_json("Parameter 'file_location' is required when state is 'backup|download' for ND versions < 3.2.1.")
176+
if not file_location and state in ["backup"]:
177+
nd.fail_json("Parameter 'file_location' is required when state is 'backup' for ND versions < 3.2.1.")
179178

180179
if encryption_key is not None and len(encryption_key) < 8:
181180
nd.fail_json("Please provide a minimum of 8 characters for the encryption key.")
@@ -255,6 +254,8 @@ def main():
255254
if not module.check_mode:
256255
response = nd.request("{0}/{1}?action=download".format(path, name), method="GET", data=None, output_format="raw")
257256
write_file(module, file_location, to_bytes(response))
257+
elif state == "download" and nd.version < "3.2.1":
258+
nd.fail_json("The O(state=download) is only supported on ND v3.2.1 and later.")
258259

259260
nd.exit_json()
260261

plugins/modules/nd_backup_restore.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,13 @@ def main():
175175

176176
if state == "absent":
177177
if not module.check_mode:
178-
nd.request("{0}/{1}".format(import_path, restore_key) if nd.version < "3.2.1" else import_path, method="DELETE")
178+
if nd.version < "3.2.1":
179+
if restore_key is None and name is None:
180+
nd.fail_json("Please provide a valid O(restore_key) or O(name) to delete a restored job.")
181+
nd.request("{0}/{1}".format(import_path, restore_key), method="DELETE")
182+
else:
183+
nd.request(import_path, method="DELETE")
184+
179185
nd.existing = {}
180186

181187
elif state == "restore":

plugins/modules/nd_rest.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,16 @@
4848
- The file path containing the body of the HTTP request.
4949
type: path
5050
aliases: [ config_file ]
51-
ignore_previous_state:
51+
suppress_previous:
5252
description:
53+
- If enabled, a GET call to check previous object state will not be sent before a PUT, PATCH and DELETE update to ND.
54+
- This causes the previous return value to be empty.
55+
- The previous state of the object will not be checked and PUT, PATCH and DELETE update calls to ND will contain all properties specified in the task.
5356
- Certain ND API endpoints do not support the GET method for querying the current status of an object before updating or deleting it.
54-
- Use O(ignore_previous_state=true) to avoid making unsupported GET requests to such ND API endpoints.
57+
- Use O(suppress_previous=true) to avoid making unsupported GET requests to such ND API endpoints.
5558
type: bool
59+
aliases: [ no_previous, ignore_previous ]
60+
5661
extends_documentation_fragment:
5762
- cisco.nd.modules
5863
- cisco.nd.check_mode
@@ -217,7 +222,7 @@ def main():
217222
),
218223
content=dict(type="raw", aliases=["payload"]),
219224
file_path=dict(type="path", aliases=["config_file"]),
220-
ignore_previous_state=dict(type="bool"),
225+
suppress_previous=dict(type="bool", aliases=["no_previous", "ignore_previous"]),
221226
)
222227

223228
module = AnsibleModule(
@@ -228,7 +233,7 @@ def main():
228233
content = module.params.get("content")
229234
path = module.params.get("path")
230235
file_path = module.params.get("config_file")
231-
ignore_previous_state = module.params.get("ignore_previous_state")
236+
suppress_previous = module.params.get("suppress_previous")
232237

233238
nd = NDModule(module)
234239

@@ -257,11 +262,11 @@ def main():
257262
method = nd.params.get("method").upper()
258263

259264
# Append previous state of the object
260-
# Purpose of ignore_previous_state:
261-
# The ignore_previous_state was introduced because querying existing objects via the GET method on the /api/config/routes endpoint is not supported.
262-
# To avoid the /api/config/routes GET call ignore_previous_state was introduced.
265+
# Purpose of suppress_previous:
266+
# The suppress_previous was introduced because querying existing objects via the GET method on the /api/config/routes endpoint is not supported.
267+
# To avoid the /api/config/routes GET call suppress_previous was introduced.
263268
# Additionally, POST and DELETE methods return None for the /api/config/routes.
264-
if method in ("PUT", "DELETE", "PATCH") and not ignore_previous_state:
269+
if method in ("PUT", "DELETE", "PATCH") and not suppress_previous:
265270
nd.existing = nd.previous = sanitize(nd.query_obj(path, ignore_not_found_error=True), ND_REST_KEYS_TO_SANITIZE)
266271
nd.result["previous"] = nd.previous
267272

tests/integration/targets/nd_backup/tasks/main.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
- add_local_backup.current.name == "localbackup"
9595
- add_local_backup.current.path == "localbackup.tar.gz"
9696
- add_local_backup.current.schedule == ""
97-
- add_local_backup.current.endTime == "0001-01-01T00:00:00Z"
97+
- add_local_backup.current.endTime is defined
9898
- add_local_backup.current.startTime is defined
9999
- add_local_backup.current.status == "in-progress"
100100
- add_local_backup.current.type == "config-only"
@@ -563,6 +563,16 @@
563563
ignore_errors: true
564564
register: delete_wrong_key_nexus
565565

566+
- name: Negative test download backup with state=download
567+
cisco.nd.nd_backup:
568+
output_level: debug
569+
name: nexus
570+
encryption_key: Testtest123
571+
file_location: "{{ role_path }}/backups/nexus2_{{ ansible_host }}.tgz"
572+
state: download
573+
ignore_errors: true
574+
register: nt_download_backup
575+
566576
- name: Verify all assertions
567577
ansible.builtin.assert:
568578
that:
@@ -590,7 +600,9 @@
590600
- query_duplicate_nexus.msg == delete_duplicate_nexus.msg == "Multiple backups with the name 'nexus' found. Please provide a backup key for the corresponding backup."
591601
- delete_wrong_key_nexus.msg == "Provided key for the backup 'nexus' not found. Please provide a valid backup key by querying all the backups and looking up the desired backup key."
592602
- add_nexus_without_file_location is not changed
593-
- add_nexus_without_file_location.msg == "Parameter 'file_location' is required when state is 'backup|download' for ND versions < 3.2.1."
603+
- add_nexus_without_file_location.msg == "Parameter 'file_location' is required when state is 'backup' for ND versions < 3.2.1."
604+
- nt_download_backup is failed
605+
- nt_download_backup.msg == "The O(state=download) is only supported on ND v3.2.1 and later."
594606

595607
- name: Query all backups for deleting them
596608
cisco.nd.nd_backup:

tests/integration/targets/nd_backup_restore/tasks/main.yml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
- name: Delete all Data Routes
3535
cisco.nd.nd_rest:
3636
method: delete
37-
ignore_previous_state: true
37+
suppress_previous: true
3838
path: "/api/config/routes/{{ item.destination }}"
3939
loop: "{{ setup_query_all_routes.current | list }}"
4040

@@ -83,7 +83,7 @@
8383

8484
- name: Delete Data Route after ND local backup
8585
cisco.nd.nd_rest:
86-
ignore_previous_state: true
86+
suppress_previous: true
8787
method: delete
8888
output_level: debug
8989
path: /api/config/routes/12.23.45.68%2f32
@@ -147,7 +147,7 @@
147147
- name: Delete all Data Routes
148148
cisco.nd.nd_rest:
149149
method: delete
150-
ignore_previous_state: true
150+
suppress_previous: true
151151
path: "/api/config/routes/{{ item.destination }}"
152152
loop: "{{ query_all_routes.current | list }}"
153153

@@ -202,7 +202,7 @@
202202
- name: Delete Data Route after ND remote backup
203203
cisco.nd.nd_rest:
204204
output_level: debug
205-
ignore_previous_state: true
205+
suppress_previous: true
206206
method: delete
207207
path: "{{ item }}"
208208
loop:
@@ -275,7 +275,7 @@
275275
cisco.nd.nd_rest:
276276
output_level: debug
277277
method: delete
278-
ignore_previous_state: true
278+
suppress_previous: true
279279
path: "/api/config/routes/{{ item.destination }}"
280280
loop: "{{ query_all_routes.current | list }}"
281281

@@ -338,7 +338,7 @@
338338
cisco.nd.nd_rest:
339339
output_level: debug
340340
method: delete
341-
ignore_previous_state: true
341+
suppress_previous: true
342342
path: "{{ item }}"
343343
loop:
344344
- /api/config/routes/12.23.45.68%2f32
@@ -415,7 +415,7 @@
415415
cisco.nd.nd_rest:
416416
output_level: debug
417417
method: delete
418-
ignore_previous_state: true
418+
suppress_previous: true
419419
path: "/api/config/routes/{{ item.destination }}"
420420
loop: "{{ query_all_routes.current | list }}"
421421

@@ -669,6 +669,13 @@
669669
query_all_routes_restored2: "{{ query_all_routes_after_second_import.current | map(attribute='spec') | list | sort(attribute='destination') }}"
670670
query_all_routes_restored3: "{{ query_all_routes_after_third_import.current | map(attribute='spec') | list | sort(attribute='destination') }}"
671671

672+
- name: Delete restored job without name and restore key
673+
cisco.nd.nd_backup_restore:
674+
output_level: debug
675+
state: absent
676+
ignore_errors: true
677+
register: delete_restored_job_without_restore_key_and_name
678+
672679
- name: Verify all assertions
673680
ansible.builtin.assert:
674681
that:
@@ -686,6 +693,8 @@
686693
- delete_nexus2.current == delete_nexus2_cm.current == delete_nexus2_again.current == {}
687694
- query_duplicate_nexus.msg == delete_duplicate_nexus.msg == "Multiple restore jobs with the name 'nexus' found. Please provide a restore key for the corresponding restored job."
688695
- delete_wrong_key_nexus.msg == "Provided key for the restore 'nexus' not found. Please provide a valid restore key by querying all the restored jobs and looking up the desired restore key."
696+
- delete_restored_job_without_restore_key_and_name is failed
697+
- delete_restored_job_without_restore_key_and_name.msg == "Please provide a valid O(restore_key) or O(name) to delete a restored job."
689698

690699
- name: Query all restored jobs for deleting them
691700
cisco.nd.nd_backup_restore:

0 commit comments

Comments
 (0)