Skip to content

Commit 95f13ee

Browse files
Addressed Review Comments
1 parent 56463d3 commit 95f13ee

2 files changed

Lines changed: 122 additions & 78 deletions

File tree

plugins/module_utils/catalystcenter.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,44 @@ def get_site_id(self, site_name):
11921192

11931193
return (site_exists, site_id)
11941194

1195+
def get_global_site_id(self):
1196+
"""
1197+
Retrieve the Global site ID from Cisco Catalyst Center.
1198+
1199+
Args:
1200+
None
1201+
1202+
Returns:
1203+
str: The site ID (UUID) for the Global site.
1204+
1205+
Raises:
1206+
Calls fail_and_exit if the Global site cannot be resolved.
1207+
1208+
Description:
1209+
This helper function retrieves the Global site UUID from Cisco Catalyst Center.
1210+
Since the Global site always exists in Catalyst Center, this function either returns
1211+
the site_id or fails the module with a clear error message if resolution fails.
1212+
The function uses the site_exists() method to validate and retrieve the Global site ID.
1213+
"""
1214+
(site_exists, site_id) = self.site_exists("Global")
1215+
if site_exists:
1216+
self.log(
1217+
"Resolved Global site UUID for golden tagging workflow: {0}".format(
1218+
str(site_id)
1219+
),
1220+
"INFO",
1221+
)
1222+
return site_id
1223+
1224+
self.log(
1225+
"Global site lookup did not return a valid site ID for Catalyst Center version {0}."
1226+
.format(self.get_ccc_version()),
1227+
"ERROR",
1228+
)
1229+
self.msg = "Unable to resolve the Global site ID in Cisco Catalyst Center."
1230+
self.log(self.msg, "ERROR")
1231+
self.fail_and_exit(self.msg)
1232+
11951233
def assign_device_to_site(self, device_ids, site_name, site_id):
11961234
"""
11971235
Assign devices to the specified site.

plugins/modules/swim_workflow_manager.py

Lines changed: 84 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,15 @@
337337
To replace an existing golden tag for a specific role:
338338
- **Unassign** the tag from the current role (e.g., `ACCESS`).
339339
- **Assign** the tag to the new role (e.g., `CORE`).
340-
Idempotency Note:
341-
- If an image is already tagged with 'ALL', requesting tagging for specific roles
342-
(e.g., 'DISTRIBUTION,ACCESS') will result in no change (changed=0), because 'ALL'
343-
is a superset that inherently includes all individual roles. The module checks the
344-
golden tag status per role and recognizes that the requested roles are already covered.
340+
Idempotency (per-role check, Catalyst Center > 2.3.7.9):
341+
- Tagging is evaluated per role. If the image is already golden for 'ACCESS' and you
342+
request tagging for 'CORE', the module tags 'CORE' (changed=True). Previously this
343+
was silently skipped.
344+
- The module skips (changed=False) only when all requested roles are already tagged.
345+
- 'ALL' is treated as a superset: an image tagged with 'ALL' skips any subsequent
346+
request for one or more specific roles, since those roles are already covered.
347+
- For untagging, the module skips (changed=False) only when all requested roles are
348+
already untagged.
345349
Examples:
346350
- device_role: "ACCESS" tags only the `ACCESS` role as golden.
347351
- device_role: "ACCESS,CORE" tags both `ACCESS` and `CORE` roles as golden.
@@ -361,11 +365,10 @@
361365
Ordinal value.
362366
type: int
363367
tagging:
364-
description: Boolean value to tag/untag
365-
SWIM image as golden If True then the
366-
given image will be tagged as golden.
367-
If False then the given image will be
368-
un-tagged as golden.
368+
description: Boolean value to tag/untag the
369+
SWIM image as golden. If True, the given
370+
image is tagged as golden. If False, the
371+
given image is un-tagged as golden.
369372
type: bool
370373
image_distribution_details:
371374
description: |
@@ -704,13 +707,22 @@
704707
- SDK Method used are
705708
software_image_management_swim.SoftwareImageManagementSwim.import_software_image_via_url,
706709
software_image_management_swim.SoftwareImageManagementSwim.tag_as_golden_image,
710+
software_image_management_swim.SoftwareImageManagementSwim.remove_golden_tag_for_image,
711+
software_image_management_swim.SoftwareImageManagementSwim.get_golden_tag_status_of_an_image,
712+
software_image_management_swim.SoftwareImageManagementSwim.tagging_golden_image,
713+
software_image_management_swim.SoftwareImageManagementSwim.untagging_golden_image,
714+
software_image_management_swim.SoftwareImageManagementSwim.returns_network_device_product_names_for_a_site,
707715
software_image_management_swim.SoftwareImageManagementSwim.trigger_software_image_distribution,
708716
software_image_management_swim.SoftwareImageManagementSwim.trigger_software_image_activation,
709717
software_image_management_swim.SoftwareImageManagementSwim.delete_image_v1,
710718
711719
- Paths used are
712720
post /dna/intent/api/v1/image/importation/source/url,
713721
post /dna/intent/api/v1/image/importation/golden,
722+
get /dna/intent/api/v1/image/importation/golden/site/{siteId}/family/{deviceFamilyIdentifier}/role/{deviceRole}/image/{imageId},
723+
post /dna/intent/api/v1/images/{id}/sites/{siteId}/tagGolden,
724+
post /dna/intent/api/v1/images/{id}/sites/{siteId}/untagGolden,
725+
get /dna/intent/api/v1/siteWiseProductNames,
714726
post /dna/intent/api/v1/image/distribution,
715727
post /dna/intent/api/v1/image/activation/device,
716728
delete /dna/intent/api/v1/images/{id},
@@ -2272,28 +2284,14 @@ def get_have(self):
22722284
),
22732285
"INFO",
22742286
)
2275-
(site_exists, site_id) = self.site_exists("Global")
2276-
if site_exists:
2277-
have["site_id"] = site_id
2278-
self.log(
2279-
"Resolved Global site UUID for golden tagging workflow: {0}".format(
2280-
str(site_id)
2281-
),
2282-
"INFO",
2283-
)
2284-
else:
2285-
self.log(
2286-
"Global site lookup did not return a valid site ID for Catalyst Center version {0}."
2287-
" Golden tagging cannot continue without a real Global site UUID.".format(
2288-
self.get_ccc_version()
2289-
),
2290-
"ERROR",
2291-
)
2292-
self.msg = "Unable to resolve the Global site ID in Cisco Catalyst Center for golden tagging."
2293-
self.log(self.msg, "ERROR")
2294-
self.status = "failed"
2295-
self.result["response"] = self.msg
2296-
self.check_return_status()
2287+
global_site_id = self.get_global_site_id()
2288+
have["site_id"] = global_site_id
2289+
self.log(
2290+
"Resolved Global site UUID for golden tagging workflow: {0}".format(
2291+
str(global_site_id)
2292+
),
2293+
"INFO",
2294+
)
22972295

22982296
self.have.update(have)
22992297
# check if given device family name exists, store indentifier value
@@ -3396,11 +3394,35 @@ def get_diff_tagging(self):
33963394
api_response = response.get("response")
33973395
if api_response:
33983396
is_tagged = api_response.get("taggedGolden", False)
3397+
self.log(
3398+
"Golden tag status for role '{0}' is taggedGolden={1}".format(
3399+
role, is_tagged
3400+
),
3401+
"DEBUG",
3402+
)
33993403
if is_tagged:
3404+
self.log(
3405+
"SWIM Image '{0}' already tagged as Golden image in Cisco Catalyst Center for role '{1}'".format(
3406+
image_name, role
3407+
),
3408+
"INFO",
3409+
)
34003410
already_tagged_roles.add(role)
34013411
else:
3412+
self.log(
3413+
"SWIM Image '{0}' already un-tagged from Golden image in Cisco Catalyst Center for role '{1}'".format(
3414+
image_name, role
3415+
),
3416+
"INFO",
3417+
)
34023418
already_untagged_roles.add(role)
34033419
else:
3420+
self.log(
3421+
"No golden status response returned for role '{0}'. Assuming role is untagged.".format(
3422+
role
3423+
),
3424+
"DEBUG",
3425+
)
34043426
already_untagged_roles.add(role)
34053427
except Exception as e:
34063428
self.log(
@@ -3422,12 +3444,6 @@ def get_diff_tagging(self):
34223444
if tag_image_golden:
34233445
# All desired roles are already tagged → idempotent skip
34243446
if desired_roles_set.issubset(already_tagged_roles):
3425-
self.log(
3426-
"All requested roles {0} are already golden-tagged. Skipping as idempotent.".format(
3427-
sorted(desired_roles_set)
3428-
),
3429-
"DEBUG",
3430-
)
34313447
self.msg = (
34323448
"SWIM Image '{0}' is already Golden tagged for device role(s) {1}. Skipping operation."
34333449
.format(image_name, role_display)
@@ -3437,12 +3453,6 @@ def get_diff_tagging(self):
34373453
else:
34383454
# All desired roles are already untagged → idempotent skip
34393455
if desired_roles_set.issubset(already_untagged_roles):
3440-
self.log(
3441-
"All requested roles {0} are already not golden-tagged. Skipping untagging as idempotent.".format(
3442-
sorted(desired_roles_set)
3443-
),
3444-
"DEBUG",
3445-
)
34463456
self.msg = (
34473457
"SWIM Image '{0}' is already not Golden tagged for device role(s) {1}. Skipping operation."
34483458
.format(image_name, role_display)
@@ -3513,7 +3523,7 @@ def get_diff_tagging(self):
35133523
op_modifies=True,
35143524
params={
35153525
"id": image_id,
3516-
"site_id" : self.have.get("site_id"),
3526+
"site_id": self.have.get("site_id"),
35173527
"payload": payload
35183528
}
35193529
)
@@ -3536,14 +3546,10 @@ def get_diff_tagging(self):
35363546
device_family = tagging_details.get("device_image_family_name") or "Unknown"
35373547

35383548
action = "Tagging" if tag_image_golden else "Un-Tagging"
3549+
display_roles = "ALL" if raw_roles.lower() == "all" else role_display
35393550
success_msg = (
3540-
"{0} image {1} golden for site {2}, family {3}, device role(s) {4} successful."
3541-
.format(
3542-
action,
3543-
image_name,
3544-
site_name,
3545-
device_family,
3546-
"ALL" if raw_roles.lower() == "all" else ", ".join(sorted(desired_roles_set)) if desired_roles_set else "ALL",
3551+
"{0} image {1} golden for site {2}, family {3}, device role(s) {4} successful.".format(
3552+
action, image_name, site_name, device_family, display_roles
35473553
)
35483554
)
35493555

@@ -5474,6 +5480,18 @@ def verify_diff_tagged(self):
54745480
self.have.get("site_id"),
54755481
)
54765482
if product_name_ordinal is None:
5483+
self.log(
5484+
(
5485+
"Unable to verify golden tag status for image '{0}' because "
5486+
"product_name_ordinal could not be resolved for family '{1}' "
5487+
"at site_id '{2}'."
5488+
).format(
5489+
image_name,
5490+
tagging_details.get("device_image_family_name"),
5491+
self.have.get("site_id"),
5492+
),
5493+
"WARNING",
5494+
)
54775495
return self
54785496

54795497
image_params = dict(
@@ -5510,20 +5528,14 @@ def verify_diff_tagged(self):
55105528
)
55115529

55125530
if image_status == tag_image_golden:
5513-
if tag_image_golden:
5514-
self.msg = """The requested image '{0}' has been tagged as golden in the Cisco Catalyst Center and
5515-
its status has been successfully verified for device role(s) {1}.""".format(
5516-
image_name,
5517-
device_role,
5518-
)
5519-
self.log(self.msg, "INFO")
5520-
else:
5521-
self.msg = """The requested image '{0}' has been un-tagged as golden in the Cisco Catalyst Center and
5522-
its status has been successfully verified for device role(s) {1}.""".format(
5523-
image_name,
5524-
device_role,
5531+
tag_action = "tagged" if tag_image_golden else "un-tagged"
5532+
self.msg = (
5533+
"The requested image '{0}' has been {1} as golden in the Cisco Catalyst Center and "
5534+
"its status has been successfully verified for device role(s) {2}.".format(
5535+
image_name, tag_action, device_role
55255536
)
5526-
self.log(self.msg, "INFO")
5537+
)
5538+
self.log(self.msg, "INFO")
55275539
else:
55285540
self.log(
55295541
"""Mismatch between the playbook input for tagging/un-tagging image as golden and the Cisco Catalyst Center indicates that
@@ -5570,20 +5582,14 @@ def verify_diff_tagged(self):
55705582
"DEBUG",
55715583
)
55725584
if image_status == tag_image_golden:
5573-
if tag_image_golden:
5574-
self.msg = """The requested image '{0}' has been tagged as golden in the Cisco Catalyst Center and
5575-
its status has been successfully verified for device role(s) {1}.""".format(
5576-
image_name,
5577-
device_role,
5578-
)
5579-
self.log(self.msg, "INFO")
5580-
else:
5581-
self.msg = """The requested image '{0}' has been un-tagged as golden in the Cisco Catalyst Center and
5582-
image status has been verified for device role(s) {1}.""".format(
5583-
image_name,
5584-
device_role,
5585+
tag_action = "tagged" if tag_image_golden else "un-tagged"
5586+
self.msg = (
5587+
"The requested image '{0}' has been {1} as golden in the Cisco Catalyst Center and "
5588+
"its status has been successfully verified for device role(s) {2}.".format(
5589+
image_name, tag_action, device_role
55855590
)
5586-
self.log(self.msg, "INFO")
5591+
)
5592+
self.log(self.msg, "INFO")
55875593
else:
55885594
self.log(
55895595
"""Mismatch between the playbook input for tagging/un-tagging image as golden and the Cisco Catalyst Center indicates that

0 commit comments

Comments
 (0)