Exposing Azure HTTP requests method in Azurecore extension for external consumption (#14135)

* Exposing azure HTTP request in azurecore
Moving migration specific request from azurecore to migration
Created a migrations typing file

* Deleting the typings file in sql migration

* Fixed typos in comments

* Adding default host for azure https requests

* Fixed operator in service url modification

* Changed path and host logic

* Made chagned requested in the PR

* Fixed variable names

* Adding / check for path.

* Changing error code check

* Fixed status logic in azure rest request
Fixed comment logic
Converting error array to string while throwing

* Fixed status check

* Fixed typos and cleaning up
This commit is contained in:
Aasim Khan
2021-02-03 09:31:59 -08:00
committed by GitHub
parent 9ac180d772
commit b390052c86
7 changed files with 127 additions and 130 deletions

View File

@@ -83,26 +83,5 @@ declare module 'azureResource' {
export interface BlobContainer extends AzureResource { }
export interface FileShare extends AzureResource { }
export interface MigrationControllerProperties {
name: string;
subscriptionId: string;
resourceGroup: string;
location: string;
provisioningState: string;
integrationRuntimeState?: string;
isProvisioned?: boolean;
}
export interface MigrationController {
properties: MigrationControllerProperties;
location: string;
id: string;
name: string;
error: {
code: string,
message: string
}
}
}
}

View File

@@ -7,7 +7,7 @@ import { ResourceGraphClient } from '@azure/arm-resourcegraph';
import { TokenCredentials } from '@azure/ms-rest-js';
import axios, { AxiosRequestConfig } from 'axios';
import * as azdata from 'azdata';
import { HttpRequestResult, GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult, GetBlobContainersResult, GetFileSharesResult, GetMigrationControllerResult, CreateMigrationControllerResult, GetMigrationControllerAuthKeysResult } from 'azurecore';
import { AzureRestResponse, GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult, GetBlobContainersResult, GetFileSharesResult, HttpRequestMethod } from 'azurecore';
import { azureResource } from 'azureResource';
import { EOL } from 'os';
import * as nls from 'vscode-nls';
@@ -288,18 +288,19 @@ export async function getSelectedSubscriptions(appContext: AppContext, account?:
return result;
}
enum HttpRequestType {
GET,
POST,
PUT,
DELETE
}
/**
* Make a HTTP request to Azure REST apis.
* Makes Azure REST requests to create, retrieve, update or delete access to azure service's resources.
* For reference to different service URLs, See https://docs.microsoft.com/rest/api/?view=Azure
* @param account The azure account used to acquire access token
* @param subscription The subscription under azure account where the service will perform operations.
* @param path The path for the service starting from '/subscription/..'. See https://docs.microsoft.com/rest/api/azure/.
* @param requestType Http request method. Currently GET, PUT, POST and DELETE methods are supported.
* @param requestBody Optional request body to be used in PUT and POST requests.
* @param ignoreErrors When this flag is set the method will not throw any runtime or service errors and will return the errors in errors array.
* @param host Use this to override the host. The default host is https://management.azure.com
*/
export async function makeHttpRequest(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, ignoreErrors: boolean = false, url: string, requestType: HttpRequestType, requestBody?: any): Promise<HttpRequestResult> {
const result: HttpRequestResult = { response: {}, errors: [] };
export async function makeHttpRequest(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, path: string, requestType: HttpRequestMethod, requestBody?: any, ignoreErrors: boolean = false, host: string = 'https://management.azure.com'): Promise<AzureRestResponse> {
const result: AzureRestResponse = { response: {}, errors: [] };
if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) {
const error = new Error(invalidAzureAccount);
@@ -347,24 +348,35 @@ export async function makeHttpRequest(account: azdata.Account, subscription: azu
validateStatus: () => true // Never throw
};
let response;
// Adding '/' if path does not begin with it.
if (path.indexOf('/') !== 0) {
path = `/${path}`;
}
let requestUrl: string;
if (host) {
requestUrl = `${host}${path}`;
} else {
requestUrl = `https://management.azure.com${path}`;
}
let response;
switch (requestType) {
case HttpRequestType.GET:
response = await axios.get(url, config);
case HttpRequestMethod.GET:
response = await axios.get(requestUrl, config);
break;
case HttpRequestType.POST:
response = await axios.post(url, requestBody, config);
case HttpRequestMethod.POST:
response = await axios.post(requestUrl, requestBody, config);
break;
case HttpRequestType.PUT:
response = await axios.put(url, requestBody, config);
case HttpRequestMethod.PUT:
response = await axios.put(requestUrl, requestBody, config);
break;
case HttpRequestType.DELETE:
response = await axios.delete(url, config);
case HttpRequestMethod.DELETE:
response = await axios.delete(requestUrl, config);
break;
}
if (response.status !== 200) {
if (response.status < 200 || response.status > 299) {
let errorMessage: string[] = [];
errorMessage.push(response.status.toString());
errorMessage.push(response.statusText);
@@ -384,8 +396,8 @@ export async function makeHttpRequest(account: azdata.Account, subscription: azu
}
export async function getBlobContainers(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, storageAccount: azureResource.AzureGraphResource, ignoreErrors: boolean): Promise<GetBlobContainersResult> {
const apiEndpoint = `https://management.azure.com/subscriptions/${subscription.id}/resourceGroups/${storageAccount.resourceGroup}/providers/Microsoft.Storage/storageAccounts/${storageAccount.name}/blobServices/default/containers?api-version=2019-06-01`;
const response = await makeHttpRequest(account, subscription, ignoreErrors, apiEndpoint, HttpRequestType.GET);
const path = `/subscriptions/${subscription.id}/resourceGroups/${storageAccount.resourceGroup}/providers/Microsoft.Storage/storageAccounts/${storageAccount.name}/blobServices/default/containers?api-version=2019-06-01`;
const response = await makeHttpRequest(account, subscription, path, HttpRequestMethod.GET, undefined, ignoreErrors);
return {
blobContainers: response?.response?.data?.value ?? [],
errors: response.errors ? response.errors : []
@@ -393,42 +405,10 @@ export async function getBlobContainers(account: azdata.Account, subscription: a
}
export async function getFileShares(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, storageAccount: azureResource.AzureGraphResource, ignoreErrors: boolean): Promise<GetFileSharesResult> {
const apiEndpoint = `https://management.azure.com/subscriptions/${subscription.id}/resourceGroups/${storageAccount.resourceGroup}/providers/Microsoft.Storage/storageAccounts/${storageAccount.name}/fileServices/default/shares?api-version=2019-06-01`;
const response = await makeHttpRequest(account, subscription, ignoreErrors, apiEndpoint, HttpRequestType.GET);
const path = `/subscriptions/${subscription.id}/resourceGroups/${storageAccount.resourceGroup}/providers/Microsoft.Storage/storageAccounts/${storageAccount.name}/fileServices/default/shares?api-version=2019-06-01`;
const response = await makeHttpRequest(account, subscription, path, HttpRequestMethod.GET, undefined, ignoreErrors);
return {
fileShares: response?.response?.data?.value ?? [],
errors: response.errors ? response.errors : []
};
}
export async function getMigrationControllers(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, resourceGroupName: string, regionName: string, controllerName: string, ignoreErrors: boolean): Promise<GetMigrationControllerResult> {
const apiEndpoint = `https://${regionName}.management.azure.com/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DataMigration/Controllers/${controllerName}?api-version=2020-09-01-preview`;
const response = await makeHttpRequest(account, subscription, false, apiEndpoint, HttpRequestType.GET);
return {
controller: response?.response?.data ?? undefined,
errors: response.errors ? response.errors : []
};
}
export async function createMigrationController(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, resourceGroupName: string, regionName: string, controllerName: string, ignoreErrors: boolean): Promise<CreateMigrationControllerResult> {
const apiEndpoint = `https://${regionName}.management.azure.com/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DataMigration/Controllers/${controllerName}?api-version=2020-09-01-preview`;
const requestBody = {
'location': regionName
};
const response = await makeHttpRequest(account, subscription, ignoreErrors, apiEndpoint, HttpRequestType.PUT, requestBody);
return {
controller: response?.response?.data ?? undefined,
errors: response.errors ? response.errors : []
};
}
export async function getMigrationControllerAuthKeys(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, resourceGroupName: string, regionName: string, controllerName: string, ignoreErrors: boolean): Promise<GetMigrationControllerAuthKeysResult> {
const apiEndpoint = `https://${regionName}.management.azure.com/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DataMigration/Controllers/${controllerName}/ListAuthKeys?api-version=2020-09-01-preview`;
const response = await makeHttpRequest(account, subscription, ignoreErrors, apiEndpoint, HttpRequestType.POST);
return {
keyName1: response?.response?.data?.keyName1 ?? '',
keyName2: response?.response?.data?.keyName2 ?? '',
errors: response.errors ? response.errors : []
};
}