sleeveforarm
Version:
Making Azure Easy
257 lines • 13 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs-extra");
const Path = require("path");
const ReplaceInFile = require("replace-in-file");
const Winston = require("winston");
const applicationInsights_1 = require("./applicationInsights");
// tslint:disable-next-line:max-line-length
const ApplicationInsightsInfrastructure = require("./applicationInsightsInfrastructure");
const CommonUtilities = require("./common-utilities");
const Data = require("./data");
const keyvault_1 = require("./keyvault");
const KeyVaultInfrastructure = require("./keyvaultInfrastructure");
const mysql_azure_1 = require("./mysql-azure");
const MySqlAzureInfrastructure = require("./mysql-azureInfrastructure");
const Resource = require("./resource");
const resourcegroup_1 = require("./resourcegroup");
const ResourceGroupInfrastructure = require("./resourcegroupInfrastructure");
const webapp_node_azure_1 = require("./webapp-node-azure");
// tslint:disable-next-line:max-line-length
const WebappNodeAzureInfrastructure = require("./webapp-node-azureInfrastructure");
function createInfraResource(resource, targetDirectoryPath) {
let infraResource = null;
if (CommonUtilities.isClass(resource, resourcegroup_1.default)) {
infraResource =
new ResourceGroupInfrastructure.ResourceGroupInfrastructure();
}
if (CommonUtilities.isClass(resource, keyvault_1.default)) {
infraResource = new KeyVaultInfrastructure.KeyVaultInfrastructure();
}
if (CommonUtilities.isClass(resource, webapp_node_azure_1.default)) {
infraResource =
new WebappNodeAzureInfrastructure.WebappNodeAzureInfrastructure();
}
if (CommonUtilities.isClass(resource, mysql_azure_1.default)) {
infraResource = new MySqlAzureInfrastructure.MySqlAzureInfrastructure();
}
if (CommonUtilities.isClass(resource, applicationInsights_1.default)) {
infraResource =
new ApplicationInsightsInfrastructure.ApplicationInsightsInfrastructure();
}
if (infraResource === null) {
throw new Error("Unrecognized resource type!");
}
infraResource.initialize(resource, targetDirectoryPath);
return infraResource;
}
function init(currentWorkingDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const assetPath = Path.join(__dirname, "..", "assets", "cliInit");
if (!(yield CommonUtilities.validateResource(Path.basename(process.cwd()), Data.data.ProjectNameLength))) {
throw new Error(`Project name should be less than \
${Data.data.ProjectNameLength} characters, contains only \
alphanumeric characters and start with a letter\n`);
}
yield fs.copy(assetPath, currentWorkingDirectory);
const aiInfrastructure = new ApplicationInsightsInfrastructure.ApplicationInsightsInfrastructure();
const aiSleevePath = Path.join(currentWorkingDirectory, "AppInsights");
yield aiInfrastructure
.initialize(null, aiSleevePath)
.setup();
const aiReplaceOptions = {
files: Path.join(aiSleevePath, "sleeve.js"),
from: /new applicationInsights\(\);/,
to: "new applicationInsights().setGlobalDefault(true);"
};
yield ReplaceInFile(aiReplaceOptions);
// NPM publish turns all .gitignore into .npmignore. For awhile it
// seemed that you could put in both a .gitignore and a .npmignore
// and the .gitignore would be ignored but no longer. So now we
// ship a .npmignore and then rename it after install.
yield fs.move(Path.join(currentWorkingDirectory, ".npmignore"), Path.join(currentWorkingDirectory, ".gitignore"));
const locations = yield CommonUtilities.azAppServiceListLocations();
const dataCenterEnum = locations[0].name.replace(/ /g, "");
const replaceInFileOptions = {
files: Path.join(currentWorkingDirectory, "sleeve.js"),
from: /XXXX/,
to: `DataCenterNames.${dataCenterEnum}`
};
yield ReplaceInFile(replaceInFileOptions);
yield CommonUtilities.npmSetup(currentWorkingDirectory);
yield CommonUtilities.executeOnSleeveResources(currentWorkingDirectory, (path) => {
return CommonUtilities.npmSetup(path);
});
if ((yield fs.pathExists(Path.join(currentWorkingDirectory, ".git")))
=== false) {
CommonUtilities.exec("git init", currentWorkingDirectory);
}
});
}
exports.init = init;
function setup(currentWorkingDirectory, serviceName, serviceType) {
return __awaiter(this, void 0, void 0, function* () {
const rootPath = yield CommonUtilities.findGitRootDir(currentWorkingDirectory);
const targetPath = Path.join(rootPath, serviceName);
let infraResource;
switch (serviceType) {
case Resource.ResourcesWeSupportSettingUp.MySqlAzure: {
infraResource = new MySqlAzureInfrastructure.MySqlAzureInfrastructure();
break;
}
case Resource.ResourcesWeSupportSettingUp.WebAppNode: {
infraResource =
new WebappNodeAzureInfrastructure.WebappNodeAzureInfrastructure();
break;
}
default: {
throw new Error(`Unsupported resource type ${serviceType}`);
}
}
infraResource.initialize(null, targetPath);
yield infraResource.setup();
return targetPath;
});
}
exports.setup = setup;
function hydrateEnvironment(currentWorkingDirectory, deploymentType) {
return __awaiter(this, void 0, void 0, function* () {
const resourcesInEnvironment = [];
const rootOfDeploymentPath = yield CommonUtilities.findGitRootDir(currentWorkingDirectory);
const rootSleevePath = Path.join(rootOfDeploymentPath, "sleeve.js");
if (!(fs.existsSync(rootSleevePath))) {
// tslint:disable-next-line:no-console
console.log("There is no sleeve.js in the root, \
this is not a properly configured project");
process.exit(-1);
}
yield CommonUtilities.npmSetup(rootOfDeploymentPath);
const rootResourceGroup = require(rootSleevePath);
// tslint:disable-next-line:max-line-length
const rootResourceGroupInfra = createInfraResource(rootResourceGroup, rootOfDeploymentPath);
yield rootResourceGroupInfra.hydrate(resourcesInEnvironment, deploymentType);
resourcesInEnvironment.push(rootResourceGroupInfra);
yield CommonUtilities.executeOnSleeveResources(rootOfDeploymentPath, (candidatePath) => __awaiter(this, void 0, void 0, function* () {
yield CommonUtilities.npmSetup(candidatePath);
const sleevePath = Path.join(candidatePath, "sleeve.js");
const resource = require(sleevePath);
const infraResource = createInfraResource(resource, candidatePath);
resourcesInEnvironment.push(yield infraResource.hydrate(resourcesInEnvironment, deploymentType));
}));
return resourcesInEnvironment;
});
}
// TODO: developmentDeploy is really just intended for Node WebAPPs so that
// we deploy code in Azure that will properly set up the environment
// to take a version of Sleeve from the local machine and not look to
// NPM. But we really need to shove this into some kind of property bag
// as the name and usage is confusing.
function deployResources(currentWorkingDirectory, deploymentType, developmentDeploy = false) {
return __awaiter(this, void 0, void 0, function* () {
const resourcesInEnvironment = yield hydrateEnvironment(currentWorkingDirectory, deploymentType);
if (resourcesInEnvironment.length === 0) {
// tslint:disable-next-line:no-console
console.log("There are no resources to deploy");
process.exit(-1);
}
const promisesToWaitFor = [];
for (const resource of resourcesInEnvironment) {
promisesToWaitFor.push(resource.deployResource(developmentDeploy));
}
yield Promise.all(promisesToWaitFor);
if (deploymentType === Resource.DeployType.Production) {
for (const resource of resourcesInEnvironment) {
if (resource instanceof
WebappNodeAzureInfrastructure.WebappNodeAzureInfrastructure) {
const baseDeployWebApp =
// tslint:disable-next-line:max-line-length
yield resource
.getBaseDeployClassInstance();
console.log(`Web app ${resource.baseName} is available at \
${yield baseDeployWebApp.getDeployedURL()}`);
}
}
}
return resourcesInEnvironment;
});
}
exports.deployResources = deployResources;
function getAppInsightsURL(aiName, resourceGroupName) {
return CommonUtilities.runAzCommand(`az resource show --name ${aiName} \
--resource-group ${resourceGroupName} \
--resource-type Microsoft.Insights/components`)
.then((result) => {
if (result && result.properties) {
return `https://ms.portal.azure.com/#resource/subscriptions/\
${result.properties.TenantId}/resourceGroups/${resourceGroupName}\
/providers/Microsoft.Insights/components/${aiName}/overview`;
}
return "";
});
}
function createEnvironmentToGetAiLocation(currentWorkingDirectory, deploymentType) {
return __awaiter(this, void 0, void 0, function* () {
const resourcesInEnvironment = yield hydrateEnvironment(currentWorkingDirectory, deploymentType);
const rootResourceGroupInfra = CommonUtilities
.findGlobalDefaultResourceByType(resourcesInEnvironment,
// tslint:disable-next-line:max-line-length
ResourceGroupInfrastructure.ResourceGroupInfrastructure);
const rootAiInfra = CommonUtilities
.findGlobalDefaultResourceByType(resourcesInEnvironment,
// tslint:disable-next-line:max-line-length
ApplicationInsightsInfrastructure.ApplicationInsightsInfrastructure);
return getAppInsightsURL(rootAiInfra.appInsightsFullName, rootResourceGroupInfra.resourceGroupName);
});
}
function getManageResourceData(currentWorkingDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const results = {};
results[Resource.DeployType.LocalDevelopment] =
yield createEnvironmentToGetAiLocation(currentWorkingDirectory, Resource.DeployType.LocalDevelopment);
results[Resource.DeployType.Production] =
yield createEnvironmentToGetAiLocation(currentWorkingDirectory, Resource.DeployType.Production);
return results;
});
}
exports.getManageResourceData = getManageResourceData;
function printManageResults(deployType, deployResult) {
const printPrefix = `${deployType} deployment:`;
if (deployResult === "") {
console.log(`${printPrefix} NO DEPLOYMENT`);
return;
}
console.log(`${printPrefix} ${deployResult}`);
}
function manageResource(currentWorkingDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const manageResults = yield getManageResourceData(currentWorkingDirectory);
const devDeployResults = manageResults[Resource.DeployType.LocalDevelopment];
const productionDeployResults = manageResults[Resource.DeployType.Production];
printManageResults(Resource.DeployType.LocalDevelopment, devDeployResults);
printManageResults(Resource.DeployType.Production, productionDeployResults);
});
}
exports.manageResource = manageResource;
function setLoggingIfNeeded(argv) {
if (argv.verbose) {
Winston.add(Winston.transports.File, {
filename: "log.txt",
level: "silly"
});
Winston.remove(Winston.transports.Console);
Winston.add(Winston.transports.Console, {
level: "silly",
stderrLevels: []
});
}
}
exports.setLoggingIfNeeded = setLoggingIfNeeded;
//# sourceMappingURL=cliUtilities.js.map