ssh-client-wrapper 2.13.2 → 2.15.0

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.
@@ -1,106 +0,0 @@
1
- process.on("unhandledRejection", console.dir);
2
-
3
- //setup test framework
4
- import * as chai from "chai";
5
- import { expect } from "chai";
6
- import chaiAsPromised from "chai-as-promised";
7
- chai.use(chaiAsPromised);
8
-
9
- //testee
10
- import { sanityCheck } from "../lib/util.js";
11
-
12
- describe("test for sanityCheck", ()=>{
13
- const host = "testHostName";
14
- const defaultValues = {
15
- ControlPersist: 180,
16
- maxRetry: 3,
17
- retryDuration: 1000
18
- };
19
- it("should throw error for empty host", ()=>{
20
- expect(sanityCheck.bind(null, { host: " ", user: " ", port: 22 })).to.throw(/empty host is not allowed/);
21
- });
22
- it("should throw error if host is not in argument object", ()=>{
23
- expect(sanityCheck.bind(null, { user: " ", port: 22 })).to.throw(/host is required/);
24
- });
25
- it("should just remove empty string props", ()=>{
26
- expect(sanityCheck({
27
- host,
28
- user: " ",
29
- port: 22
30
- })).to.deep.equal({
31
- host,
32
- ...defaultValues,
33
- port: 22
34
- });
35
- });
36
- it("should remove empty string member in sshOpt", ()=>{
37
- expect(sanityCheck({
38
- host,
39
- sshOpt: ["foo", " ", "bar"],
40
- user: "user",
41
- port: 33
42
- })).to.deep.equal({
43
- host,
44
- ...defaultValues,
45
- sshOpt: ["foo", "bar"],
46
- user: "user",
47
- port: 33
48
- });
49
- });
50
- it("should just change type if string value specified for number", ()=>{
51
- expect(sanityCheck({
52
- host,
53
- port: "11",
54
- ControlPersist: "22",
55
- ConnectTimeout: "33",
56
- maxRetry: "44",
57
- retryDuration: "55"
58
- })).to.deep.equal({
59
- host,
60
- port: 11,
61
- ControlPersist: 22,
62
- ConnectTimeout: 33,
63
- maxRetry: 44,
64
- retryDuration: 55
65
- });
66
- });
67
- it("should remove out of range members", ()=>{
68
- expect(sanityCheck({
69
- host,
70
- ControlPersist: "-1",
71
- ConnectTimeout: "-1",
72
- maxRetry: "-1",
73
- retryDuration: "-1"
74
- })).to.deep.equal({
75
- host
76
- });
77
- });
78
- it("should just change type if string value specified for boolean member", ()=>{
79
- expect(sanityCheck({
80
- host,
81
- noStrictHostKeyChecking: "true"
82
- })).to.deep.equal({
83
- host,
84
- ...defaultValues,
85
- noStrictHostKeyChecking: true
86
- });
87
- });
88
- it("should just change type if number value specified for boolean member", ()=>{
89
- expect(sanityCheck({
90
- host,
91
- noStrictHostKeyChecking: 0
92
- })).to.deep.equal({
93
- host,
94
- ...defaultValues,
95
- noStrictHostKeyChecking: false
96
- });
97
- });
98
- it("shold keep addtional properties", ()=>{
99
- const testData = {
100
- host,
101
- hoge: 3,
102
- foo: ()=>{}
103
- };
104
- expect(sanityCheck(testData)).to.deep.equal(testData);
105
- });
106
- });
package/test/sshExec.js DELETED
@@ -1,145 +0,0 @@
1
- import path from "path";
2
- import { fileURLToPath } from "url";
3
-
4
- process.on("unhandledRejection", console.dir);
5
- Error.traceLimit = 100000;
6
-
7
- //setup test framework
8
- import * as chai from "chai";
9
- import { expect } from "chai";
10
- import sinon from "sinon";
11
- import sinonChai from "sinon-chai";
12
- import chaiAsPromised from "chai-as-promised";
13
- chai.use(sinonChai);
14
- chai.use(chaiAsPromised);
15
-
16
- const sshout = sinon.stub();
17
-
18
- //testee
19
- import { sshExec, canConnect, disconnect } from "../lib/sshExec.js";
20
-
21
- //test helpers
22
- import hostInfo from "./testUtil/hostInfo.js";
23
- import { clearRemoteTestFiles, clearLocalTestFiles, nonExisting } from "./testUtil/testFiles.js";
24
- import { send } from "../lib/rsyncExec.js";
25
-
26
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
27
-
28
- describe("test for ssh execution", function () {
29
- const rcfilePath = "/home/testuser/testrc";
30
- this.timeout(65000);
31
- beforeEach(async ()=>{
32
- sshout.reset();
33
- await clearRemoteTestFiles(hostInfo);
34
- });
35
- before(async ()=>{
36
- await send(hostInfo, [path.resolve(__dirname, "./testUtil/testrc")], rcfilePath, [], 0);
37
- });
38
- after(async ()=>{
39
- if (!process.env.TEST_KEEP_FILES) {
40
- await clearRemoteTestFiles(hostInfo);
41
- await clearLocalTestFiles();
42
- await sshExec(hostInfo, `rm ${rcfilePath}`);
43
- }
44
- await disconnect(hostInfo);
45
- });
46
- describe("#exec", ()=>{
47
- const testText = "hoge";
48
- it("should execute single command with stdout", async ()=>{
49
- const rt = await sshExec(hostInfo, `echo ${testText}`, 0, sshout);
50
- expect(rt).to.equal(0);
51
- expect(sshout).to.be.called;
52
-
53
- expect(sshout).to.be.calledWithMatch(/^hoge/);
54
- });
55
- it("should execute single command with stderr", async ()=>{
56
- const rt = await sshExec(hostInfo, `echo ${testText} >&2`, 0, sshout);
57
- expect(rt).to.equal(0);
58
- expect(sshout).to.be.called;
59
- expect(sshout).to.be.calledWithMatch(/^hoge/);
60
- });
61
- it("should execute 2 command by prependCmd ", async ()=>{
62
- const rt = await sshExec(hostInfo, `echo ${testText}`, 0, sshout, null, "echo foo");
63
- expect(rt).to.equal(0);
64
- expect(sshout).to.be.calledOnce;
65
- expect(sshout).to.be.calledWithMatch(/^foo\nhoge\n/);
66
- });
67
- it("should execute 2 command by hostInfo.prependCmd ", async ()=>{
68
- hostInfo.prependCmd = "echo foo";
69
- const rt = await sshExec(hostInfo, `echo ${testText}`, 0, sshout, null);
70
- expect(rt).to.equal(0);
71
- expect(sshout).to.be.calledOnce;
72
- expect(sshout).to.be.calledWithMatch(/^foo\nhoge\n/);
73
- delete hostInfo.prependCmd;
74
- });
75
- it("should execute 2 command by rcfile", async ()=>{
76
- const rt = await sshExec(hostInfo, `echo ${testText}`, 0, sshout, rcfilePath);
77
- expect(rt).to.equal(0);
78
- expect(sshout).to.be.calledOnce;
79
- expect(sshout).to.be.calledWithMatch(/^this is test rcfile\nhoge\n/);
80
- });
81
- it("should execute 2 command by hostInfo.prependCmd ", async ()=>{
82
- hostInfo.rcfile = rcfilePath;
83
- const rt = await sshExec(hostInfo, `echo ${testText}`, 0, sshout, null);
84
- expect(rt).to.equal(0);
85
- expect(sshout).to.be.calledOnce;
86
- expect(sshout).to.be.calledWithMatch(/^this is test rcfile\nhoge\n/);
87
- delete hostInfo.rcfile;
88
- });
89
- //please note that exec() resolves with non-zero value
90
- //(126 permission deny or 127 file not found)
91
- //but does not reject in following 2 cases
92
- it("should not execute command which do not have exec permission", async ()=>{
93
- await sshExec(hostInfo, "echo echo hoge >hoge");
94
- await sshExec(hostInfo, "chmod ugo-x hoge");
95
- const rt = await sshExec(hostInfo, "./hoge");
96
- expect(rt).to.equal(126);
97
- });
98
- it("should resolve with 127 if command is not found", async ()=>{
99
- const rt = await sshExec(hostInfo, `./${nonExisting}`);
100
- expect(rt).to.equal(127);
101
- });
102
- it("should be rejected if timeout expired", async ()=>{
103
- return expect(sshExec(hostInfo, "sleep 60", 1)).to.be.rejectedWith("watchdog timer expired");
104
- });
105
- });
106
- describe("#canConnect", ()=>{
107
- let hostInfo2;
108
- beforeEach(async ()=>{
109
- await disconnect(hostInfo);
110
- hostInfo2 = { ...hostInfo };
111
- hostInfo2.masterPty = null;
112
- });
113
- afterEach(async ()=>{
114
- await disconnect(hostInfo2);
115
- });
116
- it("should be resolved with true", async ()=>{
117
- return expect(await canConnect(hostInfo2, 5)).to.be.true;
118
- });
119
- it("should be rejected if user does not exist", async ()=>{
120
- hostInfo2.user = "xxxx";
121
- return expect(canConnect(hostInfo2, 2)).to.be.rejected;
122
- });
123
- it("should be rejected if password is wrong", async ()=>{
124
- hostInfo2.password = "xxxx";
125
- return expect(canConnect(hostInfo2, 2)).to.be.rejected;
126
- });
127
- it("should be rejected if host does not exist", async ()=>{
128
- hostInfo2.host = "foo.bar.example.com";
129
- return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith(255);
130
- });
131
- it("should be rejected if host(ip address) does not exist", async ()=>{
132
- hostInfo2.host = "192.0.2.1";
133
- hostInfo2.ConnectTimeout = 8; //please note each test will be timed out in 20 seconds
134
- return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith(255);
135
- });
136
- it("should be rejected if port number is out of range(-1)", async ()=>{
137
- hostInfo2.port = -1;
138
- return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith("invalid port specified -1");
139
- });
140
- it("should be rejected if port number is out of range(65536)", async ()=>{
141
- hostInfo2.port = 65536;
142
- return expect(canConnect(hostInfo2, 2)).to.be.rejectedWith("invalid port specified 65536");
143
- });
144
- });
145
- });
@@ -1,9 +0,0 @@
1
- export default {
2
- host: process.env.TEST_HOST || "localhost",
3
- user: process.env.TEST_USER || null,
4
- port: process.env.TEST_PORT || 22,
5
- password: process.env.TEST_PW,
6
- passphrase: process.env.TEST_PH,
7
- keyFile: process.env.TEST_PRIVATE_KEY,
8
- noStrictHostkeyChecking: true
9
- };
@@ -1,101 +0,0 @@
1
- import fs from "fs-extra";
2
- import path from "path";
3
-
4
- import { sshExec } from "../../lib/sshExec.js";
5
-
6
- /*
7
- * test directory tree
8
- * ${ROOT}
9
- * +-- huga/ (empty directory)
10
- * +-- foo
11
- * +-- bar
12
- * +-- baz
13
- * +-- hoge
14
- * +-- piyo
15
- * +-- puyo
16
- * +-- poyo
17
- *
18
- * ${ROOT} is "ARssh_testLocalDir" on local side
19
- * it is ARssh_testLocalDir on remote side
20
- *
21
- */
22
-
23
- const localRoot = "ARssh_testLocalDir";
24
- const localEmptyDir = path.join(localRoot, "huga");
25
- const localFiles = [
26
- path.join(localRoot, "foo"),
27
- path.join(localRoot, "bar"),
28
- path.join(localRoot, "baz"),
29
- path.join(localRoot, "hoge", "piyo"),
30
- path.join(localRoot, "hoge", "puyo"),
31
- path.join(localRoot, "hoge", "poyo")
32
- ];
33
-
34
- const remoteRoot = "ARssh_testRemoteDir";
35
- const remoteEmptyDir = `${remoteRoot}/huga`;
36
- const remoteFiles = [
37
- `${remoteRoot}/foo`,
38
- `${remoteRoot}/bar`,
39
- `${remoteRoot}/baz`,
40
- `${remoteRoot}/hoge/piyo`,
41
- `${remoteRoot}/hoge/puyo`,
42
- `${remoteRoot}/hoge/poyo`
43
- ];
44
- const nonExisting = "ARSSH_nonExisting";
45
-
46
- /*
47
- * prepare local files which contain its filename
48
- */
49
- /**
50
- *
51
- */
52
- export async function createLocalFiles() {
53
- const localDir2 = path.join(localRoot, "hoge");
54
- const promises = [];
55
- await fs.mkdir(localRoot);
56
- await fs.mkdir(localDir2);
57
- promises.push(fs.mkdir(localEmptyDir));
58
- localFiles.forEach((localFile)=>{
59
- promises.push(fs.writeFile(localFile, `${localFile}\n`));
60
- });
61
- return Promise.all(promises);
62
- }
63
-
64
- /**
65
- *
66
- */
67
- export async function clearLocalTestFiles() {
68
- return fs.remove(localRoot);
69
- }
70
-
71
- /**
72
- *
73
- * @param hostInfo
74
- */
75
- export async function createRemoteFiles(hostInfo) {
76
- //create remote files
77
- await sshExec(hostInfo, `mkdir -p ${remoteRoot}/hoge`);
78
- await sshExec(hostInfo, `mkdir -p ${remoteEmptyDir}`);
79
- const script = remoteFiles.reduce((a, remoteFile)=>{
80
- return `${a}echo ${remoteFile} > ${remoteFile};`;
81
- }, "");
82
- return sshExec(hostInfo, `${script}`);
83
- }
84
-
85
- /**
86
- *
87
- * @param hostInfo
88
- */
89
- export async function clearRemoteTestFiles(hostInfo) {
90
- return sshExec(hostInfo, `rm -fr ${remoteRoot}`);
91
- }
92
-
93
- export {
94
- localRoot,
95
- localEmptyDir,
96
- localFiles,
97
- nonExisting,
98
- remoteRoot,
99
- remoteEmptyDir,
100
- remoteFiles
101
- };
@@ -1 +0,0 @@
1
- echo this is test rcfile