From 1d41226ac59b479515c6311cf86953e7850c4d16 Mon Sep 17 00:00:00 2001 From: James Wallis Date: Wed, 12 Aug 2020 12:17:44 +0100 Subject: [PATCH 1/4] Refactor File-watcher projectName, add subdir to location when available Signed-off-by: James Wallis --- .../src/controllers/projectsController.ts | 8 ++-- .../server/src/projects/Validator.ts | 5 ++- .../server/src/projects/actions.ts | 4 +- .../server/src/projects/projectUtil.ts | 45 ++++++++++++++----- .../file-watcher/server/src/utils/logger.ts | 3 +- .../tests/projectUtil.module.test.ts | 33 +++++++++++++- src/pfe/portal/modules/FileWatcher.js | 6 ++- src/pfe/portal/modules/Templates.js | 5 ++- src/pfe/portal/routes/projects/bind.route.js | 36 +++++++++++---- .../unit/routes/projects/bind.route.test.js | 36 +++++++++++++++ 10 files changed, 148 insertions(+), 33 deletions(-) diff --git a/src/pfe/file-watcher/server/src/controllers/projectsController.ts b/src/pfe/file-watcher/server/src/controllers/projectsController.ts index dcc8ae17f..2f5434750 100644 --- a/src/pfe/file-watcher/server/src/controllers/projectsController.ts +++ b/src/pfe/file-watcher/server/src/controllers/projectsController.ts @@ -146,7 +146,7 @@ export async function createProject(req: ICreateProjectParams): Promise { const projectMetadata = getProjectMetadataById(projectID); const projectInfo: ProjectInfo = await getProjectInfoFromFile(projectMetadata.infoFile); const projectLocation = projectInfo.location; - const projectName = projectLocation.split("/").pop(); + const projectName = projectUtil.getProjectNameFromPath(projectLocation); logger.logProjectTrace("Retrieved project information for project " + projectMetadata.infoFile, projectID); logger.logProjectTrace(JSON.stringify(projectInfo), projectID); @@ -1154,7 +1154,7 @@ export function saveProjectInfo(projectID: string, projectInfo: ProjectInfo, sav const projectJSON = JSON.stringify(projectInfo); const infoFile = getProjectMetadataById(projectID).infoFile; projectInfoCache[infoFile] = projectJSON; - const projectName = projectInfo.location.split("/").pop(); + const projectName = projectUtil.getProjectNameFromPath(projectInfo.location); logger.logProjectTrace(JSON.stringify(projectInfoCache), projectID); if (saveIntoJsonFile) { fs.writeFile(infoFile, projectJSON, "utf8", (err) => { diff --git a/src/pfe/file-watcher/server/src/projects/Validator.ts b/src/pfe/file-watcher/server/src/projects/Validator.ts index 7e8fe117f..70a0200b4 100644 --- a/src/pfe/file-watcher/server/src/projects/Validator.ts +++ b/src/pfe/file-watcher/server/src/projects/Validator.ts @@ -14,6 +14,7 @@ import * as io from "../utils/socket"; import * as locale from "../utils/locale"; import * as logger from "../utils/logger"; import { Operation } from "./operation"; +import { getProjectNameFromPath } from "./projectUtil"; /** * @class @@ -57,7 +58,7 @@ export class Validator { async validateRequiredFiles (requiredFiles: string[]): Promise { if (requiredFiles) { const projectID = this.projectID; - const projectName = this.location.split("/").pop(); + const projectName = getProjectNameFromPath(this.location); const OR_SPLIT = "|"; try { @@ -179,7 +180,7 @@ export class Validator { */ sendResult(): void { const projectID = this.projectID; - const projectName = this.location.split("/").pop(); + const projectName = getProjectNameFromPath(this.location); logger.logProjectInfo("Sending validation result", projectID, projectName); io.emitOnListener("projectValidated", this.result()); } diff --git a/src/pfe/file-watcher/server/src/projects/actions.ts b/src/pfe/file-watcher/server/src/projects/actions.ts index 5c132e14e..4fda7f0a6 100644 --- a/src/pfe/file-watcher/server/src/projects/actions.ts +++ b/src/pfe/file-watcher/server/src/projects/actions.ts @@ -57,7 +57,7 @@ export const validate = async function(args: IProjectActionParams): Promise<{ op "projectType": projectType, "location": location } as ProjectInfo; - const projectName = location.split("/").pop(); + const projectName = projectUtil.getProjectNameFromPath(location); if (args.extensionID) { projectInfo.extensionID = args.extensionID; } @@ -131,7 +131,7 @@ export const enableautobuild = async function (args: IProjectActionParams): Prom async function enableAndBuild(projectInfo: ProjectInfo): Promise { const projectHandler = await projectExtensions.getProjectHandler(projectInfo); const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = projectUtil.getProjectNameFromPath(projectInfo.location); if (projectHandler.hasOwnProperty("setAutoBuild")) { const operation = new Operation("enableautobuild", projectInfo); diff --git a/src/pfe/file-watcher/server/src/projects/projectUtil.ts b/src/pfe/file-watcher/server/src/projects/projectUtil.ts index 69c867df5..ef69b94c9 100644 --- a/src/pfe/file-watcher/server/src/projects/projectUtil.ts +++ b/src/pfe/file-watcher/server/src/projects/projectUtil.ts @@ -104,7 +104,7 @@ export async function containerCreate(operation: Operation, script: string, comm const event = "projectCreation"; const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); const projectType = operation.projectInfo.projectType; if (projectList.indexOf(projectID) === -1) projectList.push(projectID); @@ -173,6 +173,7 @@ export async function containerCreate(operation: Operation, script: string, comm (operation.projectInfo.forceAction) ? String(operation.projectInfo.forceAction) : "NONE", logDir, imagePushRegistry, userMavenSettings]; } else if (["odo", "odo-devfile"].includes(projectType)) { const componentName: string = await getComponentName(projectName); + const logDir: string = await logHelper.getLogDir(projectID, projectName); args = [ projectLocation, @@ -211,7 +212,7 @@ export async function containerUpdate(operation: Operation, script: string, comm const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); const projectType = operation.projectInfo.projectType; logger.logProjectInfo("Updating container for " + operation.projectInfo.projectType + " project " + projectLocation, projectID, projectName); operation.containerName = await getContainerName(operation.projectInfo); @@ -280,6 +281,7 @@ export async function containerUpdate(operation: Operation, script: string, comm (operation.projectInfo.forceAction) ? String(operation.projectInfo.forceAction) : "NONE", logDir, imagePushRegistry, userMavenSettings]; } else if (["odo", "odo-devfile"].includes(projectType)) { const componentName: string = await getComponentName(projectName); + const logDir: string = await logHelper.getLogDir(projectID, projectName); args = [ projectLocation, @@ -316,7 +318,7 @@ export async function containerUpdate(operation: Operation, script: string, comm async function executeBuildScript(operation: Operation, script: string, args: Array, event: string): Promise { const projectID = operation.projectInfo.projectID; const projectLocation = operation.projectInfo.location; - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); const projectInfo = { operationId: operation.operationId, projectID: operation.projectInfo.projectID @@ -612,7 +614,7 @@ export async function getProjectMavenSettings(projectInfo: ProjectInfo): Promise export async function getProjectLogs(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; const projectLocation = projectInfo.location; - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); const projectType = projectInfo.projectType; const projectLogDir = await logHelper.getLogDir(projectID, projectName); const logDirectory = path.join(projectConstants.projectsLogDir, projectLogDir); @@ -655,7 +657,7 @@ export async function getProjectLogs(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = getProjectNameFromPath(projectInfo.location); const containerName = await getContainerName(projectInfo); const imagePushRegistry = projectInfo.deploymentRegistry; logger.logProjectInfo("containerDelete: Kill running processes and remove container... ", projectID, projectName); @@ -725,7 +727,7 @@ export function getLogName(projectID: string, projectLocation: string): string { const hash = crypto.createHash("sha1", "utf8").update(projectLocation); let logName = projectConstants.containerPrefix + projectID + "-" + hash.digest("hex"); - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); if (process.env.IN_K8 === "true" && logName.length > 53) { logName = logName.substring(0, 53); @@ -1255,6 +1257,7 @@ export async function runScript(projectInfo: ProjectInfo, script: string, comman if (["odo", "odo-devfile"].includes(projectInfo.projectType)) { const componentName: string = await getComponentName(projectName); + const logDir: string = await logHelper.getLogDir(projectID, projectName); args = [ projectInfo.location, @@ -1290,7 +1293,7 @@ export async function buildAndRun(operation: Operation, command: string): Promis const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); if (projectList.indexOf(projectID) === -1) projectList.push(projectID); @@ -1446,7 +1449,7 @@ export async function buildAndRun(operation: Operation, command: string): Promis */ async function containerBuildAndRun(event: string, buildInfo: BuildRequest, operation: Operation): Promise { const normalizedProjectLocation = path.resolve(buildInfo.projectLocation); - const projectName = normalizedProjectLocation.split("/").reverse()[0]; + const projectName = getProjectNameFromPath(normalizedProjectLocation); const logDir = await logHelper.getLogDir(buildInfo.projectID, projectName); const dockerBuildLog = path.resolve(buildInfo.projectLocation + "/../.logs/" + logDir, logHelper.buildLogs.dockerBuild + logHelper.logExtension); if (process.env.IN_K8 === "true") { @@ -1668,7 +1671,7 @@ async function containerBuildAndRun(event: string, buildInfo: BuildRequest, oper */ async function runLocalContainer(buildInfo: BuildRequest): Promise { const normalizedProjectLocation = path.resolve(buildInfo.projectLocation); - const projectName = normalizedProjectLocation.split("/").reverse()[0]; + const projectName = getProjectNameFromPath(normalizedProjectLocation); const logDir = await logHelper.getLogDir(buildInfo.projectID, projectName); const appLog = path.resolve(buildInfo.projectLocation + "/../.logs/" + logDir, logHelper.appLogs.app + logHelper.logExtension); try { @@ -1799,7 +1802,7 @@ export async function isApplicationPodUp(buildInfo: BuildRequest, projectName: s export async function removeProject(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = getProjectNameFromPath(projectInfo.location); const containerName = await getContainerName(projectInfo); logger.logProjectInfo("removeProject: Kill running processes and remove container... ", projectID, projectName); logger.logProjectInfo("Project ID: " + projectInfo.projectID, projectID, projectName); @@ -1903,7 +1906,7 @@ async function getPODInfoAndSendToPortal(operation: Operation, event: string = " const projectInfo = operation.projectInfo; const projectLocation = projectInfo.location; const projectID = projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = getProjectNameFromPath(projectLocation); const keyValuePair: UpdateProjectInfoPair = { key: "buildRequest", value: false @@ -2203,8 +2206,26 @@ export async function updateDetailedAppStatus(projectID: string, ip: string, por export async function exposeOverIngress(projectInfo: ProjectInfo, appPort?: number): Promise { if (process.env.IN_K8) { const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = getProjectNameFromPath(projectInfo.location); projectInfo.appBaseURL = await kubeutil.exposeOverIngress(projectID, projectName, projectInfo.isHttps, appPort, projectInfo.appBaseURL); await projectsController.saveProjectInfo(projectID, projectInfo, true); } } + +/** + * Get the projectName from a path + * + * @param location The project's location + */ +export function getProjectNameFromPath(location: string): string { + const splitPaths = location.split("/"); + const cwIndex = splitPaths.indexOf("codewind-workspace"); + if (cwIndex === -1) { + logger.logError("Unable to get project name from path: codewind-workspace isn't in the path"); + // Fall back to old method if codewind-workspace isn't in the path + return splitPaths.pop(); + } + // Project name is the directory after codewind-workspace + const projectName = splitPaths[cwIndex + 1]; + return projectName; +} diff --git a/src/pfe/file-watcher/server/src/utils/logger.ts b/src/pfe/file-watcher/server/src/utils/logger.ts index 9a76bdd58..df05a4292 100644 --- a/src/pfe/file-watcher/server/src/utils/logger.ts +++ b/src/pfe/file-watcher/server/src/utils/logger.ts @@ -15,6 +15,7 @@ import * as path from "path"; import { promisify } from "util"; import * as constants from "../projects/constants"; import * as stackTrace from "stack-trace"; +import { getProjectNameFromPath } from "../projects/projectUtil"; const chalk = require("chalk"); // tslint:disable-line:no-require-imports const GENERAL_LOG_FILE_NAME = "Turbine.log"; @@ -101,7 +102,7 @@ export async function getProjectNameByProjectID(projectID: string): Promise { + const tests = [ + { + title: "should return 'projectName' when it's the directory after 'codewind-workspace'", + path: '/codewind-workspace/projectName', + want: 'projectName', + }, + { + title: "should return 'projectName' when the path is normalized", + path: path.resolve('/codewind-workspace/projectName'), + want: 'projectName', + }, + { + title: "should return 'projectName' when subdirectories are given", + path: path.resolve('/codewind-workspace/projectName/templates/default'), + want: 'projectName', + }, + { + title: "returns 'finalDir' as 'codewind-workspace' isn't in the path", + path: path.resolve('/projectName/templates/default/finalDir'), + want: 'finalDir', + }, + ]; + tests.forEach(({ title, path, want }) => { + it(`should return '${want}' when the input is '${path}'`, () => { + const got = projectUtil.getProjectNameFromPath(path); + expect(got).to.equal(want); + }); + }); + }); +} diff --git a/src/pfe/portal/modules/FileWatcher.js b/src/pfe/portal/modules/FileWatcher.js index 1390a85ce..7c59cd2ae 100644 --- a/src/pfe/portal/modules/FileWatcher.js +++ b/src/pfe/portal/modules/FileWatcher.js @@ -736,7 +736,11 @@ function createProjectActionForBuildAndRun(project, settings) { autoBuild, ports, } = project; - const location = project.projectPath(); + + let location = project.projectPath(); + if (extension && extension.projectSubDirectory) { + location = path.join(location, extension.projectSubDirectory); + } const projectAction = { projectID, diff --git a/src/pfe/portal/modules/Templates.js b/src/pfe/portal/modules/Templates.js index d1ec34804..bb3f737ed 100644 --- a/src/pfe/portal/modules/Templates.js +++ b/src/pfe/portal/modules/Templates.js @@ -326,7 +326,7 @@ async function constructRepositoryObject(url, description, name, isRepoProtected } if (gitCredentials) { if (gitCredentials.username) { - repository.authentication = { username: gitCredentials.username }; + repository.authentication = { username: gitCredentials.username }; } else if (gitCredentials.personalAccessToken) { repository.authentication = {}; } @@ -503,6 +503,9 @@ async function getTemplatesFromRepo(repository, gitCredentials) { if (summary.projectStyle) { template.projectStyle = summary.projectStyle; } + if (summary.subDirectory || summary.subDirectory === "") { + template.subDirectory = summary.subDirectory; + } if (repository.name) { template.source = repository.name; } diff --git a/src/pfe/portal/routes/projects/bind.route.js b/src/pfe/portal/routes/projects/bind.route.js index 3390d1ac6..713ba7db2 100644 --- a/src/pfe/portal/routes/projects/bind.route.js +++ b/src/pfe/portal/routes/projects/bind.route.js @@ -102,8 +102,16 @@ async function bindStart(req, res) { let extension = user.extensionList.getExtensionForProjectType(projectType); if (extension) { projectDetails.extension = extension; - if (extension.config.needsMount && !global.codewind.RUNNING_IN_K8S) + if (extension.config.needsMount && !global.codewind.RUNNING_IN_K8S) { projectDetails.workspace = global.codewind.MOUNTED_WORKSPACE; + } + + const allTemplates = user.templates.getTemplates(false); + // Check the template for this project to see if it has a subDirectory field + const subDirectory = getSubDirectoryFromTemplate(allTemplates, projectType, language); + // Add the subdirectory to the directory path so we sync the correct path to file-watcher + // For open-liberty it'll be something like /codewind-workspace/openlib/templates/default + projectDetails.extension.projectSubDirectory = subDirectory; } } @@ -125,9 +133,9 @@ async function bindStart(req, res) { try { let tempDirName = path.join(global.codewind.CODEWIND_WORKSPACE, global.codewind.CODEWIND_TEMP_WORKSPACE); let dirName = newProject.projectPath(); - await fs.mkdir(dirName); + await fs.ensureDir(dirName); let tempProjPath = path.join(tempDirName, newProject.name); - await fs.mkdir(tempProjPath); + await fs.ensureDir(tempProjPath); newProject.workspaceDir = dirName; log.debug(`Creating directory in ${dirName} and ${tempDirName}`); @@ -209,19 +217,19 @@ async function uploadEnd(req, res) { const timeStamp = req.sanitizeBody('timeStamp'); const IFileChangeEvent = []; const user = req.cw_user; - + let project; let pathToTempProj; let directoriesToDelete; let filesToDelete; - + try { project = user.projectList.retrieveProject(projectID); if (!project) { res.sendStatus(404); return; } - + pathToTempProj = path.join(global.codewind.CODEWIND_WORKSPACE, global.codewind.CODEWIND_TEMP_WORKSPACE, project.name); const tempProjectExists = await fs.pathExists(pathToTempProj); if (modifiedList.length === 0 && !tempProjectExists) { @@ -255,13 +263,13 @@ async function uploadEnd(req, res) { } res.sendStatus(200); - + } catch (err) { log.error(err); res.status(500).send(err); return; } - + try { const wasProjectChanged = directoriesToDelete.length > 0 || filesToDelete.length > 0 @@ -529,7 +537,7 @@ router.get('/api/v1/projects/:id/fileList', validateReq, async (req, res) => { return; } const pathToTempProj = path.join(global.codewind.CODEWIND_WORKSPACE, global.codewind.CODEWIND_TEMP_WORKSPACE, project.name); - + const files = await recursivelyListFilesOrDirectories(false, pathToTempProj); res.status(200).send(files); } catch (err) { @@ -539,4 +547,14 @@ router.get('/api/v1/projects/:id/fileList', validateReq, async (req, res) => { }); +function getSubDirectoryFromTemplate(templates, projectType, language) { + // Use the first template that matches the filter + const [{ subDirectory }] = templates.filter(template => ( + template.projectType === projectType && + template.language === language + )); + + return subDirectory; +} + module.exports = router; diff --git a/test/src/unit/routes/projects/bind.route.test.js b/test/src/unit/routes/projects/bind.route.test.js index 266520637..9242ce4ba 100644 --- a/test/src/unit/routes/projects/bind.route.test.js +++ b/test/src/unit/routes/projects/bind.route.test.js @@ -252,6 +252,42 @@ describe('bind.route.js', () => { }); }); }); + describe('getSubDirectoryFromTemplate(templates, projectType, language)', () => { + const getSubDirectoryFromTemplate = bind.__get__('getSubDirectoryFromTemplate'); + const templates = [ + { + label: 'OpenShift Devfiles NodeJS Runtime', + description: 'Stack with NodeJS 12', + language: 'nodejs', + url: 'https://github.com/odo-devfiles/nodejs-ex', + projectType: 'odo-devfile', + subDirectory: '', + projectStyle: 'OpenShift Devfiles', + source: 'OpenShift Devfile templates', + sourceURL: 'file:///codewind-workspace/.extensions/codewind-odo-extension-devfile/templates/index.json', + }, + { + label: 'OpenShift Devfiles Open Liberty', + description: 'Open Liberty microservice in Java', + language: 'java-openliberty', + url: 'https://github.com/OpenLiberty/application-stack', + projectType: 'odo-devfile', + subDirectory: '/templates/default', + projectStyle: 'OpenShift Devfiles', + source: 'OpenShift Devfile templates', + sourceURL: 'file:///codewind-workspace/.extensions/codewind-odo-extension-devfile/templates/index.json', + }, + ]; + + it('returns the subDirectory when one exists', () => { + const subDirectory = getSubDirectoryFromTemplate(templates, 'odo-devfile', 'java-openliberty'); + subDirectory.should.equal('/templates/default'); + }); + it('returns an empty string when the subDirectory is empty', () => { + const subDirectory = getSubDirectoryFromTemplate(templates, 'odo-devfile', 'nodejs'); + subDirectory.should.equal(''); + }); + }); }); function createFilesFromArray(directory, fileArray) { From 3bb507e909593ed66d270df6ff424a8f09ee7503 Mon Sep 17 00:00:00 2001 From: James Wallis Date: Wed, 12 Aug 2020 13:58:12 +0100 Subject: [PATCH 2/4] remove more bad projectName getters Signed-off-by: James Wallis --- .../server/src/extensions/projectExtensions.ts | 3 ++- .../server/src/projects/OdoExtensionProject.ts | 8 ++++---- .../server/src/projects/ShellExtensionProject.ts | 2 +- .../file-watcher/server/src/projects/projectUtil.ts | 6 +++--- src/pfe/file-watcher/server/src/utils/kubeutil.ts | 11 ++++++----- .../test/unit-test/tests/projectUtil.module.test.ts | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts b/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts index 1f8dc1c99..f113b2772 100644 --- a/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts +++ b/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts @@ -24,6 +24,7 @@ import { DockerProject } from "../projects/DockerProject"; import { ShellExtensionProject } from "../projects/ShellExtensionProject"; import { OdoExtensionProject } from "../projects/OdoExtensionProject"; import { ProjectInfo, ProjectCapabilities, defaultProjectCapabilities } from "../projects/Project"; +import { getProjectNameFromPath } from "../projects/projectUtil"; import { workspaceConstants } from "../projects/constants"; export const DOCKER_TYPE = "docker"; @@ -164,7 +165,7 @@ export function getAllProjectTypes(): Array { async function getExtensionProjectHandler(projectInfo: ProjectInfo): Promise { const key = projectInfo.projectID; - const projectName = path.basename(projectInfo.location); + const projectName = getProjectNameFromPath(projectInfo.location); let handler = extensionProjectHandlers[key]; // is there an extension handler for the project? diff --git a/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts b/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts index c7d239e78..bbdf7ce8e 100644 --- a/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts +++ b/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts @@ -207,7 +207,7 @@ export class OdoExtensionProject implements IExtensionProject { */ getContainerName = async (projectID: string, projectLocation: string): Promise => { let podName: string = undefined; - const projectName: string = path.basename(projectLocation); + const projectName: string = projectUtil.getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, @@ -246,7 +246,7 @@ export class OdoExtensionProject implements IExtensionProject { let appName: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = path.basename(projectLocation); + const projectName = projectUtil.getProjectNameFromPath(projectLocation); const args: string[] = [ projectLocation, "", @@ -284,7 +284,7 @@ export class OdoExtensionProject implements IExtensionProject { let appPort: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = path.basename(projectLocation); + const projectName = projectUtil.getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, @@ -323,7 +323,7 @@ export class OdoExtensionProject implements IExtensionProject { let appBaseURL: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = path.basename(projectLocation); + const projectName = projectUtil.getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, diff --git a/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts b/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts index 4ceeead40..1c1fab639 100644 --- a/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts +++ b/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts @@ -112,7 +112,7 @@ export class ShellExtensionProject implements IExtensionProject { private setLanguage = async (projectInfo: ProjectInfo): Promise => { const logDir = await logHelper.getLogDir( - projectInfo.projectID, path.basename(projectInfo.location)); + projectInfo.projectID, projectUtil.getProjectNameFromPath(projectInfo.location)); const args = [ projectInfo.location, diff --git a/src/pfe/file-watcher/server/src/projects/projectUtil.ts b/src/pfe/file-watcher/server/src/projects/projectUtil.ts index ef69b94c9..689173a80 100644 --- a/src/pfe/file-watcher/server/src/projects/projectUtil.ts +++ b/src/pfe/file-watcher/server/src/projects/projectUtil.ts @@ -753,7 +753,7 @@ export function getDefaultContainerName(projectID: string, projectLocation: stri } // Sanitize project name to ensure project name only supports lower case letter and number - const projectNameOrigin: string = path.basename(projectLocation); + const projectNameOrigin: string = getProjectNameFromPath(projectLocation); const letterNumber: RegExp = /[A-Za-z0-9]/; const upperCaseLetter: RegExp = /[A-Z]/; const defaultProjectName: string = "cw"; @@ -1251,7 +1251,7 @@ export async function runScript(projectInfo: ProjectInfo, script: string, comman const containerName = await getContainerName(projectInfo); const logName = getLogName(projectInfo.projectID, projectInfo.location); const logDir = await logHelper.getLogDir(projectInfo.projectID, projectInfo.projectName); - const projectName = path.basename(projectInfo.location); + const projectName = getProjectNameFromPath(projectInfo.location); let args = [projectInfo.location, LOCAL_WORKSPACE, projectID, command, containerName, String(projectInfo.autoBuildEnabled), logName, projectInfo.startMode, projectInfo.debugPort, "NONE", logDir]; @@ -2223,7 +2223,7 @@ export function getProjectNameFromPath(location: string): string { if (cwIndex === -1) { logger.logError("Unable to get project name from path: codewind-workspace isn't in the path"); // Fall back to old method if codewind-workspace isn't in the path - return splitPaths.pop(); + return path.basename(location); } // Project name is the directory after codewind-workspace const projectName = splitPaths[cwIndex + 1]; diff --git a/src/pfe/file-watcher/server/src/utils/kubeutil.ts b/src/pfe/file-watcher/server/src/utils/kubeutil.ts index 71b6290cf..0c9385586 100644 --- a/src/pfe/file-watcher/server/src/utils/kubeutil.ts +++ b/src/pfe/file-watcher/server/src/utils/kubeutil.ts @@ -21,6 +21,7 @@ import * as processManager from "./processManager"; import { ProcessResult } from "./processManager"; import { ProjectInfo } from "../projects/Project"; import * as logHelper from "../projects/logHelper"; +import { getProjectNameFromPath } from "../projects/projectUtil"; const k8s = require("@kubernetes/client-node"); // tslint:disable-line:no-require-imports @@ -90,13 +91,13 @@ export async function getApplicationContainerInfo(projectInfo: ProjectInfo, oper if (!projectInfo.compositeAppName) { return undefined; } - const componentName = path.basename(projectInfo.location); + const componentName = getProjectNameFromPath(projectInfo.location); releaseLabel = "deploymentconfig=" + "cw-" + componentName + "-" + projectInfo.compositeAppName; } else if (projectInfo.projectType == "odo-devfile") { - const componentName = path.basename(projectInfo.location); + const componentName = getProjectNameFromPath(projectInfo.location); releaseLabel = "component=" + "cw-" + componentName; } - const projectName = path.basename(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); // Before deploying the application, we added a release label to the deployment, pod, and service, // Use that to get the application's pod and service names. @@ -127,7 +128,7 @@ export async function getApplicationContainerInfo(projectInfo: ProjectInfo, oper logger.logProjectInfo("Pod name was not found while looking up service information for project.", projectID, projectName); } } catch (err) { - logger.logProjectError("Failed to get the pod name for: " + path.basename(projectLocation), projectID, projectName); + logger.logProjectError("Failed to get the pod name for: " + getProjectNameFromPath(projectLocation), projectID, projectName); logger.logProjectError(err, projectID, projectName); } @@ -292,7 +293,7 @@ export async function isContainerActive(containerName: string, projectInfo?: Pro try { let releaseLabel = "release=" + containerName; if (projectInfo && ["odo", "odo-devfile"].includes(projectInfo.projectType)) { - const componentName = path.basename(projectInfo.location); + const componentName = getProjectNameFromPath(projectInfo.location); releaseLabel = projectInfo.projectType === "odo" ? "deploymentconfig=" + "cw-" + componentName + "-" + projectInfo.compositeAppName : "component=" + "cw-" + componentName; diff --git a/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts b/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts index cf965616e..8605be19e 100644 --- a/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts +++ b/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts @@ -450,7 +450,7 @@ export function projectUtilTestModule(): void { } }); - describe.only("getProjectNameFromPath", () => { + describe("getProjectNameFromPath", () => { const tests = [ { title: "should return 'projectName' when it's the directory after 'codewind-workspace'", From b468348dd4674f4c2f3852990583014af883e4c1 Mon Sep 17 00:00:00 2001 From: James Wallis Date: Wed, 12 Aug 2020 14:19:28 +0100 Subject: [PATCH 3/4] Remove unneeded function call Signed-off-by: James Wallis --- src/pfe/file-watcher/server/src/projects/projectUtil.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pfe/file-watcher/server/src/projects/projectUtil.ts b/src/pfe/file-watcher/server/src/projects/projectUtil.ts index 689173a80..762b782f3 100644 --- a/src/pfe/file-watcher/server/src/projects/projectUtil.ts +++ b/src/pfe/file-watcher/server/src/projects/projectUtil.ts @@ -173,7 +173,6 @@ export async function containerCreate(operation: Operation, script: string, comm (operation.projectInfo.forceAction) ? String(operation.projectInfo.forceAction) : "NONE", logDir, imagePushRegistry, userMavenSettings]; } else if (["odo", "odo-devfile"].includes(projectType)) { const componentName: string = await getComponentName(projectName); - const logDir: string = await logHelper.getLogDir(projectID, projectName); args = [ projectLocation, @@ -281,7 +280,6 @@ export async function containerUpdate(operation: Operation, script: string, comm (operation.projectInfo.forceAction) ? String(operation.projectInfo.forceAction) : "NONE", logDir, imagePushRegistry, userMavenSettings]; } else if (["odo", "odo-devfile"].includes(projectType)) { const componentName: string = await getComponentName(projectName); - const logDir: string = await logHelper.getLogDir(projectID, projectName); args = [ projectLocation, @@ -1257,7 +1255,6 @@ export async function runScript(projectInfo: ProjectInfo, script: string, comman if (["odo", "odo-devfile"].includes(projectInfo.projectType)) { const componentName: string = await getComponentName(projectName); - const logDir: string = await logHelper.getLogDir(projectID, projectName); args = [ projectInfo.location, From 797de340e9d6cdb9b8e4bf96553ef2af8d0e0bbb Mon Sep 17 00:00:00 2001 From: James Wallis Date: Wed, 12 Aug 2020 15:42:24 +0100 Subject: [PATCH 4/4] Move getProjectNameFromPath function to remove circular dependency Signed-off-by: James Wallis --- .../src/controllers/projectsController.ts | 8 ++-- .../src/extensions/projectExtensions.ts | 3 +- .../src/projects/OdoExtensionProject.ts | 9 ++-- .../src/projects/ShellExtensionProject.ts | 3 +- .../server/src/projects/Validator.ts | 5 +- .../server/src/projects/actions.ts | 4 +- .../server/src/projects/projectUtil.ts | 46 ++++++------------- .../file-watcher/server/src/utils/kubeutil.ts | 2 +- .../file-watcher/server/src/utils/logger.ts | 2 +- .../file-watcher/server/src/utils/utils.ts | 19 ++++++++ .../tests/projectUtil.module.test.ts | 31 ------------- .../test/unit-test/tests/utils.module.test.ts | 31 +++++++++++++ 12 files changed, 82 insertions(+), 81 deletions(-) diff --git a/src/pfe/file-watcher/server/src/controllers/projectsController.ts b/src/pfe/file-watcher/server/src/controllers/projectsController.ts index 2f5434750..ef7971060 100644 --- a/src/pfe/file-watcher/server/src/controllers/projectsController.ts +++ b/src/pfe/file-watcher/server/src/controllers/projectsController.ts @@ -146,7 +146,7 @@ export async function createProject(req: ICreateProjectParams): Promise { const projectMetadata = getProjectMetadataById(projectID); const projectInfo: ProjectInfo = await getProjectInfoFromFile(projectMetadata.infoFile); const projectLocation = projectInfo.location; - const projectName = projectUtil.getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); logger.logProjectTrace("Retrieved project information for project " + projectMetadata.infoFile, projectID); logger.logProjectTrace(JSON.stringify(projectInfo), projectID); @@ -1154,7 +1154,7 @@ export function saveProjectInfo(projectID: string, projectInfo: ProjectInfo, sav const projectJSON = JSON.stringify(projectInfo); const infoFile = getProjectMetadataById(projectID).infoFile; projectInfoCache[infoFile] = projectJSON; - const projectName = projectUtil.getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); logger.logProjectTrace(JSON.stringify(projectInfoCache), projectID); if (saveIntoJsonFile) { fs.writeFile(infoFile, projectJSON, "utf8", (err) => { diff --git a/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts b/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts index f113b2772..6ce80fdb2 100644 --- a/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts +++ b/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts @@ -24,7 +24,6 @@ import { DockerProject } from "../projects/DockerProject"; import { ShellExtensionProject } from "../projects/ShellExtensionProject"; import { OdoExtensionProject } from "../projects/OdoExtensionProject"; import { ProjectInfo, ProjectCapabilities, defaultProjectCapabilities } from "../projects/Project"; -import { getProjectNameFromPath } from "../projects/projectUtil"; import { workspaceConstants } from "../projects/constants"; export const DOCKER_TYPE = "docker"; @@ -165,7 +164,7 @@ export function getAllProjectTypes(): Array { async function getExtensionProjectHandler(projectInfo: ProjectInfo): Promise { const key = projectInfo.projectID; - const projectName = getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); let handler = extensionProjectHandlers[key]; // is there an extension handler for the project? diff --git a/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts b/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts index bbdf7ce8e..65e7a38fa 100644 --- a/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts +++ b/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts @@ -22,6 +22,7 @@ import { ProjectInfo, BuildLog, AppLog, ProjectCapabilities, defaultProjectCapab import { Validator } from "./Validator"; import { IExtensionProject } from "../extensions/IExtensionProject"; import { IFileChangeEvent } from "../utils/fileChanges"; +import { getProjectNameFromPath } from "../utils/utils"; // skeleton for the logs originated from the extension json const logsOrigin: logHelper.ILogTypes = { @@ -207,7 +208,7 @@ export class OdoExtensionProject implements IExtensionProject { */ getContainerName = async (projectID: string, projectLocation: string): Promise => { let podName: string = undefined; - const projectName: string = projectUtil.getProjectNameFromPath(projectLocation); + const projectName: string = getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, @@ -246,7 +247,7 @@ export class OdoExtensionProject implements IExtensionProject { let appName: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = projectUtil.getProjectNameFromPath(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); const args: string[] = [ projectLocation, "", @@ -284,7 +285,7 @@ export class OdoExtensionProject implements IExtensionProject { let appPort: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = projectUtil.getProjectNameFromPath(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, @@ -323,7 +324,7 @@ export class OdoExtensionProject implements IExtensionProject { let appBaseURL: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = projectUtil.getProjectNameFromPath(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, diff --git a/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts b/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts index 1c1fab639..d63b34f1b 100644 --- a/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts +++ b/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts @@ -14,6 +14,7 @@ import fs from "fs-extra"; import * as path from "path"; import * as projectUtil from "./projectUtil"; +import { getProjectNameFromPath } from "../utils/utils"; import { Operation } from "./operation"; import { ProjectInfo, BuildLog, AppLog, ProjectCapabilities, defaultProjectCapabilities } from "./Project"; import { Validator } from "./Validator"; @@ -112,7 +113,7 @@ export class ShellExtensionProject implements IExtensionProject { private setLanguage = async (projectInfo: ProjectInfo): Promise => { const logDir = await logHelper.getLogDir( - projectInfo.projectID, projectUtil.getProjectNameFromPath(projectInfo.location)); + projectInfo.projectID, getProjectNameFromPath(projectInfo.location)); const args = [ projectInfo.location, diff --git a/src/pfe/file-watcher/server/src/projects/Validator.ts b/src/pfe/file-watcher/server/src/projects/Validator.ts index 70a0200b4..90dcebf23 100644 --- a/src/pfe/file-watcher/server/src/projects/Validator.ts +++ b/src/pfe/file-watcher/server/src/projects/Validator.ts @@ -14,7 +14,6 @@ import * as io from "../utils/socket"; import * as locale from "../utils/locale"; import * as logger from "../utils/logger"; import { Operation } from "./operation"; -import { getProjectNameFromPath } from "./projectUtil"; /** * @class @@ -58,7 +57,7 @@ export class Validator { async validateRequiredFiles (requiredFiles: string[]): Promise { if (requiredFiles) { const projectID = this.projectID; - const projectName = getProjectNameFromPath(this.location); + const projectName = utils.getProjectNameFromPath(this.location); const OR_SPLIT = "|"; try { @@ -180,7 +179,7 @@ export class Validator { */ sendResult(): void { const projectID = this.projectID; - const projectName = getProjectNameFromPath(this.location); + const projectName = utils.getProjectNameFromPath(this.location); logger.logProjectInfo("Sending validation result", projectID, projectName); io.emitOnListener("projectValidated", this.result()); } diff --git a/src/pfe/file-watcher/server/src/projects/actions.ts b/src/pfe/file-watcher/server/src/projects/actions.ts index 4fda7f0a6..71897f298 100644 --- a/src/pfe/file-watcher/server/src/projects/actions.ts +++ b/src/pfe/file-watcher/server/src/projects/actions.ts @@ -57,7 +57,7 @@ export const validate = async function(args: IProjectActionParams): Promise<{ op "projectType": projectType, "location": location } as ProjectInfo; - const projectName = projectUtil.getProjectNameFromPath(location); + const projectName = utils.getProjectNameFromPath(location); if (args.extensionID) { projectInfo.extensionID = args.extensionID; } @@ -131,7 +131,7 @@ export const enableautobuild = async function (args: IProjectActionParams): Prom async function enableAndBuild(projectInfo: ProjectInfo): Promise { const projectHandler = await projectExtensions.getProjectHandler(projectInfo); const projectID = projectInfo.projectID; - const projectName = projectUtil.getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); if (projectHandler.hasOwnProperty("setAutoBuild")) { const operation = new Operation("enableautobuild", projectInfo); diff --git a/src/pfe/file-watcher/server/src/projects/projectUtil.ts b/src/pfe/file-watcher/server/src/projects/projectUtil.ts index 762b782f3..e4d0913c3 100644 --- a/src/pfe/file-watcher/server/src/projects/projectUtil.ts +++ b/src/pfe/file-watcher/server/src/projects/projectUtil.ts @@ -104,7 +104,7 @@ export async function containerCreate(operation: Operation, script: string, comm const event = "projectCreation"; const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectType = operation.projectInfo.projectType; if (projectList.indexOf(projectID) === -1) projectList.push(projectID); @@ -211,7 +211,7 @@ export async function containerUpdate(operation: Operation, script: string, comm const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectType = operation.projectInfo.projectType; logger.logProjectInfo("Updating container for " + operation.projectInfo.projectType + " project " + projectLocation, projectID, projectName); operation.containerName = await getContainerName(operation.projectInfo); @@ -316,7 +316,7 @@ export async function containerUpdate(operation: Operation, script: string, comm async function executeBuildScript(operation: Operation, script: string, args: Array, event: string): Promise { const projectID = operation.projectInfo.projectID; const projectLocation = operation.projectInfo.location; - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectInfo = { operationId: operation.operationId, projectID: operation.projectInfo.projectID @@ -612,7 +612,7 @@ export async function getProjectMavenSettings(projectInfo: ProjectInfo): Promise export async function getProjectLogs(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; const projectLocation = projectInfo.location; - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectType = projectInfo.projectType; const projectLogDir = await logHelper.getLogDir(projectID, projectName); const logDirectory = path.join(projectConstants.projectsLogDir, projectLogDir); @@ -655,7 +655,7 @@ export async function getProjectLogs(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; - const projectName = getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); const containerName = await getContainerName(projectInfo); const imagePushRegistry = projectInfo.deploymentRegistry; logger.logProjectInfo("containerDelete: Kill running processes and remove container... ", projectID, projectName); @@ -725,7 +725,7 @@ export function getLogName(projectID: string, projectLocation: string): string { const hash = crypto.createHash("sha1", "utf8").update(projectLocation); let logName = projectConstants.containerPrefix + projectID + "-" + hash.digest("hex"); - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); if (process.env.IN_K8 === "true" && logName.length > 53) { logName = logName.substring(0, 53); @@ -751,7 +751,7 @@ export function getDefaultContainerName(projectID: string, projectLocation: stri } // Sanitize project name to ensure project name only supports lower case letter and number - const projectNameOrigin: string = getProjectNameFromPath(projectLocation); + const projectNameOrigin: string = utils.getProjectNameFromPath(projectLocation); const letterNumber: RegExp = /[A-Za-z0-9]/; const upperCaseLetter: RegExp = /[A-Z]/; const defaultProjectName: string = "cw"; @@ -1249,7 +1249,7 @@ export async function runScript(projectInfo: ProjectInfo, script: string, comman const containerName = await getContainerName(projectInfo); const logName = getLogName(projectInfo.projectID, projectInfo.location); const logDir = await logHelper.getLogDir(projectInfo.projectID, projectInfo.projectName); - const projectName = getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); let args = [projectInfo.location, LOCAL_WORKSPACE, projectID, command, containerName, String(projectInfo.autoBuildEnabled), logName, projectInfo.startMode, projectInfo.debugPort, "NONE", logDir]; @@ -1290,7 +1290,7 @@ export async function buildAndRun(operation: Operation, command: string): Promis const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); if (projectList.indexOf(projectID) === -1) projectList.push(projectID); @@ -1446,7 +1446,7 @@ export async function buildAndRun(operation: Operation, command: string): Promis */ async function containerBuildAndRun(event: string, buildInfo: BuildRequest, operation: Operation): Promise { const normalizedProjectLocation = path.resolve(buildInfo.projectLocation); - const projectName = getProjectNameFromPath(normalizedProjectLocation); + const projectName = utils.getProjectNameFromPath(normalizedProjectLocation); const logDir = await logHelper.getLogDir(buildInfo.projectID, projectName); const dockerBuildLog = path.resolve(buildInfo.projectLocation + "/../.logs/" + logDir, logHelper.buildLogs.dockerBuild + logHelper.logExtension); if (process.env.IN_K8 === "true") { @@ -1668,7 +1668,7 @@ async function containerBuildAndRun(event: string, buildInfo: BuildRequest, oper */ async function runLocalContainer(buildInfo: BuildRequest): Promise { const normalizedProjectLocation = path.resolve(buildInfo.projectLocation); - const projectName = getProjectNameFromPath(normalizedProjectLocation); + const projectName = utils.getProjectNameFromPath(normalizedProjectLocation); const logDir = await logHelper.getLogDir(buildInfo.projectID, projectName); const appLog = path.resolve(buildInfo.projectLocation + "/../.logs/" + logDir, logHelper.appLogs.app + logHelper.logExtension); try { @@ -1799,7 +1799,7 @@ export async function isApplicationPodUp(buildInfo: BuildRequest, projectName: s export async function removeProject(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; - const projectName = getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); const containerName = await getContainerName(projectInfo); logger.logProjectInfo("removeProject: Kill running processes and remove container... ", projectID, projectName); logger.logProjectInfo("Project ID: " + projectInfo.projectID, projectID, projectName); @@ -1903,7 +1903,7 @@ async function getPODInfoAndSendToPortal(operation: Operation, event: string = " const projectInfo = operation.projectInfo; const projectLocation = projectInfo.location; const projectID = projectInfo.projectID; - const projectName = getProjectNameFromPath(projectLocation); + const projectName = utils.getProjectNameFromPath(projectLocation); const keyValuePair: UpdateProjectInfoPair = { key: "buildRequest", value: false @@ -2203,26 +2203,8 @@ export async function updateDetailedAppStatus(projectID: string, ip: string, por export async function exposeOverIngress(projectInfo: ProjectInfo, appPort?: number): Promise { if (process.env.IN_K8) { const projectID = projectInfo.projectID; - const projectName = getProjectNameFromPath(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); projectInfo.appBaseURL = await kubeutil.exposeOverIngress(projectID, projectName, projectInfo.isHttps, appPort, projectInfo.appBaseURL); await projectsController.saveProjectInfo(projectID, projectInfo, true); } } - -/** - * Get the projectName from a path - * - * @param location The project's location - */ -export function getProjectNameFromPath(location: string): string { - const splitPaths = location.split("/"); - const cwIndex = splitPaths.indexOf("codewind-workspace"); - if (cwIndex === -1) { - logger.logError("Unable to get project name from path: codewind-workspace isn't in the path"); - // Fall back to old method if codewind-workspace isn't in the path - return path.basename(location); - } - // Project name is the directory after codewind-workspace - const projectName = splitPaths[cwIndex + 1]; - return projectName; -} diff --git a/src/pfe/file-watcher/server/src/utils/kubeutil.ts b/src/pfe/file-watcher/server/src/utils/kubeutil.ts index 0c9385586..2676543f3 100644 --- a/src/pfe/file-watcher/server/src/utils/kubeutil.ts +++ b/src/pfe/file-watcher/server/src/utils/kubeutil.ts @@ -21,7 +21,7 @@ import * as processManager from "./processManager"; import { ProcessResult } from "./processManager"; import { ProjectInfo } from "../projects/Project"; import * as logHelper from "../projects/logHelper"; -import { getProjectNameFromPath } from "../projects/projectUtil"; +import { getProjectNameFromPath } from "./utils"; const k8s = require("@kubernetes/client-node"); // tslint:disable-line:no-require-imports diff --git a/src/pfe/file-watcher/server/src/utils/logger.ts b/src/pfe/file-watcher/server/src/utils/logger.ts index df05a4292..53c6b3dee 100644 --- a/src/pfe/file-watcher/server/src/utils/logger.ts +++ b/src/pfe/file-watcher/server/src/utils/logger.ts @@ -15,7 +15,7 @@ import * as path from "path"; import { promisify } from "util"; import * as constants from "../projects/constants"; import * as stackTrace from "stack-trace"; -import { getProjectNameFromPath } from "../projects/projectUtil"; +import { getProjectNameFromPath } from "./utils"; const chalk = require("chalk"); // tslint:disable-line:no-require-imports const GENERAL_LOG_FILE_NAME = "Turbine.log"; diff --git a/src/pfe/file-watcher/server/src/utils/utils.ts b/src/pfe/file-watcher/server/src/utils/utils.ts index b448228da..1046bfecb 100644 --- a/src/pfe/file-watcher/server/src/utils/utils.ts +++ b/src/pfe/file-watcher/server/src/utils/utils.ts @@ -13,6 +13,7 @@ import * as fs from "fs"; import * as util from "util"; import * as logger from "./logger"; import * as fse from "fs-extra"; +import * as path from "path"; const promisify = util.promisify; const accessAsync = promisify(fs.access); @@ -156,3 +157,21 @@ export async function asyncReadDir(dir: string): Promise> { return undefined; } } + +/** + * Get the projectName from a path + * + * @param location The project's location + */ +export function getProjectNameFromPath(location: string): string { + const splitPaths = location.split("/"); + const cwIndex = splitPaths.indexOf("codewind-workspace"); + if (cwIndex === -1) { + logger.logError("Unable to get project name from path: codewind-workspace isn't in the path"); + // Fall back to old method if codewind-workspace isn't in the path + return path.basename(location); + } + // Project name is the directory after codewind-workspace + const projectName = splitPaths[cwIndex + 1]; + return projectName; +} diff --git a/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts b/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts index 8605be19e..0258eeb7a 100644 --- a/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts +++ b/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts @@ -449,35 +449,4 @@ export function projectUtilTestModule(): void { }); } }); - - describe("getProjectNameFromPath", () => { - const tests = [ - { - title: "should return 'projectName' when it's the directory after 'codewind-workspace'", - path: '/codewind-workspace/projectName', - want: 'projectName', - }, - { - title: "should return 'projectName' when the path is normalized", - path: path.resolve('/codewind-workspace/projectName'), - want: 'projectName', - }, - { - title: "should return 'projectName' when subdirectories are given", - path: path.resolve('/codewind-workspace/projectName/templates/default'), - want: 'projectName', - }, - { - title: "returns 'finalDir' as 'codewind-workspace' isn't in the path", - path: path.resolve('/projectName/templates/default/finalDir'), - want: 'finalDir', - }, - ]; - tests.forEach(({ title, path, want }) => { - it(`should return '${want}' when the input is '${path}'`, () => { - const got = projectUtil.getProjectNameFromPath(path); - expect(got).to.equal(want); - }); - }); - }); } diff --git a/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts b/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts index 68b664855..8a34ce18e 100644 --- a/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts +++ b/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts @@ -362,4 +362,35 @@ export function utilsTestModule(): void { } }); + describe("getProjectNameFromPath", () => { + const tests = [ + { + title: "should return 'projectName' when it's the directory after 'codewind-workspace'", + path: '/codewind-workspace/projectName', + want: 'projectName', + }, + { + title: "should return 'projectName' when the path is normalized", + path: path.resolve('/codewind-workspace/projectName'), + want: 'projectName', + }, + { + title: "should return 'projectName' when subdirectories are given", + path: path.resolve('/codewind-workspace/projectName/templates/default'), + want: 'projectName', + }, + { + title: "returns 'finalDir' as 'codewind-workspace' isn't in the path", + path: path.resolve('/projectName/templates/default/finalDir'), + want: 'finalDir', + }, + ]; + tests.forEach(({ title, path, want }) => { + it(`should return '${want}' when the input is '${path}'`, () => { + const got = utils.getProjectNameFromPath(path); + expect(got).to.equal(want); + }); + }); + }); + }