Bot deployment and key getting done.

This commit is contained in:
Rodrigo Rodriguez (pragmatismo.io) 2018-10-24 12:06:47 -03:00
parent c3d49e3288
commit d030ed8278
5 changed files with 124 additions and 74 deletions

View file

@ -47,6 +47,7 @@ import * as simplegit from "simple-git/promise";
import { AppServicePlan } from "azure-arm-website/lib/models"; import { AppServicePlan } from "azure-arm-website/lib/models";
import { GBConfigService } from "../../../deploy/core.gbapp/services/GBConfigService"; import { GBConfigService } from "../../../deploy/core.gbapp/services/GBConfigService";
const Spinner = require('cli-spinner').Spinner;
const scanf = require("scanf"); const scanf = require("scanf");
const msRestAzure = require("ms-rest-azure"); const msRestAzure = require("ms-rest-azure");
const git = simplegit(); const git = simplegit();
@ -68,6 +69,7 @@ export class AzureDeployerService extends GBService {
accessToken: string; accessToken: string;
location: string; location: string;
public subscriptionId: string; public subscriptionId: string;
static apiVersion = "2017-12-01";
constructor(credentials, subscriptionId, location) { constructor(credentials, subscriptionId, location) {
super(); super();
@ -103,26 +105,11 @@ export class AzureDeployerService extends GBService {
let instance: any = {}; let instance: any = {};
let culture = "en-us"; let culture = "en-us";
logger.info(`Starting infrastructure deployment...`); let spinner = new Spinner('%s');
spinner.start();
spinner.setSpinnerString("⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈");
let keys: any; let keys: any;
logger.info(`Deploying NLP...`);
let nlp = await this.createNLP(name, `${name}-nlp`, location);
keys = await this.cognitiveClient.accounts.listKeys(name, nlp.name);
let nlpAppId = await this.createLUISApp(name, name, location, culture);
await this.deployBootBot(
instance,
name,
proxyAddress,
nlpAppId,
keys.key1,
this.subscriptionId
);
instance.nlpEndpoint = nlp.endpoint;
instance.nlpKey = keys.key1;
instance.nlpAppId = nlpAppId;
logger.info(`Deploying Deploy Group...`); logger.info(`Deploying Deploy Group...`);
await this.createDeployGroup(name, location); await this.createDeployGroup(name, location);
@ -174,7 +161,13 @@ export class AzureDeployerService extends GBService {
instance.searchIndexer = "azuresql-indexer"; instance.searchIndexer = "azuresql-indexer";
instance.searchKey = searchKeys[0].key; instance.searchKey = searchKeys[0].key;
////////////// LUS logger.info(`Deploying NLP...`);
let nlp = await this.createNLP(name, `${name}-nlp`, location);
keys = await this.cognitiveClient.accounts.listKeys(name, nlp.name);
let nlpAppId = await this.createLUISApp(name, name, location, culture);
instance.nlpEndpoint = nlp.endpoint;
instance.nlpKey = keys.key1;
instance.nlpAppId = nlpAppId;
logger.info(`Deploying Speech...`); logger.info(`Deploying Speech...`);
let speech = await this.createSpeech(name, `${name}-speech`, location); let speech = await this.createSpeech(name, `${name}-speech`, location);
@ -208,6 +201,20 @@ export class AzureDeployerService extends GBService {
instance.textAnalyticsEndpoint = textAnalytics.endpoint; instance.textAnalyticsEndpoint = textAnalytics.endpoint;
instance.textAnalyticsKey = keys.key1; instance.textAnalyticsKey = keys.key1;
let appId = msRestAzure.generateUuid();
logger.info(`Deploying Bot...`);
instance = await this.deployBootBot(
instance,
name,
`${proxyAddress}/api/messages/${name}`,
nlpAppId,
keys.key1,
this.subscriptionId,
appId
);
spinner.stop();
return instance; return instance;
} }
@ -217,12 +224,19 @@ export class AzureDeployerService extends GBService {
endpoint, endpoint,
nlpAppId, nlpAppId,
nlpKey, nlpKey,
subscriptionId subscriptionId,
appId
) { ) {
logger.info(`Deploying Bot...`); logger.info(`Deploying Bot...`);
await this.internalDeployBot(
let botId = name + AzureDeployerService.getRndBotId();
[
instance.marketplacePassword,
instance.webchatKey
] = await this.internalDeployBot(
this.accessToken, this.accessToken,
name, botId,
name, name,
name, name,
"General BootBot", "General BootBot",
@ -230,11 +244,11 @@ export class AzureDeployerService extends GBService {
"global", "global",
nlpAppId, nlpAppId,
nlpKey, nlpKey,
subscriptionId subscriptionId,
appId
); );
instance.webchatKey = "********"; instance.marketplaceId = appId;
instance.marketplaceId = "0ff1ce73-0aea-442a-a222-dcc340eca294"; instance.botId = botId;
instance.marketplacePassword = "************";
return instance; return instance;
} }
@ -280,29 +294,33 @@ export class AzureDeployerService extends GBService {
let res = await httpClient.sendRequest(req); let res = await httpClient.sendRequest(req);
} }
/**
* @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( private async internalDeployBot(
accessToken, accessToken,
botId, botId,
group,
name, name,
group,
description, description,
endpoint, endpoint,
location, location,
nlpAppId, nlpAppId,
nlpKey, nlpKey,
subscriptionId subscriptionId,
appId
) { ) {
let baseUrl = `https://management.azure.com/`; let baseUrl = `https://management.azure.com/`;
this.registerProviders(subscriptionId, baseUrl, accessToken); await this.registerProviders(subscriptionId, baseUrl, accessToken);
let appId = msRestAzure.generateUuid();
let appPassword = AzureDeployerService.getRndPassword();
let parameters = { let parameters = {
location: location, location: location,
sku: { sku: {
name: "F0" name: "F0"
}, },
name: name, name: botId,
id: botId,
kind: "sdk", kind: "sdk",
properties: { properties: {
description: description, description: description,
@ -311,30 +329,49 @@ export class AzureDeployerService extends GBService {
iconUrl: iconUrl, iconUrl: iconUrl,
luisAppIds: [nlpAppId], luisAppIds: [nlpAppId],
luisKey: nlpKey, luisKey: nlpKey,
msaAppId: appId msaAppId: appId,
msaAppPassword: appPassword
} }
}; };
let httpClient = new ServiceClient();
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${ let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider this.provider
}/botServices/${botId}?api-version=2017-12-01`; }/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`;
let requestUrl = UrlJoin(baseUrl, query); let url = UrlJoin(baseUrl, query);
let req = this.createRequestObject(
url,
accessToken,
JSON.stringify(parameters)
);
let res = await httpClient.sendRequest(req);
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,
JSON.stringify(parameters)
);
let resChannel = await httpClient.sendRequest(req);
let key = (resChannel.bodyAsJson as any).properties.properties.sites[0].key;
return [appPassword, key];
}
private createRequestObject(url: string, accessToken: string, body) {
let req = new WebResource(); let req = new WebResource();
req.method = "PUT"; req.method = "PUT";
req.url = requestUrl; req.url = url;
req.headers = {}; req.headers = {};
req.headers["Content-Type"] = "application/json"; req.headers["Content-Type"] = "application/json";
req.headers["accept-language"] = "*"; req.headers["accept-language"] = "*";
req.headers["Authorization"] = "Bearer " + accessToken; req.headers["Authorization"] = "Bearer " + accessToken;
req.body = body;
let requestContent = JSON.stringify(parameters); return req;
req.body = requestContent;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
return JSON.parse(res.bodyAsJson as string);
} }
private async createLUISApp( private async createLUISApp(
@ -350,14 +387,14 @@ export class AzureDeployerService extends GBService {
}; };
let requestUrl = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/`; let requestUrl = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/apps/`;
let req = new WebResource(); let req = new WebResource();
req.method = "POST"; req.method = "POST";
req.url = requestUrl; req.url = requestUrl;
req.headers = {}; req.headers = {};
req.headers["Content-Type"] = "application/json"; req.headers["Content-Type"] = "application/json";
req.headers["accept-language"] = "*"; req.headers["accept-language"] = "*";
let authoringKey; let authoringKey = GBConfigService.get("NLP_AUTHORING_KEY");
let retriveAuthoringKey = () => { let retriveAuthoringKey = () => {
if (!authoringKey) { if (!authoringKey) {
process.stdout.write( process.stdout.write(
@ -378,7 +415,7 @@ export class AzureDeployerService extends GBService {
let httpClient = new ServiceClient(); let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req); let res = await httpClient.sendRequest(req);
return res.bodyAsText; return res.bodyAsJson;
} }
private async createSearch(group, name, location) { private async createSearch(group, name, location) {
@ -540,6 +577,20 @@ export class AzureDeployerService extends GBService {
return `sa${generated}`; return `sa${generated}`;
} }
private static getRndBotId() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: false,
lowerCaseAlpha: true,
number: true,
specialCharacter: false,
minimumLength: 8,
maximumLength: 8
};
let generated = passwordGenerator.generatePassword(options);
return `${generated}`;
}
private static getRndPassword() { private static getRndPassword() {
const passwordGenerator = new PasswordGenerator(); const passwordGenerator = new PasswordGenerator();
const options = { const options = {
@ -548,7 +599,7 @@ export class AzureDeployerService extends GBService {
number: true, number: true,
specialCharacter: true, specialCharacter: true,
minimumLength: 8, minimumLength: 8,
maximumLength: 8 maximumLength: 14
}; };
let password = passwordGenerator.generatePassword(options); let password = passwordGenerator.generatePassword(options);
return password; return password;

View file

@ -1,22 +1,8 @@
export const Messages = { export const Messages = {
"en-US": { "en-US": {
about_suggestions: "Suggestions are welcomed and improve my quality...", about_suggestions: "Suggestions are welcomed and improve my quality...",
what_about_service: "What about my service?",
glad_you_liked: "I'm glad you liked. I'm here for you.",
we_will_improve: "Let's take note of that, thanks for sharing.",
what_about_me: "What about the service, please rate between 1 and 5.",
thanks: "Thanks!",
im_sorry_lets_try: "I'm sorry. Let's try again...",
great_thanks: "Great, thanks for sharing your thoughts."
}, },
"pt-BR": { "pt-BR": {
about_suggestions: "Sugestões melhoram muito minha qualidade...", about_suggestions: "Sugestões melhoram muito minha qualidade...",
what_about_service:"O que achou do meu atendimento?",
glad_you_liked: "Bom saber que você gostou. Conte comigo.",
we_will_improve: "Vamos registrar sua questão, obrigado pela sinceridade.",
what_about_me: "O que achou do meu atendimento, de 1 a 5?",
thanks: "Obrigado!",
im_sorry_lets_try: "Desculpe-me, vamos tentar novamente.",
great_thanks: "Ótimo, obrigado por contribuir com sua resposta."
} }
}; };

View file

@ -36,7 +36,6 @@ import * as fs from "fs";
"use strict"; "use strict";
export class GBConfigService { export class GBConfigService {
static init(): any { static init(): any {
try { try {
require("dotenv-extended").load({ require("dotenv-extended").load({
@ -52,9 +51,8 @@ export class GBConfigService {
} }
public writeEntry(name, value) { public writeEntry(name, value) {
if (fs.exists) { if (fs.exists) {
fs.appendFileSync('.env',`${name}=${value}`); fs.appendFileSync(".env", `${name}=${value}`);
} }
} }
@ -63,35 +61,48 @@ export class GBConfigService {
if (!value) { if (!value) {
switch (key) { switch (key) {
case "CLOUD_USERNAME":
value = undefined;
break;
case "CLOUD_PASSWORD":
value = undefined;
break;
case "CLOUD_SUBSCRIPTIONID":
value = undefined;
break;
case "CLOUD_LOCATION":
value = undefined;
break;
case "NLP_AUTHORING_KEY":
value = undefined;
break;
case "STORAGE_DIALECT": case "STORAGE_DIALECT":
value = "sqlite"; value = "sqlite";
break; break;
case "STORAGE_STORAGE": case "STORAGE_STORAGE":
value = "./guaribas.sqlite"; value = "./guaribas.sqlite";
break; break;
case "ADDITIONAL_DEPLOY_PATH": case "ADDITIONAL_DEPLOY_PATH":
value = undefined; value = undefined;
break; break;
case "STORAGE_SYNC": case "STORAGE_SYNC":
value = "false";
break;
case "STORAGE_SYNC_ALTER": case "STORAGE_SYNC_ALTER":
value = "false";
break;
case "STORAGE_SYNC_FORCE": case "STORAGE_SYNC_FORCE":
value = "false"; value = "false";
break; break;
case "STORAGE_LOGGING": case "STORAGE_LOGGING":
value = "false"; value = "false";
break; break;
case "STORAGE_ENCRYPT": case "STORAGE_ENCRYPT":
value = "true"; value = "true";
break; break;
default: default:
logger.info( logger.warn(
`Guaribas General Error: Invalid key on .env file: '${key}'` `Invalid key on .env file: '${key}'`
); );
break; break;
} }

View file

@ -55,6 +55,7 @@
"chai": "4.2.0", "chai": "4.2.0",
"child_process": "^1.0.2", "child_process": "^1.0.2",
"chokidar": "2.0.4", "chokidar": "2.0.4",
"cli-spinner": "^0.2.8",
"csv-parse": "3.1.3", "csv-parse": "3.1.3",
"dotenv-extended": "2.3.0", "dotenv-extended": "2.3.0",
"express": "4.16.4", "express": "4.16.4",

View file

@ -97,8 +97,9 @@ export class GBServer {
// Ensures cloud / on-premises infrastructure is setup. // Ensures cloud / on-premises infrastructure is setup.
logger.info(`Connecting to the infrastructure...`); logger.info(`Establishing a development local proxy...`);
let proxyAddress = await core.ensureProxy(); let proxyAddress = await core.ensureProxy();
logger.info(`Ensuring services availability...`);
let cloudDeployer = await AzureDeployerService.ensureDeployer(); let cloudDeployer = await AzureDeployerService.ensureDeployer();
let instance = await cloudDeployer.deployFarm('gbot', 'westus', proxyAddress); let instance = await cloudDeployer.deployFarm('gbot', 'westus', proxyAddress);