Skip to content

Commit b0a5d88

Browse files
author
Glenn Snyder
committed
adding sample showing how to clone or copy overrides from a baseline version to other versions in the same project
1 parent 80d85dd commit b0a5d88

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

examples/clone_baseline_overrides.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env python
2+
3+
import argparse
4+
import arrow
5+
import json
6+
import logging
7+
import sys
8+
9+
from blackduck.HubRestApi import HubInstance, object_id
10+
11+
def get_policy_status_comment(policy_status):
12+
'''Return the most recent policy status comment
13+
'''
14+
comments = list()
15+
for view in policy_status.get('policyRuleViolationViews', []):
16+
for record in view.get('updatedBy', []):
17+
comments.append((record['comment'], arrow.get(record['updatedAt'])))
18+
comments = sorted(comments, key=lambda c: c[1])
19+
return comments[-1]
20+
21+
def components_with_overrides(hub_instance, version):
22+
# components_url = hub_instance.get_link(version, "components") + "?limit=999"
23+
# components = hub_instance.execute_get(components_url).json().get('items', [])
24+
components = hub_instance.get_version_components(version, limit=999).get('items', [])
25+
have_overrides = [c for c in components if c['policyStatus'] == 'IN_VIOLATION_OVERRIDDEN']
26+
# need to retrieve override comments
27+
for component in have_overrides:
28+
policy_status_url = hub_instance.get_link(component, "policy-status")
29+
# Note: The public endpoint/media type does NOT return the override comment
30+
# shown in the GUI. So, using a private internal media type, below, which allows retrieval
31+
# of the comment info.
32+
# Ref: <blackduck_url>/api-doc/public.html#policy-status-representation
33+
#
34+
# Warning: Use of an internal media type is not supported. What does this mean?
35+
# It can break on a future release of Black Duck so this script will
36+
# need to be re-tested for each future version of Black Duck. And, if it fails,
37+
# it will need to be reworked accordingly
38+
custom_headers = {'Accept':'application/vnd.blackducksoftware.internal-1+json'}
39+
policy_status = hub_instance.execute_get(policy_status_url, custom_headers=custom_headers).json()
40+
comment, comment_dt = get_policy_status_comment(policy_status)
41+
component['comment'] = comment
42+
component['comment_dt'] = comment_dt
43+
return have_overrides
44+
45+
def clone_policy_status(hub_instance, version, component_overrides):
46+
overrides_by_name = {f"{c['componentName']}:{c['componentVersionName']}":c for c in component_overrides}
47+
components = hub_instance.get_version_components(version, limit = 999).get('items', [])
48+
for component in components:
49+
cn = f"{component['componentName']}:{component['componentVersionName']}"
50+
override = overrides_by_name.get(cn)
51+
if override:
52+
policy_status_url = hub_instance.get_link(component, "policy-status")
53+
# TODO: use comment_dt from override or accept the dt for when we cloned?
54+
data = {
55+
'approvalStatus': override['policyStatus'],
56+
'comment': override['comment'],
57+
}
58+
response = hub_instance.execute_put(policy_status_url, data=data)
59+
if response.status_code == 202:
60+
logging.info(f"Cloned override to {cn} in version {version['versionName']}")
61+
else:
62+
logging.error(f"Failed to clone overide to {cn} in version {version['versionName']}")
63+
else:
64+
logging.debug(f"{cn} not in overrides to clone")
65+
66+
67+
def clone_overrides(hub_instance, project, baseline_version_name):
68+
versions = hub_instance.get_project_versions(project).get('items', [])
69+
version_names = ",".join([v['versionName'] for v in versions])
70+
assert baseline_version_name in version_names, "The baseline version must exist in the project"
71+
72+
logging.debug(f"Cloning overrides from version '{baseline_version_name}' to the other versions ({version_names}) in project {project['name']}")
73+
baseline_version = next(v for v in versions if v['versionName'] == baseline_version_name)
74+
overrides_to_clone = components_with_overrides(hub_instance, baseline_version)
75+
versions_to_clone_to = [v for v in versions if v['versionName'] != baseline_version_name]
76+
for version in versions_to_clone_to:
77+
clone_policy_status(hub_instance, version, overrides_to_clone)
78+
79+
parser = argparse.ArgumentParser("Clone component everrides from a baseline version to all other versions in the project")
80+
parser.add_argument("-p", "--project", help="Specify a project to do the override cloning on (default is to clone overrides in all projects)")
81+
parser.add_argument("-b", "--baseline_version", default="baseline", help="The name of the baseline version from which to clone overrides")
82+
args = parser.parse_args()
83+
84+
85+
logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', stream=sys.stderr, level=logging.DEBUG)
86+
logging.getLogger("requests").setLevel(logging.WARNING)
87+
logging.getLogger("urllib3").setLevel(logging.WARNING)
88+
logging.getLogger("blackduck").setLevel(logging.WARNING)
89+
90+
hub = HubInstance()
91+
92+
if args.project:
93+
projects = [hub.get_project_by_name(args.project)]
94+
else:
95+
projects = hub.get_projects(limit=999).get('items', [])
96+
97+
for project in projects:
98+
clone_overrides(hub, project, args.baseline_version)
99+

0 commit comments

Comments
 (0)