From dcbd5e6ff1f8bdabf6bcd54ce0c83be6f35d9b7b Mon Sep 17 00:00:00 2001 From: Piotr Grzesik Date: Fri, 26 Nov 2021 12:16:27 +0100 Subject: [PATCH 1/4] refactor: Use `ServerlessError` in `docker` --- lib/docker.js | 36 ++++++++++++++++++++++-------------- lib/pip.js | 5 +++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/docker.js b/lib/docker.js index 9da6da6a..5157803f 100644 --- a/lib/docker.js +++ b/lib/docker.js @@ -8,7 +8,7 @@ const path = require('path'); * @param {string[]} options * @return {Object} */ -async function dockerCommand(options) { +async function dockerCommand(options, pluginInstance) { const cmd = 'docker'; try { return await spawn(cmd, options, { encoding: 'utf-8' }); @@ -17,7 +17,10 @@ async function dockerCommand(options) { e.stderrBuffer && e.stderrBuffer.toString().includes('command not found') ) { - throw new Error('docker not found! Please install it.'); + throw new pluginInstance.serverless.classes.Error( + 'docker not found! Please install it.', + 'PYTHON_REQUIREMENTS_DOCKER_NOT_FOUND' + ); } throw e; } @@ -29,19 +32,22 @@ async function dockerCommand(options) { * @param {string[]} extraArgs * @return {string} The name of the built docker image. */ -async function buildImage(dockerFile, extraArgs) { +async function buildImage(dockerFile, extraArgs, pluginInstance) { const imageName = 'sls-py-reqs-custom'; const options = ['build', '-f', dockerFile, '-t', imageName]; if (Array.isArray(extraArgs)) { options.push(...extraArgs); } else { - throw new Error('dockerRunCmdExtraArgs option must be an array'); + throw new pluginInstance.serverless.classes.Error( + 'dockerRunCmdExtraArgs option must be an array', + 'PYTHON_REQUIREMENTS_INVALID_DOCKER_EXTRA_ARGS' + ); } options.push('.'); - await dockerCommand(options); + await dockerCommand(options, pluginInstance); return imageName; } @@ -50,7 +56,7 @@ async function buildImage(dockerFile, extraArgs) { * @param {string} servicePath * @return {string} file name */ -function findTestFile(servicePath) { +function findTestFile(servicePath, pluginInstance) { if (fse.pathExistsSync(path.join(servicePath, 'serverless.yml'))) { return 'serverless.yml'; } @@ -63,8 +69,9 @@ function findTestFile(servicePath) { if (fse.pathExistsSync(path.join(servicePath, 'requirements.txt'))) { return 'requirements.txt'; } - throw new Error( - 'Unable to find serverless.{yml|yaml|json} or requirements.txt for getBindPath()' + throw new pluginInstance.serverless.classes.Error( + 'Unable to find serverless.{yml|yaml|json} or requirements.txt for getBindPath()', + 'PYTHON_REQUIREMENTS_MISSING_GET_BIND_PATH_FILE' ); } @@ -73,7 +80,8 @@ function findTestFile(servicePath) { * @param {string} bindPath * @return {boolean} */ -async function tryBindPath(bindPath, testFile, { serverless, log }) { +async function tryBindPath(bindPath, testFile, pluginInstance) { + const { serverless, log } = pluginInstance; const debug = process.env.SLS_DEBUG; const options = [ 'run', @@ -92,7 +100,7 @@ async function tryBindPath(bindPath, testFile, { serverless, log }) { serverless.cli.log(`Trying bindPath ${bindPath} (${options})`); } } - const ps = await dockerCommand(options); + const ps = await dockerCommand(options, pluginInstance); if (debug) { if (log) { log.debug(ps.stdoutBuffer.trim()); @@ -126,7 +134,7 @@ async function getBindPath(servicePath, pluginInstance) { } // test docker is available - await dockerCommand(['version']); + await dockerCommand(['version'], pluginInstance); // find good bind path for Windows let bindPaths = []; @@ -159,7 +167,7 @@ async function getBindPath(servicePath, pluginInstance) { bindPaths.push(`/mnt/${drive.toUpperCase()}/${path}`); bindPaths.push(`${drive.toUpperCase()}:/${path}`); - const testFile = findTestFile(servicePath); + const testFile = findTestFile(servicePath, pluginInstance); for (let i = 0; i < bindPaths.length; i++) { const bindPath = bindPaths[i]; @@ -176,7 +184,7 @@ async function getBindPath(servicePath, pluginInstance) { * @param {string} bindPath * @return {boolean} */ -async function getDockerUid(bindPath) { +async function getDockerUid(bindPath, pluginInstance) { const options = [ 'run', '--rm', @@ -188,7 +196,7 @@ async function getDockerUid(bindPath) { '%u', '/bin/sh', ]; - const ps = await dockerCommand(options); + const ps = await dockerCommand(options, pluginInstance); return ps.stdoutBuffer.trim(); } diff --git a/lib/pip.js b/lib/pip.js index 2f6d4571..24d4c55f 100644 --- a/lib/pip.js +++ b/lib/pip.js @@ -251,7 +251,8 @@ async function installRequirements(targetFolder, pluginInstance) { try { dockerImage = await buildImage( options.dockerFile, - options.dockerBuildCmdExtraArgs + options.dockerBuildCmdExtraArgs, + pluginInstance ); } finally { buildDockerImageProgress && buildDockerImageProgress.remove(); @@ -335,7 +336,7 @@ async function installRequirements(targetFolder, pluginInstance) { ]); } else { // Use same user so --cache-dir works - dockerCmd.push('-u', await getDockerUid(bindPath)); + dockerCmd.push('-u', await getDockerUid(bindPath, pluginInstance)); } for (let path of options.dockerExtraFiles) { From 4a897c8e0b8236f37670db17a7c1ef88ebd9c58d Mon Sep 17 00:00:00 2001 From: Piotr Grzesik Date: Fri, 26 Nov 2021 12:22:22 +0100 Subject: [PATCH 2/4] refactor: Use `ServerlessError` in `poetry` --- lib/poetry.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/poetry.js b/lib/poetry.js index 12904fd9..23f43dc0 100644 --- a/lib/poetry.js +++ b/lib/poetry.js @@ -50,8 +50,9 @@ async function pyprojectTomlToRequirements() { e.stderrBuffer && e.stderrBuffer.toString().includes('command not found') ) { - throw new Error( - `poetry not found! Install it according to the poetry docs.` + throw new this.serverless.classes.Error( + `poetry not found! Install it according to the poetry docs.`, + 'PYTHON_REQUIREMENTS_POETRY_NOT_FOUND' ); } throw e; From 0792c4897abd04af7fb08c5085bdb5e7aaa24c52 Mon Sep 17 00:00:00 2001 From: Piotr Grzesik Date: Fri, 26 Nov 2021 12:23:04 +0100 Subject: [PATCH 3/4] refactor: Use `ServerlessError` in `pipenv` --- lib/pipenv.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pipenv.js b/lib/pipenv.js index 4949e924..5856d47b 100644 --- a/lib/pipenv.js +++ b/lib/pipenv.js @@ -42,8 +42,9 @@ async function pipfileToRequirements() { e.stderrBuffer && e.stderrBuffer.toString().includes('command not found') ) { - throw new Error( - `pipenv not found! Install it with 'pip install pipenv'.` + throw new this.serverless.classes.Error( + `pipenv not found! Install it according to the poetry docs.`, + 'PYTHON_REQUIREMENTS_PIPENV_NOT_FOUND' ); } throw e; From 4044581d55e6ff88cb0275efb9846723262eee36 Mon Sep 17 00:00:00 2001 From: Piotr Grzesik Date: Fri, 26 Nov 2021 12:28:02 +0100 Subject: [PATCH 4/4] refactor: Use `ServerlessError` in `pip` --- lib/pip.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/pip.js b/lib/pip.js index 24d4c55f..ce348532 100644 --- a/lib/pip.js +++ b/lib/pip.js @@ -107,7 +107,7 @@ function generateRequirementsFile( } } -async function pipAcceptsSystem(pythonBin) { +async function pipAcceptsSystem(pythonBin, pluginInstance) { // Check if pip has Debian's --system option and set it if so try { const pipTestRes = await spawn(pythonBin, ['-m', 'pip', 'help', 'install']); @@ -120,7 +120,10 @@ async function pipAcceptsSystem(pythonBin) { e.stderrBuffer && e.stderrBuffer.toString().includes('command not found') ) { - throw new Error(`${pythonBin} not found! Try the pythonBin option.`); + throw new pluginInstance.serverless.classes.Error( + `${pythonBin} not found! Install it according to the poetry docs.`, + 'PYTHON_REQUIREMENTS_PYTHON_NOT_FOUND' + ); } throw e; } @@ -167,10 +170,9 @@ async function installRequirements(targetFolder, pluginInstance) { // Check if we're using the legacy --cache-dir command... if (options.pipCmdExtraArgs.indexOf('--cache-dir') > -1) { if (options.dockerizePip) { - throw ( - 'Error: You can not use --cache-dir with Docker any more, please\n' + - ' use the new option useDownloadCache instead. Please see:\n' + - ' https://github.com/UnitedIncome/serverless-python-requirements#caching' + throw new pluginInstance.serverless.classes.Error( + 'You cannot use --cache-dir with Docker any more, please use the new option useDownloadCache instead. Please see: https://github.com/UnitedIncome/serverless-python-requirements#caching for more details.', + 'PYTHON_REQUIREMENTS_CACHE_DIR_DOCKER_INVALID' ); } else { if (log) { @@ -222,7 +224,7 @@ async function installRequirements(targetFolder, pluginInstance) { pipCmd.push('--cache-dir', downloadCacheDir); } - if (await pipAcceptsSystem(options.pythonBin)) { + if (await pipAcceptsSystem(options.pythonBin, pluginInstance)) { pipCmd.push('--system'); } } @@ -358,7 +360,10 @@ async function installRequirements(targetFolder, pluginInstance) { if (Array.isArray(options.dockerRunCmdExtraArgs)) { dockerCmd.push(...options.dockerRunCmdExtraArgs); } else { - throw new Error('dockerRunCmdExtraArgs option must be an array'); + throw new pluginInstance.serverless.classes.Error( + 'dockerRunCmdExtraArgs option must be an array', + 'PYTHON_REQUIREMENTS_INVALID_DOCKER_EXTRA_ARGS' + ); } dockerCmd.push(dockerImage); @@ -405,7 +410,10 @@ async function installRequirements(targetFolder, pluginInstance) { cmd.indexOf('python') > -1 ? 'Try the pythonBin option' : 'Please install it'; - throw new Error(`${cmd} not found! ${advice}`); + throw new pluginInstance.serverless.classes.Error( + `${cmd} not found! ${advice}`, + 'PYTHON_REQUIREMENTS_COMMAND_NOT_FOUND' + ); } throw e; }