<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/*
 * Copyright (c) 2018, Joyent, Inc.
 */

//
// Depending on the end-point we're hitting, we have different load options:
//
// LIST /images || POST /machines: load only active images, we don't
// want any user creating a new machine with a disabled dataset.
//
// GET /images/:image_uuid || GET|POST /machines/:uuid: load by UUID
// we'll try to skip loading all the images when possible.
//
// LIST /machines => load Active and, additionally, load deactivated too, given
// a machine could have been provisioned in the past using an Image which has
// been deactivated since then


var p = console.log;
var assert = require('assert-plus');
var util = require('util');
var semver = require('semver');
var restify = require('restify'),
    MissingParameterError = restify.MissingParameterError,
    InvalidArgumentError = restify.InvalidArgumentError,
    ResourceNotFoundError = restify.ResourceNotFoundError;

var resources = require('./resources');
// --- Globals

var UUID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;


// --- Helpers

/**
 * Translate an IMGAPI client error into a cloudapi response error.
 */
function errFromImgapiErr(imgapiErr) {
    var err;
    switch (imgapiErr.body.code) {
    default:
        // TODO: eventually should change to wrapping all errors from imgapi
        err = imgapiErr;
        break;
    }
    return err;
}

/**
 * Translate an IMGAPI image object with an "error" field into an error object
 * that we want to expose on cloudapi image objects. Note that the IMGAPI image
 * "error.code" values are often the set of codes from `imgadm create` in
 * the platform.
 */
function errorObjFromImgapiImage(image) {
    var e = {};
    switch (image.error.code) {
    case 'PrepareImageDidNotRun':
        /* BEGIN JSSTYLED */
        /**
         * Example:
         *  {"code": "PrepareImageDidNotRun",
         *   "message": "prepare-image script did not indicate it was run (old guest tools in VM 96c7d71c-0c62-ed29-9ee3-b765f23066b4?)"}
         */
        /* END JSSTYLED */
        e.code = image.error.code;
        e.message = image.error.message;
        // JSSTYLED
        //TODO e.url += 'http://wiki.joyent.com/wiki/display/jpc2/Troubleshooting+Image+Creation#PrepareImageDidNotRun'
        break;
    case 'VmHasNoOrigin':
        /* BEGIN JSSTYLED */
        /**
         * Example:
         *  {"code": "VmHasNoOrigin",
         *   "message": "cannot create an incremental image: vm \"593c760c-24e1-437f-d92c-a3901105f047\" has no origin"}
         */
        /* END JSSTYLED */
        e.code = image.error.code;
        e.message = image.error.message;
        // JSSTYLED
        //TODO e.url += 'http://wiki.joyent.com/wiki/display/jpc2/Troubleshooting+Image+Creation#VmHasNoOrigin'
        break;
    case 'NotSupported':
        /* BEGIN JSSTYLED */
        /**
         * Example:
         *  {"code": "NotSupported",
         *   "message": "cannot create incremental image for VM 7cfc6e0d-36e1-69de-92de-990991badadd: incremental images of incremental images are not currently supported"}
         *   "message": "cannot create an incremental image: vm \"593c760c-24e1-437f-d92c-a3901105f047\" has no origin"}
         */
        /* END JSSTYLED */
        e.code = image.error.code;
        e.message = image.error.message;
        // JSSTYLED
        //TODO e.url += 'http://wiki.joyent.com/wiki/display/jpc2/Troubleshooting+Image+Creation#NotSupported'
        break;
    default:
        e.code = 'InternalError';
        e.message = 'an unexpected error occurred '
            + '(Contact support for assistance.)';
        break;
    }
    return e;
}


function translate(req, dataset) {
    assert.ok(req);
    assert.ok(dataset);

    var obj = {
        id: dataset.uuid,
        name: dataset.name,
        version: dataset.version,
        os: dataset.os,
        requirements: {}
    };

    if (dataset.type) {
        var ver = req.getVersion();

        if (semver.satisfies('8.0.0', ver) || semver.ltr('8.0.0', ver)) {
            obj.type = dataset.type;
        } else {
            obj.type = (dataset.type === 'zvol' ? 'virtualmachine'
                                                : 'smartmachine');
        }
    }

    if (dataset.description) {
        obj.description = dataset.description;
    }

    var objReqs = obj.requirements;
    var dsetReqs = dataset.requirements;
    if (dataset.requirements) {
        [
            ['max_memory', 'max_ram'],
            ['max_ram', 'max_ram'],
            ['min_memory', 'min_ram'],
            ['min_ram', 'min_ram'],
            ['brand', 'brand']
        ].forEach(function (mapping) {
            if (dsetReqs[mapping[1]]) {
                objReqs[mapping[0]] = dsetReqs[mapping[1]];
            }
        });
    }

    var fields = {
        tags: true,
        homepage: true,
        published_at: true
    };

    var v = req.getVersion();

    // Everything greater than or equal to 7.1.0 must have the following set of
    // properties:
    if (semver.satisfies('7.1.0', v) || semver.ltr('7.1.0', v)) {
        fields.owner = true;
        fields.public = true;
        fields.state = true;
        fields.eula = true;
        fields.acl = true;
        fields.origin = true;
        fields.error = true;
    }

    // can't add fields.files since we are whitelisting the file fields here<commit_msg>TRITON-784 Add requirements.bootrom to the list of allowed image fields in CloudAPI Reviewed by: <NAME> <<EMAIL>> Approved by: <NAME> <<EMAIL>><commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/*
 * Copyright (c) 2018, Joyent, Inc.
 */

//
// Depending on the end-point we're hitting, we have different load options:
//
// LIST /images || POST /machines: load only active images, we don't
// want any user creating a new machine with a disabled dataset.
//
// GET /images/:image_uuid || GET|POST /machines/:uuid: load by UUID
// we'll try to skip loading all the images when possible.
//
// LIST /machines => load Active and, additionally, load deactivated too, given
// a machine could have been provisioned in the past using an Image which has
// been deactivated since then


var p = console.log;
var assert = require('assert-plus');
var util = require('util');
var semver = require('semver');
var restify = require('restify'),
    MissingParameterError = restify.MissingParameterError,
    InvalidArgumentError = restify.InvalidArgumentError,
    ResourceNotFoundError = restify.ResourceNotFoundError;

var resources = require('./resources');
// --- Globals

var UUID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;


// --- Helpers

/**
 * Translate an IMGAPI client error into a cloudapi response error.
 */
function errFromImgapiErr(imgapiErr) {
    var err;
    switch (imgapiErr.body.code) {
    default:
        // TODO: eventually should change to wrapping all errors from imgapi
        err = imgapiErr;
        break;
    }
    return err;
}

/**
 * Translate an IMGAPI image object with an "error" field into an error object
 * that we want to expose on cloudapi image objects. Note that the IMGAPI image
 * "error.code" values are often the set of codes from `imgadm create` in
 * the platform.
 */
function errorObjFromImgapiImage(image) {
    var e = {};
    switch (image.error.code) {
    case 'PrepareImageDidNotRun':
        /* BEGIN JSSTYLED */
        /**
         * Example:
         *  {"code": "PrepareImageDidNotRun",
         *   "message": "prepare-image script did not indicate it was run (old guest tools in VM 96c7d71c-0c62-ed29-9ee3-b765f23066b4?)"}
         */
        /* END JSSTYLED */
        e.code = image.error.code;
        e.message = image.error.message;
        // JSSTYLED
        //TODO e.url += 'http://wiki.joyent.com/wiki/display/jpc2/Troubleshooting+Image+Creation#PrepareImageDidNotRun'
        break;
    case 'VmHasNoOrigin':
        /* BEGIN JSSTYLED */
        /**
         * Example:
         *  {"code": "VmHasNoOrigin",
         *   "message": "cannot create an incremental image: vm \"593c760c-24e1-437f-d92c-a3901105f047\" has no origin"}
         */
        /* END JSSTYLED */
        e.code = image.error.code;
        e.message = image.error.message;
        // JSSTYLED
        //TODO e.url += 'http://wiki.joyent.com/wiki/display/jpc2/Troubleshooting+Image+Creation#VmHasNoOrigin'
        break;
    case 'NotSupported':
        /* BEGIN JSSTYLED */
        /**
         * Example:
         *  {"code": "NotSupported",
         *   "message": "cannot create incremental image for VM 7cfc6e0d-36e1-69de-92de-990991badadd: incremental images of incremental images are not currently supported"}
         *   "message": "cannot create an incremental image: vm \"593c760c-24e1-437f-d92c-a3901105f047\" has no origin"}
         */
        /* END JSSTYLED */
        e.code = image.error.code;
        e.message = image.error.message;
        // JSSTYLED
        //TODO e.url += 'http://wiki.joyent.com/wiki/display/jpc2/Troubleshooting+Image+Creation#NotSupported'
        break;
    default:
        e.code = 'InternalError';
        e.message = 'an unexpected error occurred '
            + '(Contact support for assistance.)';
        break;
    }
    return e;
}


function translate(req, dataset) {
    assert.ok(req);
    assert.ok(dataset);

    var obj = {
        id: dataset.uuid,
        name: dataset.name,
        version: dataset.version,
        os: dataset.os,
        requirements: {}
    };

    if (dataset.type) {
        var ver = req.getVersion();

        if (semver.satisfies('8.0.0', ver) || semver.ltr('8.0.0', ver)) {
            obj.type = dataset.type;
        } else {
            obj.type = (dataset.type === 'zvol' ? 'virtualmachine'
                                                : 'smartmachine');
        }
    }

    if (dataset.description) {
        obj.description = dataset.description;
    }

    var objReqs = obj.requirements;
    var dsetReqs = dataset.requirements;
    if (dataset.requirements) {
        [
            ['max_memory', 'max_ram'],
            ['max_ram', 'max_ram'],
            ['min_memory', 'min_ram'],
            ['min_ram', 'min_ram'],
            ['brand', 'brand'],
            ['bootrom', 'bootrom']
        ].forEach(function (mapping) {
            if (dsetReqs[mapping[1]]) {
                objReqs[mapping[0]] = dsetReqs[mapping[1]];
            }
        });
    }

    var fields = {
        tags: true,
        homepage: true,
        published_at: true
    };

    var v = req.getVersion();

    // Everything greater than or equal to 7.1.0 must have the following set of
    // properties:
    if (semver.satisfies('7.1.0', v) || semver.ltr('7.1.0', v)) {
        fields.owner = true;
        fields.public = true;
        fields.state = true;
        fields.eula = true;
        fields.acl = true;
        fields.origin = true;
        fields.error = true;
    }

    // can't add fields.files since we are whitelisting the file fields here
{'fraction_non_alphanumeric': 0.13099209833187006, 'fraction_numerical': 0.02309043020193152, 'mean_word_length': 2.183622135271101, 'pattern_counts': {'":': 14, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6151126', 'n_tokens_mistral': 3720, 'n_tokens_neox': 3532, 'n_words': 956}