botserver/packages/azuredeployer.gbapp/services/AzureDeployerService.ts

913 lines
27 KiB
TypeScript
Raw Normal View History

/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
2018-11-11 19:09:18 -02:00
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
2018-11-11 19:09:18 -02:00
/**
* @fileoverview General Bots server core.
*/
'use strict';
import { CognitiveServicesManagementClient } from 'azure-arm-cognitiveservices';
import { CognitiveServicesAccount } from 'azure-arm-cognitiveservices/lib/models';
import {
ResourceManagementClient,
SubscriptionClient
} from 'azure-arm-resource';
import { SearchManagementClient } from 'azure-arm-search';
import { SqlManagementClient } from 'azure-arm-sql';
import { WebSiteManagementClient } from 'azure-arm-website';
import { AppServicePlan } from 'azure-arm-website/lib/models';
import { GBService, IGBInstance } from 'botlib';
import { HttpMethods, ServiceClient, WebResource } from 'ms-rest-js';
import { GBDeployer } from 'packages/core.gbapp/services/GBDeployer';
import * as simplegit from 'simple-git/promise';
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService';
import { GBCorePackage } from '../../../packages/core.gbapp';
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService';
const Spinner = require('cli-spinner').Spinner;
const scanf = require('scanf');
const git = simplegit();
const logger = require('../../../src/logger');
const UrlJoin = require('url-join');
const iconUrl =
'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png';
const publicIp = require('public-ip');
2018-10-15 21:03:17 -03:00
export class AzureDeployerService extends GBService {
public static apiVersion = '2017-12-01';
public instance: IGBInstance;
public resourceClient: ResourceManagementClient.ResourceManagementClient;
public webSiteClient: WebSiteManagementClient;
public storageClient: SqlManagementClient;
public cognitiveClient: CognitiveServicesManagementClient;
public searchClient: SearchManagementClient;
public provider = 'Microsoft.BotService';
public subscriptionClient: SubscriptionClient.SubscriptionClient;
public accessToken: string;
public location: string;
public subscriptionId: string;
public farmName: any;
public deployer: GBDeployer;
constructor(deployer: GBDeployer) {
2018-11-04 17:26:29 -02:00
super();
this.deployer = deployer;
}
public static async getSubscriptions(credentials) {
const subscriptionClient = new SubscriptionClient.default(credentials);
return subscriptionClient.subscriptions.list();
}
public static getKBSearchSchema(indexName) {
return {
name: indexName,
fields: [
{
name: 'questionId',
type: 'Edm.String',
searchable: false,
filterable: false,
retrievable: true,
sortable: false,
facetable: false,
key: true
},
{
name: 'subject1',
type: 'Edm.String',
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: 'subject2',
type: 'Edm.String',
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: 'subject3',
type: 'Edm.String',
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: 'subject4',
type: 'Edm.String',
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: 'content',
type: 'Edm.String',
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: 'answerId',
type: 'Edm.Int32',
searchable: false,
filterable: false,
retrievable: true,
sortable: false,
facetable: false,
key: false
},
{
name: 'instanceId',
type: 'Edm.Int32',
searchable: false,
filterable: true,
retrievable: true,
sortable: false,
facetable: false,
key: false
},
{
name: 'packageId',
type: 'Edm.Int32',
searchable: false,
filterable: true,
retrievable: true,
sortable: false,
facetable: false,
key: false
}
],
scoringProfiles: [],
defaultScoringProfile: null,
corsOptions: null
};
}
2018-10-25 18:13:51 -03:00
public async deployFarm(proxyAddress: string): Promise<IGBInstance> {
const culture = 'en-us';
2018-10-25 18:13:51 -03:00
// Tries do get information from .env file otherwise asks in command-line.
2018-10-25 18:13:51 -03:00
let instance: IGBInstance = {};
instance = await this.ensureConfiguration(instance);
instance.marketplacePassword = GBAdminService.getRndPassword();
2018-10-25 18:13:51 -03:00
const spinner = new Spinner('%s');
2018-10-24 12:06:47 -03:00
spinner.start();
spinner.setSpinnerString('|/-\\');
2018-10-15 21:03:17 -03:00
let keys: any;
const name = instance.botId;
2018-10-15 21:03:17 -03:00
2018-10-25 18:13:51 -03:00
logger.info(`Deploying Deploy Group (It may take a few minutes)...`);
await this.createDeployGroup(name, instance.cloudLocation);
2018-10-15 21:03:17 -03:00
logger.info(`Deploying Bot Server...`);
const serverFarm = await this.createHostingPlan(
name,
`${name}-server-plan`,
2018-10-25 18:13:51 -03:00
instance.cloudLocation
);
await this.createServer(
serverFarm.id,
name,
`${name}-server`,
instance.cloudLocation
);
2018-10-17 19:57:22 -03:00
logger.info(`Deploying Bot Storage...`);
const administratorLogin = `sa${GBAdminService.getRndReadableIdentifier()}`;
const administratorPassword = GBAdminService.getRndPassword();
const storageServer = `${name}-storage-server`;
const storageName = `${name}-storage`;
await this.createStorageServer(
name,
2018-10-25 18:13:51 -03:00
storageServer,
administratorLogin,
administratorPassword,
2018-10-25 18:13:51 -03:00
storageServer,
instance.cloudLocation
);
await this.createStorage(
name,
2018-10-25 18:13:51 -03:00
storageServer,
storageName,
instance.cloudLocation
);
instance.storageUsername = administratorLogin;
instance.storagePassword = administratorPassword;
2018-10-25 18:13:51 -03:00
instance.storageName = storageName;
instance.storageDialect = 'mssql';
2018-10-25 18:13:51 -03:00
instance.storageServer = storageServer;
2018-10-15 21:03:17 -03:00
logger.info(`Deploying Search...`);
const searchName = `${name}-search`;
2018-10-25 18:13:51 -03:00
await this.createSearch(name, searchName, instance.cloudLocation);
const searchKeys = await this.searchClient.adminKeys.get(
name,
searchName
);
2018-10-15 21:03:17 -03:00
instance.searchHost = `${searchName}.search.windows.net`;
instance.searchIndex = 'azuresql-index';
instance.searchIndexer = 'azuresql-indexer';
2018-11-04 17:26:29 -02:00
instance.searchKey = searchKeys.primaryKey;
this.deployer.rebuildIndex(instance);
2018-10-15 21:03:17 -03:00
logger.info(`Deploying Speech...`);
const speech = await this.createSpeech(
2018-10-25 18:13:51 -03:00
name,
`${name}-speech`,
instance.cloudLocation
);
keys = await this.cognitiveClient.accounts.listKeys(name, speech.name);
instance.speechKeyEndpoint = speech.endpoint;
instance.speechKey = keys.key1;
2018-10-15 21:03:17 -03:00
logger.info(`Deploying SpellChecker...`);
const spellChecker = await this.createSpellChecker(
name,
`${name}-spellchecker`,
2018-10-25 18:13:51 -03:00
instance.cloudLocation
);
keys = await this.cognitiveClient.accounts.listKeys(
name,
spellChecker.name
);
instance.spellCheckerKey = keys.key1;
instance.spellCheckerEndpoint = spellChecker.endpoint;
2018-10-15 21:03:17 -03:00
logger.info(`Deploying Text Analytics...`);
const textAnalytics = await this.createTextAnalytics(
name,
`${name}-textanalytics`,
2018-10-25 18:13:51 -03:00
instance.cloudLocation
);
keys = await this.cognitiveClient.accounts.listKeys(
name,
textAnalytics.name
);
instance.textAnalyticsEndpoint = textAnalytics.endpoint;
instance.textAnalyticsKey = keys.key1;
2018-10-25 18:13:51 -03:00
logger.info(`Deploying NLP...`);
const nlp = await this.createNLP(name, `${name}-nlp`, instance.cloudLocation);
2018-10-25 18:13:51 -03:00
keys = await this.cognitiveClient.accounts.listKeys(name, nlp.name);
const nlpAppId = await this.createLUISApp(
2018-10-25 18:13:51 -03:00
name,
name,
instance.cloudLocation,
culture,
instance.nlpAuthoringKey
);
2018-10-25 18:13:51 -03:00
instance.nlpEndpoint = nlp.endpoint;
instance.nlpKey = keys.key1;
instance.nlpAppId = nlpAppId;
2018-10-24 12:06:47 -03:00
logger.info(`Deploying Bot...`);
instance = await this.deployBootBot(
instance,
name,
`${proxyAddress}/api/messages/${name}`,
instance.nlpAppId,
instance.nlpKey,
instance.cloudSubscriptionId
2018-10-24 12:06:47 -03:00
);
spinner.stop();
2018-10-25 18:13:51 -03:00
return instance;
}
public async openStorageFirewall(groupName, serverName) {
const username = GBConfigService.get('CLOUD_USERNAME');
const password = GBConfigService.get('CLOUD_PASSWORD');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
2018-10-25 18:13:51 -03:00
const credentials = await GBAdminService.getADALCredentialsFromUsername(
2018-10-25 18:13:51 -03:00
username,
password
);
const storageClient = new SqlManagementClient(credentials, subscriptionId);
2018-10-25 18:13:51 -03:00
const ip = await publicIp.v4();
const params = {
2018-10-25 18:13:51 -03:00
startIpAddress: ip,
endIpAddress: ip
};
await storageClient.firewallRules.createOrUpdate(
groupName,
serverName,
'gb',
2018-10-25 18:13:51 -03:00
params
);
}
public async deployBootBot(
instance,
botId,
endpoint,
nlpAppId,
nlpKey,
subscriptionId
) {
let appId = GBConfigService.get('MARKETPLACE_ID');
let appPassword = GBConfigService.get('MARKETPLACE_SECRET');
if (!appId || !appPassword) {
process.stdout.write(
'Sorry, this part cannot be automated yet due to Microsoft schedule, please go to https://apps.dev.microsoft.com/portal/register-app to generate manually an App ID and App Secret.\n'
);
}
const retriveAppId = () => {
if (!appId) {
process.stdout.write('Generated Application Id (MARKETPLACE_ID):');
appId = scanf('%s').replace(/(\n|\r)+$/, '');
}
};
const retriveAppPassword = () => {
if (!appPassword) {
process.stdout.write('Generated Password (MARKETPLACE_SECRET):');
appPassword = scanf('%s').replace(/(\n|\r)+$/, '');
}
};
retriveAppId();
retriveAppPassword();
await this.internalDeployBot(
instance,
this.accessToken,
botId,
botId,
botId,
'General BootBot',
endpoint,
'global',
nlpAppId,
nlpKey,
appId,
appPassword,
subscriptionId
);
instance.marketplaceId = appId;
instance.marketplacePassword = appPassword;
instance.botId = botId;
return instance;
}
public async updateBotProxy(botId, group, endpoint) {
const baseUrl = `https://management.azure.com/`;
const username = GBConfigService.get('CLOUD_USERNAME');
const password = GBConfigService.get('CLOUD_PASSWORD');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
const accessToken = await GBAdminService.getADALTokenFromUsername(
username,
password
);
const httpClient = new ServiceClient();
const parameters = {
properties: {
endpoint: endpoint
}
};
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`;
const url = UrlJoin(baseUrl, query);
const req = this.createRequestObject(
url,
accessToken,
'PATCH',
JSON.stringify(parameters)
);
const res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) {
throw res.bodyAsText;
}
logger.info(`Bot proxy updated at: ${endpoint}.`);
}
public async deployGeneralBotsToAzure() {
const status = await git.status();
// TODO: Copy github to webapp.
}
2018-10-25 18:13:51 -03:00
private async ensureConfiguration(instance: IGBInstance) {
let username = GBConfigService.get('CLOUD_USERNAME');
let password = GBConfigService.get('CLOUD_PASSWORD');
let subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
let location = GBConfigService.get('CLOUD_LOCATION');
let botId = GBConfigService.get('BOT_ID');
2018-10-25 18:13:51 -03:00
// No .env so asks for cloud credentials to start a new farm.
if (!username || !password || !subscriptionId || !location || !botId) {
process.stdout.write(
'A empty enviroment is detected. To start automatic deploy, please enter some information:\n'
2018-10-25 18:13:51 -03:00
);
}
const retriveUsername = () => {
2018-10-25 18:13:51 -03:00
if (!username) {
2018-11-04 17:26:29 -02:00
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_USERNAME:`);
username = scanf('%s').replace(/(\n|\r)+$/, '');
2018-10-25 18:13:51 -03:00
}
};
const retrivePassword = () => {
2018-10-25 18:13:51 -03:00
if (!password) {
2018-11-04 17:26:29 -02:00
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_PASSWORD:`);
password = scanf('%s').replace(/(\n|\r)+$/, '');
2018-10-25 18:13:51 -03:00
}
};
const retrieveBotId = () => {
2018-10-25 18:13:51 -03:00
if (!botId) {
process.stdout.write(
2018-11-04 17:26:29 -02:00
`${GBAdminService.GB_PROMPT}Bot Id must only contain lowercase letters, digits or dashes, cannot start or end with or contain consecutive dashes and is limited from 4 to 42 characters long.\n`
2018-10-25 18:13:51 -03:00
);
2018-11-04 17:26:29 -02:00
process.stdout.write(`${GBAdminService.GB_PROMPT}BOT_ID:`);
botId = scanf('%s').replace(/(\n|\r)+$/, ''); // TODO: Update this regexp to match description of it.
2018-10-25 18:13:51 -03:00
}
};
let authoringKey = GBConfigService.get('NLP_AUTHORING_KEY');
const retriveAuthoringKey = () => {
2018-10-25 18:13:51 -03:00
if (!authoringKey) {
process.stdout.write(
2018-11-04 17:26:29 -02:00
`${GBAdminService.GB_PROMPT}Due to this opened issue: https://github.com/Microsoft/botbuilder-tools/issues/550\n`
2018-10-25 18:13:51 -03:00
);
2018-11-04 17:26:29 -02:00
process.stdout.write(`${GBAdminService.GB_PROMPT}Please enter your LUIS Authoring Key:`);
authoringKey = scanf('%s').replace(/(\n|\r)+$/, '');
2018-10-25 18:13:51 -03:00
}
};
while (!authoringKey) {
retriveAuthoringKey();
}
while (!botId) {
retrieveBotId();
}
while (!username) {
retriveUsername();
}
while (!password) {
retrivePassword();
}
// Connects to the cloud and retrives subscriptions.
const credentials = await GBAdminService.getADALCredentialsFromUsername(
2018-10-25 18:13:51 -03:00
username,
password
);
if (!subscriptionId) {
const map = {};
2018-10-25 18:13:51 -03:00
let index = 1;
const list = await AzureDeployerService.getSubscriptions(credentials);
2018-10-25 18:13:51 -03:00
list.forEach(element => {
console.log(
`${index}: ${element.displayName} (${element.subscriptionId})`
);
map[index++] = element;
});
let subscriptionIndex;
const retrieveSubscription = () => {
2018-10-25 18:13:51 -03:00
if (!subscriptionIndex) {
process.stdout.write('CLOUD_SUBSCRIPTIONID (type a number):');
subscriptionIndex = scanf('%d');
2018-10-25 18:13:51 -03:00
}
};
while (!subscriptionIndex) {
retrieveSubscription();
}
subscriptionId = map[subscriptionIndex].subscriptionId;
}
const retriveLocation = () => {
2018-10-25 18:13:51 -03:00
if (!location) {
process.stdout.write('CLOUD_LOCATION (eg. \'westus\'):');
location = scanf('%s');
2018-10-25 18:13:51 -03:00
}
};
while (!location) {
retriveLocation();
}
// Prepares the first instance on bot farm.
instance.botId = botId;
instance.cloudUsername = username;
instance.cloudPassword = password;
instance.cloudSubscriptionId = subscriptionId;
instance.cloudLocation = location;
instance.nlpAuthoringKey = authoringKey;
instance.adminPass = GBAdminService.getRndPassword();
2018-10-25 18:13:51 -03:00
this.resourceClient = new ResourceManagementClient.default(
credentials,
subscriptionId
);
this.webSiteClient = new WebSiteManagementClient(
credentials,
subscriptionId
);
this.storageClient = new SqlManagementClient(credentials, subscriptionId);
this.cognitiveClient = new CognitiveServicesManagementClient(
credentials,
subscriptionId
);
this.searchClient = new SearchManagementClient(credentials, subscriptionId);
this.accessToken = credentials.tokenCache._entries[0].accessToken;
2018-10-24 12:06:47 -03:00
return instance;
}
private async createStorageServer(
group,
name,
administratorLogin,
administratorPassword,
serverName,
location
) {
const params = {
location: location,
administratorLogin: administratorLogin,
administratorLoginPassword: administratorPassword,
fullyQualifiedDomainName: `${serverName}.database.windows.net`
};
return this.storageClient.servers.createOrUpdate(group, name, params);
}
private async registerProviders(subscriptionId, baseUrl, accessToken) {
const query = `subscriptions/${subscriptionId}/providers/${
this.provider
}/register?api-version=2018-02-01`;
const requestUrl = UrlJoin(baseUrl, query);
const req = new WebResource();
req.method = 'POST';
req.url = requestUrl;
req.headers = {};
req.headers['Content-Type'] = 'application/json; charset=utf-8';
req.headers['accept-language'] = '*';
req.headers.Authorization = 'Bearer ' + accessToken;
const httpClient = new ServiceClient();
const res = await httpClient.sendRequest(req);
// TODO: Check res for error.
}
2018-10-24 12:06:47 -03:00
/**
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json
*/
private async internalDeployBot(
instance,
accessToken,
botId,
name,
2018-10-24 12:06:47 -03:00
group,
description,
endpoint,
location,
nlpAppId,
nlpKey,
appId,
appPassword,
subscriptionId
) {
return new Promise(async (resolve, reject) => {
const baseUrl = `https://management.azure.com/`;
await this.registerProviders(subscriptionId, baseUrl, accessToken);
2018-10-24 12:06:47 -03:00
instance.marketplaceId = appId;
instance.marketplacePassword = appPassword;
instance.engineName = GBCorePackage.CurrentEngineName;
const parameters = {
location: location,
sku: {
name: 'F0'
},
name: botId,
kind: 'bot',
properties: {
description: description,
displayName: name,
endpoint: endpoint,
iconUrl: iconUrl,
luisAppIds: [nlpAppId],
luisKey: nlpKey,
msaAppId: appId,
msaAppPassword: appPassword,
enabledChannels: ['webchat'], // , "skype", "facebook"],
configuredChannels: ['webchat'] // , "skype", "facebook"]
}
};
const httpClient = new ServiceClient();
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`;
let url = UrlJoin(baseUrl, query);
let req = this.createRequestObject(
url,
accessToken,
'PUT',
JSON.stringify(parameters)
);
const res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) {
reject(res.bodyAsText);
return;
}
setTimeout(async () => {
try {
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${
AzureDeployerService.apiVersion
}`;
url = UrlJoin(baseUrl, query);
req = this.createRequestObject(
url,
accessToken,
'GET',
JSON.stringify(parameters)
);
const resChannel = await httpClient.sendRequest(req);
const key = (resChannel.bodyAsJson as any).properties.properties
.sites[0].key;
instance.webchatKey = key;
resolve(instance);
} catch (error) {
reject(error);
}
}, 20000);
});
}
private createRequestObject(
url: string,
accessToken: string,
verb: HttpMethods,
body: string
) {
const req = new WebResource();
req.method = verb;
2018-10-24 12:06:47 -03:00
req.url = url;
req.headers = {};
req.headers['Content-Type'] = 'application/json';
req.headers['accept-language'] = '*';
req.headers.Authorization = 'Bearer ' + accessToken;
2018-10-24 12:06:47 -03:00
req.body = body;
return req;
}
private async createLUISApp(
name: string,
description: string,
location: string,
2018-10-25 18:13:51 -03:00
culture: string,
authoringKey: string
) {
const parameters = {
name: name,
description: description,
culture: culture
};
2018-10-24 12:06:47 -03:00
const body = JSON.stringify(parameters);
const apps = await this.makeNlpRequest(
2018-10-25 18:13:51 -03:00
location,
authoringKey,
null,
'GET',
'apps'
2018-10-25 18:13:51 -03:00
);
const app = (apps.bodyAsJson as any).filter(x => x.name == name)[0];
2018-10-25 18:13:51 -03:00
let id: string;
if (!app) {
const res = await this.makeNlpRequest(
2018-10-25 18:13:51 -03:00
location,
authoringKey,
body,
'POST',
'apps'
2018-10-25 18:13:51 -03:00
);
id = res.bodyAsText;
} else {
id = app.id;
}
return id;
}
private async makeNlpRequest(
location: string,
authoringKey: string,
body: string,
method: HttpMethods,
resource: string
) {
const req = new WebResource();
2018-10-25 18:13:51 -03:00
req.method = method;
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/${resource}`;
req.headers = {};
req.headers['Content-Type'] = 'application/json';
req.headers['accept-language'] = '*';
req.headers['Ocp-Apim-Subscription-Key'] = authoringKey;
2018-10-25 18:13:51 -03:00
req.body = body;
const httpClient = new ServiceClient();
const res = await httpClient.sendRequest(req);
2018-10-25 18:13:51 -03:00
return res;
}
private async createSearch(group, name, location) {
const params = {
sku: { name: 'free' },
location: location
};
return this.searchClient.services.createOrUpdate(group, name, params);
}
private async createStorage(group, serverName, name, location) {
const params = {
sku: { name: 'Free' },
createMode: 'Default',
location: location
};
return this.storageClient.databases.createOrUpdate(
group,
serverName,
name,
params
);
}
private async createCognitiveServices(
group,
name,
location,
kind
): Promise<CognitiveServicesAccount> {
const params = {
sku: { name: 'F0' },
createMode: 'Default',
location: location,
kind: kind,
properties: {}
};
return await this.cognitiveClient.accounts.create(group, name, params);
}
private async createSpeech(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
location,
'SpeechServices'
);
}
private async createNLP(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, location, 'LUIS');
}
private async createSpellChecker(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
'global',
'Bing.SpellCheck.v7'
);
}
private async createTextAnalytics(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
location,
'TextAnalytics'
);
}
2018-10-15 21:03:17 -03:00
private async createDeployGroup(name, location) {
const params = { location: location };
return this.resourceClient.resourceGroups.createOrUpdate(name, params);
}
private async createHostingPlan(
group,
name,
location
): Promise<AppServicePlan> {
const params = {
serverFarmWithRichSkuName: name,
location: location,
sku: {
name: 'F1',
capacity: 1,
tier: 'Free'
}
};
return this.webSiteClient.appServicePlans.createOrUpdate(
group,
name,
params
);
}
private async createServer(farmId, group, name, location) {
const parameters = {
location: location,
serverFarmId: farmId
};
return this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
}
private async updateWebisteConfig(group, serverFarmId, name, location) {
const siteConfig = {
location: location,
serverFarmId: serverFarmId,
numberOfWorkers: 1,
phpVersion: '5.5'
};
// TODO: Copy .env to app settings.
return this.webSiteClient.webApps.createOrUpdateConfiguration(
group,
name,
siteConfig
);
}
}