Skip to content

Commit

Permalink
Update migration assessment on-flight
Browse files Browse the repository at this point in the history
Signed-off-by: Marek Aufart <[email protected]>
  • Loading branch information
aufi committed Oct 27, 2023
1 parent ffa9dba commit a06f7d0
Showing 1 changed file with 79 additions and 83 deletions.
162 changes: 79 additions & 83 deletions hack/tool/tackle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ parser.add_argument('-n','--no-auth', dest='noAuth', action='store_const', const
help='Skip Keycloak token creation, use empty Auth token in Tackle API calls.')
parser.add_argument('-b','--skip-buckets', dest='skipBuckets', action='store_const', const=True, default=False,
help='Skip Tackle 2 Buckets content export.')
parser.add_argument('-t','--token', type=str, help='Bearer auth token for Hub API (login/password is a fallback to create it).',
nargs='?', default='')
parser.add_argument('-p','--pathfinder-url', type=str, help='In-cluster Pathfinder endpoint URL.',
nargs='?', default='')
args = parser.parse_args()

###############################################################################
Expand Down Expand Up @@ -82,20 +86,24 @@ def debugPrint(str):
if args.verbose:
print(str)

def getHubToken(host, username, password):
print("Getting auth token via Hub from %s" % host)
url = "%s/hub/auth/login" % host
data = '{"user": "%s", "password": "%s"}' % (username, password)

r = requests.post(url, data=data, verify=False)
if r.ok:
respData = json.loads(r.text)
debugPrint("Got access token: %s" % respData['token'])
return respData['token']
def getHubToken(host, username, password, token):
if token:
print("Skipping login, using provided auth token.")
return token
else:
print("ERROR getting auth token from %s" % url)
print(data, r)
exit(1)
print("Getting auth token via Hub from %s" % host)
url = "%s/hub/auth/login" % host
data = '{"user": "%s", "password": "%s"}' % (username, password)

r = requests.post(url, data=data, verify=False)
if r.ok:
respData = json.loads(r.text)
debugPrint("Got access token: %s" % respData['token'])
return respData['token']
else:
print("ERROR getting auth token from %s" % url)
print(data, r)
exit(1)

def getKeycloakToken(host, username, password, client_id='tackle-ui', realm='tackle'):
if args.noAuth:
Expand Down Expand Up @@ -725,72 +733,54 @@ class TackleTool:
# Push the updated assessment
apiJSON(self.tackle2Url + tackle2path("assessments/%d" % assmnt2['id']), self.tackle2Token, data=assmnt2, method='PATCH', ignoreErrors=ignoreErrors)

def migrateAssessments(self, assessmentsFileName="assessments", ignoreErrors=False):
# Migrate Pathfinder Assessment to Konveyor (expecting Pathfinder hard-coded questionnaire ID=1)
def migrateAssessments(self, pathfinderUrl, ignoreErrors=False):
cnt = 0
## Export Pathfinder data for each Application
#for app in apiJSON(self.tackle2Url + "/hub/applications", self.tackle2Token):
# for assm2 in apiJSON(self.tackle2Url + "/hub/pathfinder/assessments?applicationId=%d" % app.id, self.tackle2Token):
# # Prepare Assessment and find its ID
# assm = Tackle2Object()
# assm.id = assm2['id']
# assm.applicationId = assm2['applicationId']
# assm.status = assm2['status']
# # Prepare Assessment questions and answers
# asqa2 = apiJSON(self.tackle2Url + "/hub/pathfinder/assessments/%d" % assm.id, self.tackle2Token)
# asqa = Tackle2Object()
# asqa.id = asqa2['id']
# asqa.applicationId = asqa2['applicationId']
# asqa.status = asqa2['status']
# asqa.stakeholders = asqa2['stakeholders']
# asqa.stakeholderGroups = asqa2['stakeholderGroups']
# asqa.questionnaire = asqa2['questionnaire']
# self.add('assessments', asqa)
#saveJSON(os.path.join(self.dataDir, assessmentsFileName), self.data["assessments"])

# Upload assessment to Konveyor (expecting Pathfinder hard-coded questionnaire)
dictCollection = loadDump(os.path.join(self.dataDir, assessmentsFileName + '.json'))
print("Processing Pathfinder assessments..")
for passmnt in dictCollection:
print("# Assessment for Application %s" % passmnt["applicationId"])
appAssessmentsPath = "/hub/applications/%d/assessments" % passmnt["applicationId"]
# Skip if Assessment for given Application already exists
if len(apiJSON(self.tackle2Url + appAssessmentsPath, self.tackle2Token, data={"questionnaire": {"id": 1}})) > 0:
print(" Assessment already exists, skipping.")
continue
apps = apiJSON(self.tackle2Url + "/hub/applications", self.tackle2Token)
print("There are %d Applications, looking for their Assessments.." % len(apps))
for app in apps:
# Export Pathfinder data for each Application
for passmnt in apiJSON(pathfinderUrl + "/assessments?applicationId=%d" % app['id'], self.tackle2Token):
print("# Assessment for Application %s" % passmnt["applicationId"])
appAssessmentsPath = "/hub/applications/%d/assessments" % passmnt["applicationId"]
# Skip if Assessment for given Application already exists
if len(apiJSON(self.tackle2Url + appAssessmentsPath, self.tackle2Token, data={"questionnaire": {"id": 1}})) > 0:
print(" Assessment already exists, skipping.")
continue

# Prepare new Assessment
assmnt = dict()
assmnt['questionnaire'] = {"id": 1} # Default new Questionnaire "Pathfinder Legacy"
assmnt['application'] = {"id": passmnt["applicationId"]}
assmnt['stakeholders'] = []
for sh in passmnt['stakeholders']:
assmnt['stakeholders'].append({"id": sh})
assmnt['stakeholderGroups'] = []
for shg in passmnt['stakeholderGroups']:
assmnt['stakeholderGroups'].append({"id": shg})

# Transformate Questions, Answers and related structures
for category in passmnt['questionnaire']['categories']:
del category['id']
category['name'] = category.pop('title')
for question in category["questions"]:
del question['id']
question["text"] = question.pop('question')
question["explanation"] = question.pop('description')
question["answers"] = question.pop('options')
for answer in question['answers']:
del answer['id']
answer['text'] = answer.pop('option')
answer['selected'] = answer.pop('checked')
answer['risk'] = answer['risk'].lower()
if answer['risk'] == "amber":
answer['risk'] = "yellow"
assmnt['sections'] = passmnt['questionnaire']['categories']

# Post the Assessment
apiJSON(self.tackle2Url + appAssessmentsPath, self.tackle2Token, data=assmnt, method='POST')
cnt += 1
print("Assessment submitted.")
# Prepare new Assessment
assmnt = dict()
assmnt['questionnaire'] = {"id": 1} # Default new Questionnaire "Pathfinder Legacy"
assmnt['application'] = {"id": passmnt["applicationId"]}
assmnt['stakeholders'] = []
for sh in passmnt['stakeholders']:
assmnt['stakeholders'].append({"id": sh})
assmnt['stakeholderGroups'] = []
for shg in passmnt['stakeholderGroups']:
assmnt['stakeholderGroups'].append({"id": shg})

# Transformate Questions, Answers and related structures
for category in passmnt['questionnaire']['categories']:
del category['id']
category['name'] = category.pop('title')
for question in category["questions"]:
del question['id']
question["text"] = question.pop('question')
question["explanation"] = question.pop('description')
question["answers"] = question.pop('options')
for answer in question['answers']:
del answer['id']
answer['text'] = answer.pop('option')
answer['selected'] = answer.pop('checked')
answer['risk'] = answer['risk'].lower()
if answer['risk'] == "amber":
answer['risk'] = "yellow"
assmnt['sections'] = passmnt['questionnaire']['categories']

# Post the Assessment
apiJSON(self.tackle2Url + appAssessmentsPath, self.tackle2Token, data=assmnt, method='POST')
cnt += 1
print("Assessment submitted.")
return cnt

def preImportCheck(self):
Expand Down Expand Up @@ -956,7 +946,7 @@ if cmdWanted(args, "export-tackle1"):
if cmdWanted(args, "export"):
cmdExecuted = True
# Gather Keycloak access tokens for Tackle2
token2 = getHubToken(c['url'], c['username'], c['password'])
token2 = getHubToken(c['url'], c['username'], c['password'], args.token)

# Setup data migration object
tool = TackleTool(args.data_dir, '', '', c['url'], token2, c['encryption_passphase'])
Expand All @@ -979,7 +969,7 @@ if cmdWanted(args, "export"):
if cmdWanted(args, "import"):
cmdExecuted = True
# Gather Keycloak access token for Tackle 2
token2 = getHubToken(c['url'], c['username'], c['password'])
token2 = getHubToken(c['url'], c['username'], c['password'], args.token)

# Setup Tackle 1.2->2.0 data migration object
tool = TackleTool(args.data_dir, '', '', c['url'], token2, c['encryption_passphase'])
Expand All @@ -1001,7 +991,7 @@ if cmdWanted(args, "import"):
if cmdWanted(args, "clean"):
cmdExecuted = True
# Gather Keycloak access token for Tackle 2
token2 = getHubToken(c['url'], c['username'], c['password'])
token2 = getHubToken(c['url'], c['username'], c['password'], args.token)

# Setup Tackle 1.2->2.0 data migration object
tool = TackleTool(args.data_dir, '', '', c['url'], token2)
Expand All @@ -1015,7 +1005,7 @@ if cmdWanted(args, "clean"):
if cmdWanted(args, "clean-all"):
cmdExecuted = True
# Gather Keycloak access token for Tackle 2
token2 = getHubToken(c['url'], c['username'], c['password'])
token2 = getHubToken(c['url'], c['username'], c['password'], args.token)

# Setup Tackle 1.2->2.0 data migration object
tool = TackleTool(args.data_dir, '', '', c['url'], token2)
Expand All @@ -1027,15 +1017,21 @@ if cmdWanted(args, "clean-all"):
# Migrate Pathfinder Assessments to Konveyor Assessments
if cmdWanted(args, "migrate-assessments"):
cmdExecuted = True

# Check Pathfinder URL arg
if not args.pathfinder_url:
print("Error: Pathfinder URL is required, specify it with -p or --pathfinder-url option.")
exit(1)

# Gather Keycloak access token for Tackle 2
token2 = getHubToken(c['url'], c['username'], c['password'])
token2 = getHubToken(c['url'], c['username'], c['password'], args.token)

# Setup Tackle data migration object
tool = TackleTool(args.data_dir, '', '', c['url'], token2)

# Run the import
print("Starting Pathfinder Assessments to Konveyor Assessment migration.")
appCnt = tool.migrateAssessments(ignoreErrors=args.ignoreImportErrors)
appCnt = tool.migrateAssessments(args.pathfinder_url)

print("Done. %d new Assessment(s) for Application(s) were migrated!" % appCnt)

Expand Down

0 comments on commit a06f7d0

Please sign in to comment.