Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
MTA Assessment Workflow
Browse files Browse the repository at this point in the history
This is an assessment workflow which is based on the Migration Analysis
infra workflow.
The main differne is that the checker of that workflow downloads the
html report and tries to extract a table of scores of issues found by
the analysis. The ProcessAnalysisTask has a predicate passed in the
constructor to test against the scores of the analysis and based on that
the task returns the passOption or the defaultOption. The passOption is
the next flow to invoke, that should be the move2kube.

The flow is roughly:

Start
  -
Infra flow start
  -
submit analysis report
  -
End

Start
  -
Checker flow start
  -
check report is ready
  -
switch (is ready?)
  yes -> go to parse
  no  -> go to check report is ready
  -
parse
  -
switch (match incidents on predicate)
  true - return pass option (move2kube)
  false - return default option
  -
End

Signed-off-by: Roy Golan <rgolan@redhat.com>
  • Loading branch information
rgolangh committed Jun 2, 2023
1 parent a8020ca commit ee17910
Show file tree
Hide file tree
Showing 19 changed files with 470 additions and 120 deletions.
1 change: 1 addition & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
5 changes: 5 additions & 0 deletions parodos-model-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>dev.parodos</groupId>
<artifactId>notification-service-sdk</artifactId>
<version>1.0.14-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.redhat.parodos.workflow.task.infrastructure;

import com.redhat.parodos.notification.sdk.model.NotificationMessageCreateRequestDTO;

public interface Notifier {

void send(NotificationMessageCreateRequestDTO message);

}
6 changes: 6 additions & 0 deletions prebuilt-tasks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@
<version>${jgit-version}</version>
</dependency>

<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>

<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.archive</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package com.redhat.parodos.tasks.migrationtoolkit;

import java.net.URI;
import java.util.List;

import com.redhat.parodos.workflow.exception.MissingParameterException;
import com.redhat.parodos.workflow.parameter.WorkParameter;
import com.redhat.parodos.workflow.parameter.WorkParameterType;
import com.redhat.parodos.workflow.task.infrastructure.BaseInfrastructureWorkFlowTask;
import com.redhat.parodos.workflows.work.DefaultWorkReport;
import com.redhat.parodos.workflows.work.WorkContext;
import com.redhat.parodos.workflows.work.WorkReport;
import com.redhat.parodos.workflows.work.WorkStatus;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

/**
Expand All @@ -37,21 +33,6 @@ public CreateApplicationTask(URI serverURL, String bearerToken) {
mtaClient = new MTAClient(serverURL, bearerToken);
}

@Override
public @NonNull List<WorkParameter> getWorkFlowTaskParameters() {
return List.of(
WorkParameter.builder().key("applicationName").type(WorkParameterType.TEXT).optional(false)
.description("The application name. Can be generated from the repository name").build(),
WorkParameter.builder().key("repositoryURL").type(WorkParameterType.TEXT).optional(false)
.description("The application git repository URL. Can be generated from the repository name")
.build(),
WorkParameter.builder().key("serverURL").type(WorkParameterType.TEXT).optional(true).description(
"Base URL of the MTA instance - e.g https://mta-openshift-mta.app.clustername.clusterdomain")
.build(),
WorkParameter.builder().key("bearerToken").type(WorkParameterType.TEXT).optional(true)
.description("Bearer token to authenticate server requests").build());
}

/**
* @param workContext optional context values: serverURL, and bearerToken for the
* mtaClient.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import java.net.URI;
import java.util.List;
import java.util.function.Consumer;

import com.redhat.parodos.email.Message;
import javax.inject.Inject;

import com.redhat.parodos.notification.sdk.model.NotificationMessageCreateRequestDTO;
import com.redhat.parodos.workflow.exception.MissingParameterException;
import com.redhat.parodos.workflow.parameter.WorkParameter;
import com.redhat.parodos.workflow.parameter.WorkParameterType;
import com.redhat.parodos.workflow.task.infrastructure.BaseInfrastructureWorkFlowTask;
import com.redhat.parodos.workflow.task.infrastructure.Notifier;
import com.redhat.parodos.workflows.work.DefaultWorkReport;
import com.redhat.parodos.workflows.work.WorkContext;
import com.redhat.parodos.workflows.work.WorkReport;
Expand All @@ -35,12 +37,13 @@ public class GetAnalysisTask extends BaseInfrastructureWorkFlowTask {

private URI serverUrl;

private final Consumer<Message> messageConsumer;
@Inject
private Notifier notificationSender;

public GetAnalysisTask(URI serverURL, String bearerToken, Consumer<Message> messageConsumer) {
public GetAnalysisTask(URI serverURL, String bearerToken, Notifier notifer) {
this.serverUrl = serverURL;
this.mtaClient = new MTAClient(serverURL, bearerToken);
this.messageConsumer = messageConsumer;
this.notificationSender = notifer;
}

@Override
Expand Down Expand Up @@ -95,8 +98,8 @@ else if (result instanceof Result.Success<TaskGroup> success) {
&& success.value().tasks()[0].state().equals("Succeeded")) {
String reportURL = String.format("%s/hub/applications/%d/bucket/%s", serverUrl,
success.value().tasks()[0].application().id(), success.value().data().output());
sendEmail(reportURL, getOptionalParameterValue("email", null));
addParameter("reportURL", reportURL);
sendNotification(reportURL);
return new DefaultWorkReport(WorkStatus.COMPLETED, workContext);
}
else if ("Failed".equals(success.value().state())) {
Expand All @@ -108,13 +111,14 @@ else if ("Failed".equals(success.value().state())) {
throw new IllegalArgumentException();
}

private void sendEmail(String reportURL, String recipient) {
if (recipient == null) {
return;
}
messageConsumer.accept(new Message(recipient, "parodos-task-notification@redhat.com",
"Parodos: Analysis report is done",
String.format("The analysis report is done. Find it here %s", reportURL)));
private void sendNotification(String reportURL) {
var request = new NotificationMessageCreateRequestDTO();
request.setMessageType("text");
request.setBody("Report URL: " + reportURL);
request.subject("Migration Analysis Report Completed");
request.setUsernames(List.of("test"));
request.setGroupNames(List.of("test"));
notificationSender.send(request);
}

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package com.redhat.parodos.tasks.migrationtoolkit;

import java.net.URI;
import java.util.List;

import com.redhat.parodos.workflow.exception.MissingParameterException;
import com.redhat.parodos.workflow.parameter.WorkParameter;
import com.redhat.parodos.workflow.parameter.WorkParameterType;
import com.redhat.parodos.workflow.task.infrastructure.BaseInfrastructureWorkFlowTask;
import com.redhat.parodos.workflows.work.DefaultWorkReport;
import com.redhat.parodos.workflows.work.WorkContext;
import com.redhat.parodos.workflows.work.WorkReport;
import com.redhat.parodos.workflows.work.WorkStatus;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

/**
Expand All @@ -36,22 +32,6 @@ public GetApplicationTask(URI serverURL, String bearerToken) {
mtaClient = new MTAClient(serverURL, bearerToken);
}

@Override
public @NonNull List<WorkParameter> getWorkFlowTaskParameters() {
return List.of(
WorkParameter.builder().key("serverURL").type(WorkParameterType.TEXT).optional(true).description(
"Base URL of the MTA instance - e.g https://mta-openshift-mta.app.clustername.clusterdomain")
.build(),
WorkParameter.builder().key("bearerToken").type(WorkParameterType.TEXT).optional(true)
.description("Bearer token to authenticate server requests").build(),
WorkParameter.builder().key("applicationName").type(WorkParameterType.TEXT).optional(false).description(
"The application name as presented in the application hub. Can be generated from the repository name")
.build(),
WorkParameter.builder().key("sourceRepository").type(WorkParameterType.TEXT).optional(true).description(
"The application name as presented in the application hub. Can be generated from the repository name")
.build());
}

/**
* @param workContext optional context values: serverURL, and bearerToken for the
* mtaClient.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package com.redhat.parodos.tasks.migrationtoolkit;

import java.net.URI;
import java.util.List;

import com.redhat.parodos.workflow.exception.MissingParameterException;
import com.redhat.parodos.workflow.parameter.WorkParameter;
import com.redhat.parodos.workflow.parameter.WorkParameterType;
import com.redhat.parodos.workflow.task.infrastructure.BaseInfrastructureWorkFlowTask;
import com.redhat.parodos.workflows.work.DefaultWorkReport;
import com.redhat.parodos.workflows.work.WorkContext;
import com.redhat.parodos.workflows.work.WorkReport;
import com.redhat.parodos.workflows.work.WorkStatus;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

/**
Expand Down Expand Up @@ -41,19 +37,6 @@ public SubmitAnalysisTask(URI serverURL, String bearerToken) {
this.mtaClient = new MTAClient(serverURL, bearerToken);
}

@Override
public @NonNull List<WorkParameter> getWorkFlowTaskParameters() {
return List.of(
WorkParameter.builder().key("applicationName").type(WorkParameterType.TEXT).optional(false).description(
"The application name as presented in the application hub. Can be generated from the repository name")
.build(),
WorkParameter.builder().key("serverURL").type(WorkParameterType.TEXT).optional(true).description(
"Base URL of the MTA instance - e.g https://mta-openshift-mta.app.clustername.clusterdomain")
.build(),
WorkParameter.builder().key("bearerToken").type(WorkParameterType.TEXT).optional(true)
.description("Bearer token to authenticate server requests").build());
}

/**
* @param workContext optional context values: serverURL, and bearerToken for the
* mtaClient.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import com.redhat.parodos.notification.sdk.api.ApiClient;
import com.redhat.parodos.notification.sdk.api.ApiException;
Expand All @@ -31,8 +32,15 @@ public class NotificationWorkFlowTask extends BaseWorkFlowTask {

private final NotificationMessageApi apiInstance;

public NotificationWorkFlowTask(String basePath, String auth) {
private Function<WorkContext, NotificationMessageCreateRequestDTO> messageFunc = (
context) -> new NotificationMessageCreateRequestDTO();

public NotificationWorkFlowTask(String basePath, String auth,
Function<WorkContext, NotificationMessageCreateRequestDTO> messageFunc) {
this(basePath, null, auth);
if (messageFunc != null) {
this.messageFunc = messageFunc;
}
}

protected NotificationWorkFlowTask(String basePath, NotificationMessageApi apiInstance) {
Expand Down Expand Up @@ -78,7 +86,7 @@ public HashMap<String, Map<String, Object>> getAsJsonSchema() {

@Override
public WorkReport execute(WorkContext workContext) {
NotificationMessageCreateRequestDTO notificationMessageCreateRequestDTO = new NotificationMessageCreateRequestDTO();
NotificationMessageCreateRequestDTO notificationMessageCreateRequestDTO = messageFunc.apply(workContext);

try {
notificationMessageCreateRequestDTO.messageType(getRequiredParameterValue("type"));
Expand Down
1 change: 1 addition & 0 deletions prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("local")
public class OcpOnboardingWorkFlowConfiguration {

// Assessment workflow
Expand All @@ -69,13 +71,23 @@ WorkFlowOption notSupportOption() {
.setDescription("Non-Supported Workflow Steps").build();
}

@Bean
WorkFlowOption analyzeOption() {
return new WorkFlowOption.Builder("analyzeOption", "AnalyzeApplication")
.addToDetails("Analyze an application's source code before migrating it."
+ " Produces a containerization report by MTA")
.displayName("Migration Analysis").setDescription("Migration Analysis step").build();
}

// An AssessmentTask returns one or more WorkFlowOption wrapped in a WorkflowOptions
@Bean
OnboardingOcpAssessmentTask onboardingAssessmentTask(
@Qualifier("onboardingOcpOption") WorkFlowOption onboardingOcpOption,
@Qualifier("badRepoOption") WorkFlowOption badRepoOption,
@Qualifier("notSupportOption") WorkFlowOption notSupportOption) {
return new OnboardingOcpAssessmentTask(List.of(onboardingOcpOption, badRepoOption, notSupportOption));
@Qualifier("notSupportOption") WorkFlowOption notSupportOption,
@Qualifier("analyzeOption") WorkFlowOption analyzeOption) {
return new OnboardingOcpAssessmentTask(
List.of(onboardingOcpOption, badRepoOption, notSupportOption, analyzeOption));
}

// A Workflow designed to execute and return WorkflowOption(s) that can be executed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ NotificationWorkFlowTask notificationTask() {
String notificationWorkFlowBasePath = "http://" + serverIp + ":" + serverPort;
log.info("NotificationWorkFlowTask basePath: {}", notificationWorkFlowBasePath);
return new NotificationWorkFlowTask(notificationWorkFlowBasePath,
"Basic " + CredUtils.getBase64Creds("test", "test"));
"Basic " + CredUtils.getBase64Creds("test", "test"), null);
}

@Bean(name = "prebuiltWorkFlow" + WorkFlowConstants.INFRASTRUCTURE_WORKFLOW)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.redhat.parodos.examples.prebuilt.migrationtoolkit;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;

public class MTAAnalysisReport {

/**
* migrationIssuesReport is assumed to be valid html. MTA 6.1 should supply a CSV as
* well. Throw and exception when the parsing fails or if it can't extract data
*/
public record AnalysisIncidents(int mandatory, int optional, int potential, int cloudMandatory, int cloudOptional,
int information) {
}

/**
* Extract an AnalysisIncident from the report index html page
* @rpeortIndex is the content the page
* /report/reports/report_index_{name_of_project}.html
*/
public static AnalysisIncidents extractIncidents(String reportIndex) throws Exception {
var doc = Jsoup.parse(reportIndex);

var tables = doc.select("tbody#incidentsByTypeTBody");
if (tables.size() == 1) {
var t = tables.get(0);
int mandatory = countOf(t, "mandatory");
int optional = countOf(t, "optional");
int potential = countOf(t, "potential");
int cloudMandatory = countOf(t, "cloud-mandatory");
int cloudOptional = countOf(t, "cloud-optional");
int information = countOf(t, "information");

return new AnalysisIncidents(mandatory, optional, potential, cloudMandatory, cloudOptional, information);
}
throw new Exception("Didn't find a table to parse and extract incidents from");
}

private static int countOf(Element t, String column) throws Exception {
var element = t.select("td:matches(^%s)".formatted(column));
if (element != null && !element.isEmpty()) {
try {
String count = element.next().select("td.numeric-column").text();
return Integer.parseInt(count);
}
catch (NumberFormatException | NullPointerException e) {
throw new Exception("Failed to extracts columns information from the table", e);
}
}
throw new Exception("Failed to find or parse a table cell with text " + column);
}

}
Loading

0 comments on commit ee17910

Please sign in to comment.