Skip to content

Commit 0243b83

Browse files
committed
cmd overrides for ssh profile
Signed-off-by: Paul Cooper <[email protected]>
1 parent 6cf7acb commit 0243b83

File tree

7 files changed

+311
-52
lines changed

7 files changed

+311
-52
lines changed

__tests__/api/BundlePush/BundlePusher.test.ts

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ describe("BundlePusher01", () => {
112112
cmciSpy = jest.spyOn(cmci, "getResource").mockImplementation(() => ({ response: { records: {} } }));
113113
consoleText = "";
114114
zosmfProfile = { host: "wibble", user: "user", password: "thisIsntReal", port: 443, rejectUnauthorized: true };
115-
sshProfile = { host: "wibble", user: "user", password: "thisIsntReal" };
115+
sshProfile = { host: "wibble", user: "user", password: "thisIsntReal", port: 22 };
116116
cicsProfile = undefined;
117117
});
118118
afterEach(() => {
@@ -200,8 +200,6 @@ describe("BundlePusher01", () => {
200200
expect(zosMFSpy).toHaveBeenCalledTimes(1);
201201
});
202202
it("should implement --zosmf-* overrides" , async () => {
203-
zosmfProfile = { host: "wibble", user: "user" };
204-
sshProfile = { host: "wibble", user: "user" };
205203
const parms = getCommonParmsForPushTests();
206204
parms.arguments.zh = "overrideHost";
207205
parms.arguments.zp = 123;
@@ -258,74 +256,125 @@ describe("BundlePusher01", () => {
258256
expect(zosMFSpy).toHaveBeenCalledTimes(1);
259257
expect(sshSpy).toHaveBeenCalledTimes(1);
260258
});
259+
it("should implement --ssh-* overrides" , async () => {
260+
const parms = getCommonParmsForPushTests();
261+
parms.arguments.sh = "overrideHost";
262+
parms.arguments.sp = 500;
263+
parms.arguments.su = "overrideUser";
264+
parms.arguments.spw = "overridePassword";
265+
parms.arguments.spk = "overridePrivateKey";
266+
parms.arguments.skp = "overrideKeyPassphrase";
267+
parms.arguments.sht = 555;
268+
sshSpy.mockImplementationOnce((profile: IProfile) => {
269+
expect(profile.host).toMatch("overrideHost");
270+
expect(profile.port).toEqual(500);
271+
expect(profile.user).toMatch("overrideUser");
272+
expect(profile.password).toMatch("overridePassword");
273+
expect(profile.privateKey).toMatch("overridePrivateKey");
274+
expect(profile.keyPassphrase).toMatch("overrideKeyPassphrase");
275+
expect(profile.handshakeTimeout).toEqual(555);
276+
});
277+
278+
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
279+
"PUSH operation completed", parms);
280+
});
281+
it("should complain if ssh-host notset" , async () => {
282+
sshProfile = undefined;
283+
284+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
285+
"Required parameter --ssh-host is not set.");
286+
});
287+
it("should complain if ssh-port notset" , async () => {
288+
sshProfile = { host: "wibble" };
289+
290+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
291+
"Required parameter --ssh-port is not set.");
292+
});
293+
it("should complain if ssh-user notset" , async () => {
294+
sshProfile = { host: "wibble", port: 22 };
295+
296+
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
297+
"Required parameter --ssh-user is not set.");
298+
});
261299
it("should complain with mismatching zOSMF and SSH profile host names", async () => {
262-
sshProfile = { host: "wobble", user: "user" };
300+
const parms = getCommonParmsForPushTests();
301+
parms.arguments.zh = "wibble";
302+
parms.arguments.sh = "wobble";
263303

264304
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
265-
"PUSH operation completed");
266-
expect(consoleText).toContain("WARNING: ssh profile --host value 'wobble' does not match zosmf value 'wibble'.");
305+
"PUSH operation completed", parms);
306+
expect(consoleText).toContain("WARNING: --ssh-host value 'wobble' does not match --zosmf-host value 'wibble'.");
267307
});
268308
it("should not complain with matching zOSMF and SSH profile host names", async () => {
269-
sshProfile = { host: "wibble", user: "user" };
309+
const parms = getCommonParmsForPushTests();
310+
parms.arguments.zh = "wibble";
311+
parms.arguments.sh = "wibble";
270312

271313
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
272-
"PUSH operation completed");
273-
expect(consoleText).not.toContain("WARNING: ssh profile");
314+
"PUSH operation completed", parms);
315+
expect(consoleText).not.toContain("WARNING: --ssh-host");
274316
});
275317
it("should complain with mismatching zOSMF and CICS profile host names", async () => {
276318
cicsProfile = { host: "different", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
277319

278320
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
279321
"PUSH operation completed");
280-
expect(consoleText).toContain("WARNING: cics profile --host value 'different' does not match zosmf value 'wibble'.");
322+
expect(consoleText).toContain("WARNING: --cics-host value 'different' does not match --zosmf-host value 'wibble'.");
281323
});
282324
it("should not complain with matching zOSMF and CICS profile host names", async () => {
283325
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
284326

285327
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
286328
"PUSH operation completed");
287-
expect(consoleText).not.toContain("WARNING: cics profile");
329+
expect(consoleText).not.toContain("WARNING: --cics-host");
288330
});
289331
it("should complain with mismatching zOSMF and SSH profile user names", async () => {
290-
sshProfile = { host: "wibble", user: "joe" };
332+
const parms = getCommonParmsForPushTests();
333+
parms.arguments.zu = "fred";
334+
parms.arguments.su = "joe";
291335

292336
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
293-
"PUSH operation completed");
294-
expect(consoleText).toContain("WARNING: ssh profile --user value 'joe' does not match zosmf value 'user'.");
337+
"PUSH operation completed", parms);
338+
expect(consoleText).toContain("WARNING: --ssh-user value 'joe' does not match --zosmf-user value 'fred'.");
295339
});
296340
it("should not complain with matching zOSMF and SSH profile user names", async () => {
297-
sshProfile = { host: "wibble", user: "user" };
341+
const parms = getCommonParmsForPushTests();
342+
parms.arguments.zu = "fred";
343+
parms.arguments.su = "fred";
298344

299345
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
300-
"PUSH operation completed");
301-
expect(consoleText).not.toContain("WARNING: ssh profile");
346+
"PUSH operation completed", parms);
347+
expect(consoleText).not.toContain("WARNING: --ssh-user");
302348
});
303349
it("should not complain with matching zOSMF and SSH profile user names - case", async () => {
304-
sshProfile = { host: "wibble", user: "USER" };
350+
const parms = getCommonParmsForPushTests();
351+
parms.arguments.zu = "fred";
352+
parms.arguments.su = "FRED";
305353

306354
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
307-
"PUSH operation completed");
308-
expect(consoleText).not.toContain("WARNING: ssh profile");
355+
"PUSH operation completed", parms);
356+
expect(consoleText).not.toContain("WARNING: --ssh-user");
309357
});
310358
it("should complain with mismatching zOSMF and CICS profile user names", async () => {
311-
sshProfile = { host: "wibble", user: "fred" };
312359
cicsProfile = { host: "wibble", user: "joe", password: "thisIsntReal", cicsPlex: "12345678" };
313360

314361
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
315362
"PUSH operation completed");
316-
expect(consoleText).toContain("WARNING: cics profile --user value 'joe' does not match zosmf value 'user'.");
363+
expect(consoleText).toContain("WARNING: --cics-user value 'joe' does not match --zosmf-user value 'user'.");
317364
});
318365
it("should complain with mismatching zOSMF and SSH profile passwords", async () => {
319-
sshProfile = { host: "wibble", user: "user", password: "fakeSshPassword" };
366+
const parms = getCommonParmsForPushTests();
367+
parms.arguments.zpw = "fakeZosmfPassword";
368+
parms.arguments.spw = "fakeSshPassword";
320369

321370
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
322-
"Incompatible security credentials exist in the zosmf and ssh profiles.");
371+
"Incompatible security credentials exist in the zosmf and ssh configurations.", parms);
323372

324-
expect(consoleText).not.toContain("thisIsntReal");
373+
expect(consoleText).not.toContain("fakeZosmfPassword");
325374
expect(consoleText).not.toContain("fakeSshPassword");
326375
});
327376
it("should tolerate mismatching zOSMF and SSH credentials if SSH keys are used", async () => {
328-
sshProfile = { host: "wibble", user: "fred", privateKey: "fakeSshKey" };
377+
sshProfile = { host: "wibble", user: "fred", privateKey: "fakeSshKey", port: 22 };
329378

330379
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
331380
"PUSH operation completed");
@@ -337,18 +386,11 @@ describe("BundlePusher01", () => {
337386
cicsProfile = { host: "wibble", user: "user", password: "fakePassword2", cicsPlex: "12345678" };
338387

339388
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
340-
"Incompatible security credentials exist in the zosmf and cics profiles.");
389+
"Incompatible security credentials exist in the zosmf and cics configurations.");
341390

342391
expect(consoleText).not.toContain("thisIsntReal");
343392
expect(consoleText).not.toContain("fakePassword2");
344393
});
345-
it("should complain with mismatching cics-deploy and CICS plex names", async () => {
346-
cicsProfile = { host: "wibble", user: "fred", password: "thisIsntReal", cicsPlex: "wibble", regionName: "12345678" };
347-
348-
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
349-
"PUSH operation completed");
350-
expect(consoleText).toContain("WARNING: cics profile --cics-plex value 'wibble' does not match --cicsplex value '12345678'.");
351-
});
352394
it("should complain if remote bundle dir mkdir fails", async () => {
353395
createSpy.mockImplementationOnce(() => { throw new Error( "Injected Create error" ); });
354396
await runPushTestWithError("__tests__/__resources__/ExampleBundle01", false,
@@ -1600,5 +1642,12 @@ function getCommonParmsForPushTests(): IHandlerParameters {
16001642
parms.arguments.zpw = undefined;
16011643
parms.arguments.zru = undefined;
16021644
parms.arguments.zbp = undefined;
1645+
parms.arguments.sh = undefined;
1646+
parms.arguments.sp = undefined;
1647+
parms.arguments.su = undefined;
1648+
parms.arguments.spw = undefined;
1649+
parms.arguments.spk = undefined;
1650+
parms.arguments.skp = undefined;
1651+
parms.arguments.sht = undefined;
16031652
return parms;
16041653
}

docs/pages/cdp/CLIReadme.md

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,38 @@ Push a CICS bundle from the working directory to a target CICSplex\.
331331
prepend the base path to all z/OSMF resources when making REST requests\. Do not
332332
specify this option if you are not using an API mediation layer\.
333333

334-
#### Profile Options
334+
#### z/OS Ssh Connection Options
335335

336-
* `--ssh-profile` | `--ssh-p` *(string)*
336+
* `--ssh-host` | `--sh` *(string)*
337337

338-
* The name of a (ssh) profile to load for this command execution\.
338+
* The z/OS SSH server host name\.
339+
340+
* `--ssh-port` | `--sp` *(number)*
341+
342+
* The z/OS SSH server port\.
343+
344+
* `--ssh-user` | `--su` *(string)*
345+
346+
* Mainframe user name, which can be the same as your TSO login\.
347+
348+
* `--ssh-password` | `--spw` *(string)*
349+
350+
* Mainframe password, which can be the same as your TSO password\.
351+
352+
* `--ssh-private-key` | `--spk` *(string)*
353+
354+
* Path to a file containing your private key, that must match a public key stored
355+
in the server for authentication
356+
357+
* `--ssh-key-passphrase` | `--skp` *(string)*
358+
359+
* Private key passphrase, which unlocks the private key\.
360+
361+
* `--ssh-handshake-timeout` | `--sht` *(number)*
362+
363+
* How long in milliseconds to wait for the SSH handshake to complete\.
364+
365+
#### Profile Options
339366

340367
* `--cics-deploy-profile` | `--cics-deploy-p` *(string)*
341368

@@ -345,6 +372,10 @@ Push a CICS bundle from the working directory to a target CICSplex\.
345372

346373
* The name of a (zosmf) profile to load for this command execution\.
347374

375+
* `--ssh-profile` | `--ssh-p` *(string)*
376+
377+
* The name of a (ssh) profile to load for this command execution\.
378+
348379
* `--cics-profile` | `--cics-p` *(string)*
349380

350381
* The name of a (cics) profile to load for this command execution\.

src/api/BundlePush/BundlePusher.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { BundleDeployer } from "../BundleDeploy/BundleDeployer";
1818
import { Bundle } from "../BundleContent/Bundle";
1919
import { SubtaskWithStatus } from "./SubtaskWithStatus";
2020
import { ZosmfConfig } from "./ZosmfConfig";
21+
import { SshConfig } from "./SshConfig";
2122

2223

2324
/**
@@ -78,6 +79,7 @@ export class BundlePusher {
7879
const sshProfile = this.getProfile("ssh", true);
7980
const cicsProfile = this.getProfile("cics", false);
8081
ZosmfConfig.mergeProfile(zosMFProfile, this.params);
82+
SshConfig.mergeProfile(sshProfile, this.params);
8183
this.validateProfiles(zosMFProfile, sshProfile, cicsProfile);
8284

8385
// Create a zOSMF session
@@ -214,13 +216,13 @@ export class BundlePusher {
214216
let sameHostAndUser = true;
215217
if (zosmfProfile.host !== sshProfile.host) {
216218
sameHostAndUser = false;
217-
this.issueWarning("ssh profile --host value '" + sshProfile.host + "' does not match zosmf value '" + zosmfProfile.host + "'.");
219+
this.issueWarning("--ssh-host value '" + sshProfile.host + "' does not match --zosmf-host value '" + zosmfProfile.host + "'.");
218220
}
219221

220222
// Do the required profiles share the same user name?
221223
if (zosmfProfile.user.toUpperCase() !== sshProfile.user.toUpperCase()) {
222224
sameHostAndUser = false;
223-
this.issueWarning("ssh profile --user value '" + sshProfile.user + "' does not match zosmf value '" + zosmfProfile.user + "'.");
225+
this.issueWarning("--ssh-user value '" + sshProfile.user + "' does not match --zosmf-user value '" + zosmfProfile.user + "'.");
224226
}
225227

226228
// If the zoSMF user and host are the same then validate that the passwords are the same too.
@@ -229,7 +231,7 @@ export class BundlePusher {
229231
if (sameHostAndUser) {
230232
if (sshProfile.password !== undefined) {
231233
if (zosmfProfile.password !== sshProfile.password) {
232-
throw new Error("Incompatible security credentials exist in the zosmf and ssh profiles.");
234+
throw new Error("Incompatible security credentials exist in the zosmf and ssh configurations.");
233235
}
234236
}
235237
}
@@ -239,24 +241,18 @@ export class BundlePusher {
239241
sameHostAndUser = true;
240242
if (zosmfProfile.host !== cicsProfile.host) {
241243
sameHostAndUser = false;
242-
this.issueWarning("cics profile --host value '" + cicsProfile.host + "' does not match zosmf value '" + zosmfProfile.host + "'.");
244+
this.issueWarning("--cics-host value '" + cicsProfile.host + "' does not match --zosmf-host value '" + zosmfProfile.host + "'.");
243245
}
244246
if (zosmfProfile.user.toUpperCase() !== cicsProfile.user.toUpperCase()) {
245247
sameHostAndUser = false;
246-
this.issueWarning("cics profile --user value '" + cicsProfile.user + "' does not match zosmf value '" + zosmfProfile.user + "'.");
248+
this.issueWarning("--cics-user value '" + cicsProfile.user + "' does not match --zosmf-user value '" + zosmfProfile.user + "'.");
247249
}
248250

249251
if (sameHostAndUser) {
250252
if (zosmfProfile.password !== cicsProfile.password) {
251-
throw new Error("Incompatible security credentials exist in the zosmf and cics profiles.");
253+
throw new Error("Incompatible security credentials exist in the zosmf and cics configurations.");
252254
}
253255
}
254-
255-
// Do the cics-plexes match?
256-
if (cicsProfile.cicsPlex !== undefined && this.params.arguments.cicsplex !== cicsProfile.cicsPlex) {
257-
this.issueWarning("cics profile --cics-plex value '" + cicsProfile.cicsPlex +
258-
"' does not match --cicsplex value '" + this.params.arguments.cicsplex + "'.");
259-
}
260256
}
261257
}
262258

0 commit comments

Comments
 (0)