403Webshell
Server IP : 34.87.99.72  /  Your IP : 216.73.217.31
Web Server : Apache/2.4.46 (Unix) OpenSSL/1.1.1n
System : Linux zlock-bitnami-lamp-prod-v2-vm 4.19.0-16-cloud-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64
User : bitnami ( 1000)
PHP Version : 7.4.18
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : OFF
Directory :  /opt/bitnami/nami/node_modules/provisioner/lib/tools/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/bitnami/nami/node_modules/provisioner/lib/tools/definitions_handler.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const nami_wrapper_1 = require("../nami_wrapper");
const YAML = require("js-yaml");
const released_nami_module_1 = require("./released_nami_module");
const app_catalogue_helper_1 = require("./app_catalogue_helper");
const s3_helper_1 = require("./s3_helper");
// input for the generic definitions
const definitionsDirectory = `${__dirname}/../../definitions`;
// path where version-specific definitions are stored
exports.definitionsS3Path = "s3://bitnami-autobuild-ondemand/multi-tier-definitions";
/**
 * Class for managing generic definitions and creating version-specific definitions based on generic
 * definition as input and modules.json file
 */
class DefinitionsHandler {
    constructor(application, version) {
        this.application = application;
        this.version = version;
        this.metadataDir = null;
    }
    /**
     * Set version property based on latest version already stored as version-specific definition
     */
    setVersionFromLatestStored() {
        this.version = this.readStoredDefinitionVersion();
    }
    /**
     * Set version property based on latest version released - i.e. from modules.json or
     * based on on artifact version
     */
    setVersionFromLatestReleased() {
        this.version = this.releasedNamiModule.version;
    }
    /**
     * Path to system where the version-specific definition should be stored for current application and version
     */
    get localDefinitionPath() {
        return `${this._getUpdatedDefinitionsPath()}/${this.application}-${this.version}.yml`;
    }
    /**
     * Write version-specific definition to local folder
     * @param contents contents of the definition, as string
     */
    writeLocalDefinition(contents) {
        console.log(`Writing definition to local path: ${this.localDefinitionPath}`);
        nami_wrapper_1.file.write(this.localDefinitionPath, contents);
    }
    /**
     * Path to S3 where the version-specific definition is stored for current application and version
     */
    get storedDefinitionPath() {
        return `${exports.definitionsS3Path}/${this.application}/${this.version}.yml`;
    }
    /**
     * Path to S3 where the latest version number is stored for current application
     */
    get storedDefinitionVersionPath() {
        return `${exports.definitionsS3Path}/${this.application}/latest`;
    }
    /**
     * Retrieve version-specific definition from S3 and return it
     */
    readStoredDefinition() {
        return s3_helper_1.readS3File(this.storedDefinitionPath);
    }
    /**
     * Path to S3 where the latest stored definition is stored
     */
    get latestStoredDefinition() {
        const latestVersion = s3_helper_1.readS3File(this.storedDefinitionVersionPath);
        return `${exports.definitionsS3Path}/${this.application}/${latestVersion}.yml`;
    }
    /**
     * Retrieve latest definition from S3 and return it
     */
    readLatestStoredDefinition() {
        return s3_helper_1.readS3File(this.latestStoredDefinition);
    }
    /**
     * Write version-specific definition to S3
     * @param contents contents of the definition, as string
     */
    writeStoredDefinition(contents) {
        console.log(`Writing definition to s3: ${this.storedDefinitionPath}`);
        s3_helper_1.writeS3File(this.storedDefinitionPath, contents);
    }
    /**
     * Retrieve version of version-specific definition from S3 and return it
     */
    readStoredDefinitionVersion() {
        return s3_helper_1.readS3File(this.storedDefinitionVersionPath).trim();
    }
    /**
     * Write currently set version as version of version-specific definition to S3
     */
    writeStoredDefinitionVersion() {
        s3_helper_1.writeS3File(this.storedDefinitionVersionPath, this.version);
    }
    /**
     * Create or return ReleasedNamiModule object that can be used to handle modules.json
     * metadata and/or retrieval of version from artifact
     */
    get releasedNamiModule() {
        if (!this._releasedNamiModule) {
            this._releasedNamiModule = new released_nami_module_1.ReleasedNamiModule(this.application, this.version);
        }
        return this._releasedNamiModule;
    }
    /**
     * Check whether the stored version-specific definition differs from a given definition
     * @param data to compare
     */
    doesStoredDefinitionDiffersFrom(data) {
        let oldData;
        // try to download current version of the definition, but do not fail as it may not exist yet
        try {
            console.log(`Reading stored definition: ${this.latestStoredDefinition}`);
            oldData = this.readLatestStoredDefinition();
        }
        catch (e) {
            console.log(`Unable to read stored definition: ${e.message}`);
        }
        return (oldData !== data);
    }
    /**
     * Enhances the definition with version info, taken from this.version or latest
     * released if any
     */
    getVersionSpecificDefinition() {
        let newDefinition;
        let newData;
        // if the version was not specified, assume latest released version
        if (!this.version) {
            this.setVersionFromLatestReleased();
        }
        // create cu
        newDefinition = this.createVersionSpecificDefinition();
        newData = convertToYaml(newDefinition);
        // attempt to determine version from current version-specific definition, as it may be there
        if (!this.version) {
            this.version = newDefinition.details.version;
            console.log("Missing version, fallback to new definition version");
            console.log(`Version: ${this.version}`);
        }
        // make sure version is set - otherwise throw an error as it is needed to continue
        if (!this.version) {
            throw new Error(`Unable to determine version for ${this.application}`);
        }
        return newData;
    }
    /**
     * Create version-specific definition based on generic definition and version information
     * retrieved by ReleasedNamiModule object
     */
    createVersionSpecificDefinition() {
        let data = this._readRawDefinition();
        console.log("RAW definition:");
        console.log(`---\n${JSON.stringify(data)}\n---\n`);
        data = this._updateVersionsFromVesionMap(data);
        console.log("RAW definition (versions feed):");
        console.log(`---\n${JSON.stringify(data)}\n---\n`);
        data = this._addLocalSystemPackages(data);
        console.log("RAW definition (local system packages feed):");
        console.log(`---\n${JSON.stringify(data)}\n---\n`);
        return data;
    }
    /**
     * Provide a map of all clouds and topologies supported
     * @result a
     */
    getTopologiesForClouds() {
        let result = {};
        let standardTopologies = [];
        const data = this._readRawDefinition();
        if (data.supportedTopologies) {
            for (let cloud of Object.keys(data.supportedTopologies)) {
                const topologies = standardTopologies.concat(data.supportedTopologies[cloud]);
                result[cloud] = [...new Set(topologies)]; // remove duplicated values
            }
        }
        return result;
    }
    /**
     * Retrieve the supported platforms for this definition
     */
    getSupportedPlatforms() {
        const data = this._readRawDefinition();
        return data.supportedPlatforms || [];
    }
    _updateVersionsFromVesionMap(data) {
        // map of all versions from module metadata to apply
        let versionMap = this.releasedNamiModule.getAllNamiModuleVersionMap();
        console.log("Components version map (initial):");
        console.log(`---\n${JSON.stringify(versionMap, null, 2)}\n---`);
        this._releasedNamiModule = new released_nami_module_1.ReleasedNamiModule(this.application, this.version);
        // main module that is used in the definition, helpful for determining version
        const mainModuleName = data.details.mainModule || data.details.key;
        // list of modules known to be present in the original nami module definition ; if
        // ReleasedNamiModule did not return version map, assume it should be only the main module
        const knownModuleNames = versionMap ? Object.keys(versionMap) : [mainModuleName];
        // list of all modules that are used in definition
        let usedModules = [];
        if (!versionMap) {
            // if there is no nami module metadata, assume the version map only consists of main module ;
            versionMap = {};
            // get any versions hardcoded in the generic definition
            this._retrieveVersionsDefinedInTiers(versionMap, data);
            // in case this definition has no equivalent nami module (i.e. LAMP/MEAN), determine version
            // from version of main module, as the version was not retrieved from anywhere else
            this.version = this.version || versionMap[mainModuleName];
            versionMap[mainModuleName] = this.version;
        }
        else {
            // if versions were rertieved, apply additional versions hardcoded in the generic definition
            this._retrieveVersionsDefinedInTiers(versionMap, data);
            console.log("Components version map (tier hardcoded versions feed):");
            console.log(`---\n${JSON.stringify(versionMap, null, 2)}\n---`);
        }
        // get all versions from others modules
        let definedModules = this._retrieveModulesDefinedInTiers(data);
        definedModules.forEach((m) => {
            const moduleMetadata = new released_nami_module_1.ReleasedNamiModule(m);
            const moduleVersionMap = moduleMetadata.getAllNamiModuleVersionMap();
            Object.keys(moduleVersionMap || {}).forEach((module) => {
                versionMap[module] = versionMap[module] ? versionMap[module] : moduleVersionMap[module];
            });
        });
        console.log("Components version map (tier released components feed):");
        console.log(`---\n${JSON.stringify(versionMap, null, 2)}\n---`);
        // set version of the definition
        data.details.version = this.version;
        // for each tier, apply versions fom versionMap to each nami module installed
        console.log("Updating versions in tiers data:");
        for (let tier of Object.keys(data.tiers)) {
            console.log(` ==> ${tier}`);
            data.tiers[tier] = this._applyVersionsToTier(data.tiers[tier], versionMap, usedModules);
            console.log(`---\n${JSON.stringify(data.tiers[tier])}\n---`);
        }
        // check there are no new modules in released nami module metadata that
        // are not used in multi-tier definition - we should fail in this case to
        // ensure it is added to the definition
        for (let moduleName of knownModuleNames) {
            if (usedModules.indexOf(moduleName) < 0) {
                throw new Error(`Module ${moduleName} is not used in definition`);
            }
        }
        return data;
    }
    _addLocalSystemPackages(data) {
        const packageList = this.releasedNamiModule.getLocalSystemPackages();
        // The dependencies above are hardcoded in the definition
        data.dependencies = data.dependencies || {};
        // Merge if needed
        if (data.dependencies.systemPackages) {
            Object.keys(data.dependencies.systemPackages || {}).forEach((distro) => {
                let systemPackages = data.dependencies.systemPackages[distro] || [];
                console.log(` => Adding system packages for ${distro}: ${JSON.stringify(systemPackages, null, 2)}`);
                if (packageList[distro]) {
                    packageList[distro] = systemPackages.concat(packageList[distro]).sort();
                    // Remove duplicated
                    packageList[distro] = packageList[distro].filter((pkg, index, list) => list.indexOf(pkg, index + 1) < 0);
                }
                else {
                    packageList[distro] = systemPackages;
                }
            });
            data.dependencies.systemPackages = packageList;
        }
        return data;
    }
    _applyVersionsToTier(data, versionMap, usedModules) {
        if (data.modules) {
            for (let moduleInfo of data.modules) {
                // keep a list of all modules that were used in this definition, allows ensuring
                // the definition uses all modules that are in the released nami module metadata
                if (usedModules.indexOf(moduleInfo.name) < 0) {
                    usedModules.push(moduleInfo.name);
                }
                moduleInfo.version = versionMap[moduleInfo.name];
                // ensure all modules have known versions, fail otherwise
                if (!moduleInfo.version) {
                    throw new Error(`Unable to determine version for ${moduleInfo.name} for tier`);
                }
            }
        }
        return data;
    }
    /**
     * Get any hardcoded versions from the generic definition - in some cases the definition
     * includes additional modules that are not considered part of the release
     * (i.e. jenkins-swarm or in cases like LAMP/MEAN where there is no modules JSON)
     */
    _retrieveVersionsDefinedInTiers(versionMap, data) {
        // list of all modules already handled by this method
        let modulesHandled = [];
        for (let tier of Object.keys(data.tiers || {})) {
            const tierData = data.tiers[tier];
            for (let moduleInfo of tierData.modules) {
                if (moduleInfo.version) {
                    if (versionMap[moduleInfo.name]) {
                        // if module has version set, but was not yet processed by this method, fail as the
                        // version was set from released nami module metadata - and in this case it
                        // should not be in the generic definition
                        if (modulesHandled.indexOf(moduleInfo.name) < 0) {
                            throw new Error(`Module ${moduleInfo.name} version in definition and released data`);
                        }
                        // fail if versions are set differently across definition
                        if (moduleInfo.version !== versionMap[moduleInfo.name]) {
                            throw new Error(`Module ${moduleInfo.name} version mismatch`);
                        }
                    }
                    // set the version accordingly and store the module was already processed
                    versionMap[moduleInfo.name] = moduleInfo.version;
                    modulesHandled.push(moduleInfo.name);
                }
            }
        }
    }
    /**
     * Get all modules from the generic definition
     */
    _retrieveModulesDefinedInTiers(data) {
        // list of all modules already handled by this method
        let modulesHandled = [];
        for (let tier of Object.keys(data.tiers || {})) {
            const tierData = data.tiers[tier];
            tierData.modules.forEach((m) => {
                let moduleName = m.name;
                if (modulesHandled.indexOf(moduleName) === -1) {
                    modulesHandled.push(moduleName);
                }
            });
        }
        return modulesHandled;
    }
    _getUpdatedDefinitionsPath() {
        return `definitions/updated`;
    }
    _getDefinitionsPath() {
        return `definitions`;
    }
    _readRawDefinition() {
        if (!this.rawDefinition) {
            const rawDefinitionPath = `${this._getDefinitionsPath()}/${this.application}.yml`;
            this.rawDefinition = YAML.safeLoad(nami_wrapper_1.file.read(rawDefinitionPath));
        }
        return this.rawDefinition;
    }
    getRawDefinition() {
        return this._readRawDefinition();
    }
}
exports.DefinitionsHandler = DefinitionsHandler;
function convertToYaml(data) {
    let yaml = YAML.dump(data);
    // ensure YAML begins with "---" so it can be properly parsed
    if (yaml.substring(0, 3) !== "---") {
        yaml = `---\n${yaml}`;
    }
    return yaml;
}
/**
 * List all defined applications by checking the definitions folder for .yml files
 */
function listDefinedApplications() {
    let applications = [];
    console.log(`Getting definitions from ${definitionsDirectory} folder...`);
    for (let name of nami_wrapper_1.file.glob(`${definitionsDirectory}/*.yml`)) {
        let nameList = nami_wrapper_1.file.split(name);
        let app = nameList[nameList.length - 1].replace(/\.yml$/, "");
        applications.push(app);
        console.log(` => ${app}`);
    }
    return applications;
}
/**
 * List all definitions and versions and write them to file or stdout
 */
function listAllDefinitionVersions(outputFile) {
    const s3 = nami_wrapper_1.s3cs();
    let applications = listDefinedApplications();
    const filelist = s3.list(exports.definitionsS3Path, { recursive: true });
    let versionsForApp = {};
    let result = [];
    // map all files in S3 definitions storage that match /:app/:version.yml pattern
    // and store them in the versionsForApp map
    for (let filename of filelist) {
        let match = filename.match(/^.*\/(.*?)\/(.*?)\.yml$/);
        if (match) {
            const fileApp = match[1];
            const fileVersion = match[2];
            versionsForApp[fileApp] = versionsForApp[fileApp] || [];
            versionsForApp[fileApp].push(fileVersion);
        }
    }
    for (let application of applications) {
        // perform for applications that are a valid application at this time and have versions in S3
        if (versionsForApp[application]) {
            let versions = versionsForApp[application];
            let handler = new DefinitionsHandler(application);
            // try to sort versions using version-utils package if it is available
            try {
                versions = versions.sort((v1, v2) => {
                    return require("version-utils").compareVersions(v2, v1);
                });
            }
            catch (e) {
                console.log(`Unable to order versions from latest to oldest: ${e.message}`);
            }
            const supportedPlatforms = handler
                .getSupportedPlatforms()
                .map(o => o.bitnamiPlatforms)
                .reduce((acum, cur) => acum.concat(cur), []);
            // push the list in the format required by CI to the output list
            result.push({
                name: application,
                versions: versions,
                topologies: handler.getTopologiesForClouds(),
                supportedPlatforms: supportedPlatforms,
                latest: handler.readStoredDefinitionVersion()
            });
        }
    }
    // write list to file
    if (outputFile) {
        nami_wrapper_1.file.write(outputFile, JSON.stringify(result, null, 2));
    }
}
exports.listAllDefinitionVersions = listAllDefinitionVersions;
/**
 * Get a full definition for a given application
 * It uses app-catalogue as metadata source
 */
function getFullDefinition(application, metadataDir) {
    const versionsList = {};
    const dh = new DefinitionsHandler(application);
    const def = dh.getRawDefinition();
    const dependencies = def.dependencies || {};
    const packagesList = dependencies.systemPackages || {};
    // Default supported platforms
    const supportedPlatforms = def.supportedPlatforms;
    for (let t of Object.keys(def.tiers)) {
        const tierModules = [];
        for (let sp of supportedPlatforms) {
            packagesList[sp.distro] = packagesList[sp.distro] || [];
            for (let mo of def.tiers[t].modules) {
                const ach = new app_catalogue_helper_1.AppCatalogueHelper(mo.name, metadataDir, sp.os, sp.distro, sp.arch, mo.branch, mo.version);
                // Currently, we use the same definition for all distributions and tiers. Therefore, we can
                // only set a version per module. If a definition supports vmware (centos-7) we are using
                // the debian-10 version. `versionsList` will store only the versions of the first round of modules (debian-10)
                if (!versionsList[mo.name]) {
                    console.log(` * Updating ${mo.name} version: (${ach.branch} ~> ${ach.version})`);
                    versionsList[mo.name] = ach.version;
                }
                // Store the list of modules dependencies
                packagesList[sp.distro] = packagesList[sp.distro].concat(ach.systemPackages);
                // Update modules information (version)
                if (tierModules.filter(m => m.name === mo.name).length === 0) {
                    // NOTE (jdrios) As we are storing only the versions of the debian-10 modules, this prevent the loop
                    // from using the versions of a different distro
                    mo.version = versionsList[mo.name];
                    tierModules.push(mo);
                }
            }
        }
        // Update app main version
        def.details.version = versionsList[def.details.mainModule];
        // Update tier modules
        def.tiers[t].modules = tierModules;
    }
    // Update definition requirements
    for (let sp of supportedPlatforms) {
        // Sort
        const pkgs = packagesList[sp.distro].sort();
        // Remove duplicates
        packagesList[sp.distro] = pkgs.filter((pkg, pos) => { return pkgs.indexOf(pkg) === pos; });
        console.log(` * Updating dependencies for ${sp.distro}:`);
        if (packagesList[sp.distro].length > 0) {
            console.log(`    - ${packagesList[sp.distro].join("\n    - ")}`);
        }
    }
    def.dependencies = { systemPackages: packagesList };
    return def;
}
exports.getFullDefinition = getFullDefinition;
/**
 * Get full definitions and upload them to S3
 */
function updateFullDefinitions(applications, metadataDir, force, upload) {
    let failures = [];
    if (!applications) {
        applications = listDefinedApplications();
    }
    for (let application of applications) {
        console.log(`\n === Updating ${application} ===`);
        try {
            const dh = new DefinitionsHandler(application);
            const def = getFullDefinition(application, metadataDir);
            dh.version = def.details.version;
            const data = convertToYaml(def);
            // Always write local definition
            dh.writeLocalDefinition(data);
            // Check whether the current latest definition differs from the one being calculated
            const hasChanged = dh.doesStoredDefinitionDiffersFrom(data);
            // if it has changed or the force parameter was set, write the definition and update version
            if (hasChanged || force) {
                console.log(`The new definition for ${application} differs from the latest stored definition!`);
                if (upload) {
                    console.log(`Writing definition for ${application} ${dh.version}: ${dh.storedDefinitionPath}`);
                    dh.writeStoredDefinition(data);
                    console.log(`Updating latest file for ${application} ${dh.version}: ${dh.storedDefinitionVersionPath}`);
                    dh.writeStoredDefinitionVersion();
                }
            }
            else {
                console.log(`The new definition for ${application} does not differ from`, `the remote definition at ${dh.storedDefinitionPath}!`);
            }
        }
        catch (e) {
            console.log(`Unable to update ${application}: ${e.message}\n`, e.stack);
            failures.push(application);
        }
    }
    if (failures.length > 0) {
        throw new Error(`Unable to udpate definitions for: ${failures.join(", ")}`);
    }
}
exports.updateFullDefinitions = updateFullDefinitions;
/**
 * Create and/or update latest definitions of all or some applications in the S3 storage
 */
function updateDefinitions(applications, force, upload) {
    let failures = [];
    if (!applications) {
        applications = listDefinedApplications();
    }
    for (let application of applications) {
        console.log(`\n === Updating ${application} ===`);
        try {
            const dh = new DefinitionsHandler(application);
            const definition = dh.getVersionSpecificDefinition();
            const hasChanged = dh.doesStoredDefinitionDiffersFrom(definition);
            // Always write local definition
            dh.writeLocalDefinition(definition);
            // if it has changed or the force parameter was set, write the definition and update version
            if (hasChanged && upload) {
                console.log(`Writing definition for ${application} ${dh.version}:`, `${hasChanged ? "has changed" : "unchanged, but forced"}`);
                dh.writeStoredDefinition(definition);
                dh.writeStoredDefinitionVersion();
            }
            else {
                console.log(`Not uploading definition for ${application} ${dh.version}: no changes`);
            }
        }
        catch (e) {
            console.log(`Unable to update ${application}: ${e.message}\n`, e.stack);
            failures.push(application);
        }
    }
    if (failures.length > 0) {
        throw new Error(`Unable to udpate definitions for: ${failures.join(", ")}`);
    }
}
exports.updateDefinitions = updateDefinitions;
/**
 * If version is specified, use it ; otherwise get latest stored definition version
 * stored on S3 and return it
 * @param application Application key
 * @param version Optional version to use
 * @return The version to use
 */
function getApplicationVersion(application, version) {
    if (!version) {
        let handler = new DefinitionsHandler(application, version);
        version = handler.readStoredDefinitionVersion();
    }
    return version;
}
exports.getApplicationVersion = getApplicationVersion;
/**
 * Download version-specific definition and store it in a temporary file
 * @param application Application for which to download the version-specific definition
 * @param version Version for which to download the version-specific definition
 * @return path to temporary file with the definition
 */
function downloadStoredDefinition(application, version) {
    let handler = new DefinitionsHandler(application, getApplicationVersion(application, version));
    const tempDir = nami_wrapper_1.os.createTempDir();
    const tempFile = `${tempDir}/${handler.application}/${handler.version}.yml`;
    nami_wrapper_1.file.write(tempFile, handler.readStoredDefinition());
    return tempFile;
}
exports.downloadStoredDefinition = downloadStoredDefinition;

Youez - 2016 - github.com/yon3zu
LinuXploit