diff --git a/Composer/packages/lib/bot-deploy/package.json b/Composer/packages/lib/bot-deploy/package.json index 55dd29c3a5..0e233c0d6e 100644 --- a/Composer/packages/lib/bot-deploy/package.json +++ b/Composer/packages/lib/bot-deploy/package.json @@ -10,7 +10,9 @@ "author": "", "license": "MIT", "dependencies": { + "@azure/arm-appinsights": "^2.1.0", "@azure/arm-appservice-profile-2019-03-01-hybrid": "^1.0.0", + "@azure/arm-botservice": "^1.0.0", "@azure/arm-deploymentmanager": "^3.0.0", "@azure/arm-resources": "^2.1.0", "@azure/arm-subscriptions": "^2.0.0", diff --git a/Composer/packages/lib/bot-deploy/src/botProjectDeploy.ts b/Composer/packages/lib/bot-deploy/src/botProjectDeploy.ts index e3b5508e2e..73e1c97332 100644 --- a/Composer/packages/lib/bot-deploy/src/botProjectDeploy.ts +++ b/Composer/packages/lib/bot-deploy/src/botProjectDeploy.ts @@ -5,6 +5,8 @@ import * as path from 'path'; import * as util from 'util'; import { ResourceManagementClient } from '@azure/arm-resources'; +import { ApplicationInsightsManagementClient } from '@azure/arm-appinsights'; +import { AzureBotService } from '@azure/arm-botservice'; import { Deployment, DeploymentsCreateOrUpdateResponse, @@ -658,7 +660,7 @@ export class BotProjectDeploy { createLuisAuthoringResource = true, createCosmosDb = true, createStorage = true, - createAppInsignts = true + createAppInsights = true ) { if (!this.tenantId) { this.tenantId = await this.getTenantId(); @@ -735,7 +737,7 @@ export class BotProjectDeploy { name, createLuisAuthoringResource, createLuisResource, - createAppInsignts, + createAppInsights, createCosmosDb, createStorage ); @@ -813,6 +815,78 @@ export class BotProjectDeploy { throw new Error(`! Error: ${validation.error}`); } + // If application insights created, update the application insights settings in azure bot service + if (createAppInsights) { + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> Linking Application Insights settings to Bot Service ...`, + }); + + const appinsightsClient = new ApplicationInsightsManagementClient(this.creds, this.subId); + const appComponents = await appinsightsClient.components.get(resourceGroupName, resourceGroupName); + const appinsightsId = appComponents.appId; + const appinsightsInstrumentationKey = appComponents.instrumentationKey; + const apiKeyOptions = { + name: `${resourceGroupName}-provision-${timeStamp}`, + linkedReadProperties: [ + `/subscriptions/${this.subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/api`, + `/subscriptions/${this.subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/agentconfig`, + ], + linkedWriteProperties: [ + `/subscriptions/${this.subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/annotations`, + ], + }; + const appinsightsApiKeyResponse = await appinsightsClient.aPIKeys.create( + resourceGroupName, + resourceGroupName, + apiKeyOptions + ); + const appinsightsApiKey = appinsightsApiKeyResponse.apiKey; + + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> AppInsights AppId: ${appinsightsId} ...`, + }); + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> AppInsights InstrumentationKey: ${appinsightsInstrumentationKey} ...`, + }); + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> AppInsights ApiKey: ${appinsightsApiKey} ...`, + }); + + if (appinsightsId && appinsightsInstrumentationKey && appinsightsApiKey) { + const botServiceClient = new AzureBotService(this.creds, this.subId); + const botCreated = await botServiceClient.bots.get(resourceGroupName, name); + if (botCreated.properties) { + botCreated.properties.developerAppInsightKey = appinsightsInstrumentationKey; + botCreated.properties.developerAppInsightsApiKey = appinsightsApiKey; + botCreated.properties.developerAppInsightsApplicationId = appinsightsId; + const botUpdateResult = await botServiceClient.bots.update(resourceGroupName, name, botCreated); + + if (botUpdateResult._response.status != 200) { + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_ERROR, + message: `! Something went wrong while trying to link Application Insights settings to Bot Service Result: ${JSON.stringify( + botUpdateResult + )}`, + }); + throw new Error(`Linking Application Insights Failed.`); + } + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> Linking Application Insights settings to Bot Service Success!`, + }); + } else { + this.logger({ + status: BotProjectDeployLoggerType.PROVISION_WARNING, + message: `! The Bot doesn't have a keys properties to update.`, + }); + } + } + } + // Validate that everything was successfully created. // Then, update the settings file with information about the new resources const updateResult = await this.updateDeploymentJsonFile(client, resourceGroupName, timeStamp, appId, appPassword); diff --git a/Composer/packages/plugins/samples/assets/shared/scripts/package.json b/Composer/packages/plugins/samples/assets/shared/scripts/package.json index 256b826ec5..13b5294de5 100644 --- a/Composer/packages/plugins/samples/assets/shared/scripts/package.json +++ b/Composer/packages/plugins/samples/assets/shared/scripts/package.json @@ -8,6 +8,8 @@ "start": "node provisionComposer.js" }, "dependencies": { + "@azure/arm-appinsights": "^2.1.0", + "@azure/arm-botservice": "^1.0.0", "@azure/arm-resources": "^2.1.0", "@azure/graph": "^5.0.1", "@azure/ms-rest-nodeauth": "^3.0.3", diff --git a/Composer/packages/plugins/samples/assets/shared/scripts/provisionComposer.js b/Composer/packages/plugins/samples/assets/shared/scripts/provisionComposer.js index bed7c99f74..c20440fc14 100644 --- a/Composer/packages/plugins/samples/assets/shared/scripts/provisionComposer.js +++ b/Composer/packages/plugins/samples/assets/shared/scripts/provisionComposer.js @@ -8,6 +8,8 @@ const path = require('path'); const rp = require('request-promise'); const { promisify } = require('util'); const { GraphRbacManagementClient } = require('@azure/graph'); +const { ApplicationInsightsManagementClient } = require('@azure/arm-appinsights'); +const { AzureBotService } = require('@azure/arm-botservice'); const { ResourceManagementClient } = require('@azure/arm-resources'); const readFile = promisify(fs.readFile); const ora = require('ora'); @@ -89,7 +91,7 @@ const createLuisResource = argv.createLuisResource == 'false' ? false : true; const createLuisAuthoringResource = argv.createLuisAuthoringResource == 'false' ? false : true; const createCosmosDb = argv.createCosmosDb == 'false' ? false : true; const createStorage = argv.createStorage == 'false' ? false : true; -const createAppInsignts = argv.createAppInsignts == 'false' ? false : true; +const createAppInsights = argv.createAppInsights == 'false' ? false : true; var tenantId = argv.tenantId ? argv.tenantId : ''; const templatePath = @@ -275,7 +277,7 @@ const updateDeploymentJsonFile = async (client, resourceGroupName, deployName, a }; const outputObj = unpackObject(outputResult); - if (!createAppInsignts) { + if (!createAppInsights) { delete outputObj.applicationInsights; } if (!createCosmosDb) { @@ -338,7 +340,7 @@ const create = async ( createLuisAuthoringResource = true, createCosmosDb = true, createStorage = true, - createAppInsignts = true + createAppInsights = true ) => { // If tenantId is empty string, get tenanId from API if (!tenantId) { @@ -416,7 +418,7 @@ const create = async ( name, createLuisAuthoringResource, createLuisResource, - createAppInsignts, + createAppInsights, createCosmosDb, createStorage ); @@ -478,6 +480,78 @@ const create = async ( return provisionFailed(); } + // If application insights created, update the application insights settings in azure bot service + if (createAppInsights) { + logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> Linking Application Insights settings to Bot Service ...`, + }); + + const appinsightsClient = new ApplicationInsightsManagementClient(creds, subId); + const appComponents = await appinsightsClient.components.get(resourceGroupName, resourceGroupName); + const appinsightsId = appComponents.appId; + const appinsightsInstrumentationKey = appComponents.instrumentationKey; + const apiKeyOptions = { + name: `${resourceGroupName}-provision-${timeStamp}`, + linkedReadProperties: [ + `/subscriptions/${subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/api`, + `/subscriptions/${subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/agentconfig`, + ], + linkedWriteProperties: [ + `/subscriptions/${subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/annotations`, + ], + }; + const appinsightsApiKeyResponse = await appinsightsClient.aPIKeys.create( + resourceGroupName, + resourceGroupName, + apiKeyOptions + ); + const appinsightsApiKey = appinsightsApiKeyResponse.apiKey; + + logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> AppInsights AppId: ${appinsightsId} ...`, + }); + logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> AppInsights InstrumentationKey: ${appinsightsInstrumentationKey} ...`, + }); + logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> AppInsights ApiKey: ${appinsightsApiKey} ...`, + }); + + if (appinsightsId && appinsightsInstrumentationKey && appinsightsApiKey) { + const botServiceClient = new AzureBotService(creds, subId); + const botCreated = await botServiceClient.bots.get(resourceGroupName, name); + if (botCreated.properties) { + botCreated.properties.developerAppInsightKey = appinsightsInstrumentationKey; + botCreated.properties.developerAppInsightsApiKey = appinsightsApiKey; + botCreated.properties.developerAppInsightsApplicationId = appinsightsId; + const botUpdateResult = await botServiceClient.bots.update(resourceGroupName, name, botCreated); + + if (botUpdateResult._response.status != 200) { + logger({ + status: BotProjectDeployLoggerType.PROVISION_ERROR, + message: `! Something went wrong while trying to link Application Insights settings to Bot Service Result: ${JSON.stringify( + botUpdateResult + )}`, + }); + throw new Error(`Linking Application Insights Failed.`); + } + logger({ + status: BotProjectDeployLoggerType.PROVISION_INFO, + message: `> Linking Application Insights settings to Bot Service Success!`, + }); + } else { + logger({ + status: BotProjectDeployLoggerType.PROVISION_WARNING, + message: `! The Bot doesn't have a keys properties to update.`, + }); + } + } + } + spinner.succeed('Success!'); // Validate that everything was successfully created. @@ -548,7 +622,7 @@ msRestNodeAuth createLuisAuthoringResource, createCosmosDb, createStorage, - createAppInsignts + createAppInsights ); if (createResult) { diff --git a/Composer/yarn.lock b/Composer/yarn.lock index ce227e7006..6d4c8e4ec6 100644 --- a/Composer/yarn.lock +++ b/Composer/yarn.lock @@ -7,6 +7,15 @@ resolved "https://botbuilder.myget.org/F/botframework-cli/npm/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" integrity sha1-vFtVMuyv2SOmHy+wl+OxCMAQaj8= +"@azure/arm-appinsights@^2.1.0": + version "2.1.0" + resolved "https://botbuilder.myget.org/F/botframework-cli/npm/@azure/arm-appinsights/-/@azure/arm-appinsights-2.1.0.tgz#a14238e5fa1e0ae949d6f65d49020459116f16fd" + integrity sha1-oUI45foeCulJ1vZdSQIEWRFvFv0= + dependencies: + "@azure/ms-rest-azure-js" "^1.1.0" + "@azure/ms-rest-js" "^1.1.0" + tslib "^1.9.3" + "@azure/arm-appservice-profile-2019-03-01-hybrid@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@azure/arm-appservice-profile-2019-03-01-hybrid/-/arm-appservice-profile-2019-03-01-hybrid-1.0.0.tgz#36b41dd5ce2d7d07ac8828efb4bc0badf9820c3e" @@ -16,6 +25,15 @@ "@azure/ms-rest-js" "^1.8.1" tslib "^1.9.3" +"@azure/arm-botservice@^1.0.0": + version "1.0.0" + resolved "https://botbuilder.myget.org/F/botframework-cli/npm/@azure/arm-botservice/-/@azure/arm-botservice-1.0.0.tgz#439140b234831895dd3c9fdec524fef5fc94c5e3" + integrity sha1-Q5FAsjSDGJXdPJ/exST+9fyUxeM= + dependencies: + "@azure/ms-rest-azure-js" "^1.3.2" + "@azure/ms-rest-js" "^1.8.1" + tslib "^1.9.3" + "@azure/arm-deploymentmanager@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@azure/arm-deploymentmanager/-/arm-deploymentmanager-3.0.0.tgz#793ae174d043d2118d520eaec67f0986c319f7a3" @@ -86,7 +104,7 @@ "@azure/ms-rest-js" "^2.0.4" tslib "^1.10.0" -"@azure/ms-rest-azure-js@^1.3.2": +"@azure/ms-rest-azure-js@^1.1.0", "@azure/ms-rest-azure-js@^1.3.2": version "1.3.8" resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-js/-/ms-rest-azure-js-1.3.8.tgz#96b518223d3baa2496b2981bc07288b3d887486e" integrity sha512-AHLfDTCyIH6wBK6+CpImI6sc9mLZ17ZgUrTx3Rhwv+3Mb3Z73BxormkarfR6Stb6scrBYitxJ27FXyndXlGAYg== @@ -118,6 +136,20 @@ uuid "^3.2.1" xml2js "^0.4.19" +"@azure/ms-rest-js@^1.1.0": + version "1.8.15" + resolved "https://botbuilder.myget.org/F/botframework-cli/npm/@azure/ms-rest-js/-/@azure/ms-rest-js-1.8.15.tgz#4267b6b8c00d85301791fe0cf347e0455a807338" + integrity sha1-Qme2uMANhTAXkf4M80fgRVqAczg= + dependencies: + "@types/tunnel" "0.0.0" + axios "^0.19.0" + form-data "^2.3.2" + tough-cookie "^2.4.3" + tslib "^1.9.2" + tunnel "0.0.6" + uuid "^3.2.1" + xml2js "^0.4.19" + "@azure/ms-rest-js@^1.8.1", "@azure/ms-rest-js@^1.8.10": version "1.8.14" resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-1.8.14.tgz#657fc145db20b6eb3d58d1a2055473aa72eb609d"