Dedicated Gateway Portal Changes (#540)

* Portal changes for DedicatedGateway

Changes to support creation and deletion of DedicatedGateway resource.

Tested locally with various scenarios.

* Portal changes for DedicatedGateway. CR feedback

* Stylecop changes

* Removing TODO comments

* exposed baselineValues

* added getOnSaveNotification

* disable UI when onSave is taking place

* minro edits

* made polling optional

* added optional polling

* added default

* Added portal notifications

* merged more changes

* minor edits

* added label for description

* Added correlationids and polling of refresh

* Added correlationids and polling of refresh

* minor edit

* added label tooltip

* removed ClassInfo decorator

* Added dynamic decription

* added info and warninf types for description

* more changes to promise retry

* promise retry changes

* compile errors fixed

* New changes

* added operationstatus link

* merged sqlxEdits

* undid sqlx changes

* added completed notification

* passed retryInterval in notif options

* more changes

* added polling on landing on the page

* edits for error display

* added keys blade link

* added link generation

* added link to blade

* Modified info and description

* fixed format errors

* Second cut of the Portal

* OnChange for Number of instances

* added keys for texts

* fixed lint errors

* Added support for undefined dynamic description

* fixed failing test

* disable save/discard buttons

* fixed sqlx errors

* Dedicated Gateway changes to add the keys blade

* Change connectionStringText

* Change connectionStringText

* Text changes

* Added UI improvements

* Code review feedback

* undid package lock changes

Co-authored-by: Srinath Narayanan <srnara@microsoft.com>
This commit is contained in:
fnbalaji 2021-03-18 14:00:28 -07:00 committed by GitHub
parent be4e490a64
commit 909a9fa522
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 441 additions and 54 deletions

View File

@ -204,7 +204,7 @@
"pack:fast": "node --max_old_space_size=10196 ./node_modules/webpack/bin/webpack.js --mode development --progress", "pack:fast": "node --max_old_space_size=10196 ./node_modules/webpack/bin/webpack.js --mode development --progress",
"copyToConsumers": "node copyToConsumers", "copyToConsumers": "node copyToConsumers",
"test": "rimraf coverage && jest", "test": "rimraf coverage && jest",
"test:e2e": "jest -c ./jest.config.e2e.js --detectOpenHandles selfServeExample.spec.ts", "test:e2e": "jest -c ./jest.config.e2e.js --detectOpenHandles",
"watch": "npm run start", "watch": "npm run start",
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/", "wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
"build:ase": "gulp build:ase", "build:ase": "gulp build:ase",

View File

@ -36,6 +36,57 @@
"SubmissionMessageErrorText": "Data update failed because of errors.", "SubmissionMessageErrorText": "Data update failed because of errors.",
"OnSaveFailureMessage": "Data save operation not currently permitted." "OnSaveFailureMessage": "Data save operation not currently permitted."
}, },
"SqlX": {} "SqlX": {
"DedicatedGatewayDescription": "Provision a dedicated gateway cluster for your Azure Cosmos DB account. A dedicated gateway is compute that is a front-end to data in your Azure Cosmos DB account. Your dedicated gateway automatically includes the integrated cache, which can improve read performance. ",
"DedicatedGateway": "Dedicated Gateway",
"Enable": "Enable",
"Disable": "Disable",
"LearnAboutDedicatedGateway": "Learn more about dedicated gateway.",
"DeprovisioningDetailsText": "Learn more about deprovisioning the dedicated gateway.",
"DedicatedGatewayPricing": "Learn more about dedicated gateway pricing",
"SKUs": "SKUs",
"SKUsPlaceHolder": "Select SKUs",
"NumberOfInstances": "Number of instances",
"CosmosD4s": "Cosmos.D4s (General Purpose Cosmos Compute with 4 vCPUs, 16 GB Memory)",
"CosmosD8s": "Cosmos.D8s (General Purpose Cosmos Compute with 8 vCPUs, 32 GB Memory)",
"CosmosD16s": "Cosmos.D16s (General Purpose Cosmos Compute with 16 vCPUs, 64 GB Memory)",
"CosmosD32s": "Cosmos.D32s (General Purpose Cosmos Compute with 32 vCPUs, 128 GB Memory)",
"CreateMessage": "Dedicated gateway resource is being created.",
"CreateInitializeTitle": "Provisioning resource",
"CreateInitializeMessage": "Dedicated gateway resource will be provisioned.",
"CreateSuccessTitle": "Resource provisioned",
"CreateSuccesseMessage": "Dedicated gateway resource provisioned.",
"CreateFailureTitle": "Failed to provision resource",
"CreateFailureMessage": "Dedicated gateway resource provisioning failed.",
"UpdateMessage": "Dedicated gateway resource is being updated.",
"UpdateInitializeTitle": "Updating resource",
"UpdateInitializeMessage": "Dedicated gateway resource will be updated.",
"UpdateSuccessTitle": "Resource updated",
"UpdateSuccesseMessage": "Dedicated gateway resource updated.",
"UpdateFailureTitle": "Failed to update resource",
"UpdateFailureMessage": "Dedicated gateway resource updation failed.",
"DeleteMessage": "Dedicated gateway resource is being deleted.",
"DeleteInitializeTitle": "Deleting resource",
"DeleteInitializeMessage": "Dedicated gateway resource will be deleted.",
"DeleteSuccessTitle": "Resource deleted",
"DeleteSuccesseMessage": "Dedicated gateway resource deleted.",
"DeleteFailureTitle": "Failed to delete resource",
"DeleteFailureMessage": "Dedicated gateway resource deletion failed.",
"CannotSave": "Cannot save the changes to the Dedicated gateway resource at the moment",
"DedicatedGatewayEndpoint": "Dedicated gatewayEndpoint",
"NoValue": "",
"SKUDetails": "SKU Details: ",
"CosmosD4Details": "General Purpose Cosmos Compute with 4 vCPUs, 16 GB Memory",
"CosmosD8Details": "General Purpose Cosmos Compute with 8 vCPUs, 32 GB Memory",
"CosmosD16Details": "General Purpose Cosmos Compute with 16 vCPUs, 64 GB Memory",
"CosmosD32Details": "General Purpose Cosmos Compute with 32 vCPUs, 128 GB Memory",
"Cost": "Cost",
"CostText": "Hourly cost of the dedicated gateway resource depends on the SKU selection, number of instances per region, and number of regions.",
"ConnectionString": "Connection String",
"ConnectionStringText": "To use the dedicated gateway, use the connection string shown in ",
"KeysBlade": "the keys blade",
"WarningBannerOnUpdate": "Adding or modifying dedicated gateway instances may affect your bill.",
"WarningBannerOnDelete": "After deprovisioning the dedicated gateway, you must update any applications using the old dedicated gateway connection string."
}
} }
} }

View File

@ -1,33 +1,98 @@
import { RefreshResult } from "../SelfServeTypes"; import { RefreshResult } from "../SelfServeTypes";
import { userContext } from "../../UserContext";
import { armRequestWithoutPolling } from "../../Utils/arm/request";
import { configContext } from "../../ConfigContext";
import { SqlxServiceResource, UpdateDedicatedGatewayRequestParameters } from "./SqlxTypes";
const apiVersion = "2020-06-01-preview";
export enum ResourceStatus {
Running = "Running",
Creating = "Creating",
Updating = "Updating",
Deleting = "Deleting",
}
export interface DedicatedGatewayResponse { export interface DedicatedGatewayResponse {
sku: string; sku: string;
instances: number; instances: number;
status: string;
endpoint: string;
} }
export const getRegionSpecificMinInstances = async (): Promise<number> => { export const getPath = (subscriptionId: string, resourceGroup: string, name: string): string => {
// TODO: write RP call to get min number of instances needed for this region return `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${name}/services/sqlx`;
throw new Error("getRegionSpecificMinInstances not implemented");
}; };
export const getRegionSpecificMaxInstances = async (): Promise<number> => { export const updateDedicatedGatewayResource = async (sku: string, instances: number): Promise<string> => {
// TODO: write RP call to get max number of instances needed for this region const path = getPath(userContext.subscriptionId, userContext.resourceGroup, userContext.databaseAccount.name);
throw new Error("getRegionSpecificMaxInstances not implemented"); const body: UpdateDedicatedGatewayRequestParameters = {
properties: {
instanceSize: sku,
instanceCount: instances,
serviceType: "Sqlx",
},
};
const armRequestResult = await armRequestWithoutPolling({
host: configContext.ARM_ENDPOINT,
path,
method: "PUT",
apiVersion,
body,
});
return armRequestResult.operationStatusUrl;
}; };
export const updateDedicatedGatewayProvisioning = async (sku: string, instances: number): Promise<void> => { export const deleteDedicatedGatewayResource = async (): Promise<string> => {
// TODO: write RP call to update dedicated gateway provisioning const path = getPath(userContext.subscriptionId, userContext.resourceGroup, userContext.databaseAccount.name);
throw new Error( const armRequestResult = await armRequestWithoutPolling({
`updateDedicatedGatewayProvisioning not implemented. Parameters- sku: ${sku}, instances:${instances}` host: configContext.ARM_ENDPOINT,
); path,
method: "DELETE",
apiVersion,
});
return armRequestResult.operationStatusUrl;
}; };
export const initializeDedicatedGatewayProvisioning = async (): Promise<DedicatedGatewayResponse> => { export const getDedicatedGatewayResource = async (): Promise<SqlxServiceResource> => {
// TODO: write RP call to initialize UI for dedicated gateway provisioning const path = getPath(userContext.subscriptionId, userContext.resourceGroup, userContext.databaseAccount.name);
throw new Error("initializeDedicatedGatewayProvisioning not implemented"); const armRequestResult = await armRequestWithoutPolling<SqlxServiceResource>({
host: configContext.ARM_ENDPOINT,
path,
method: "GET",
apiVersion,
});
return armRequestResult.result;
};
export const getCurrentProvisioningState = async (): Promise<DedicatedGatewayResponse> => {
try {
const response = await getDedicatedGatewayResource();
return {
sku: response.properties.instanceSize,
instances: response.properties.instanceCount,
status: response.properties.status,
endpoint: response.properties.sqlxEndPoint,
};
} catch (e) {
return { sku: undefined, instances: undefined, status: undefined, endpoint: undefined };
}
}; };
export const refreshDedicatedGatewayProvisioning = async (): Promise<RefreshResult> => { export const refreshDedicatedGatewayProvisioning = async (): Promise<RefreshResult> => {
// TODO: write RP call to check if dedicated gateway update has gone through try {
throw new Error("refreshDedicatedGatewayProvisioning not implemented"); const response = await getDedicatedGatewayResource();
if (response.properties.status === ResourceStatus.Running.toString()) {
return { isUpdateInProgress: false, updateInProgressMessageTKey: undefined };
} else if (response.properties.status === ResourceStatus.Creating.toString()) {
return { isUpdateInProgress: true, updateInProgressMessageTKey: "CreateMessage" };
} else if (response.properties.status === ResourceStatus.Deleting.toString()) {
return { isUpdateInProgress: true, updateInProgressMessageTKey: "DeleteMessage" };
} else {
return { isUpdateInProgress: true, updateInProgressMessageTKey: "UpdateMessage" };
}
} catch {
//TODO differentiate between different failures
return { isUpdateInProgress: false, updateInProgressMessageTKey: undefined };
}
}; };

View File

@ -1,6 +1,7 @@
import { IsDisplayable, OnChange, Values } from "../Decorators"; import { IsDisplayable, OnChange, RefreshOptions, Values } from "../Decorators";
import { import {
ChoiceItem, ChoiceItem,
Description,
DescriptionType, DescriptionType,
InputType, InputType,
NumberUiType, NumberUiType,
@ -9,65 +10,284 @@ import {
SelfServeBaseClass, SelfServeBaseClass,
SmartUiInput, SmartUiInput,
} from "../SelfServeTypes"; } from "../SelfServeTypes";
import { refreshDedicatedGatewayProvisioning } from "./SqlX.rp"; import { BladeType, generateBladeLink } from "../SelfServeUtils";
import {
deleteDedicatedGatewayResource,
getCurrentProvisioningState,
refreshDedicatedGatewayProvisioning,
updateDedicatedGatewayResource,
} from "./SqlX.rp";
const costPerHourValue: Description = {
textTKey: "CostText",
type: DescriptionType.Text,
link: {
href: "https://azure.microsoft.com/en-us/pricing/details/cosmos-db/",
textTKey: "DedicatedGatewayPricing",
},
};
const connectionStringValue: Description = {
textTKey: "ConnectionStringText",
type: DescriptionType.Text,
link: {
href: generateBladeLink(BladeType.SqlKeys),
textTKey: "KeysBlade",
},
};
const CosmosD4s = "Cosmos.D4s";
const CosmosD8s = "Cosmos.D8s";
const CosmosD16s = "Cosmos.D16s";
const CosmosD32s = "Cosmos.D32s";
const getSKUDetails = (sku: string): string => {
if (sku === CosmosD4s) {
return "CosmosD4Details";
} else if (sku === CosmosD8s) {
return "CosmosD8Details";
} else if (sku === CosmosD16s) {
return "CosmosD16Details";
} else if (sku === CosmosD32s) {
return "CosmosD32Details";
}
return "Not Supported Yet";
};
const onSKUChange = (newValue: InputType, currentValues: Map<string, SmartUiInput>): Map<string, SmartUiInput> => {
currentValues.set("sku", { value: newValue });
currentValues.set("skuDetails", {
value: { textTKey: getSKUDetails(`${newValue.toString()}`), type: DescriptionType.Text } as Description,
});
currentValues.set("costPerHour", { value: costPerHourValue });
return currentValues;
};
const onNumberOfInstancesChange = (
newValue: InputType,
currentValues: Map<string, SmartUiInput>
): Map<string, SmartUiInput> => {
currentValues.set("instances", { value: newValue });
currentValues.set("warningBanner", {
value: { textTKey: "WarningBannerOnUpdate" } as Description,
hidden: false,
});
return currentValues;
};
const onEnableDedicatedGatewayChange = ( const onEnableDedicatedGatewayChange = (
newValue: InputType, newValue: InputType,
currentState: Map<string, SmartUiInput> currentValues: Map<string, SmartUiInput>,
baselineValues: ReadonlyMap<string, SmartUiInput>
): Map<string, SmartUiInput> => { ): Map<string, SmartUiInput> => {
const sku = currentState.get("sku"); currentValues.set("enableDedicatedGateway", { value: newValue });
const instances = currentState.get("instances"); const dedicatedGatewayOriginallyEnabled = baselineValues.get("enableDedicatedGateway")?.value as boolean;
const isSkuHidden = newValue === undefined || !(newValue as boolean); if (dedicatedGatewayOriginallyEnabled === newValue) {
currentState.set("enableDedicatedGateway", { value: newValue }); currentValues.set("sku", baselineValues.get("sku"));
currentState.set("sku", { value: sku.value, hidden: isSkuHidden }); currentValues.set("instances", baselineValues.get("instances"));
currentState.set("instances", { value: instances.value, hidden: isSkuHidden }); currentValues.set("skuDetails", baselineValues.get("skuDetails"));
return currentState; currentValues.set("costPerHour", baselineValues.get("costPerHour"));
currentValues.set("warningBanner", baselineValues.get("warningBanner"));
currentValues.set("connectionString", baselineValues.get("connectionString"));
return currentValues;
}
currentValues.set("warningBanner", undefined);
if (newValue === true) {
currentValues.set("warningBanner", {
value: {
textTKey: "WarningBannerOnUpdate",
link: {
href: "https://docs.microsoft.com/en-us/azure/cosmos-db/introduction",
textTKey: "DedicatedGatewayPricing",
},
} as Description,
hidden: false,
});
} else {
currentValues.set("warningBanner", {
value: {
textTKey: "WarningBannerOnDelete",
link: {
href: "https://docs.microsoft.com/en-us/azure/cosmos-db/introduction",
textTKey: "DeprovisioningDetailsText",
},
} as Description,
hidden: false,
});
}
const sku = currentValues.get("sku");
const instances = currentValues.get("instances");
const hideAttributes = newValue === undefined || !(newValue as boolean);
currentValues.set("sku", {
value: sku.value,
hidden: hideAttributes,
disabled: dedicatedGatewayOriginallyEnabled,
});
currentValues.set("instances", {
value: instances.value,
hidden: hideAttributes,
disabled: dedicatedGatewayOriginallyEnabled,
});
currentValues.set("skuDetails", {
value: { textTKey: getSKUDetails(`${currentValues.get("sku").value}`), type: DescriptionType.Text } as Description,
hidden: hideAttributes,
disabled: dedicatedGatewayOriginallyEnabled,
});
currentValues.set("costPerHour", { value: costPerHourValue, hidden: hideAttributes });
currentValues.set("connectionString", {
value: connectionStringValue,
hidden: !newValue || !dedicatedGatewayOriginallyEnabled,
});
return currentValues;
}; };
const skuDropDownItems: ChoiceItem[] = [
{ label: "CosmosD4s", key: CosmosD4s },
{ label: "CosmosD8s", key: CosmosD8s },
{ label: "CosmosD16s", key: CosmosD16s },
{ label: "CosmosD32s", key: CosmosD32s },
];
const getSkus = async (): Promise<ChoiceItem[]> => { const getSkus = async (): Promise<ChoiceItem[]> => {
// TODO: get SKUs from getRegionSpecificSkus() RP call and return array of {label:..., key:...}. return skuDropDownItems;
throw new Error("getSkus not implemented.");
}; };
const getInstancesMin = async (): Promise<number> => { const getInstancesMin = async (): Promise<number> => {
// TODO: get SKUs from getRegionSpecificSkus() RP call and return array of {label:..., key:...}. return 1;
throw new Error("getInstancesMin not implemented.");
}; };
const getInstancesMax = async (): Promise<number> => { const getInstancesMax = async (): Promise<number> => {
// TODO: get SKUs from getRegionSpecificSkus() RP call and return array of {label:..., key:...}. return 5;
throw new Error("getInstancesMax not implemented.");
};
const validate = (currentValues: Map<string, SmartUiInput>): void => {
// TODO: add cusom validation logic to be called before Saving the data.
throw new Error(`validate not implemented. No. of properties to validate: ${currentValues.size}`);
}; };
@IsDisplayable() @IsDisplayable()
@RefreshOptions({ retryIntervalInMs: 20000 })
export default class SqlX extends SelfServeBaseClass { export default class SqlX extends SelfServeBaseClass {
public onRefresh = async (): Promise<RefreshResult> => { public onRefresh = async (): Promise<RefreshResult> => {
return refreshDedicatedGatewayProvisioning(); return await refreshDedicatedGatewayProvisioning();
}; };
public onSave = async (currentValues: Map<string, SmartUiInput>): Promise<OnSaveResult> => { public onSave = async (
validate(currentValues); currentValues: Map<string, SmartUiInput>,
// TODO: add pre processing logic before calling the updateDedicatedGatewayProvisioning() RP call. baselineValues: Map<string, SmartUiInput>
throw new Error(`onSave not implemented. No. of properties to save: ${currentValues.size}`); ): Promise<OnSaveResult> => {
const dedicatedGatewayCurrentlyEnabled = currentValues.get("enableDedicatedGateway")?.value as boolean;
const dedicatedGatewayOriginallyEnabled = baselineValues.get("enableDedicatedGateway")?.value as boolean;
currentValues.set("warningBanner", undefined);
//TODO : Add try catch for each RP call and return relevant notifications
if (dedicatedGatewayOriginallyEnabled) {
if (!dedicatedGatewayCurrentlyEnabled) {
const operationStatusUrl = await deleteDedicatedGatewayResource();
return {
operationStatusUrl: operationStatusUrl,
portalNotification: {
initialize: {
titleTKey: "DeleteInitializeTitle",
messageTKey: "DeleteInitializeMessage",
},
success: {
titleTKey: "DeleteSuccessTitle",
messageTKey: "DeleteSuccesseMessage",
},
failure: {
titleTKey: "DeleteFailureTitle",
messageTKey: "DeleteFailureMessage",
},
},
};
} else {
// Check for scaling up/down/in/out
return {
operationStatusUrl: undefined,
portalNotification: {
initialize: {
titleTKey: "UpdateInitializeTitle",
messageTKey: "UpdateInitializeMessage",
},
success: {
titleTKey: "UpdateSuccessTitle",
messageTKey: "UpdateSuccesseMessage",
},
failure: {
titleTKey: "UpdateFailureTitle",
messageTKey: "UpdateFailureMessage",
},
},
};
}
} else {
const sku = currentValues.get("sku")?.value as string;
const instances = currentValues.get("instances").value as number;
const operationStatusUrl = await updateDedicatedGatewayResource(sku, instances);
return {
operationStatusUrl: operationStatusUrl,
portalNotification: {
initialize: {
titleTKey: "CreateInitializeTitle",
messageTKey: "CreateInitializeTitle",
},
success: {
titleTKey: "CreateSuccessTitle",
messageTKey: "CreateSuccesseMessage",
},
failure: {
titleTKey: "CreateFailureTitle",
messageTKey: "CreateFailureMessage",
},
},
};
}
}; };
public initialize = async (): Promise<Map<string, SmartUiInput>> => { public initialize = async (): Promise<Map<string, SmartUiInput>> => {
// TODO: get initialization data from initializeDedicatedGatewayProvisioning() RP call. // Based on the RP call enableDedicatedGateway will be true if it has not yet been enabled and false if it has.
throw new Error("onSave not implemented"); const defaults = new Map<string, SmartUiInput>();
defaults.set("enableDedicatedGateway", { value: false });
defaults.set("sku", { value: CosmosD4s, hidden: true });
defaults.set("instances", { value: await getInstancesMin(), hidden: true });
defaults.set("skuDetails", undefined);
defaults.set("costPerHour", undefined);
defaults.set("connectionString", undefined);
const response = await getCurrentProvisioningState();
if (response.status && response.status !== "Deleting") {
defaults.set("enableDedicatedGateway", { value: true });
defaults.set("sku", { value: response.sku, disabled: true });
defaults.set("instances", { value: response.instances, disabled: true });
defaults.set("costPerHour", { value: costPerHourValue });
defaults.set("skuDetails", {
value: { textTKey: getSKUDetails(`${defaults.get("sku").value}`), type: DescriptionType.Text } as Description,
hidden: false,
});
defaults.set("connectionString", {
value: connectionStringValue,
hidden: false,
});
}
defaults.set("warningBanner", undefined);
return defaults;
}; };
@Values({
isDynamicDescription: true,
})
warningBanner: string;
@Values({ @Values({
description: { description: {
textTKey: "Provisioning dedicated gateways for SqlX accounts.", textTKey: "DedicatedGatewayDescription",
type: DescriptionType.Text, type: DescriptionType.Text,
link: { link: {
href: "https://docs.microsoft.com/en-us/azure/cosmos-db/introduction", href: "https://docs.microsoft.com/en-us/azure/cosmos-db/introduction",
textTKey: "Learn more about dedicated gateway.", textTKey: "LearnAboutDedicatedGateway",
}, },
}, },
}) })
@ -76,24 +296,44 @@ export default class SqlX extends SelfServeBaseClass {
@OnChange(onEnableDedicatedGatewayChange) @OnChange(onEnableDedicatedGatewayChange)
@Values({ @Values({
labelTKey: "DedicatedGateway", labelTKey: "DedicatedGateway",
trueLabelTKey: "Enable", trueLabelTKey: "Provisioned",
falseLabelTKey: "Disable", falseLabelTKey: "Deprovisioned",
}) })
enableDedicatedGateway: boolean; enableDedicatedGateway: boolean;
@OnChange(onSKUChange)
@Values({ @Values({
labelTKey: "SKUs", labelTKey: "SKUs",
choices: getSkus, choices: getSkus,
placeholderTKey: "Select SKUs", placeholderTKey: "SKUsPlaceHolder",
}) })
sku: ChoiceItem; sku: ChoiceItem;
@Values({ @Values({
labelTKey: "Number of instances", labelTKey: "SKUDetails",
isDynamicDescription: true,
})
skuDetails: string;
@OnChange(onNumberOfInstancesChange)
@Values({
labelTKey: "NumberOfInstances",
min: getInstancesMin, min: getInstancesMin,
max: getInstancesMax, max: getInstancesMax,
step: 1, step: 1,
uiType: NumberUiType.Spinner, uiType: NumberUiType.Spinner,
}) })
instances: number; instances: number;
@Values({
labelTKey: "Cost",
isDynamicDescription: true,
})
costPerHour: string;
@Values({
labelTKey: "ConnectionString",
isDynamicDescription: true,
})
connectionString: string;
} }

View File

@ -0,0 +1,31 @@
export type SqlxServiceResource = {
id: string;
name: string;
type: string;
properties: SqlxServiceProps;
locations: SqlxServiceLocations;
};
export type SqlxServiceProps = {
serviceType: string;
creationTime: string;
status: string;
instanceSize: string;
instanceCount: number;
sqlxEndPoint: string;
};
export type SqlxServiceLocations = {
location: string;
status: string;
sqlxEndpoint: string;
};
export type UpdateDedicatedGatewayRequestParameters = {
properties: UpdateDedicatedGatewayRequestProperties;
};
export type UpdateDedicatedGatewayRequestProperties = {
instanceSize: string;
instanceCount: number;
serviceType: string;
};