Skip to content

Commit 6d76f1a

Browse files
Merge pull request #201 from pcoop/branch1
Better detection of Node.js content in bundle
2 parents b0213e9 + f2212d7 commit 6d76f1a

File tree

4 files changed

+154
-59
lines changed

4 files changed

+154
-59
lines changed

__tests__/api/BundlePush/BundlePusher.test.ts

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ describe("BundlePusher01", () => {
114114
lstatSpy = jest.spyOn(fs, "lstatSync").mockImplementation(() => ( IS_NOT_DIRECTORY ));
115115
cmciSpy = jest.spyOn(cmci, "getResource").mockImplementation(() => ({ response: { records: {} } }));
116116
consoleText = "";
117-
zosmfProfile = {};
118-
sshProfile = {};
117+
zosmfProfile = { host: "testhost", user: "testuser" };
118+
sshProfile = { host: "testhost", user: "testuser" };
119119
cicsProfile = undefined;
120120
});
121121
afterEach(() => {
@@ -210,29 +210,27 @@ describe("BundlePusher01", () => {
210210
expect(sshSpy).toHaveBeenCalledTimes(1);
211211
});
212212
it("should complain with mismatching zOSMF and SSH profile host names", async () => {
213-
zosmfProfile = { host: "wibble" };
214-
sshProfile = { host: "wobble" };
213+
zosmfProfile = { host: "wibble", user: "user" };
214+
sshProfile = { host: "wobble", user: "user" };
215215

216216
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
217217
"PUSH operation completed.");
218218
expect(consoleText).toContain("WARNING: ssh profile --host value 'wobble' does not match zosmf value 'wibble'.");
219219
});
220220
it("should not complain with matching zOSMF and SSH profile host names", async () => {
221-
zosmfProfile = { host: "wibble" };
222-
sshProfile = { host: "wibble" };
221+
zosmfProfile = { host: "wibble", user: "user" };
222+
sshProfile = { host: "wibble", user: "user" };
223223

224224
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
225225
"PUSH operation completed.");
226226
expect(consoleText).not.toContain("WARNING: ssh profile");
227227
});
228228
it("should complain with mismatching zOSMF and CICS profile host names", async () => {
229-
zosmfProfile = { host: "wibble" };
230-
sshProfile = { host: "wibble" };
231-
cicsProfile = { host: "wobble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
229+
cicsProfile = { host: "wibble", user: "testuser", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
232230

233231
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
234232
"PUSH operation completed.");
235-
expect(consoleText).toContain("WARNING: cics profile --host value 'wobble' does not match zosmf value 'wibble'.");
233+
expect(consoleText).toContain("WARNING: cics profile --host value 'wibble' does not match zosmf value 'testhost'.");
236234
});
237235
it("should not complain with matching zOSMF and CICS profile host names", async () => {
238236
zosmfProfile = { host: "wibble", user: "user" };
@@ -259,6 +257,14 @@ describe("BundlePusher01", () => {
259257
"PUSH operation completed.");
260258
expect(consoleText).not.toContain("WARNING: ssh profile");
261259
});
260+
it("should not complain with matching zOSMF and SSH profile user names - case", async () => {
261+
zosmfProfile = { host: "wibble", user: "fred" };
262+
sshProfile = { host: "wibble", user: "FRED" };
263+
264+
await runPushTest("__tests__/__resources__/ExampleBundle01", true,
265+
"PUSH operation completed.");
266+
expect(consoleText).not.toContain("WARNING: ssh profile");
267+
});
262268
it("should complain with mismatching zOSMF and CICS profile user names", async () => {
263269
zosmfProfile = { host: "wibble", user: "fred" };
264270
sshProfile = { host: "wibble", user: "fred" };
@@ -1043,6 +1049,13 @@ describe("BundlePusher01", () => {
10431049
zosmfProfile = { host: "wibble", user: "user" };
10441050
sshProfile = { host: "wibble", user: "user" };
10451051
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678" };
1052+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1053+
if (data.indexOf("cics.xml") > -1) {
1054+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1055+
"<define name=\"test\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/WIBBLE\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1056+
"</manifest>";
1057+
}
1058+
});
10461059
cmciSpy.mockImplementation((cicsSession: any, regionData: cmci.IResourceParms) => {
10471060
if (regionData.name === "CICSRegion") {
10481061
return { response: {
@@ -1112,7 +1125,14 @@ describe("BundlePusher01", () => {
11121125
sshProfile = { host: "wibble", user: "user" };
11131126
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal" };
11141127
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
1115-
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2055I http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP"}] );
1128+
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2055I"}] );
1129+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1130+
if (data.indexOf("cics.xml") > -1) {
1131+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1132+
"<define name=\"test\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1133+
"</manifest>";
1134+
}
1135+
});
11161136
cmciSpy.mockImplementation((cicsSession: any, regionData: cmci.IResourceParms) => {
11171137
if (regionData.name === "CICSRegion") {
11181138
return { response: {
@@ -1186,7 +1206,14 @@ describe("BundlePusher01", () => {
11861206
sshProfile = { host: "wibble", user: "user" };
11871207
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
11881208
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
1189-
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP"}] );
1209+
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I"}] );
1210+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1211+
if (data.indexOf("cics.xml") > -1) {
1212+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1213+
"<define name=\"test\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1214+
"</manifest>";
1215+
}
1216+
});
11901217
cmciSpy.mockImplementation((cicsSession: any, nodejsData: cmci.IResourceParms) => {
11911218
if (nodejsData.name === "CICSNodejsapp") {
11921219
throw new Error("Injected CMCI GET error");
@@ -1226,7 +1253,14 @@ describe("BundlePusher01", () => {
12261253
sshProfile = { host: "wibble", user: "user" };
12271254
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
12281255
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
1229-
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP"}] );
1256+
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I"}] );
1257+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1258+
if (data.indexOf("cics.xml") > -1) {
1259+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1260+
"<define name=\"test\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1261+
"</manifest>";
1262+
}
1263+
});
12301264
cmciSpy.mockImplementation((cicsSession: any, nodejsData: cmci.IResourceParms) => {
12311265
if (nodejsData.name === "CICSNodejsapp") {
12321266
return {};
@@ -1266,7 +1300,14 @@ describe("BundlePusher01", () => {
12661300
sshProfile = { host: "wibble", user: "user" };
12671301
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
12681302
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
1269-
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP"}] );
1303+
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I"}] );
1304+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1305+
if (data.indexOf("cics.xml") > -1) {
1306+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1307+
"<define name=\"name\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1308+
"</manifest>";
1309+
}
1310+
});
12701311
cmciSpy.mockImplementation((cicsSession: any, nodejsData: cmci.IResourceParms) => {
12711312
if (nodejsData.name === "CICSNodejsapp") {
12721313
return { response: {
@@ -1318,7 +1359,14 @@ describe("BundlePusher01", () => {
13181359
sshProfile = { host: "wibble", user: "user" };
13191360
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
13201361
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
1321-
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP"}] );
1362+
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I"}] );
1363+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1364+
if (data.indexOf("cics.xml") > -1) {
1365+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1366+
"<define name=\"name\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1367+
"</manifest>";
1368+
}
1369+
});
13221370
cmciSpy.mockImplementation((cicsSession: any, nodejsData: cmci.IResourceParms) => {
13231371
if (nodejsData.name === "CICSNodejsapp") {
13241372
return { response: {
@@ -1370,7 +1418,15 @@ describe("BundlePusher01", () => {
13701418
sshProfile = { host: "wibble", user: "user" };
13711419
cicsProfile = { host: "wibble", user: "user", password: "thisIsntReal", cicsPlex: "12345678", regionName: "12345678" };
13721420
submitSpy = jest.spyOn(SubmitJobs, "submitJclString").mockImplementation(() =>
1373-
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP"}] );
1421+
[{ddName: "SYSTSPRT", stepName: "DFHDPLOY", data: "DFHRL2012I"}] );
1422+
readSpy = jest.spyOn(fs, "readFileSync").mockImplementation((data: string) => {
1423+
if (data.indexOf("cics.xml") > -1) {
1424+
return "<manifest xmlns=\"http://www.ibm.com/xmlns/prod/cics/bundle\">" +
1425+
"<define name=\"name\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1426+
"<define name=\"name2\" type=\"http://www.ibm.com/xmlns/prod/cics/bundle/NODEJSAPP\" path=\"nodejsapps/test.nodejsapp\"></define>" +
1427+
"</manifest>";
1428+
}
1429+
});
13741430
cmciSpy.mockImplementation((cicsSession: any, nodejsData: cmci.IResourceParms) => {
13751431
if (nodejsData.name === "CICSNodejsapp") {
13761432
return { response: {

src/api/BundleContent/Bundle.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ node_modules -
126126
return true;
127127
}
128128

129+
/**
130+
* Determines whether the Bundle contains any resources of the specified type
131+
* @param {string} resource - The resource to query
132+
* @returns {boolean}
133+
* @throws ImperativeError
134+
* @memberof Bundle
135+
*/
136+
public containsDefinitionsOfType(resourceType: string): boolean {
137+
return this.manifest.containsDefinitionsOfType(resourceType);
138+
}
139+
129140
/**
130141
* Returns the Bundle's identity (id) value.
131142
* @returns {string}

src/api/BundleContent/Manifest.ts

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -316,18 +316,8 @@ export class Manifest {
316316

317317
const definition = bundlePart.getPartData();
318318

319-
// Create the array of definitions if it doesn't already exist
320-
if (this.manifestAsJson.manifest.define === undefined) {
321-
this.manifestAsJson.manifest.define = [];
322-
}
323-
324-
// If what already exists is an object (as may happen when appending
325-
// to an existing XML manifest with only one entry) convert it to an array;
326-
if (Array.isArray(this.manifestAsJson.manifest.define) === false) {
327-
const obj = this.manifestAsJson.manifest.define as any;
328-
this.manifestAsJson.manifest.define = [];
329-
this.manifestAsJson.manifest.define.push(obj as IBundlePartDataType);
330-
}
319+
// Ensure that the definitions array is usable
320+
this.prepareDefinitionsArray();
331321

332322
// Search the array for a definition with the same name and
333323
// type as the one we're trying to add, if found then update
@@ -347,6 +337,47 @@ export class Manifest {
347337
this.manifestAsJson.manifest.define.push(definition);
348338
}
349339

340+
/**
341+
* Does the bundle contain any resource definitions of the
342+
* specified type?
343+
*
344+
* @param {String} resourceType - the resource type
345+
* @throws ImperativeError
346+
* @memberof Manifest
347+
*/
348+
public containsDefinitionsOfType(resourceType: string): boolean {
349+
350+
// Ensure that the definitions array is usable
351+
this.prepareDefinitionsArray();
352+
353+
// Search the array for a definition with the nominated type
354+
let i: number;
355+
for (i = 0; i < this.manifestAsJson.manifest.define.length; i++) {
356+
const candidate = this.manifestAsJson.manifest.define[i];
357+
if (candidate.type === resourceType) {
358+
return true;
359+
}
360+
}
361+
362+
return false;
363+
}
364+
365+
366+
private prepareDefinitionsArray() {
367+
// Create the array of definitions if it doesn't already exist
368+
if (this.manifestAsJson.manifest.define === undefined) {
369+
this.manifestAsJson.manifest.define = [];
370+
}
371+
372+
// If what already exists is an object (as may happen when appending
373+
// to an existing XML manifest with only one entry) convert it to an array;
374+
if (Array.isArray(this.manifestAsJson.manifest.define) === false) {
375+
const obj = this.manifestAsJson.manifest.define as any;
376+
this.manifestAsJson.manifest.define = [];
377+
this.manifestAsJson.manifest.define.push(obj as IBundlePartDataType);
378+
}
379+
}
380+
350381
// Read an existing manifest file into an object
351382
private readManifest() {
352383
// read the manifest from the file system

0 commit comments

Comments
 (0)