This repository has been archived by the owner on Oct 25, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 11
feat: Allow to enable the access to the system shell via server features #38
Merged
Merged
Changes from 2 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
b67d8e1
feat: Allow to enable the access to the system shell via server features
mykola-mokhnach 20a8fc5
Add a separate command
mykola-mokhnach 96fdf16
Tune proxy list
mykola-mokhnach dc0f3c7
Use const
mykola-mokhnach 5ace41b
Update tests
mykola-mokhnach File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { exec } from 'teen_process'; | ||
import _ from 'lodash'; | ||
import log from '../logger'; | ||
import { fs, tempDir } from 'appium-support'; | ||
import path from 'path'; | ||
|
||
const SYSTEM_SHELL_FEATURE = 'system_shell'; | ||
|
||
const commands = {}; | ||
|
||
/** | ||
* @typedef {Object} ExecOptions | ||
* @property {?string} interpreter - Full path to the command line interpreter binary. | ||
* The current interpreter (`$SHELL`) or `/bin/bash` is used by default | ||
* @property {?boolean} throwOnFail [false] - Whether to throw an exception if | ||
* the given script has returned non-zero exit code | ||
* @property {?number} timeout [20000] - The default timeout for the script execution. | ||
* @property {?Object} env [process.env] - Additional environment variables for | ||
* the shell script | ||
*/ | ||
|
||
/** | ||
* @typedef {Object} ExecResult | ||
* @property {string} stdout - Script stdout | ||
* @property {string} stderr - Script stderr | ||
* @property {number} code - Script return code. It will never be other | ||
* than zero if `throwOnFail` option is set to `true` | ||
*/ | ||
|
||
/** | ||
* Executes the given shell script if the `system_shell` | ||
* server feature is enabled. The command blocks until | ||
* the script finishes its execution or its timeout expires. | ||
* | ||
* @param {!string} script - The actual shell script to execute. | ||
* This should be a valid script snippet. | ||
* @param {?ExecOptions} args | ||
* @return {ExecResult} - The result of the script execution | ||
* @throws {Error} If there was a problem during command execution | ||
*/ | ||
commands.execute = async function execute (script, args) { | ||
this.ensureFeatureEnabled(SYSTEM_SHELL_FEATURE); | ||
|
||
if (!_.isEmpty(script)) { | ||
log.errorAndThrow(`The 'script' argument cannot be empty`); | ||
} | ||
|
||
let opts = {}; | ||
if (_.isArray(args) && _.isPlainObject(args[0])) { | ||
opts = args[0]; | ||
} else if (_.isPlainObject(args)) { | ||
opts = args; | ||
} | ||
const { | ||
interpreter = process.env.SHELL || '/bin/bash', | ||
throwOnFail = false, | ||
timeout, | ||
env, | ||
} = opts; | ||
|
||
const tmpRoot = await tempDir.openDir(); | ||
try { | ||
const tmpScriptPath = path.resolve(tmpRoot, 'appium.sh'); | ||
await fs.writeFile(tmpScriptPath, script, 'utf8'); | ||
log.debug(`Executing script using '${interpreter}' shell interpreter:`); | ||
const execOpts = {}; | ||
if (_.isInteger(timeout)) { | ||
log.debug(`- Timeout: ${timeout}ms`); | ||
execOpts.timeout = timeout; | ||
} | ||
if (!_.isEmpty(env)) { | ||
log.debug(`- Environment: ${JSON.stringify(env)}`); | ||
execOpts.env = Object.assign({}, process.env, env); | ||
} | ||
log.debug(script); | ||
// TODO: Add some perf measurement here? | ||
const {stdout, stderr} = await exec(interpreter, [tmpScriptPath], execOpts); | ||
return { | ||
stdout, | ||
stderr, | ||
code: 0, | ||
}; | ||
} catch (e) { | ||
if (_.has(e, 'code')) { | ||
const {stdout, stderr, code} = e; | ||
// Do not throw if the script return code is not zero | ||
log.debug(`The script has returned non-zero exit code ${code}`); | ||
if (stderr) { | ||
log.debug(`Stderr: ${stderr}`); | ||
} | ||
if (!throwOnFail) { | ||
return {stdout, stderr, code}; | ||
} | ||
} | ||
throw e; | ||
} finally { | ||
await fs.rimraf(tmpRoot); | ||
} | ||
}; | ||
|
||
export { commands }; | ||
export default commands; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import executeCmds from './execute'; | ||
|
||
const commands = {}; | ||
Object.assign( | ||
commands, | ||
executeCmds, | ||
// add other command types here | ||
); | ||
|
||
export { commands }; | ||
export default commands; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we add this feature flag in readme like other modules?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I'm sometimes being lazy with documenting all the stuff. I've tried to provide accurate docstrings in the source though ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mykola-mokhnach can you please provide an example of how to actually execute a simple shell command once this feature has been enabled when starting appium server? im unsure how to use with my driver? I'm using C# fyi. Appreciate any help. Thanks :)