diff --git a/extensions/sql-migration/package.json b/extensions/sql-migration/package.json index 6b4692c3af..a22e912bc7 100644 --- a/extensions/sql-migration/package.json +++ b/extensions/sql-migration/package.json @@ -2,7 +2,7 @@ "name": "sql-migration", "displayName": "%displayName%", "description": "%description%", - "version": "1.4.7", + "version": "1.4.8", "publisher": "Microsoft", "preview": false, "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt", diff --git a/extensions/sql-migration/src/api/azure.ts b/extensions/sql-migration/src/api/azure.ts index 554bb4ea76..5980d87af6 100644 --- a/extensions/sql-migration/src/api/azure.ts +++ b/extensions/sql-migration/src/api/azure.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import * as azdata from 'azdata'; import * as azurecore from 'azurecore'; import * as constants from '../constants/strings'; -import { getSessionIdHeader } from './utils'; +import { SqlMigrationExtensionId } from './utils'; import { URL } from 'url'; import { MigrationSourceAuthenticationType, MigrationStateModel, NetworkShare } from '../models/stateMachine'; import { NetworkInterface } from './dataModels/azure/networkInterfaceModel'; @@ -43,7 +43,7 @@ export async function getLocations(account: azdata.Account, subscription: Subscr const path = `/subscriptions/${subscription.id}/providers/Microsoft.DataMigration?api-version=${ARM_MGMT_API_VERSION}`; const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const dataMigrationResourceProvider = (await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host))?.response?.data; + const dataMigrationResourceProvider = (await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()))?.response?.data; const sqlMigratonResource = dataMigrationResourceProvider?.resourceTypes?.find((r: any) => r.resourceType === 'SqlMigrationServices'); const sqlMigrationResourceLocations = sqlMigratonResource?.locations ?? []; if (response.errors?.length > 0) { @@ -234,11 +234,34 @@ export type InstanceViewStatus = { time: string, } +let userAgent: string; +function getUserAgent(): string { + if (!userAgent) { + const adsVersion = azdata.version ?? 'unknown'; + const adsQuality = azdata.env.quality ?? 'unknown'; + const sqlExt = vscode.extensions.getExtension(SqlMigrationExtensionId); + const sqlExtVersion = sqlExt?.packageJSON.version ?? 'unknown'; + userAgent = `AzureDataStudio/${adsVersion} (${adsQuality}) ${SqlMigrationExtensionId}/${sqlExtVersion}`; + } + return userAgent; +} + +export function getDefaultHeader(): Record { + return { 'User-Agent': getUserAgent() }; +} + +export function getSessionIdHeader(sessionId: string): Record { + return { + 'User-Agent': getUserAgent(), + 'SqlMigrationSessionId': sessionId, + }; +} + export async function getAvailableSqlDatabaseServers(account: azdata.Account, subscription: Subscription): Promise { const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/providers/Microsoft.Sql/servers?api-version=${SQL_SQLDB_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -253,7 +276,7 @@ export async function getAvailableSqlDatabases(account: azdata.Account, subscrip const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.Sql/servers/${serverName}/databases?api-version=${SQL_SQLDB_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -268,7 +291,7 @@ export async function getAvailableSqlVMs(account: azdata.Account, subscription: const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachines?api-version=${SQL_VM_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors @@ -284,7 +307,7 @@ export async function getVMInstanceView(sqlVm: SqlVMServer, account: azdata.Acco const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/resourceGroups/${getResourceGroupFromId(sqlVm.id)}/providers/Microsoft.Compute/virtualMachines/${sqlVm.name}/instanceView?api-version=${COMPUTE_VM_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors @@ -301,7 +324,7 @@ export async function getAzureResourceGivenId(account: azdata.Account, subscript const api = await getAzureCoreAPI(); const path = encodeURI(`${id}?api-version=${apiVersion}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors @@ -360,7 +383,7 @@ export async function getSqlMigrationServiceById(account: azdata.Account, subscr const api = await getAzureCoreAPI(); const path = encodeURI(`${sqlMigrationServiceId}?api-version=${DMSV2_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -375,7 +398,7 @@ export async function getSqlMigrationServicesByResourceGroup(account: azdata.Acc const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/resourceGroups/${resouceGroupName}/providers/Microsoft.DataMigration/sqlMigrationServices?api-version=${DMSV2_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -393,7 +416,7 @@ export async function getSqlMigrationServices(account: azdata.Account, subscript const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/providers/Microsoft.DataMigration/sqlMigrationServices?api-version=${DMSV2_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -446,7 +469,7 @@ export async function getSqlMigrationServiceAuthKeys(account: azdata.Account, su const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DataMigration/sqlMigrationServices/${sqlMigrationServiceName}/ListAuthKeys?api-version=${DMSV2_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -467,7 +490,7 @@ export async function regenerateSqlMigrationServiceAuthKey(account: azdata.Accou 'keyName': keyName, }; const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -499,7 +522,7 @@ export async function getSqlMigrationServiceMonitoringData(account: azdata.Accou const api = await getAzureCoreAPI(); const path = encodeURI(`/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DataMigration/sqlMigrationServices/${sqlMigrationService}/listMonitoringData?api-version=${DMSV2_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -544,7 +567,7 @@ export async function getMigrationDetails(account: azdata.Account, subscription: const api = await getAzureCoreAPI(); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -559,7 +582,7 @@ export async function getServiceMigrations(account: azdata.Account, subscription const path = encodeURI(`${resourceId}/listMigrations?&api-version=${DMSV2_API_VERSION}`); const api = await getAzureCoreAPI(); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -575,7 +598,7 @@ export async function getMigrationTargetInstance(account: azdata.Account, subscr const path = encodeURI(`${targetServerId}?api-version=${SQL_MI_API_VERSION}`); const api = await getAzureCoreAPI(); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -590,7 +613,7 @@ export async function getMigrationAsyncOperationDetails(account: azdata.Account, const api = await getAzureCoreAPI(); const path = url.replace((new URL(url)).origin + '/', ''); // path is everything after the hostname, e.g. the 'test' part of 'https://management.azure.com/test' const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -605,7 +628,7 @@ export async function startMigrationCutover(account: azdata.Account, subscriptio const path = encodeURI(`${migration.id}/cutover?api-version=${DMSV2_API_VERSION}`); const requestBody = { migrationOperationId: migration.properties.migrationOperationId }; const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -620,7 +643,7 @@ export async function stopMigration(account: azdata.Account, subscription: Subsc const path = encodeURI(`${migration.id}/cancel?api-version=${DMSV2_API_VERSION}`); const requestBody = { migrationOperationId: migration.properties.migrationOperationId }; const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -634,7 +657,7 @@ export async function retryMigration(account: azdata.Account, subscription: Subs const path = encodeURI(`${migration.id}/retry?api-version=${DMSV2_API_VERSION}`); const requestBody = { migrationOperationId: migration.properties.migrationOperationId }; const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.POST, requestBody, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) @@ -647,7 +670,7 @@ export async function deleteMigration(account: azdata.Account, subscription: Sub const api = await getAzureCoreAPI(); const path = encodeURI(`${migrationId}?api-version=${DMSV2_API_VERSION}`); const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint; - const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.DELETE, undefined, true, host); + const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.DELETE, undefined, true, host, getDefaultHeader()); if (response.errors.length > 0) { const message = response.errors .map(err => err.message) diff --git a/extensions/sql-migration/src/api/utils.ts b/extensions/sql-migration/src/api/utils.ts index 81e513a45e..ac5a63e6b9 100644 --- a/extensions/sql-migration/src/api/utils.ts +++ b/extensions/sql-migration/src/api/utils.ts @@ -304,10 +304,6 @@ export function decorate(decorator: (fn: Function, key: string) => Function): Fu }; } -export function getSessionIdHeader(sessionId: string): { [key: string]: string } { - return { 'SqlMigrationSessionId': sessionId }; -} - export function getMigrationStatusWithErrors(migration: azure.DatabaseMigration): string { const properties = migration.properties; const migrationStatus = getMigrationStatus(migration) ?? '';