Ngrok initialization and other startup stuff.

This commit is contained in:
Rodrigo Rodriguez (pragmatismo.io) 2018-10-28 21:56:51 -03:00
parent d3e82b5806
commit 028a4455ea
7 changed files with 1550 additions and 117 deletions

View file

@ -43,7 +43,7 @@ export class GBAdminService {
static masterBotInstanceId = 0; static masterBotInstanceId = 0;
public static StrongRegex = new RegExp( public static StrongRegex = new RegExp(
"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])(?=.{8,})" "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*\+_\-])(?=.{8,})"
); );
core: IGBCoreService; core: IGBCoreService;

View file

@ -255,22 +255,22 @@ export class AzureDeployerService extends GBService {
let retriveUsername = () => { let retriveUsername = () => {
if (!username) { if (!username) {
process.stdout.write("CLOUD_USERNAME:"); process.stdout.write("CLOUD_USERNAME:");
username = scanf("%s"); username = scanf("%s").replace(/(\n|\r)+$/, "");
} }
}; };
let retrivePassword = () => { let retrivePassword = () => {
if (!password) { if (!password) {
process.stdout.write("CLOUD_PASSWORD:"); process.stdout.write("CLOUD_PASSWORD:");
password = scanf("%s"); password = scanf("%s").replace(/(\n|\r)+$/, "");
} }
}; };
let retrieveBotId = () => { let retrieveBotId = () => {
if (!botId) { if (!botId) {
process.stdout.write( process.stdout.write(
"Bot Id must only contain lowercase letters, digits or dashes, cannot start or end with or contain consecutive dashes and is limited to 60 characters.\n" "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"
); );
process.stdout.write("BOT_ID:"); process.stdout.write("BOT_ID:");
botId = scanf("%s"); botId = scanf("%s").replace(/(\n|\r)+$/, "");
} }
}; };
let authoringKey = GBConfigService.get("NLP_AUTHORING_KEY"); let authoringKey = GBConfigService.get("NLP_AUTHORING_KEY");
@ -280,7 +280,7 @@ export class AzureDeployerService extends GBService {
"Due to this opened issue: https://github.com/Microsoft/botbuilder-tools/issues/550\n" "Due to this opened issue: https://github.com/Microsoft/botbuilder-tools/issues/550\n"
); );
process.stdout.write("Please enter your LUIS Authoring Key:"); process.stdout.write("Please enter your LUIS Authoring Key:");
authoringKey = scanf("%s"); authoringKey = scanf("%s").replace(/(\n|\r)+$/, "");
} }
}; };
while (!authoringKey) { while (!authoringKey) {
@ -326,7 +326,7 @@ export class AzureDeployerService extends GBService {
} }
let retriveLocation = () => { let retriveLocation = () => {
if (!location) { if (!location) {
process.stdout.write("CLOUD_LOCATION:"); process.stdout.write("CLOUD_LOCATION (eg. 'westus'):");
location = scanf("%s"); location = scanf("%s");
} }
}; };
@ -433,7 +433,8 @@ export class AzureDeployerService extends GBService {
/** /**
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json * @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, private async internalDeployBot(
instance,
accessToken, accessToken,
botId, botId,
name, name,
@ -480,11 +481,18 @@ export class AzureDeployerService extends GBService {
let req = this.createRequestObject( let req = this.createRequestObject(
url, url,
accessToken, accessToken,
"PUT",
JSON.stringify(parameters) JSON.stringify(parameters)
); );
let res = await httpClient.sendRequest(req); let res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) {
reject(res.bodyAsText);
return;
}
logger.info(`Bot creation request done waiting for key generation...`);
setTimeout(async () => { setTimeout(async () => {
try {
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${ query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${
AzureDeployerService.apiVersion AzureDeployerService.apiVersion
}`; }`;
@ -492,26 +500,71 @@ export class AzureDeployerService extends GBService {
req = this.createRequestObject( req = this.createRequestObject(
url, url,
accessToken, accessToken,
"PUT",
JSON.stringify(parameters) JSON.stringify(parameters)
); );
let resChannel = await httpClient.sendRequest(req); let resChannel = await httpClient.sendRequest(req);
console.log(resChannel.bodyAsText); console.log(resChannel.bodyAsText);
let key = (resChannel.bodyAsJson as any).properties.properties.sites[0] let key = (resChannel.bodyAsJson as any).properties.properties
.key; .sites[0].key;
instance.marketplacePassword = appPassword instance.marketplacePassword = appPassword;
instance.webchatKey = key instance.webchatKey = key;
resolve(instance) resolve(instance);
} catch (error) {
}, 10000); reject(error);
}
}, 20000);
}); });
} }
private createRequestObject(url: string, accessToken: string, body) { public async updateBotProxy(botId, group, endpoint) {
let baseUrl = `https://management.azure.com/`;
let username = GBConfigService.get("CLOUD_USERNAME");
let password = GBConfigService.get("CLOUD_PASSWORD");
let subscriptionId = GBConfigService.get("CLOUD_SUBSCRIPTIONID");
let credentials = await msRestAzure.loginWithUsernamePassword(
username,
password
);
let parameters = {
properties: {
endpoint: endpoint
}
};
let accessToken = credentials.tokenCache._entries[0].accessToken;
let 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,
"PATCH",
JSON.stringify(parameters)
);
let res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) {
throw res.bodyAsText;
}
logger.info(`Bot proxy updated at: ${endpoint}.`);
}
private createRequestObject(
url: string,
accessToken: string,
verb: HttpMethods,
body: string
) {
let req = new WebResource(); let req = new WebResource();
req.method = "PUT"; req.method = verb;
req.url = url; req.url = url;
req.headers = {}; req.headers = {};
req.headers["Content-Type"] = "application/json"; req.headers["Content-Type"] = "application/json";
@ -750,7 +803,7 @@ export class AzureDeployerService extends GBService {
maximumLength: 14 maximumLength: 14
}; };
let password = passwordGenerator.generatePassword(options); let password = passwordGenerator.generatePassword(options);
password = password.replace("=", ""); password = password.replace(/[=:;\?]/g, "");
return password; return password;
} }

View file

@ -306,8 +306,8 @@ export class GBCoreService implements IGBCoreService {
`STORAGE_SERVER=${instance.storageServer}.database.windows.net\n` + `STORAGE_SERVER=${instance.storageServer}.database.windows.net\n` +
`STORAGE_NAME=${instance.storageName}\n` + `STORAGE_NAME=${instance.storageName}\n` +
`STORAGE_USERNAME=${instance.storageUsername}\n` + `STORAGE_USERNAME=${instance.storageUsername}\n` +
`STORAGE_PASSWORD=${instance.storagePassword}\n`+ `STORAGE_PASSWORD=${instance.storagePassword}\n` +
`STORAGE_SYNC=true\n`+ `STORAGE_SYNC=true\n` +
`CLOUD_USERNAME=${instance.cloudUsername}\n` + `CLOUD_USERNAME=${instance.cloudUsername}\n` +
`CLOUD_PASSWORD=${instance.cloudPassword}\n` + `CLOUD_PASSWORD=${instance.cloudPassword}\n` +
`CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}\n` + `CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}\n` +
@ -318,47 +318,9 @@ export class GBCoreService implements IGBCoreService {
fs.writeFileSync(".env", env); fs.writeFileSync(".env", env);
} }
public async ensureProxy(): Promise<string> { public async ensureProxy(port): Promise<string> {
let proxyAddress: string; let proxyAddress: string;
const ngrok = require("ngrok"); const ngrok = require("ngrok");
return await ngrok.connect(); return await ngrok.connect({port:port});
// let expiresOn = new Date(
// await this.adminService.getValue(0, "proxyExpiresOn")
// );
// let proxyAddress;
// if (expiresOn.getTime() > new Date().getTime()) {
// proxyAddress = await this.adminService.getValue(
// GBAdminService.masterBotInstanceId,
// "proxyAddress"
// );
// return Promise.resolve(proxyAddress);
// } else {
// if (await processExists("ngrok.exe")) {
// logger.warn("ngrok is already running.");
// } else {
// const { exec } = require("child_process");
// const child = exec(
// "node_modules\\ngrok\\bin\\ngrok http 4242",
// (error, stdout, stderr) => {
// console.log(`child stdout:\n${stdout}`);
// }
// );
// }
// await this.adminService.setValue(
// GBAdminService.masterBotInstanceId,
// "proxyAddress",
// proxyAddress
// );
// let now = new Date();
// let expiresOn = now.setHours(now.getHours());
// await this.adminService.setValue(
// GBAdminService.masterBotInstanceId,
// "proxyExpiresOn",
// expiresOn.toString()
// );
return Promise.resolve(proxyAddress);
// }
} }
} }

View file

@ -217,7 +217,7 @@ export class GBDeployer {
.done(function(result) { .done(function(result) {
if (botPackages.length === 0) { if (botPackages.length === 0) {
logger.warn( logger.warn(
"The server is running with no bot instances, at least one .gbot file must be deployed." "No external packages to load, please use ADDITIONAL_DEPLOY_PATH to point to a .gbai package folder."
); );
} else { } else {
logger.info(`Package deployment done.`); logger.info(`Package deployment done.`);

View file

@ -307,8 +307,6 @@ export class GBMinService {
const storage = new MemoryStorage(); const storage = new MemoryStorage();
const conversationState = new ConversationState(storage); const conversationState = new ConversationState(storage);
const userState = new UserState(storage); const userState = new UserState(storage);
//const botState = new BotState(storage);
// TODO: adapter.use();
// The minimal bot is built here. // The minimal bot is built here.

1466
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -96,17 +96,20 @@ export class GBServer {
// Ensures cloud / on-premises infrastructure is setup. // Ensures cloud / on-premises infrastructure is setup.
logger.info(`Establishing a development local proxy...`); logger.info(`Establishing a development local proxy...`);
let proxyAddress = await core.ensureProxy(); let proxyAddress = await core.ensureProxy(port);
let azureDeployer = new AzureDeployerService();
try { try {
await core.initDatabase(); await core.initDatabase();
} catch (error) { } catch (error) {
logger.info(`Deploying cognitive infrastructure...`); logger.info(`Deploying cognitive infrastructure...`);
try { try {
let azureDeployer = new AzureDeployerService();
bootInstance = await azureDeployer.deployFarm(proxyAddress); bootInstance = await azureDeployer.deployFarm(proxyAddress);
} catch (error) { } catch (error) {
logger.warn("Error while deploying to the cloud, please, cleanup any objects created before running again.") logger.warn(
"Error while deploying to the cloud, please, cleanup any objects created before running again."
);
throw error; throw error;
} }
core.writeEnv(bootInstance); core.writeEnv(bootInstance);
@ -153,14 +156,23 @@ export class GBServer {
let instances: GuaribasInstance[]; let instances: GuaribasInstance[];
try { try {
instances = await core.loadInstances(); instances = await core.loadInstances();
let instance = instances[0];
if (process.env.NODE_ENV === "development") {
logger.info(`Updating bots proxies...`);
await azureDeployer.updateBotProxy(
instance.botId,
instance.botId,
`${proxyAddress}/api/messages/${instance.botId}`
);
}
} catch (error) { } catch (error) {
if (error.parent.code === "ELOGIN") { if (error.parent.code === "ELOGIN") {
let group = GBConfigService.get("CLOUD_GROUP");
let azureDeployer = new AzureDeployerService(); let serverName = GBConfigService.get("STORAGE_SERVER").split(
let group = GBConfigService.get("CLOUD_GROUP") ".database.windows.net"
let serverName = GBConfigService.get("STORAGE_SERVER").split(".database.windows.net")[0] )[0];
await azureDeployer.openStorageFirewall(group,serverName ) await azureDeployer.openStorageFirewall(group, serverName);
} else { } else {
// Check if storage is empty and needs formatting. // Check if storage is empty and needs formatting.