azure-bake
Version:
Azure cloud deployment platform for both infrasturcture as code and software
283 lines • 11.9 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 });
const azcli_npm_1 = require("azcli-npm");
const core_1 = require("@azbake/core");
const bake_loader_1 = require("./bake-loader");
const bake_runner_1 = require("./bake-runner");
const fs = require("fs");
const path = require("path");
const ps = require("process");
const os = require("os");
const minimist = require("minimist");
let bake_version = require('../package.json').version;
process.env['npm_package_version'] = bake_version;
//store the root path to bake so we can use it later with ingredient loading
let rootPath = path.join(__dirname, '../');
process.env['npm_root_path'] = rootPath;
let argv = minimist(process.argv.slice(2));
let cmd = "";
let target = "";
let args = {};
let tmpFile = path.join(os.tmpdir(), 'bake.env');
let runtimeVersion = "latest";
let recipeName = "";
function displayHelp() {
console.log('');
console.log('bake [command] [options] <image|file>');
console.log('commands:');
console.log('');
console.log('serve\t--- Serve a pre-built image recipe or local bake yaml config');
console.log('<image>\t\t: docker recipe image to download and deploy');
console.log('<file>\t\t: bake yaml file to deploy');
console.log('');
console.log('mix\t--- Mix a recipe into a docker image for publishing');
console.log('<file>\t\t: bake yaml file to mix into a recipe image. The entire parent folder will get copied into the image');
console.log('--runtime\t\t: which bake runtime to mix against (latest, v1.0.0, etc)');
console.log('--name\t\t: Name of the recipe image (docker tag)');
console.log('');
console.log('optional options for [serve]');
console.log('');
console.log('skip-auth\t\t: skip azure login for recipes that dont need it');
console.log('env-name\t\t: Full environment name for deployment');
console.log('env-code\t\t: 4 letter environment code (used for resource naming)');
console.log('regions\t\t\t: [{"name":"East US","code":"eus","shortName":"eastus"}]');
console.log('sub\t\t\t: Azure Subscription Id');
console.log('tenant\t\t\t: Azure AAD tenant for Service Principal authentication');
console.log('serviceid\t\t: Azure Service Principal Id');
console.log('key\t\t\t: Azure Service Principal secret key');
console.log('cert\t\t\t: Azure Service Principal PEM cert file (overrides secret key)');
console.log('variables\t\t: Path to local yaml file of key:value pairs for global variables');
console.log('loglevel\t\t\t: Log levels are debug, info, warn, and error (from most to least verbosity). Info is the default.');
console.log('');
console.log('optional environment variables (instead of above parameters):');
console.log('');
console.log('BAKE_ENV_NAME\t\t\t: Full environment name for deployment');
console.log('BAKE_ENV_CODE\t\t\t: 4 letter environment code (used for resource naming)');
console.log('BAKE_ENV_REGIONS\t\t: [{"name":"East US","code":"eus","shortName":"eastus"}]');
console.log('BAKE_AUTH_SKIP\t: skip azure login for recipes that dont need it');
console.log('BAKE_AUTH_SUBSCRIPTION_ID\t: Azure Subscription Id');
console.log('BAKE_AUTH_TENANT_ID\t\t: Azure AAD tenant for Service Principal authentication');
console.log('BAKE_AUTH_SERVICE_ID\t\t: Azure Service Principal Id');
console.log('BAKE_AUTH_SERVICE_KEY\t\t: Azure Service Principal secret key');
console.log('BAKE_AUTH_SERVICE_CERT\t\t: Azure Service Principal PEM cert file (overrides secret key)');
console.log('BAKE_VARIABLES\t\t\t: Path to local yaml file of key:value pairs for global variables');
console.log('BAKE_LOG_LEVEL\t\t\t: Log levels are debug, info, warn, and error (from most to least verbosity). Info is the default.');
console.log('');
canExecute = false;
}
function validateParams() {
let logger = new core_1.Logger();
if (argv._.findIndex(x => x == 'serve') >= 0) {
cmd = "serve";
}
else if (argv._.findIndex(x => x == 'mix') >= 0) {
cmd = "mix";
}
else {
displayHelp();
return;
}
if (argv._.indexOf('serve') >= 0)
argv._.splice(argv._.indexOf('serve'), 1);
if (argv._.indexOf('mix') >= 0)
argv._.splice(argv._.indexOf('mix'), 1);
if (argv._.length == 0) {
displayHelp();
return;
}
target = argv._[0];
if (cmd == "serve") {
args.skipAuth = argv['skip-auth'] || process.env.BAKE_AUTH_SKIP || "false";
args.envName = argv['env-name'] || process.env.BAKE_ENV_NAME || "default";
args.envCode = argv['env-code'] || process.env.BAKE_ENV_CODE || "de000";
args.envRegions = argv['regions'] || process.env.BAKE_ENV_REGIONS || '[{"name":"Global","code":"glob","shortName":"global"}]';
args.subId = argv['sub'] || process.env.BAKE_AUTH_SUBSCRIPTION_ID || "";
args.tenantId = argv['tenant'] || process.env.BAKE_AUTH_TENANT_ID || "";
args.serviceId = argv['serviceid'] || process.env.BAKE_AUTH_SERVICE_ID || "";
args.serviceKey = argv['key'] || process.env.BAKE_AUTH_SERVICE_KEY;
args.serviceCert = argv['cert'] || process.env.BAKE_AUTH_SERVICE_CERT;
args.variables = argv['variables'] || process.env.BAKE_VARIABLES;
args.logLevel = argv['loglevel'] || process.env.BAKE_LOG_LEVEL;
if (args.skipAuth.toLocaleLowerCase() === 'false' && (!args.envName ||
!args.envCode ||
!args.envRegions ||
!args.subId ||
!args.tenantId ||
!args.serviceId ||
(!args.serviceKey && !args.serviceCert))) {
displayHelp();
return;
}
process.env.BAKE_ENV_NAME = args.envName;
process.env.BAKE_ENV_CODE = args.envCode;
process.env.BAKE_ENV_REGIONS = args.envRegions;
process.env.BAKE_AUTH_SKIP = args.skipAuth;
process.env.BAKE_AUTH_SUBSCRIPTION_ID = args.subId;
process.env.BAKE_AUTH_TENANT_ID = args.tenantId;
process.env.BAKE_AUTH_SERVICE_ID = args.serviceId;
process.env.BAKE_AUTH_SERVICE_KEY = args.serviceKey || "";
process.env.BAKE_AUTH_SERVICE_CERT = args.serviceCert || "";
process.env.BAKE_VARIABLES = args.variables || "";
process.env.BAKE_LOG_LEVEL = args.logLevel || "";
if (fs.existsSync(target)) {
cmd = "run"; //will serve a local yaml config file
}
}
if (cmd == "mix") {
if (!argv.runtime) {
displayHelp();
return;
}
runtimeVersion = argv.runtime;
if (!argv.name) {
displayHelp();
return;
}
recipeName = argv.name;
if (!fs.existsSync(target)) {
displayHelp();
return;
}
}
}
function build() {
let cli = new azcli_npm_1.ShellRunner("docker");
//fixup to find our root folder to build a docker image against
let basePath = path.dirname(target);
if (basePath != ".") {
ps.chdir(basePath);
target = target.replace(basePath, '');
if (target[0] == "/")
target = target.substr(1);
}
let dockerIgnore = "node_modules";
fs.writeFileSync(".dockerignore", dockerIgnore);
let dockerImage = "FROM homecarehomebase/bake:" + runtimeVersion + "\r\n" +
"WORKDIR /app/bake/package\r\n" +
"COPY . .\r\n";
//rename target in container as "bake.yaml" for fixed file execution
dockerImage = dockerImage + "COPY " + target + " ./bake.yaml\r\n";
let dockerFile = "Dockerfile";
fs.writeFileSync(dockerFile, dockerImage);
console.log('Mixing...' + recipeName);
cli.start().arg('build').arg('--pull').arg("-t=" + recipeName).arg(".").execStream()
.then((code) => {
fs.unlinkSync(dockerFile);
fs.unlinkSync(".dockerignore");
if (code != 0) {
console.error('Failed to mix.');
}
else {
console.log('Mix Completed.');
}
process.exit(code);
})
.catch((e) => {
fs.unlinkSync(dockerFile);
fs.unlinkSync(".dockerignore");
console.error('Failed to mix');
console.error(e);
process.exit(15);
});
try {
}
catch (err) {
}
finally {
}
}
function run() {
return __awaiter(this, void 0, void 0, function* () {
let bakeFile = target;
//fix up the working folder to base at the bake file
let basePath = path.dirname(bakeFile);
if (basePath != ".") {
ps.chdir(basePath);
bakeFile = bakeFile.replace(basePath, '');
if (bakeFile[0] == "/")
bakeFile = bakeFile.substr(1);
}
//setup node require to support our ingredient location
let ingredientPath = path.join(basePath, 'node_modules');
process.env['npm_ingredient_root'] = ingredientPath;
let sep = ':';
if (process.platform === "win32") {
sep = ';';
}
process.env.NODE_PATH = path.join(rootPath, 'node_modules') + sep + ingredientPath;
require("module").Module._initPaths();
let regions = JSON.parse(process.env.BAKE_ENV_REGIONS || "");
var pkg = new bake_loader_1.BakePackage(bakeFile);
var runner = new bake_runner_1.BakeRunner(pkg);
try {
var result = yield runner.login();
if (result) {
yield runner.bake(regions);
return 0;
}
}
catch (err) {
console.log(err);
}
return 1;
});
}
function deploy() {
let cli = new azcli_npm_1.ShellRunner("docker");
fs.writeFileSync(tmpFile, `BAKE_ENV_NAME=${args.envName}\r\n` +
`BAKE_ENV_CODE=${args.envCode}\r\n` +
`BAKE_ENV_REGIONS=${args.envRegions}\r\n` +
`BAKE_AUTH_SKIP=${args.skipAuth}\r\n` +
`BAKE_AUTH_SUBSCRIPTION_ID=${args.subId}\r\n` +
`BAKE_AUTH_TENANT_ID=${args.tenantId}\r\n` +
`BAKE_AUTH_SERVICE_ID=${args.serviceId}\r\n` +
`BAKE_AUTH_SERVICE_KEY=${(args.serviceKey || "")}\r\n` +
`BAKE_AUTH_SERVICE_CERT=${(args.serviceCert || "")}\r\n` +
`BAKE_VARIABLES=/app/bake/.env\r\n` +
`BAKE_LOG_LEVEL=${(args.logLevel || "")}\r\n`);
try {
let runner = cli.arg('run').arg('--rm').arg('-t')
.arg('--env-file=' + tmpFile);
if (args.variables) {
runner = runner.arg(`-v=${args.variables}:/app/bake/.env`);
}
runner = runner.arg(target);
let p = runner.execStream();
p.then((r) => {
deleteEnvFile();
process.exit(r);
}).catch((r) => {
deleteEnvFile();
process.exit(15);
});
}
finally {
}
}
function deleteEnvFile() {
fs.unlinkSync(tmpFile);
}
console.log("Bake CLI v" + bake_version);
let canExecute = true;
validateParams();
if (canExecute) {
if (cmd == "mix")
build();
if (cmd == "serve")
deploy();
if (cmd == "run")
run().then(code => {
process.exit(code);
});
}
//# sourceMappingURL=index.js.map