azure-bake
Version:
Azure cloud deployment platform for both infrasturcture as code and software
199 lines • 9.18 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BakePackage = void 0;
const YAML = require("js-yaml");
const fs = require("fs");
const path = require("path");
const core_1 = require("@azbake/core");
const azcli_npm_1 = require("azcli-npm");
class BakePackage {
constructor(source) {
this._env = {};
this._loadEnvironment();
this._config = {};
this._loadPackage(source);
}
get Environment() {
return this._env;
}
get Config() {
return this._config;
}
_loadEnvironment() {
//load environment variables || defaults into an interface
this._env.toolVersion = process.env.npm_package_version || "0.0.0";
this._env.environmentName = process.env.BAKE_ENV_NAME || "";
this._env.environmentCode = process.env.BAKE_ENV_CODE || "";
this._env.regions = JSON.parse(process.env.BAKE_ENV_REGIONS || "");
this._env.authentication = {};
this._env.authentication.subscriptionId = process.env.BAKE_AUTH_SUBSCRIPTION_ID || "";
this._env.authentication.tenantId = process.env.BAKE_AUTH_TENANT_ID || "";
this._env.authentication.serviceId = process.env.BAKE_AUTH_SERVICE_ID || "";
this._env.authentication.secretKey = process.env.BAKE_AUTH_SERVICE_KEY || "";
this._env.authentication.certPath = process.env.BAKE_AUTH_SERVICE_CERT || "";
this._env.authentication.skipAuth = (process.env.BAKE_AUTH_SKIP || 'false').toLocaleLowerCase() === 'true';
this._env.logLevel = process.env.BAKE_LOG_LEVEL || "info";
//clear out the auth info
process.env.BAKE_AUTH_SUBSCRIPTION_ID = process.env.BAKE_AUTH_SERVICE_ID =
process.env.BAKE_AUTH_SERVICE_KEY = process.env.BAKE_AUTH_SERVICE_CERT =
process.env.BAKE_AUTH_TENANT_ID = "";
//yaml parse out the global variables.
let content = "";
try {
let file = process.env.BAKE_VARIABLES || "";
if (file && fs.existsSync(file)) {
content = fs.readFileSync(file, 'utf8');
let obj = YAML.safeLoad(content);
this._env.variables = (0, core_1.objToVariableMap)(obj || []);
}
}
catch (e) {
let logger = new core_1.Logger([], this._env.logLevel); //build a logger with correct log level.
logger.debug(content);
logger.error("Failed to load global environment variables");
logger.error(e);
}
}
_validatePackage(config) {
if (!config.name)
throw new Error('config.name not defined');
if (!config.shortName)
throw new Error('config.shortName not defined');
if (!config.version)
throw new Error('config.version not defined');
}
objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
_loadPackage(source) {
let file = fs.readFileSync(source, 'utf8');
let config = {};
try {
config = YAML.load(file);
}
catch (e) {
let logger = new core_1.Logger();
logger.error("Failed to load bake file: " + source);
logger.error(e);
throw e;
}
//bind all ingredients
let logger = new core_1.Logger();
logger.log('Downloading ingredients...');
//make sure the cwd path has a node_modules folder, so that we install ingredients localy
let node_path = process.env['npm_ingredient_root'] || "";
if (!fs.existsSync(node_path)) {
fs.mkdirSync(node_path);
}
let ingredients = config.ingredients || new Array();
ingredients.forEach(ingredientsType => {
let cmd = "npm";
if (process.platform === "win32")
cmd = "npm.cmd";
//first check if any version of this package is already installed
let skipNpm = false;
let npmPackageName = "";
try {
let split = ingredientsType.split("@");
let ingPackage = '';
if (split.length > 2 && !ingPackage[0]) {
ingPackage = "@" + split[split.length - 2];
npmPackageName = split[split.length - 2];
npmPackageName = npmPackageName.replace("azbake/", "");
}
else {
ingPackage = split[0];
npmPackageName = ingPackage;
}
const packageDir = path.join(ingPackage, 'package.json');
let packageVersion = require(packageDir).version;
//making it this var means we could load the ingredient as a module.
//so skip install!
//NOTE: this could mean an older ingredient is installed then what is requested
//this is only a problem for non-container deployments, which is mostly testing usage
logger.log('- ' + ingredientsType + " [SKIPPED]");
skipNpm = true;
}
catch (e) {
}
if (!skipNpm) {
logger.log('- ' + ingredientsType);
var npm = new azcli_npm_1.ShellRunner(cmd).start();
npm.arg("install").arg(ingredientsType).arg("--legacy-peer-deps");
let er = npm.exec();
if (er.code != 0) {
console.log(er);
logger.error("failed to download ingredient: " + ingredientsType);
throw new Error();
}
}
});
ingredients.forEach(ingredientType => {
let firstIdx = ingredientType.indexOf("@");
let lastIdx = ingredientType.lastIndexOf("@");
if (lastIdx != firstIdx) {
//strip off @<ver>
ingredientType = ingredientType.substr(0, lastIdx);
}
core_1.IngredientManager.Register(ingredientType);
});
logger.log('Ingredients loaded');
//start with config vars based on env based vars
let vars = (0, core_1.objToVariableMap)(config.variables);
//merge config vars into the env vars (overwriting as needed)
config.variables = this._env.variables || new Map();
vars.forEach((v, n) => {
if (config.variables)
config.variables.set(n, v);
});
//fix up json objects to act as hashmaps.
config.parallelRegions = config.parallelRegions == undefined ? true : config.parallelRegions;
config.resourceGroup = config.resourceGroup == undefined ? true : config.resourceGroup;
//only set rgOverride as a BV if the field is already set
if (config.rgOverride) {
config.rgOverride = new core_1.BakeVariable(config.rgOverride);
}
config.recipe = this.objToStrMap(config.recipe);
config.recipe.forEach(ingredient => {
let source = ingredient.properties.source;
ingredient.properties.source = new core_1.BakeVariable(source || "");
ingredient.dependsOn = ingredient.dependsOn || [];
ingredient.properties = ingredient.properties || {};
let condition = ingredient.properties.condition;
ingredient.properties.condition = condition ? new core_1.BakeVariable(condition) : undefined;
ingredient.properties.parameters = (0, core_1.objToVariableMap)(ingredient.properties.parameters || {});
ingredient.properties.tokens = (0, core_1.objToVariableMap)(ingredient.properties.tokens || new Map());
ingredient.properties.alerts = (0, core_1.objToVariableMap)(ingredient.properties.alerts || new Map());
});
this._validatePackage(config);
this._config = config;
}
Authenticate(callback) {
return __awaiter(this, void 0, void 0, function* () {
try {
return yield callback(this._env.authentication);
}
finally {
//strip auth from the public accessor, except for sub id.
this._env.authentication = {
subscriptionId: this._env.authentication.subscriptionId
};
}
});
}
}
exports.BakePackage = BakePackage;
//# sourceMappingURL=bake-loader.js.map