Skip to content

Commit

Permalink
Merge pull request #240 from zowe/schema-updates
Browse files Browse the repository at this point in the history
Remove Hardcoded Schema References
  • Loading branch information
skurnevich authored Aug 30, 2024
2 parents 250f248 + c6a4ccd commit a8017a6
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 24 deletions.
31 changes: 7 additions & 24 deletions src/actions/InstallationHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@ import * as fs from 'fs';
import { ConfigurationStore } from '../storage/ConfigurationStore';
import { InstallationArgs } from '../types/stateInterfaces';
import { FALLBACK_SCHEMA, deepMerge } from '../renderer/components/common/Utils';


//AJV did not like the regex in our current schema
const zoweDatasetMemberRegexFixed = {
"description": "PARMLIB member used by ZIS",
"type": "string",
"pattern": "^([A-Z$#@]){1}([A-Z0-9$#@]){0,7}$",
"minLength": 1,
"maxLength": 8
}
import { updateSchemaReferences } from '../services/ResolveRef';

class Installation {

Expand Down Expand Up @@ -152,19 +143,11 @@ class Installation {
}

//No reason not to always set schema to latest if user is re-running installation
if(readPaxYamlAndSchema.details.yamlSchema && readPaxYamlAndSchema.details.serverCommon){
if(readPaxYamlAndSchema.details.schemas.yamlSchema){
try {
let yamlSchema = JSON.parse(readPaxYamlAndSchema.details.yamlSchema);
const serverCommon = JSON.parse(readPaxYamlAndSchema.details.serverCommon);
if(yamlSchema && serverCommon){
yamlSchema.additionalProperties = true;
yamlSchema.properties.zowe.properties.setup.properties.dataset.properties.parmlibMembers.properties.zis = zoweDatasetMemberRegexFixed;
yamlSchema.properties.zowe.properties.setup.properties.certificate.properties.pkcs12.properties.directory = serverCommon.$defs.path;
if(yamlSchema.$defs?.networkSettings?.properties?.server?.properties?.listenAddresses?.items){
delete yamlSchema.$defs?.networkSettings?.properties?.server?.properties?.listenAddresses?.items?.ref;
yamlSchema.$defs.networkSettings.properties.server.properties.listenAddresses.items = serverCommon.$defs.ipv4
}
// console.log('Setting schema from runtime dir:', JSON.stringify(yamlSchema));
let yamlSchema = JSON.parse(readPaxYamlAndSchema.details.schemas.yamlSchema);
updateSchemaReferences(readPaxYamlAndSchema.details.schemas, yamlSchema);
if(yamlSchema){
ConfigurationStore.setSchema(yamlSchema);
parsedSchema = true;
ProgressStore.set('downloadUnpax.getSchemas', true);
Expand Down Expand Up @@ -630,10 +613,10 @@ export class FTPInstallation extends Installation {
const yamlSchema = await new FileTransfer().download(connectionArgs, yamlSchemaPath, DataType.ASCII);
const serverCommonPath = `${installDir}/schemas/server-common.json`;
const serverCommon = await new FileTransfer().download(connectionArgs, serverCommonPath, DataType.ASCII);
return {status: true, details: {yaml, yamlSchema, serverCommon}};
return {status: true, details: {yaml, schemas: {yamlSchema, serverCommon}}};
} catch (e) {
console.log("Error downloading example-zowe.yaml and schemas:", e.message);
return {status: false, details: {yaml: '', yamlSchema: '', serverCommon: ''}}
return {status: false, details: {yaml: '', schemas: {yamlSchema: '', serverCommon: ''}}};
}
}

Expand Down
92 changes: 92 additions & 0 deletions src/services/ResolveRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
let mainSchema: any;
let schemaMap: { [key: string]: any } = {};

export const updateSchemaReferences = (schemas: { [key: string]: string }, schemaObject: any): void => {
schemaMap = parseSchemas(schemas);

// Traverse and resolve references in schemas other than zowe-yaml schema
Object.values(schemaMap).forEach((schema: any) => {
if(schema?.$id !== schemaObject?.$id) {
mainSchema = schema;
traverseAndResolveReferences(schema);
}
})

// Traverse and resolve references for the zowe-yaml schema
mainSchema = schemaObject;
traverseAndResolveReferences(schemaObject);
}

// Parses all schemas and populates the schemaMap
const parseSchemas = (schemas: { [key: string]: string }): { [key: string]: any } => {
const schemaMap: { [key: string]: any } = {};
Object.entries(schemas).forEach(([key, value]) => {
try {
const schemaObject = JSON.parse(value);
const id = schemaObject?.$id;
if (id) {
schemaMap[id] = schemaObject;
}
} catch (error: any) {
console.error(`Error parsing schema for key ${key}:`, error.message);
}
});
return schemaMap;
};

// Recursively traverse and resolve $ref references in the schema object
const traverseAndResolveReferences = (schemaObj: any) => {
if (schemaObj && typeof schemaObj === "object") {
Object.keys(schemaObj).forEach((key) => {
if (key === "$ref" && typeof schemaObj[key] === "string") {
try {
const refValue = resolveRef(schemaObj[key]);
Object.assign(schemaObj, refValue);
delete schemaObj['$ref'];
} catch(error){
console.error("Error resolving reference:", error.message);
}
} else {
traverseAndResolveReferences(schemaObj[key]);
}
})
}
}

// Resolve a $ref string to its referenced schema object
const resolveRef = (ref: string) => {
let [refPath, anchorPart] = ref.split('#');
const isRefPathEmpty = !refPath;

let refSchema = isRefPathEmpty
? mainSchema
: schemaMap[Object.keys(schemaMap).find((id) => id.endsWith(refPath))];

if (!refSchema) {
throw new Error(`Schema for reference path ${refPath} not found`);
}

if (!refSchema.$defs) {
throw new Error(`No $defs found in schema ${refSchema.$id}`);
}

const anchor = anchorPart?.split("/").pop();
const refObject = isRefPathEmpty
? refSchema.$defs[anchor]
: Object.values(refSchema.$defs).find((obj:any) => obj.$anchor === anchor);

if (!refObject) {
throw new Error(`Reference ${ref} not found in schemaObject ${refSchema.$id}`);
}

// Ensure pattern is a string and remove backslashes for ajv compatibility
if (refObject.pattern) {
const pattern = typeof refObject.pattern === 'string' ? refObject.pattern : String(refObject.pattern);

if (pattern.includes("\\")) {
refObject.pattern = pattern.replace(/\\/g, '');
}
}

return refObject;
}

0 comments on commit a8017a6

Please sign in to comment.