Skip to content

Commit

Permalink
Merge pull request #1248 from GnsP/fix-CDAP-21073
Browse files Browse the repository at this point in the history
[CDAP-21073] Studio top panel disappears on editing duplicate pipelines
  • Loading branch information
GnsP authored Oct 29, 2024
2 parents 2825ff9 + e123c58 commit accc18c
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 3 deletions.
2 changes: 1 addition & 1 deletion app/cdap/components/PipelineConfigurations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export default class PipelineConfigurations extends Component<IPipelineConfigura
headerLabel = T.translate(`${PREFIX}.titleHistorical`);
} else {
headerLabel = T.translate(`${PREFIX}.title`);
if (this.props.pipelineName.length) {
if (this.props.pipelineName?.length) {
headerLabel += ` "${this.props.pipelineName}"`;
}
}
Expand Down
9 changes: 8 additions & 1 deletion app/hydrator/services/hydrator-upgrade-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,14 @@ class HydratorUpgradeService {
});
return;
}
jsonData.name = this.$state.params.cloneId;

// a pipeline can be duplicated (cloned), carried over to a next version as draft and
// become an orphaned draft. When such a pipeline is opened in edit mode, we get
// a draftId instead of a cloneId. This results in CDAP-21073 (top panel disappears)
// as the pipeline name is set to undefined.
// Fix: if cloneId is not present, use the original pipeline_name + '_copy'.
// (same behavior as generating the cloneId)
jsonData.name = this.$state.params.cloneId || (jsonData.name || '') + '_copy' ;
jsonData.parentVersion = parentVersion;
}

Expand Down
1 change: 1 addition & 0 deletions app/hydrator/templates/create/pipeline-upgrade-modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ <h4 class="stage-title {{ stage.type }} {{ stage.stageInfo.plugin.type }}">
class="btn btn-primary"
ng-click="PipelineUpgradeController.fixAll()"
data-cy="fix-all-btn"
data-testid="fix-all-btn"
>
<span ng-if="!PipelineUpgradeController.fixAllDisabled">Fix All</span>
<span ng-if="PipelineUpgradeController.fixAllDisabled">Proceed</span>
Expand Down
11 changes: 10 additions & 1 deletion src/e2e-test/features/pipeline.edit.feature
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,14 @@ Feature: Pipeline Edit
Then Click Continue draft
Then Verify changes were saved

@PIPELINE_EDIT_TEST
Scenario: Editing an orphaned pipeline draft should not break top panel
When Open HttpExecutor Page
Then Create an orphan pipeline draft
When Open pipeline draft list page
Then Go to pipeline "test-orphan-pipeline-6-10-1" draft
Then Click on FixAll Button
Then Verify Studio TopPanel is visible
When Open pipeline draft list page
Then Delete Draft Pipeline "test-orphan-pipeline-6-10-1"


65 changes: 65 additions & 0 deletions src/e2e-test/fixtures/test-orphan-pipeline-6-10-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"artifact": {
"name": "cdap-data-pipeline",
"version": "6.10.1",
"scope": "SYSTEM",
"label": "Data Pipeline - Batch"
},
"description": "",
"name": "test-orphan-pipeline-6-10-1",
"change": {
"description": ""
},
"parentVersion": "this-does-not-exist",
"config": {
"resources": {
"memoryMB": 2048,
"virtualCores": 1
},
"driverResources": {
"memoryMB": 2048,
"virtualCores": 1
},
"connections": [],
"comments": [],
"postActions": [],
"properties": {},
"processTimingEnabled": true,
"stageLoggingEnabled": false,
"stages": [
{
"name": "File",
"plugin": {
"name": "File",
"type": "batchsource",
"label": "File",
"artifact": {
"name": "core-plugins",
"version": "2.12.1",
"scope": "SYSTEM"
},
"properties": {
"sampleSize": "1000",
"enableQuotedValues": "false",
"skipHeader": "false",
"filenameOnly": "false",
"recursive": "false",
"ignoreNonExistingFolders": "false",
"fileEncoding": "UTF-8",
"schema": "{\"name\":\"fileRecord\",\"type\":\"record\",\"fields\":[{\"name\":\"offset\",\"type\":\"long\"},{\"name\":\"body\",\"type\":\"string\"}]}"
}
},
"outputSchema": "{\"name\":\"fileRecord\",\"type\":\"record\",\"fields\":[{\"name\":\"offset\",\"type\":\"long\"},{\"name\":\"body\",\"type\":\"string\"}]}",
"id": "File"
}
],
"schedule": "0 1 */1 * *",
"engine": "spark",
"numOfRecordsPreview": 100,
"rangeRecordsPreview": {
"min": 1,
"max": "5000"
},
"maxConcurrentRuns": 1
}
}
68 changes: 68 additions & 0 deletions src/e2e-test/java/io/cdap/cdap/ui/stepsdesign/CommonSteps.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.UnhandledAlertException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.support.ui.Select;

import java.io.IOException;
import java.util.UUID;

public class CommonSteps {

Expand Down Expand Up @@ -82,6 +87,12 @@ public void openConfigurationPage() {
WaitHelper.waitForPageToLoad();
}

@When("Open HttpExecutor Page")
public void openHttpExecutorPage() {
SeleniumDriver.openPage(Constants.HTTP_EXECUTOR_URL);
WaitHelper.waitForPageToLoad();
}

@When("Open Source Control Management Page")
public void openSourceControlManagementPage() {
SeleniumDriver.openPage(Constants.SOURCE_CONTROL_MANAGEMENT_URL);
Expand Down Expand Up @@ -288,6 +299,11 @@ public void openPipelineDetails(String pipelineName) {
ElementHelper.clickOnElement(Helper.locateElementByTestId("deployed-" + pipelineName));
}

@Then("Go to pipeline {string} draft")
public void openPipelineDraft(String pipelineName) {
ElementHelper.clickOnElement(Helper.locateElementByTestId("draft-" + pipelineName));
}

@Then("Add Projection node to canvas")
public void addProjectionNodeToCanvas() {
NodeInfo projectionNode = new NodeInfo("Projection", "transform", "0");
Expand All @@ -304,4 +320,56 @@ public void openProjectionNodeProperties() {
public void closeProjectionNodeProperties() {
Commands.closeConfigPopover();
}

@Then("Create an orphan pipeline draft")
public void createOrphanPipelineDraft() throws IOException {
WebElement requestMethodDropdown = Helper.locateElementByTestId("request-method-selector");
Select requestMethodSelect = new Select(requestMethodDropdown);
requestMethodSelect.selectByValue("PUT");

WebElement requestPathInput = Helper.locateElementByTestId("request-path-input");
String saveDraftPath = "namespaces/system/apps/pipeline/services/studio/methods/v1/contexts/default/drafts/"
+ UUID.randomUUID();
ElementHelper.sendKeys(requestPathInput, saveDraftPath);

WebElement requestBodyInput = Helper.locateElementByTestId("request-body");
String requestBody = Helper.readPipelineFixtureFile("test-orphan-pipeline-6-10-1.json");
ElementHelper.sendKeys(requestBodyInput, requestBody);

WebElement callApiButton = Helper.locateElementByTestId("send-btn");
ElementHelper.clickOnElement(callApiButton);

String callHistoryEntryXpath = "//*[@data-testid=\"request-path\"][text()=\"" + saveDraftPath + "\"]";
WaitHelper.waitForElementToBePresent(By.xpath(callHistoryEntryXpath));
}

@Then("Click on FixAll Button")
public void clickOnFixAllButton() {
String fixAllBtnXpath = "//*[@data-testid=\"fix-all-btn\"]";
WaitHelper.waitForElementToBePresent(
By.xpath(fixAllBtnXpath));
ElementHelper.clickOnElement(Helper.locateElementByXPath(fixAllBtnXpath));
}

@Then("Verify Studio TopPanel is visible")
public void verifyStudioTopPanelVisible() {
String orphanedPipelineXpath = "//*[@data-testid=\"pipeline-edit-status\"]";
WaitHelper.waitForElementToBePresent(
By.xpath(orphanedPipelineXpath));
Assert.assertTrue(Helper.isElementExists(By.xpath(orphanedPipelineXpath)));
}

@Then("Delete Draft Pipeline {string}")
public void deletePipelineDraft(String pipelineName) {
String actionsPopoverXpath =
"//*[@data-testid=\"draft-" + pipelineName + "\"]//*[@data-testid=\"actions-popover\"]";
WebElement actionsPopover = Helper.locateElementByXPath(actionsPopoverXpath);
ElementHelper.clickOnElement(actionsPopover);
String deleteActionXpath =
"//*[@data-testid=\"draft-" + pipelineName + "\"]//*[@data-testid=\"Delete-on-popover\"]";
ElementHelper.clickOnElement(Helper.locateElementByXPath(deleteActionXpath));
ElementHelper.clickOnElement(Helper.locateElementByTestId("Delete"));
Helper.waitSeconds();
Assert.assertFalse(Helper.isElementExists(Helper.getCssSelectorByDataTestId("draft-" + pipelineName)));
}
}
1 change: 1 addition & 0 deletions src/e2e-test/java/io/cdap/cdap/ui/utils/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ private static double getRandomArbitrary(int min, int max) {
public static final String BASE_PIPELINES_URL = BASE_URL + "/pipelines/ns/default";
public static final String CDAP_URL = BASE_URL + "/cdap";
public static final String CONFIGURATION_URL = BASE_URL + "/cdap/administration/configuration";
public static final String HTTP_EXECUTOR_URL = BASE_URL + "/cdap/httpexecutor";
public static final String SOURCE_CONTROL_MANAGEMENT_URL = BASE_URL + "/cdap/ns/default/details/scm";
public static final String SOURCE_CONTROL_SYNC_URL = BASE_URL + "/cdap/ns/default/scm/sync";
public static final String NAMESPACE_URL = BASE_URL + "/cdap/ns";
Expand Down
10 changes: 10 additions & 0 deletions src/e2e-test/java/io/cdap/cdap/ui/utils/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import io.cdap.e2e.utils.SeleniumDriver;
import io.cdap.e2e.utils.WaitHelper;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URIBuilder;
import org.eclipse.jgit.api.Git;
Expand Down Expand Up @@ -60,6 +61,7 @@
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Reader;
import java.net.URISyntaxException;
Expand Down Expand Up @@ -230,6 +232,14 @@ public static void uploadPipelineFromFile(String filename) {
}
}

public static String readPipelineFixtureFile(String filename) throws IOException {
File pipelineJSONFile = new File(Constants.FIXTURES_DIR + filename);
try (FileInputStream inputStream = new FileInputStream(pipelineJSONFile)) {
String contents = IOUtils.toString(inputStream);
return contents;
}
}

public static void deployAndTestPipeline(String filename, String pipelineName) {
SeleniumDriver.openPage(Constants.BASE_STUDIO_URL + "pipelines");
WaitHelper.waitForPageToLoad();
Expand Down

0 comments on commit accc18c

Please sign in to comment.