ssh-client-wrapper 2.2.1 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +1 -0
- package/.eslintrc.json +24 -153
- package/Dockerfile +4 -7
- package/Dockerfile-bullseye +7 -0
- package/Dockerfile-buster +7 -0
- package/docker-compose.yml +23 -3
- package/lib/index.js +0 -29
- package/lib/util.js +101 -9
- package/package.json +11 -7
- package/run_test_all.sh +11 -0
- package/test/interface.js +2 -7
- package/test/rsyncExec.js +2 -2
- package/test/sshExec.js +4 -4
- package/test/{util → testUtil}/hostInfo.js +1 -1
- package/test/util.js +76 -0
- /package/test/{util → testUtil}/testFiles.js +0 -0
package/.dockerignore
CHANGED
package/.eslintrc.json
CHANGED
|
@@ -1,163 +1,34 @@
|
|
|
1
1
|
{
|
|
2
|
-
"root": true,
|
|
3
|
-
"extends": [
|
|
4
|
-
"eslint"
|
|
5
|
-
],
|
|
6
|
-
"plugins": [
|
|
7
|
-
"node",
|
|
8
|
-
"jsdoc"
|
|
9
|
-
],
|
|
10
2
|
"env": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
3
|
+
"browser": true,
|
|
4
|
+
"commonjs": true,
|
|
5
|
+
"es2021": true
|
|
13
6
|
},
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
],
|
|
20
|
-
"arrow-body-style": [
|
|
21
|
-
"error",
|
|
22
|
-
"always"
|
|
23
|
-
],
|
|
24
|
-
"arrow-spacing": [
|
|
25
|
-
"error",
|
|
26
|
-
{
|
|
27
|
-
"before": false,
|
|
28
|
-
"after": false
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
"camelcase": [
|
|
32
|
-
"error",
|
|
33
|
-
{
|
|
34
|
-
"properties": "never"
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"eqeqeq": [
|
|
38
|
-
"error",
|
|
39
|
-
"always",
|
|
40
|
-
{
|
|
41
|
-
"null": "ignore"
|
|
42
|
-
}
|
|
43
|
-
],
|
|
44
|
-
"func-style": [
|
|
45
|
-
"error",
|
|
46
|
-
"declaration",
|
|
47
|
-
{
|
|
48
|
-
"allowArrowFunctions": true
|
|
49
|
-
}
|
|
50
|
-
],
|
|
51
|
-
"indent": [
|
|
52
|
-
"error",
|
|
53
|
-
2,
|
|
54
|
-
{
|
|
55
|
-
"SwitchCase": 1
|
|
56
|
-
}
|
|
57
|
-
],
|
|
58
|
-
"lines-around-comment": [
|
|
59
|
-
"error",
|
|
60
|
-
{
|
|
61
|
-
"beforeBlockComment": true,
|
|
62
|
-
"beforeLineComment": false
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
"lines-between-class-members": [
|
|
66
|
-
"error",
|
|
67
|
-
"always",
|
|
68
|
-
{
|
|
69
|
-
"exceptAfterSingleLine": true
|
|
70
|
-
}
|
|
71
|
-
],
|
|
72
|
-
"newline-per-chained-call": "error",
|
|
73
|
-
"no-use-before-define": [
|
|
74
|
-
"error",
|
|
75
|
-
{
|
|
76
|
-
"functions": false
|
|
77
|
-
}
|
|
78
|
-
],
|
|
79
|
-
"no-warning-comments": "warn",
|
|
80
|
-
"padded-blocks": [
|
|
81
|
-
"error",
|
|
82
|
-
"never"
|
|
83
|
-
],
|
|
84
|
-
"padding-line-between-statements": [
|
|
85
|
-
"error",
|
|
86
|
-
{
|
|
87
|
-
"blankLine": "any",
|
|
88
|
-
"prev": [
|
|
89
|
-
"const",
|
|
90
|
-
"let",
|
|
91
|
-
"var"
|
|
92
|
-
],
|
|
93
|
-
"next": "*"
|
|
7
|
+
"extends": ["standard"],
|
|
8
|
+
"overrides": [
|
|
9
|
+
{
|
|
10
|
+
"env": {
|
|
11
|
+
"node": true
|
|
94
12
|
},
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"class",
|
|
101
|
-
"do",
|
|
102
|
-
"for",
|
|
103
|
-
"function",
|
|
104
|
-
"multiline-block-like",
|
|
105
|
-
"switch",
|
|
106
|
-
"try",
|
|
107
|
-
"while"
|
|
108
|
-
]
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
"blankLine": "any",
|
|
112
|
-
"prev": [
|
|
113
|
-
"const",
|
|
114
|
-
"let",
|
|
115
|
-
"var",
|
|
116
|
-
"for",
|
|
117
|
-
"while",
|
|
118
|
-
"do",
|
|
119
|
-
"block-like",
|
|
120
|
-
"multiline-block-like"
|
|
121
|
-
],
|
|
122
|
-
"next": [
|
|
123
|
-
"block-like",
|
|
124
|
-
"do",
|
|
125
|
-
"for",
|
|
126
|
-
"multiline-block-like",
|
|
127
|
-
"switch",
|
|
128
|
-
"try",
|
|
129
|
-
"while"
|
|
130
|
-
]
|
|
13
|
+
"files": [
|
|
14
|
+
".eslintrc.{js,cjs}"
|
|
15
|
+
],
|
|
16
|
+
"parserOptions": {
|
|
17
|
+
"sourceType": "script"
|
|
131
18
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"module.exports"
|
|
140
|
-
],
|
|
141
|
-
"require-unicode-regexp": "off",
|
|
142
|
-
"node/no-unsupported-features": [
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"parserOptions": {
|
|
22
|
+
"ecmaVersion": "latest"
|
|
23
|
+
},
|
|
24
|
+
"rules": {
|
|
25
|
+
"semi": [
|
|
143
26
|
"error",
|
|
144
|
-
{
|
|
145
|
-
"version": 10
|
|
146
|
-
}
|
|
147
|
-
],
|
|
148
|
-
"jsdoc/require-hyphen-before-param-description": [
|
|
149
|
-
"warn",
|
|
150
27
|
"always"
|
|
151
28
|
],
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
"jsdoc/require-jsdoc": "off",
|
|
157
|
-
"jsdoc/require-param": "off",
|
|
158
|
-
"jsdoc/require-returns": "off"
|
|
159
|
-
},
|
|
160
|
-
"parserOptions": {
|
|
161
|
-
"ecmaVersion": 2018
|
|
29
|
+
"quotes": [
|
|
30
|
+
"error",
|
|
31
|
+
"double"
|
|
32
|
+
]
|
|
162
33
|
}
|
|
163
34
|
}
|
package/Dockerfile
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
# syntax=docker/dockerfile:1
|
|
2
|
-
|
|
3
|
-
FROM --platform=linux/amd64 node:hydrogen-bookworm-slim
|
|
4
|
-
#FROM --platform=linux/amd64 node:hydrogen-bullseye-slim
|
|
5
|
-
#FROM --platform=linux/amd64 node:hydrogen-buster-slim
|
|
2
|
+
FROM --platform=linux/amd64 node:20-bookworm-slim
|
|
6
3
|
|
|
7
|
-
WORKDIR /work
|
|
4
|
+
WORKDIR /work/ssh-client-wrapper
|
|
8
5
|
RUN apt-get update && apt -y install ssh rsync bzip2 python3 g++ build-essential
|
|
9
|
-
COPY ./
|
|
10
|
-
RUN
|
|
6
|
+
COPY ./ ./
|
|
7
|
+
RUN npm install
|
package/docker-compose.yml
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
version: "3.8"
|
|
2
2
|
services:
|
|
3
|
-
|
|
3
|
+
testbed:
|
|
4
4
|
image: naoso5/test-sshd
|
|
5
5
|
ports:
|
|
6
|
-
- 4000:22
|
|
6
|
+
- "4000:22"
|
|
7
7
|
container_name: testbed
|
|
8
8
|
tester:
|
|
9
9
|
build:
|
|
@@ -14,4 +14,24 @@ services:
|
|
|
14
14
|
TEST_PW: passw0rd
|
|
15
15
|
TEST_HOST: testbed
|
|
16
16
|
working_dir: /work/ssh-client-wrapper
|
|
17
|
-
command: bash -c "mkdir /root/.ssh 2>/dev/null; npm run
|
|
17
|
+
command: bash -c "mkdir /root/.ssh 2>/dev/null; npm run mocha"
|
|
18
|
+
tester-bullseye:
|
|
19
|
+
build:
|
|
20
|
+
context: .
|
|
21
|
+
dockerfile: Dockerfile-bullseye
|
|
22
|
+
environment:
|
|
23
|
+
TEST_USER: testuser
|
|
24
|
+
TEST_PW: passw0rd
|
|
25
|
+
TEST_HOST: testbed
|
|
26
|
+
working_dir: /work/ssh-client-wrapper
|
|
27
|
+
command: bash -c "mkdir /root/.ssh 2>/dev/null; npm run mocha"
|
|
28
|
+
tester-buster:
|
|
29
|
+
build:
|
|
30
|
+
context: .
|
|
31
|
+
dockerfile: Dockerfile-buster
|
|
32
|
+
environment:
|
|
33
|
+
TEST_USER: testuser
|
|
34
|
+
TEST_PW: passw0rd
|
|
35
|
+
TEST_HOST: testbed
|
|
36
|
+
working_dir: /work/ssh-client-wrapper
|
|
37
|
+
command: bash -c "mkdir /root/.ssh 2>/dev/null; npm run mocha"
|
package/lib/index.js
CHANGED
|
@@ -67,8 +67,6 @@ class SshClientWrapper {
|
|
|
67
67
|
* @param {Integer} timeout - timeout in secconds
|
|
68
68
|
* @param { Function } outputCallback - call back routine for output
|
|
69
69
|
* @returns {Integer} - Return code of cmd.
|
|
70
|
-
*
|
|
71
|
-
* If stdout and stderr is array, last 5 line of stdout and stderr is stored in them.
|
|
72
70
|
*/
|
|
73
71
|
async exec(cmd, timeout = 0, outputCallback = null) {
|
|
74
72
|
debug("exec called", cmd);
|
|
@@ -92,33 +90,6 @@ class SshClientWrapper {
|
|
|
92
90
|
return ls(this.hostInfo, target, lsOpt, timeout);
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
/**
|
|
96
|
-
* Execute command repeatedly until specified keyword is found in stdout and/or stderr.
|
|
97
|
-
* @param {string} cmd - Cmdline which will be executed.
|
|
98
|
-
* @param {RegExp} regexp - End condition.
|
|
99
|
-
* @param {number} retryDelay - Duration between each try (in sec).
|
|
100
|
-
* @param {number} maxRetry - Max retry count.
|
|
101
|
-
* @returns {Integer} - Return code of cmd.
|
|
102
|
-
*/
|
|
103
|
-
async watch(cmd, regexp, retryDelay = 3, maxRetry = null) {
|
|
104
|
-
debug("watch called", cmd, regexp, retryDelay, maxRetry);
|
|
105
|
-
|
|
106
|
-
if (typeof cmd !== "string") {
|
|
107
|
-
return logAndReject("cmd must be string");
|
|
108
|
-
}
|
|
109
|
-
if (!(regexp instanceof RegExp)) {
|
|
110
|
-
const err = new Error("illegal regexp specified");
|
|
111
|
-
err.regexp = regexp;
|
|
112
|
-
err.cmd = cmd;
|
|
113
|
-
err.retryDelay = retryDelay;
|
|
114
|
-
err.maxRetry = maxRetry;
|
|
115
|
-
return Promise.reject(new Error("err"));
|
|
116
|
-
}
|
|
117
|
-
//not implemented yet !!!
|
|
118
|
-
return this.exec(cmd, ()=>{
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
93
|
/**
|
|
123
94
|
* Send file or directory and its child to server.
|
|
124
95
|
* @param {string[]} src - File or directory name which to be recieve.
|
package/lib/util.js
CHANGED
|
@@ -11,6 +11,53 @@ const rePwPrompt = /password:/;
|
|
|
11
11
|
const rePhPrompt = /Enter passphrase for key/;
|
|
12
12
|
const reNewHostPrompt = /Are you sure you want to continue connecting/;
|
|
13
13
|
|
|
14
|
+
const Ajv = require("ajv");
|
|
15
|
+
|
|
16
|
+
const ajv = new Ajv({
|
|
17
|
+
allErrors: true,
|
|
18
|
+
removeAdditional: "all",
|
|
19
|
+
coerceTypes: true,
|
|
20
|
+
logger: {
|
|
21
|
+
log: debug,
|
|
22
|
+
warn: debug,
|
|
23
|
+
error: debug
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
require("ajv-keywords")(ajv, "transform");
|
|
27
|
+
|
|
28
|
+
//never validate password and passphrase value to avoid security insident
|
|
29
|
+
const hostInfoSchema = {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
host: { type: "string", pattern: "\\S+", transform: ["trim"] },
|
|
33
|
+
user: { type: "string", pattern: "\\S+", transform: ["trim"] },
|
|
34
|
+
port: { type: "number", minimum: 0, maximum: 65535 },
|
|
35
|
+
keyFile: { type: "string", pattern: "\\S+", transform: ["trim"] },
|
|
36
|
+
noStrictHostkeyChecking: { type: "boolean" },
|
|
37
|
+
ControlPersist: { type: "number", minimum: 0 },
|
|
38
|
+
ConnectTimeout: { type: "number", minimum: 0 },
|
|
39
|
+
maxRetry: { type: "number", minimum: 0 },
|
|
40
|
+
retryMinTimeout: { type: "number", minimum: 0 },
|
|
41
|
+
retryMaxTimeout: { type: "number", minimum: 0 },
|
|
42
|
+
sshOpt: { type: "array", minItems: 1, items: { type: "string", pattern: "\\S+", transform: ["trim"] } }
|
|
43
|
+
},
|
|
44
|
+
required: ["host"],
|
|
45
|
+
additionalProperties: false
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const stringOptions = [
|
|
49
|
+
"user",
|
|
50
|
+
"keyFile"
|
|
51
|
+
];
|
|
52
|
+
const numberOptions = [
|
|
53
|
+
"ControlPersist",
|
|
54
|
+
"ConnectTimeout",
|
|
55
|
+
"maxRetry",
|
|
56
|
+
"retryMinTimeout",
|
|
57
|
+
"retryMaxTimeout"
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const validate = ajv.compile(hostInfoSchema);
|
|
14
61
|
|
|
15
62
|
/**
|
|
16
63
|
* bridge function to functions which need string
|
|
@@ -23,20 +70,65 @@ const buff2String = (func, data)=>{
|
|
|
23
70
|
|
|
24
71
|
/**
|
|
25
72
|
* check if given hostInfo object is OK
|
|
26
|
-
* @param { Object} hostInfo - host information object defined in index.js
|
|
73
|
+
* @param { Object } hostInfo - host information object defined in index.js
|
|
27
74
|
*/
|
|
28
75
|
const sanityCheck = (hostInfo)=>{
|
|
29
|
-
debug("sanityCheck called");
|
|
76
|
+
debug("sanityCheck called", hostInfo);
|
|
77
|
+
//keep password, passphrase, and masterPty before validate.
|
|
78
|
+
//these properties can have invalid value for JSON.
|
|
79
|
+
//ajv will remove that at validation pahse becase of additionalProperties setting
|
|
80
|
+
//so we keep them here and put back later.
|
|
81
|
+
const { password, passphrase, masterPty } = hostInfo;
|
|
82
|
+
validate(hostInfo);
|
|
30
83
|
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
84
|
+
if (validate !== null && Array.isArray(validate.errors)) {
|
|
85
|
+
for (const e of validate.errors) {
|
|
86
|
+
debug("validation error:", e);
|
|
87
|
+
const prop = e.instancePath.replace(/^\//, "");
|
|
88
|
+
if (e.keyword === "required" && e.params.missingProperty === "host") {
|
|
89
|
+
throw new Error("host is required");
|
|
90
|
+
}
|
|
91
|
+
if (prop === "host") {
|
|
92
|
+
if (hostInfo.host === "") {
|
|
93
|
+
throw new Error("empty host is not allowed");
|
|
94
|
+
}
|
|
95
|
+
const err = new Error("invalid host specified");
|
|
96
|
+
err.hostInfo = hostInfo;
|
|
97
|
+
err.validationError = e;
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
if (prop.startsWith("sshOpt")) {
|
|
101
|
+
debug("remove empty member of sshOpt");
|
|
102
|
+
hostInfo.sshOpt = hostInfo.sshOpt.filter((opt)=>{
|
|
103
|
+
return opt !== "";
|
|
104
|
+
});
|
|
105
|
+
continue;
|
|
106
|
+
} else if (stringOptions.includes(prop) && hostInfo[prop] === "") {
|
|
107
|
+
debug("remove empty string option", prop, hostInfo[prop]);
|
|
108
|
+
delete hostInfo[prop];
|
|
109
|
+
continue;
|
|
110
|
+
} else if (numberOptions.includes(prop) && ["minimum", "maximum"].includes(e.keyword)) {
|
|
111
|
+
debug("remove out of range number option", prop, hostInfo[prop]);
|
|
112
|
+
delete hostInfo[prop];
|
|
113
|
+
continue;
|
|
114
|
+
} else {
|
|
115
|
+
const err = new Error(`invalid ${prop} specified ${hostInfo[prop]}`);
|
|
116
|
+
err.hostInfo = hostInfo;
|
|
117
|
+
err.validationError = e;
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
38
120
|
}
|
|
39
121
|
}
|
|
122
|
+
if (["string", "function"].includes(typeof password)) {
|
|
123
|
+
hostInfo.password = password;
|
|
124
|
+
}
|
|
125
|
+
if (["string", "function"].includes(typeof passphrase)) {
|
|
126
|
+
hostInfo.password = password;
|
|
127
|
+
}
|
|
128
|
+
if (masterPty === null || typeof masterPty === "function") {
|
|
129
|
+
hostInfo.masterPty = masterPty;
|
|
130
|
+
}
|
|
131
|
+
return hostInfo;
|
|
40
132
|
};
|
|
41
133
|
|
|
42
134
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ssh-client-wrapper",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.4",
|
|
4
4
|
"description": "wrapper library for open ssh client and rsync",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ssh",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"*.js": "eslint --fix"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"ajv": "^8.12.0",
|
|
38
|
+
"ajv-keywords": "^5.1.0",
|
|
37
39
|
"debug": "^4.3.4",
|
|
38
40
|
"glob": "^10.3.10",
|
|
39
41
|
"node-pty": "^0.10.1",
|
|
40
|
-
"
|
|
41
|
-
"promise-retry": "^2.0.1",
|
|
42
|
-
"rewire": "^7.0.0"
|
|
42
|
+
"promise-retry": "^2.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"chai": "^4.3.7",
|
|
@@ -47,14 +47,18 @@
|
|
|
47
47
|
"chai-fs": "^2.0.0",
|
|
48
48
|
"eslint": "^8.38.0",
|
|
49
49
|
"eslint-config-eslint": "^7.0.0",
|
|
50
|
+
"eslint-config-standard": "^17.1.0",
|
|
50
51
|
"eslint-plugin-chai-expect": "^3.0.0",
|
|
51
|
-
"eslint-plugin-chai-friendly": "^0.7.
|
|
52
|
-
"eslint-plugin-
|
|
53
|
-
"eslint-plugin-
|
|
52
|
+
"eslint-plugin-chai-friendly": "^0.7.4",
|
|
53
|
+
"eslint-plugin-import": "^2.29.1",
|
|
54
|
+
"eslint-plugin-n": "^16.6.2",
|
|
55
|
+
"eslint-plugin-promise": "^6.1.1",
|
|
54
56
|
"fs-extra": "^11.1.1",
|
|
55
57
|
"husky": "^8.0.0",
|
|
56
58
|
"lint-staged": "^13.2.1",
|
|
57
59
|
"mocha": "^10.2.0",
|
|
60
|
+
"nyc": "^15.1.0",
|
|
61
|
+
"rewire": "^7.0.0",
|
|
58
62
|
"sinon": "^15.0.3",
|
|
59
63
|
"sinon-chai": "^3.7.0"
|
|
60
64
|
}
|
package/run_test_all.sh
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
docker-compose up testbed -d
|
|
3
|
+
export TEST_HOST=localhost
|
|
4
|
+
export TEST_USER=testuser
|
|
5
|
+
export TEST_PW=passw0rd
|
|
6
|
+
export TEST_PORT=4000
|
|
7
|
+
npm run test
|
|
8
|
+
docker-compose run --build --rm tester &&
|
|
9
|
+
docker-compose run --build --rm tester-bullseye &&
|
|
10
|
+
docker-compose run --build --rm tester-buster &&
|
|
11
|
+
docker-compose rm --stop --force testbed
|
package/test/interface.js
CHANGED
|
@@ -33,20 +33,15 @@ describe("test for interface", ()=>{
|
|
|
33
33
|
expect(()=>{
|
|
34
34
|
//eslint-disable-next-line no-new
|
|
35
35
|
new SshClientWrapper({});
|
|
36
|
-
}).to.throw("host
|
|
37
|
-
expect(()=>{
|
|
38
|
-
//eslint-disable-next-line no-new
|
|
39
|
-
new SshClientWrapper({ host: 1 });
|
|
40
|
-
}).to.throw("host must be non-empty string");
|
|
36
|
+
}).to.throw("host is required");
|
|
41
37
|
expect(()=>{
|
|
42
38
|
//eslint-disable-next-line no-new
|
|
43
39
|
new SshClientWrapper({ host: "" });
|
|
44
|
-
}).to.throw("host
|
|
40
|
+
}).to.throw("empty host is not allowed");
|
|
45
41
|
});
|
|
46
42
|
it("should successfully instanciate only with host prop", ()=>{
|
|
47
43
|
expect(new SshClientWrapper({ host: "hoge" })).to.have.property("exec");
|
|
48
44
|
expect(new SshClientWrapper({ host: "hoge" })).to.have.property("ls");
|
|
49
|
-
expect(new SshClientWrapper({ host: "hoge" })).to.have.property("watch");
|
|
50
45
|
expect(new SshClientWrapper({ host: "hoge" })).to.have.property("send");
|
|
51
46
|
expect(new SshClientWrapper({ host: "hoge" })).to.have.property("recv");
|
|
52
47
|
expect(new SshClientWrapper({ host: "hoge" })).to.have.property("canConnect");
|
package/test/rsyncExec.js
CHANGED
|
@@ -28,7 +28,7 @@ const { checkRsyncVersion, send, recv } = require("../lib/rsyncExec.js");
|
|
|
28
28
|
|
|
29
29
|
//test helpers
|
|
30
30
|
const { sshExec, disconnect } = require("../lib/sshExec.js");
|
|
31
|
-
const hostInfo = require("./
|
|
31
|
+
const hostInfo = require("./testUtil/hostInfo.js");
|
|
32
32
|
const {
|
|
33
33
|
clearLocalTestFiles,
|
|
34
34
|
clearRemoteTestFiles,
|
|
@@ -40,7 +40,7 @@ const {
|
|
|
40
40
|
remoteRoot,
|
|
41
41
|
remoteEmptyDir,
|
|
42
42
|
remoteFiles
|
|
43
|
-
} = require("./
|
|
43
|
+
} = require("./testUtil/testFiles");
|
|
44
44
|
|
|
45
45
|
const formatLsOutput = (array)=>{
|
|
46
46
|
const rt = [];
|
package/test/sshExec.js
CHANGED
|
@@ -17,8 +17,8 @@ const sshout = sinon.stub();
|
|
|
17
17
|
const { sshExec, canConnect, disconnect, ls } = require("../lib/sshExec.js");
|
|
18
18
|
|
|
19
19
|
//test helpers
|
|
20
|
-
const hostInfo = require("./
|
|
21
|
-
const { clearRemoteTestFiles, clearLocalTestFiles, createRemoteFiles, nonExisting, remoteRoot, remoteEmptyDir } = require("./
|
|
20
|
+
const hostInfo = require("./testUtil/hostInfo.js");
|
|
21
|
+
const { clearRemoteTestFiles, clearLocalTestFiles, createRemoteFiles, nonExisting, remoteRoot, remoteEmptyDir } = require("./testUtil/testFiles.js");
|
|
22
22
|
|
|
23
23
|
describe("test for ssh execution", function() {
|
|
24
24
|
this.timeout(65000);//eslint-disable-line no-invalid-this
|
|
@@ -97,11 +97,11 @@ describe("test for ssh execution", function() {
|
|
|
97
97
|
});
|
|
98
98
|
it("should be rejected if port number is out of range(-1)", async ()=>{
|
|
99
99
|
hostInfo2.port = -1;
|
|
100
|
-
return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith(
|
|
100
|
+
return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith("invalid port specified -1");
|
|
101
101
|
});
|
|
102
102
|
it("should be rejected if port number is out of range(65536)", async ()=>{
|
|
103
103
|
hostInfo2.port = 65536;
|
|
104
|
-
return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith(
|
|
104
|
+
return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith("invalid port specified 65536");
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
107
|
describe("#ls", ()=>{
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
module.exports = {
|
|
3
3
|
host: process.env.TEST_HOST || "localhost",
|
|
4
4
|
user: process.env.TEST_USER || null,
|
|
5
|
-
port: process.env.TEST_PORT ||
|
|
5
|
+
port: process.env.TEST_PORT || 22,
|
|
6
6
|
password: process.env.TEST_PW,
|
|
7
7
|
passphrase: process.env.TEST_PH,
|
|
8
8
|
keyFile: process.env.TEST_PRIVATE_KEY,
|
package/test/util.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
process.on("unhandledRejection", console.dir); //eslint-disable-line no-console
|
|
3
|
+
|
|
4
|
+
//setup test framework
|
|
5
|
+
const chai = require("chai");
|
|
6
|
+
const { expect } = require("chai");
|
|
7
|
+
chai.use(require("chai-as-promised"));
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
//testee
|
|
11
|
+
const { sanityCheck } = require("../lib/util.js");
|
|
12
|
+
|
|
13
|
+
describe("test for sanityCheck", ()=>{
|
|
14
|
+
const host = "testHostName";
|
|
15
|
+
it("should throw error for empty host", ()=>{
|
|
16
|
+
expect(sanityCheck.bind(null, { host: " ", user: " ", port: 22 })).to.throw(/empty host is not allowed/);
|
|
17
|
+
});
|
|
18
|
+
it("should throw error if host is not in argument object", ()=>{
|
|
19
|
+
expect(sanityCheck.bind(null, { user: " ", port: 22 })).to.throw(/host is required/);
|
|
20
|
+
});
|
|
21
|
+
it("should just remove empty string props", ()=>{
|
|
22
|
+
expect(sanityCheck({ host, user: " ", port: 22 })).to.deep.equal({ host, port: 22 });
|
|
23
|
+
});
|
|
24
|
+
it("should remove empty string member in sshOpt", ()=>{
|
|
25
|
+
expect(sanityCheck({ host, sshOpt: ["foo", " ", "bar"], user: "user", port: 33 })).to.deep.equal({ host, sshOpt: ["foo", "bar"], user: "user", port: 33 });
|
|
26
|
+
});
|
|
27
|
+
it("should just chage type if string value specified for number", ()=>{
|
|
28
|
+
expect(sanityCheck({
|
|
29
|
+
host,
|
|
30
|
+
port: "11",
|
|
31
|
+
ControlPersist: "22",
|
|
32
|
+
ConnectTimeout: "33",
|
|
33
|
+
maxRetry: "44",
|
|
34
|
+
retryMinTimeout: "55",
|
|
35
|
+
retryMaxTimeout: "66"
|
|
36
|
+
})).to.deep.equal({
|
|
37
|
+
host,
|
|
38
|
+
port: 11,
|
|
39
|
+
ControlPersist: 22,
|
|
40
|
+
ConnectTimeout: 33,
|
|
41
|
+
maxRetry: 44,
|
|
42
|
+
retryMinTimeout: 55,
|
|
43
|
+
retryMaxTimeout: 66
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
it("should remove out of range members", ()=>{
|
|
47
|
+
expect(sanityCheck({
|
|
48
|
+
host,
|
|
49
|
+
ControlPersist: "-1",
|
|
50
|
+
ConnectTimeout: "-1",
|
|
51
|
+
maxRetry: "-1",
|
|
52
|
+
retryMinTimeout: "-1",
|
|
53
|
+
retryMaxTimeout: "-1"
|
|
54
|
+
})).to.deep.equal({
|
|
55
|
+
host
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
it("should just chage type if string value specified for boolean member", ()=>{
|
|
59
|
+
expect(sanityCheck({
|
|
60
|
+
host,
|
|
61
|
+
noStrictHostkeyChecking: "true"
|
|
62
|
+
})).to.deep.equal({
|
|
63
|
+
host,
|
|
64
|
+
noStrictHostkeyChecking: true
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
it("should just chage type if number value specified for boolean member", ()=>{
|
|
68
|
+
expect(sanityCheck({
|
|
69
|
+
host,
|
|
70
|
+
noStrictHostkeyChecking: 0
|
|
71
|
+
})).to.deep.equal({
|
|
72
|
+
host,
|
|
73
|
+
noStrictHostkeyChecking: false
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
File without changes
|