From 4617fa93648dbc23af565147ad10bd659d3e2c10 Mon Sep 17 00:00:00 2001 From: vchske Date: Fri, 16 Jun 2023 15:54:29 -0700 Subject: [PATCH] Update throughput settings tab with new elasticity properties (#1461) * Adding RU thermometer to settings throughput tab * Finalizing RU thermometer on throughput settings * Updated snapshot * Fixing formatting * Fixing lint errors * Rerun prettier * Fixing Offer properties * Fixing Types * Updating ARM clients, and enabling new elasticity properties * Updating snapshots * Updating an issue caused by updating ARM client * Latest changes based on feedback * Fixing lint and unit tests * Minor fix * Minor text change * Changed some formatting --- package.json | 2 +- src/Common/dataAccess/readCollectionOffer.ts | 12 + src/Common/dataAccess/readDatabaseOffer.ts | 12 + src/Common/dataAccess/readStoredProcedures.ts | 11 +- src/Contracts/DataModels.ts | 2 + .../Settings/SettingsRenderUtils.test.tsx | 59 +- .../Controls/Settings/SettingsRenderUtils.tsx | 155 +- .../ScaleComponent.test.tsx | 9 - .../SettingsSubComponents/ScaleComponent.tsx | 37 +- ...roughputInputAutoPilotV3Component.test.tsx | 3 +- .../ThroughputInputAutoPilotV3Component.tsx | 643 +++---- ...putInputAutoPilotV3Component.test.tsx.snap | 1523 ++++++++++++----- .../ConflictResolutionComponent.test.tsx.snap | 4 + .../ScaleComponent.test.tsx.snap | 15 - .../SubSettingsComponent.test.tsx.snap | 36 + .../SettingsRenderUtils.test.tsx.snap | 207 +-- .../cosmos/cassandraResources.ts | 6 +- .../arm/generatedClients/cosmos/collection.ts | 6 +- .../cosmos/collectionPartition.ts | 6 +- .../cosmos/collectionPartitionRegion.ts | 6 +- .../cosmos/collectionRegion.ts | 6 +- .../arm/generatedClients/cosmos/database.ts | 6 +- .../cosmos/databaseAccountRegion.ts | 6 +- .../cosmos/databaseAccounts.ts | 14 +- .../cosmos/gremlinResources.ts | 6 +- .../arm/generatedClients/cosmos/locations.ts | 27 + .../cosmos/mongoDBResources.ts | 6 +- .../arm/generatedClients/cosmos/operations.ts | 6 +- .../cosmos/partitionKeyRangeId.ts | 6 +- .../cosmos/partitionKeyRangeIdRegion.ts | 6 +- .../arm/generatedClients/cosmos/percentile.ts | 6 +- .../cosmos/percentileSourceTarget.ts | 6 +- .../cosmos/percentileTarget.ts | 6 +- .../generatedClients/cosmos/sqlResources.ts | 44 +- .../generatedClients/cosmos/tableResources.ts | 6 +- .../arm/generatedClients/cosmos/types.ts | 326 +++- tsconfig.json | 27 +- utils/armClientGenerator/generator.ts | 21 +- 38 files changed, 2194 insertions(+), 1091 deletions(-) create mode 100644 src/Utils/arm/generatedClients/cosmos/locations.ts diff --git a/package.json b/package.json index a1c438857..fd01978f6 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ "strict:find": "node ./strict-null-checks/find.js", "strict:add": "node ./strict-null-checks/auto-add.js", "compile:fullStrict": "tsc -p ./tsconfig.json --strictNullChecks", - "generateARMClients": "npx ts-node --compiler-options '{\"module\":\"commonjs\"}' utils/armClientGenerator/generator.ts" + "generateARMClients": "npx ts-node utils/armClientGenerator/generator.ts" }, "repository": { "type": "git", diff --git a/src/Common/dataAccess/readCollectionOffer.ts b/src/Common/dataAccess/readCollectionOffer.ts index 8bd5d589e..05dc3ab0a 100644 --- a/src/Common/dataAccess/readCollectionOffer.ts +++ b/src/Common/dataAccess/readCollectionOffer.ts @@ -96,6 +96,14 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri ? parseInt(resource.minimumThroughput) : resource.minimumThroughput; const autoscaleSettings = resource.autoscaleSettings; + const instantMaximumThroughput: number = + typeof resource.instantMaximumThroughput === "string" + ? parseInt(resource.instantMaximumThroughput) + : resource.instantMaximumThroughput; + const softAllowedMaximumThroughput: number = + typeof resource.softAllowedMaximumThroughput === "string" + ? parseInt(resource.softAllowedMaximumThroughput) + : resource.softAllowedMaximumThroughput; if (autoscaleSettings) { return { @@ -104,6 +112,8 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri manualThroughput: undefined, minimumThroughput, offerReplacePending: resource.offerReplacePending === "true", + instantMaximumThroughput, + softAllowedMaximumThroughput, }; } @@ -113,6 +123,8 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri manualThroughput: resource.throughput, minimumThroughput, offerReplacePending: resource.offerReplacePending === "true", + instantMaximumThroughput, + softAllowedMaximumThroughput, }; } diff --git a/src/Common/dataAccess/readDatabaseOffer.ts b/src/Common/dataAccess/readDatabaseOffer.ts index bb7366ac9..5f0055e31 100644 --- a/src/Common/dataAccess/readDatabaseOffer.ts +++ b/src/Common/dataAccess/readDatabaseOffer.ts @@ -68,6 +68,14 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise => { ? parseInt(resource.minimumThroughput) : resource.minimumThroughput; const autoscaleSettings = resource.autoscaleSettings; + const instantMaximumThroughput: number = + typeof resource.instantMaximumThroughput === "string" + ? parseInt(resource.instantMaximumThroughput) + : resource.instantMaximumThroughput; + const softAllowedMaximumThroughput: number = + typeof resource.softAllowedMaximumThroughput === "string" + ? parseInt(resource.softAllowedMaximumThroughput) + : resource.softAllowedMaximumThroughput; if (autoscaleSettings) { return { @@ -76,6 +84,8 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise => { manualThroughput: undefined, minimumThroughput, offerReplacePending: resource.offerReplacePending === "true", + instantMaximumThroughput, + softAllowedMaximumThroughput, }; } @@ -85,6 +95,8 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise => { manualThroughput: resource.throughput, minimumThroughput, offerReplacePending: resource.offerReplacePending === "true", + instantMaximumThroughput, + softAllowedMaximumThroughput, }; } diff --git a/src/Common/dataAccess/readStoredProcedures.ts b/src/Common/dataAccess/readStoredProcedures.ts index 2e8652933..a61362160 100644 --- a/src/Common/dataAccess/readStoredProcedures.ts +++ b/src/Common/dataAccess/readStoredProcedures.ts @@ -1,8 +1,9 @@ import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; +import { CloudError, SqlStoredProcedureListResult } from "Utils/arm/generatedClients/cosmos/types"; import { AuthType } from "../../AuthType"; import { userContext } from "../../UserContext"; -import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/cosmos/sqlResources"; import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; +import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/cosmos/sqlResources"; import { client } from "../CosmosClient"; import { handleError } from "../ErrorHandlingUtils"; @@ -24,7 +25,13 @@ export async function readStoredProcedures( databaseId, collectionId ); - return rpResponse?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource); + const listResult = rpResponse as SqlStoredProcedureListResult; + if (listResult) { + return listResult?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource); + } + + const cloudError = rpResponse as CloudError; + throw new Error(cloudError?.error?.message); } const response = await client() diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index e4f865c2c..dd8f95c18 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -242,6 +242,8 @@ export interface Offer { minimumThroughput: number | undefined; offerDefinition?: SDKOfferDefinition; offerReplacePending: boolean; + instantMaximumThroughput?: number; + softAllowedMaximumThroughput?: number; } export interface SDKOfferDefinition extends Resource { diff --git a/src/Explorer/Controls/Settings/SettingsRenderUtils.test.tsx b/src/Explorer/Controls/Settings/SettingsRenderUtils.test.tsx index a6aa42fe1..2e66a86f9 100644 --- a/src/Explorer/Controls/Settings/SettingsRenderUtils.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsRenderUtils.test.tsx @@ -1,46 +1,29 @@ import { shallow } from "enzyme"; import React from "react"; -import { IColumn, Text } from "@fluentui/react"; import { - getAutoPilotV3SpendElement, - getEstimatedSpendingElement, - manualToAutoscaleDisclaimerElement, - ttlWarning, - indexingPolicynUnsavedWarningMessage, - updateThroughputBeyondLimitWarningMessage, - updateThroughputDelayedApplyWarningMessage, - getThroughputApplyDelayedMessage, - getThroughputApplyShortDelayMessage, - getThroughputApplyLongDelayMessage, - getToolTipContainer, - conflictResolutionCustomToolTip, - changeFeedPolicyToolTip, - conflictResolutionLwwTooltip, - mongoIndexingPolicyDisclaimer, - mongoIndexingPolicyAADError, - mongoIndexTransformationRefreshingMessage, - renderMongoIndexTransformationRefreshMessage, - ManualEstimatedSpendingDisplayProps, PriceBreakdown, + changeFeedPolicyToolTip, + conflictResolutionCustomToolTip, + conflictResolutionLwwTooltip, + getEstimatedSpendingElement, getRuPriceBreakdown, + getThroughputApplyDelayedMessage, + getThroughputApplyLongDelayMessage, + getThroughputApplyShortDelayMessage, + getToolTipContainer, + indexingPolicynUnsavedWarningMessage, + manualToAutoscaleDisclaimerElement, + mongoIndexTransformationRefreshingMessage, + mongoIndexingPolicyAADError, + mongoIndexingPolicyDisclaimer, + renderMongoIndexTransformationRefreshMessage, + ttlWarning, + updateThroughputDelayedApplyWarningMessage, } from "./SettingsRenderUtils"; class SettingsRenderUtilsTestComponent extends React.Component { public render(): JSX.Element { - const estimatedSpendingColumns: IColumn[] = [ - { key: "costType", name: "", fieldName: "costType", minWidth: 100, maxWidth: 200, isResizable: true }, - { key: "hourly", name: "Hourly", fieldName: "hourly", minWidth: 100, maxWidth: 200, isResizable: true }, - { key: "daily", name: "Daily", fieldName: "daily", minWidth: 100, maxWidth: 200, isResizable: true }, - { key: "monthly", name: "Monthly", fieldName: "monthly", minWidth: 100, maxWidth: 200, isResizable: true }, - ]; - const estimatedSpendingItems: ManualEstimatedSpendingDisplayProps[] = [ - { - costType: Current Cost, - hourly: $ 1.02, - daily: $ 24.48, - monthly: $ 744.6, - }, - ]; + const costElement: JSX.Element = <>; const priceBreakdown: PriceBreakdown = { hourlyPrice: 1.02, dailyPrice: 24.48, @@ -52,17 +35,11 @@ class SettingsRenderUtilsTestComponent extends React.Component { return ( <> - {getAutoPilotV3SpendElement(1000, false)} - {getAutoPilotV3SpendElement(undefined, false)} - {getAutoPilotV3SpendElement(1000, true)} - {getAutoPilotV3SpendElement(undefined, true)} - - {getEstimatedSpendingElement(estimatedSpendingColumns, estimatedSpendingItems, 1000, 2, priceBreakdown, false)} + {getEstimatedSpendingElement(costElement, 1000, 2, priceBreakdown, false)} {manualToAutoscaleDisclaimerElement} {ttlWarning} {indexingPolicynUnsavedWarningMessage} - {updateThroughputBeyondLimitWarningMessage} {updateThroughputDelayedApplyWarningMessage} {getThroughputApplyDelayedMessage(false, 1000, "RU/s", "sampleDb", "sampleCollection", 2000)} diff --git a/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx b/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx index 11f00f195..b2c5c7c73 100644 --- a/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx +++ b/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx @@ -1,10 +1,7 @@ import { - DetailsList, - DetailsListLayoutMode, DetailsRow, ICheckboxStyles, IChoiceGroupStyles, - IColumn, IDetailsColumnStyles, IDetailsListStyles, IDetailsRowProps, @@ -20,7 +17,6 @@ import { Link, MessageBar, MessageBarType, - SelectionMode, Spinner, SpinnerSize, Stack, @@ -28,8 +24,7 @@ import { } from "@fluentui/react"; import * as React from "react"; import { StyleConstants, Urls } from "../../../Common/Constants"; -import { AutopilotDocumentation, hoursInAMonth } from "../../../Shared/Constants"; -import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils"; +import { hoursInAMonth } from "../../../Shared/Constants"; import { computeRUUsagePriceHourly, estimatedCostDisclaimer, @@ -103,6 +98,10 @@ export const checkBoxAndInputStackProps: Partial = { tokens: { childrenGap: 10 }, }; +export const relaxedSpacingStackProps: Partial = { + tokens: { childrenGap: 20 }, +}; + export const toolTipLabelStackTokens: IStackTokens = { childrenGap: 6, }; @@ -174,41 +173,6 @@ export function onRenderRow(props: IDetailsRowProps): JSX.Element { return ; } -export const getAutoPilotV3SpendElement = ( - maxAutoPilotThroughputSet: number, - isDatabaseThroughput: boolean, - requestUnitsUsageCostElement?: JSX.Element -): JSX.Element => { - if (!maxAutoPilotThroughputSet) { - return <>; - } - - const resource: string = isDatabaseThroughput ? "database" : "container"; - return ( - <> - - Your {resource} throughput will automatically scale from{" "} - - {AutoPilotUtils.getMinRUsBasedOnUserInput(maxAutoPilotThroughputSet)} RU/s (10% of max RU/s) -{" "} - {maxAutoPilotThroughputSet} RU/s - {" "} - based on usage. -
-
- {requestUnitsUsageCostElement} - - After the first {AutoPilotUtils.getStorageBasedOnUserInput(maxAutoPilotThroughputSet)} GB of data stored, the - max RU/s will be automatically upgraded based on the new storage value. - - {" "} - Learn more - - . - - - ); -}; - export const getRuPriceBreakdown = ( throughput: number, serverId: string, @@ -238,8 +202,7 @@ export const getRuPriceBreakdown = ( }; export const getEstimatedSpendingElement = ( - estimatedSpendingColumns: IColumn[], - estimatedSpendingItems: EstimatedSpendingDisplayProps[], + costElement: JSX.Element, throughput: number, numberOfRegions: number, priceBreakdown: PriceBreakdown, @@ -247,22 +210,25 @@ export const getEstimatedSpendingElement = ( ): JSX.Element => { const ruRange: string = isAutoscale ? throughput / 10 + " RU/s - " : ""; return ( - - - - ({"regions: "} {numberOfRegions}, {ruRange} - {throughput} RU/s, {priceBreakdown.currencySign} - {priceBreakdown.pricePerRu}/RU) - - - {estimatedCostDisclaimer} + + Cost estimate* + {costElement} + How we calculate this + + + {numberOfRegions} region{numberOfRegions > 1 && s} + + + {ruRange} + {throughput} RU/s + + + {priceBreakdown.currencySign} + {priceBreakdown.pricePerRu}/RU + + + + *{estimatedCostDisclaimer} ); @@ -293,14 +259,6 @@ export const indexingPolicynUnsavedWarningMessage: JSX.Element = ( ); -export const updateThroughputBeyondLimitWarningMessage: JSX.Element = ( - - You are about to request an increase in throughput beyond the pre-allocated capacity. The service will scale out and - increase throughput for the selected container. This operation will take 1-3 business days to complete. You can - track the status of this request in Notifications. - -); - export const updateThroughputDelayedApplyWarningMessage: JSX.Element = ( You are about to request an increase in throughput beyond the pre-allocated capacity. This operation will take some @@ -308,6 +266,61 @@ export const updateThroughputDelayedApplyWarningMessage: JSX.Element = ( ); +export const getUpdateThroughputBeyondInstantLimitMessage = (instantMaximumThroughput: number): JSX.Element => { + return ( + + Scaling up will take 4-6 hours as it exceeds what Azure Cosmos DB can instantly support currently based on your + number of physical partitions. You can increase your throughput to {instantMaximumThroughput} instantly or proceed + with this value and wait until the scale-up is completed. + + ); +}; + +export const getUpdateThroughputBeyondSupportLimitMessage = ( + instantMaximumThroughput: number, + maximumThroughput: number +): JSX.Element => { + return ( + <> + + Your request to increase throughput exceeds the pre-allocated capacity which may take longer than expected. + There are three options you can choose from to proceed: + +
    +
  1. You can instantly scale up to {instantMaximumThroughput} RU/s.
  2. + {instantMaximumThroughput < maximumThroughput && ( +
  3. You can asynchronously scale up to any value under {maximumThroughput} RU/s in 4-6 hours.
  4. + )} +
  5. + Your current quota max is {maximumThroughput} RU/s. To go over this limit, you must request a quota increase + and the Azure Cosmos DB team will review. + + Learn more + +
  6. +
+ + ); +}; + +export const getUpdateThroughputBelowMinimumMessage = (minimum: number): JSX.Element => { + return ( + + You are not able to lower throughput below your current minimum of {minimum} RU/s. For more information on this + limit, please refer to our service quote documentation. + + Learn more + + + ); +}; + export const saveThroughputWarningMessage: JSX.Element = ( Your bill will be affected as you update your throughput settings. Please review the updated cost estimate below @@ -499,7 +512,11 @@ export const getTextFieldStyles = (current: isDirtyTypes, baseline: isDirtyTypes }, }); -export const getChoiceGroupStyles = (current: isDirtyTypes, baseline: isDirtyTypes): Partial => ({ +export const getChoiceGroupStyles = ( + current: isDirtyTypes, + baseline: isDirtyTypes, + isHorizontal?: boolean +): Partial => ({ flexContainer: [ { selectors: { @@ -516,6 +533,8 @@ export const getChoiceGroupStyles = (current: isDirtyTypes, baseline: isDirtyTyp padding: "2px 5px", }, }, + display: isHorizontal ? "inline-flex" : "default", + columnGap: isHorizontal ? "30px" : "default", }, ], }); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.test.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.test.tsx index eb93add8c..9a5ff8ea0 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.test.tsx @@ -3,7 +3,6 @@ import ko from "knockout"; import React from "react"; import * as Constants from "../../../../Common/Constants"; import * as DataModels from "../../../../Contracts/DataModels"; -import * as SharedConstants from "../../../../Shared/Constants"; import { updateUserContext } from "../../../../UserContext"; import Explorer from "../../../Explorer"; import { throughputUnit } from "../SettingsRenderUtils"; @@ -12,7 +11,6 @@ import { ScaleComponent, ScaleComponentProps } from "./ScaleComponent"; import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component"; describe("ScaleComponent", () => { - const nonNationalCloudContainer = new Explorer(); const targetThroughput = 6000; const baseProps: ScaleComponentProps = { @@ -125,11 +123,4 @@ describe("ScaleComponent", () => { scaleComponent = new ScaleComponent(newProps); expect(scaleComponent.canThroughputExceedMaximumValue()).toEqual(true); }); - - it("getThroughputWarningMessage", () => { - const throughputBeyondLimit = SharedConstants.CollectionCreation.DefaultCollectionRUs1Million + 1000; - const newProps = { ...baseProps, container: nonNationalCloudContainer, throughput: throughputBeyondLimit }; - const scaleComponent = new ScaleComponent(newProps); - expect(scaleComponent.getThroughputWarningMessage().props.id).toEqual("updateThroughputBeyondLimitWarningMessage"); - }); }); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx index c1739171d..c9c3c30a2 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx @@ -1,7 +1,7 @@ -import { Label, Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react"; +import { Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react"; import * as React from "react"; import * as Constants from "../../../../Common/Constants"; -import { configContext, Platform } from "../../../../ConfigContext"; +import { Platform, configContext } from "../../../../ConfigContext"; import * as DataModels from "../../../../Contracts/DataModels"; import * as ViewModels from "../../../../Contracts/ViewModels"; import * as SharedConstants from "../../../../Shared/Constants"; @@ -15,7 +15,6 @@ import { subComponentStackProps, throughputUnit, titleAndInputStackProps, - updateThroughputBeyondLimitWarningMessage, } from "../SettingsRenderUtils"; import { hasDatabaseSharedThroughput } from "../SettingsUtils"; import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component"; @@ -68,16 +67,6 @@ export class ScaleComponent extends React.Component { return !!enableAutoScaleCapability; }; - private getStorageCapacityTitle = (): JSX.Element => { - const capacity: string = this.props.isFixedContainer ? "Fixed" : "Unlimited"; - return ( - - - {capacity} - - ); - }; - public getMaxRUs = (): number => { if (userContext.isTryCosmosDBSubscription) { return Constants.TryCosmosExperience.maxRU; @@ -131,18 +120,6 @@ export class ScaleComponent extends React.Component { return undefined; }; - public getThroughputWarningMessage = (): JSX.Element => { - const throughputExceedsBackendLimits: boolean = - this.canThroughputExceedMaximumValue() && - this.props.throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs1Million; - - if (throughputExceedsBackendLimits && !this.props.isFixedContainer) { - return updateThroughputBeyondLimitWarningMessage; - } - - return undefined; - }; - public getLongDelayMessage = (): JSX.Element => { const matches: string[] = this.props.initialNotification?.description.match( `Throughput update for (.*) ${throughputUnit}` @@ -188,9 +165,10 @@ export class ScaleComponent extends React.Component { spendAckChecked={false} onScaleSaveableChange={this.props.onScaleSaveableChange} onScaleDiscardableChange={this.props.onScaleDiscardableChange} - getThroughputWarningMessage={this.getThroughputWarningMessage} usageSizeInKB={this.props.collection?.usageSizeInKB()} throughputError={this.props.throughputError} + instantMaximumThroughput={this.offer?.instantMaximumThroughput} + softAllowedMaximumThroughput={this.offer?.softAllowedMaximumThroughput} /> ); @@ -229,12 +207,7 @@ export class ScaleComponent extends React.Component { {this.getInitialNotificationElement() && ( {this.getInitialNotificationElement()} )} - {!this.isAutoScaleEnabled() && ( - - {this.getThroughputInputComponent()} - {!this.props.database && this.getStorageCapacityTitle()} - - )} + {!this.isAutoScaleEnabled() && {this.getThroughputInputComponent()}} {/* TODO: Replace link with call to the Azure Support blade */} {this.isAutoScaleEnabled() && ( diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.test.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.test.tsx index 2944ee0e4..ff7b715b3 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.test.tsx @@ -42,7 +42,8 @@ describe("ThroughputInputAutoPilotV3Component", () => { onScaleDiscardableChange: () => { return; }, - getThroughputWarningMessage: () => undefined, + instantMaximumThroughput: 5000, + softAllowedMaximumThroughput: 1000000, }; it("throughput input visible", () => { diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.tsx index f39ff185e..7ba21f88b 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputInputAutoPilotV3Component.tsx @@ -3,10 +3,14 @@ import { ChoiceGroup, FontIcon, IChoiceGroupOption, - IColumn, + IProgressIndicatorStyles, + ISeparatorStyles, Label, Link, MessageBar, + MessageBarType, + ProgressIndicator, + Separator, Stack, Text, TextField, @@ -23,24 +27,24 @@ import { autoPilotThroughput1K } from "../../../../../Utils/AutoPilotUtils"; import { calculateEstimateNumber, usageInGB } from "../../../../../Utils/PricingUtils"; import { Int32 } from "../../../../Panes/Tables/Validators/EntityPropertyValidationCommon"; import { - AutoscaleEstimatedSpendingDisplayProps, + PriceBreakdown, checkBoxAndInputStackProps, - getAutoPilotV3SpendElement, getChoiceGroupStyles, getEstimatedSpendingElement, getRuPriceBreakdown, getTextFieldStyles, getToolTipContainer, - ManualEstimatedSpendingDisplayProps, + getUpdateThroughputBelowMinimumMessage, + getUpdateThroughputBeyondInstantLimitMessage, + getUpdateThroughputBeyondSupportLimitMessage, manualToAutoscaleDisclaimerElement, messageBarStyles, noLeftPaddingCheckBoxStyle, - PriceBreakdown, + relaxedSpacingStackProps, saveThroughputWarningMessage, titleAndInputStackProps, - transparentDetailsHeaderStyle, } from "../../SettingsRenderUtils"; -import { getSanitizedInputValue, IsComponentDirtyResult, isDirty } from "../../SettingsUtils"; +import { IsComponentDirtyResult, getSanitizedInputValue, isDirty } from "../../SettingsUtils"; import { ToolTipLabelComponent } from "../ToolTipLabelComponent"; export interface ThroughputInputAutoPilotV3Props { @@ -73,9 +77,10 @@ export interface ThroughputInputAutoPilotV3Props { onMaxAutoPilotThroughputChange: (newThroughput: number) => void; onScaleSaveableChange: (isScaleSaveable: boolean) => void; onScaleDiscardableChange: (isScaleDiscardable: boolean) => void; - getThroughputWarningMessage: () => JSX.Element; usageSizeInKB: number; throughputError?: string; + instantMaximumThroughput: number; + softAllowedMaximumThroughput: number; } interface ThroughputInputAutoPilotV3State { @@ -127,7 +132,10 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< } else if (this.props.isAutoPilotSelected) { if (isDirty(this.props.maxAutoPilotThroughput, this.props.maxAutoPilotThroughputBaseline)) { isDiscardable = true; - if (AutoPilotUtils.isValidAutoPilotThroughput(this.props.maxAutoPilotThroughput)) { + if ( + this.props.maxAutoPilotThroughput <= this.props.softAllowedMaximumThroughput && + AutoPilotUtils.isValidAutoPilotThroughput(this.props.maxAutoPilotThroughput) + ) { isSaveable = true; } } @@ -186,7 +194,15 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< let estimatedSpend: JSX.Element; - if (!this.props.isAutoPilotSelected) { + if (this.props.isAutoPilotSelected) { + estimatedSpend = this.getEstimatedAutoscaleSpendElement( + this.props.maxAutoPilotThroughputBaseline, + userContext.portalEnv, + regions, + multimaster, + isDirty ? this.props.maxAutoPilotThroughput : undefined + ); + } else { estimatedSpend = this.getEstimatedManualSpendElement( // if migrating from autoscale to manual, we use the autoscale RUs value as that is what will be set... this.overrideWithAutoPilotSettings() ? this.props.maxAutoPilotThroughput : this.props.throughputBaseline, @@ -195,14 +211,6 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< multimaster, isDirty ? this.props.throughput : undefined ); - } else { - estimatedSpend = this.getEstimatedAutoscaleSpendElement( - this.props.maxAutoPilotThroughputBaseline, - userContext.portalEnv, - regions, - multimaster, - isDirty ? this.props.maxAutoPilotThroughput : undefined - ); } return estimatedSpend; }; @@ -215,52 +223,8 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< newThroughput?: number ): JSX.Element => { const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true); - const estimatedSpendingColumns: IColumn[] = [ - { - key: "costType", - name: "", - fieldName: "costType", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - { - key: "minPerMonth", - name: "Min Per Month", - fieldName: "minPerMonth", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - { - key: "maxPerMonth", - name: "Max Per Month", - fieldName: "maxPerMonth", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - ]; - const estimatedSpendingItems: AutoscaleEstimatedSpendingDisplayProps[] = [ - { - costType: Current Cost, - minPerMonth: ( - - {prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice / 10)} - - ), - maxPerMonth: ( - - {prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)} - - ), - }, - ]; - if (newThroughput) { + const newThroughputCostElement = (): JSX.Element => { const newPrices: PriceBreakdown = getRuPriceBreakdown( newThroughput, serverId, @@ -268,37 +232,40 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< isMultimaster, true ); - estimatedSpendingItems.unshift({ - costType: ( - - Updated Cost - - ), - minPerMonth: ( - - - {newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice / 10)} - - - ), - maxPerMonth: ( - - - {newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)} - - - ), - }); - } + return ( +
+ Updated cost per month + + + {newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice / 10)} min + + + {newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)} max + + +
+ ); + }; - return getEstimatedSpendingElement( - estimatedSpendingColumns, - estimatedSpendingItems, - newThroughput ?? throughput, - numberOfRegions, - prices, - true - ); + const costElement = (): JSX.Element => { + const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true); + return ( + + {newThroughput && newThroughputCostElement()} + Current cost per month + + + {prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice / 10)} min + + + {prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)} max + + + + ); + }; + + return getEstimatedSpendingElement(costElement(), newThroughput ?? throughput, numberOfRegions, prices, true); }; private getEstimatedManualSpendElement = ( @@ -309,122 +276,55 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< newThroughput?: number ): JSX.Element => { const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, false); - const estimatedSpendingColumns: IColumn[] = [ - { - key: "costType", - name: "", - fieldName: "costType", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - { - key: "hourly", - name: "Hourly", - fieldName: "hourly", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - { - key: "daily", - name: "Daily", - fieldName: "daily", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - { - key: "monthly", - name: "Monthly", - fieldName: "monthly", - minWidth: 100, - maxWidth: 200, - isResizable: true, - styles: transparentDetailsHeaderStyle, - }, - ]; - const estimatedSpendingItems: ManualEstimatedSpendingDisplayProps[] = [ - { - costType: Current Cost, - hourly: ( - - {prices.currencySign} {calculateEstimateNumber(prices.hourlyPrice)} - - ), - daily: ( - - {prices.currencySign} {calculateEstimateNumber(prices.dailyPrice)} - - ), - monthly: ( - - {prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)} - - ), - }, - ]; - if (newThroughput) { + const newThroughputCostElement = (): JSX.Element => { const newPrices: PriceBreakdown = getRuPriceBreakdown( newThroughput, serverId, numberOfRegions, isMultimaster, - false + true ); - estimatedSpendingItems.unshift({ - costType: ( - - Updated Cost - - ), - hourly: ( - - - {newPrices.currencySign} {calculateEstimateNumber(newPrices.hourlyPrice)} - - - ), - daily: ( - - - {newPrices.currencySign} {calculateEstimateNumber(newPrices.dailyPrice)} - - - ), - monthly: ( - - - {newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)} - - - ), - }); - } + return ( +
+ Updated cost per month + + + {newPrices.currencySign} {calculateEstimateNumber(newPrices.hourlyPrice)}/hr + + + {newPrices.currencySign} {calculateEstimateNumber(newPrices.dailyPrice)}/day + + + {newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}/mo + + +
+ ); + }; - return getEstimatedSpendingElement( - estimatedSpendingColumns, - estimatedSpendingItems, - newThroughput ?? throughput, - numberOfRegions, - prices, - false - ); - }; + const costElement = (): JSX.Element => { + const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true); + return ( + + {newThroughput && newThroughputCostElement()} + Current cost per month + + + {prices.currencySign} {calculateEstimateNumber(prices.hourlyPrice)}/hr + + + {prices.currencySign} {calculateEstimateNumber(prices.dailyPrice)}/day + + + {prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}/mo + + + + ); + }; - private getAutoPilotUsageCost = (): JSX.Element => { - if (!this.props.maxAutoPilotThroughput) { - return <>; - } - return getAutoPilotV3SpendElement( - this.props.maxAutoPilotThroughput, - false /* isDatabaseThroughput */, - !this.props.isEmulator ? this.getRequestUnitsUsageCost() : <> - ); + return getEstimatedSpendingElement(costElement(), newThroughput ?? throughput, numberOfRegions, prices, false); }; private onAutoPilotThroughputChange = ( @@ -511,7 +411,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< onChange={this.onChoiceGroupChange} required={this.props.showAsMandatory} ariaLabelledBy={labelId} - styles={getChoiceGroupStyles(this.props.wasAutopilotOriginallySet, this.props.isAutoPilotSelected)} + styles={getChoiceGroupStyles(this.props.wasAutopilotOriginallySet, this.props.isAutoPilotSelected, true)} />
); @@ -520,97 +420,266 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< private onSpendAckChecked = (ev?: React.FormEvent, checked?: boolean): void => this.setState({ spendAckChecked: checked }); - private renderAutoPilotInput = (): JSX.Element => ( - <> - - Provision maximum RU/s required by this resource. Estimate your required RU/s with - - {` capacity calculator`} - - - { + const capacity: string = this.props.isFixed ? "Fixed" : "Unlimited"; + return ( + + + {capacity} + + ); + }; + + private thoughputRangeSeparatorStyles: Partial = { + root: [ + { + selectors: { + "::before": { + backgroundColor: "rgb(200, 200, 200)", + height: "3px", + marginTop: "-1px", + }, + }, + }, + ], + }; + + private currentThroughputValue = (): number => { + return this.props.isAutoPilotSelected + ? this.props.maxAutoPilotThroughput + : this.overrideWithAutoPilotSettings() + ? this.props.maxAutoPilotThroughputBaseline + : this.props.throughput; + }; + + private getCurrentRuRange = (): "below" | "instant" | "delayed" | "requireSupport" => { + if (this.currentThroughputValue() < this.props.minimum) { + return "below"; + } + if ( + this.currentThroughputValue() >= this.props.minimum && + this.currentThroughputValue() <= this.props.instantMaximumThroughput + ) { + return "instant"; + } + if (this.currentThroughputValue() > this.props.softAllowedMaximumThroughput) { + return "requireSupport"; + } + + return "delayed"; + }; + + private getRuThermometerStyles = (): Partial => ({ + progressBar: [ + { + backgroundColor: + this.getCurrentRuRange() === "instant" + ? "rgb(0, 120, 212)" + : this.getCurrentRuRange() === "delayed" + ? "rgb(255 216 109)" + : "rgb(251, 217, 203)", + }, + ], + }); + + private getRuThermometerPercentValue = (): number => { + let percentValue: number; + const currentRus = this.currentThroughputValue(); + + switch (this.getCurrentRuRange()) { + case "below": + percentValue = 0; + break; + case "instant": { + const percentOfInstantRange: number = currentRus / this.props.instantMaximumThroughput; + percentValue = percentOfInstantRange * 0.34; + break; + } + case "delayed": { + const adjustedMax = this.props.softAllowedMaximumThroughput - this.props.instantMaximumThroughput; + const adjustedRus = currentRus - this.props.instantMaximumThroughput; + const percentOfDelayedRange = adjustedRus / adjustedMax; + const adjustedPercent = percentOfDelayedRange * 0.66; + percentValue = adjustedPercent + 0.34; + break; + } + default: + // over maximum + percentValue = 1; + } + return percentValue; + }; + + private getRUThermometer = (): JSX.Element => ( + + + + {this.props.minimum.toLocaleString()} + + + + {this.props.instantMaximumThroughput.toLocaleString()} + + {this.props.softAllowedMaximumThroughput.toLocaleString()} + + + - {!this.overrideWithProvisionedThroughputSettings() && this.getAutoPilotUsageCost()} - {this.minRUperGBSurvey()} - {this.props.spendAckVisible && ( - + + Instant + + + 4-6 hrs + + + + ); + + private showThroughputWarning = (): boolean => { + return ( + this.currentThroughputValue() > this.props.instantMaximumThroughput || + this.currentThroughputValue() < this.props.minimum + ); + }; + + private getThroughputWarningMessageText = (): JSX.Element => { + switch (this.getCurrentRuRange()) { + case "below": + return getUpdateThroughputBelowMinimumMessage(this.props.minimum); + case "delayed": + return getUpdateThroughputBeyondInstantLimitMessage(this.props.instantMaximumThroughput); + case "requireSupport": + return getUpdateThroughputBeyondSupportLimitMessage( + this.props.instantMaximumThroughput, + this.props.softAllowedMaximumThroughput + ); + default: + return <>; + } + }; + + private getThroughputWarningMessageBar = (): JSX.Element => { + const isSevereWarning: boolean = + this.currentThroughputValue() > this.props.softAllowedMaximumThroughput || + this.currentThroughputValue() < this.props.minimum; + return ( + + {this.getThroughputWarningMessageText()} + + ); + }; + + private getThroughputTextField = (): JSX.Element => ( + <> + {this.props.isAutoPilotSelected ? ( + { + const sanitizedValue = getSanitizedInputValue(value); + return sanitizedValue % 1000 + ? "Throughput value must be in increments of 1000" + : this.props.throughputError; + }} + validateOnLoad={false} + /> + ) : ( + )} - {this.props.isFixed &&

When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.

} ); - private renderThroughputInput = (): JSX.Element => ( - - - Estimate your required throughput with - - {` capacity calculator`} - - - - {this.state.exceedFreeTierThroughput && ( - - {`Billing will apply if you provision more than ${SharedConstants.FreeTierLimits.RU} RU/s of manual throughput, or if the resource scales beyond ${SharedConstants.FreeTierLimits.RU} RU/s with autoscale.`} - - )} - {this.props.getThroughputWarningMessage() && ( - - {this.props.getThroughputWarningMessage()} - - )} - {!this.props.isEmulator && this.getRequestUnitsUsageCost()} - {this.minRUperGBSurvey()} - {this.props.spendAckVisible && ( - - )} -
- {this.props.isFixed &&

When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.

} + private renderThroughputComponent = (): JSX.Element => ( + + + + {this.getThroughputTextField()} + {this.props.instantMaximumThroughput && ( + + {this.getRUThermometer()} + {this.showThroughputWarning() && this.getThroughputWarningMessageBar()} + + )} + {this.props.isAutoPilotSelected ? ( + + Based on usage, your {this.props.collectionName ? "container" : "database"} throughput will scale from{" "} + + {AutoPilotUtils.getMinRUsBasedOnUserInput(this.props.maxAutoPilotThroughput)} RU/s (10% of max RU/s) -{" "} + {this.props.maxAutoPilotThroughput} RU/s + +
+
+ ) : ( + <> + {this.state.exceedFreeTierThroughput && ( + + {`Billing will apply if you provision more than ${SharedConstants.FreeTierLimits.RU} RU/s of manual throughput, or if the resource scales beyond ${SharedConstants.FreeTierLimits.RU} RU/s with autoscale.`} + + )} + + )} + {!this.overrideWithProvisionedThroughputSettings() && ( + + Estimate your required RU/s with + + {` capacity calculator`} + + + )} + {this.minRUperGBSurvey()} + {this.props.spendAckVisible && ( + + )} + {this.props.isFixed && ( +

When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.

+ )} + {this.props.collectionName && ( + {this.getStorageCapacityTitle()} + )} +
+
+ + {!this.props.isEmulator ? this.getRequestUnitsUsageCost() : <>} +
); @@ -640,7 +709,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component< {this.renderWarningMessage()} {this.renderThroughputModeChoices()} - {this.props.isAutoPilotSelected ? this.renderAutoPilotInput() : this.renderThroughputInput()} + {this.renderThroughputComponent()}
); } diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/__snapshots__/ThroughputInputAutoPilotV3Component.test.tsx.snap b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/__snapshots__/ThroughputInputAutoPilotV3Component.test.tsx.snap index b74a70612..6a0f9efd1 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/__snapshots__/ThroughputInputAutoPilotV3Component.test.tsx.snap +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/__snapshots__/ThroughputInputAutoPilotV3Component.test.tsx.snap @@ -112,6 +112,8 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "30px", + "display": "inline-flex", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": undefined, @@ -132,42 +134,411 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = ` } /> - - Provision maximum RU/s required by this resource. Estimate your required RU/s with - - capacity calculator - - - + + > + + + + + + + + 10,000 + + + + + 5,000 + + + 1,000,000 + + + + + + + + Instant + + + + + 4-6 hrs + + + + + + + You are not able to lower throughput below your current minimum of + 10000 + RU/s. For more information on this limit, please refer to our service quote documentation. + + Learn more + + + + + + Based on usage, your + container + throughput will scale from + + + 400 + RU/s (10% of max RU/s) - + + 4000 + RU/s + +
+
+ + + + Storage capacity + + + Unlimited + + + +
+
+ + + + Cost estimate* + + +
+ + Updated cost per month + + + + $ + + 35.04 + min + + + $ + + 350.40 + max + + +
+ + Current cost per month + + + + $ + + 35.04 + min + + + $ + + 350.40 + max + + +
+ + How we calculate this + + + + 1 + region + + + 400 RU/s - + 4000 + RU/s + + + $ + 0.00012 + /RU + + + + + * + This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account + + +
+
+ `; @@ -222,6 +593,8 @@ exports[`ThroughputInputAutoPilotV3Component spendAck checkbox visible 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "30px", + "display": "inline-flex", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -243,205 +616,382 @@ exports[`ThroughputInputAutoPilotV3Component spendAck checkbox visible 1`] = ` /> - - Estimate your required throughput with - - capacity calculator - - - - - - - - Current Cost - , - "daily": - $ - - 0.19 - , - "hourly": - $ - - 0.0080 - , - "monthly": - $ - - 5.84 - , - }, - ] + tokens={ + Object { + "childrenGap": 20, + } } - layoutMode={1} - onRenderRow={[Function]} - selectionMode={0} - /> - - ( - regions: - - 1 - , - 100 - RU/s, - $ - 0.00008 - /RU) - - - - This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account - - - - + + + + + + 10,000 + + + + + 5,000 + + + 1,000,000 + + + + + + + + Instant + + + + + 4-6 hrs + + + + + + + You are not able to lower throughput below your current minimum of + 10000 + RU/s. For more information on this limit, please refer to our service quote documentation. + + Learn more + + + + + + Estimate your required RU/s with + + capacity calculator + + + + + + + + + Storage capacity + + + Unlimited + + + + + + -
+ > + + + Cost estimate* + + + + Current cost per month + + + + $ + + 0.012 + /hr + + + $ + + 0.29 + /day + + + $ + + 8.76 + /mo + + + + + How we calculate this + + + + 1 + region + + + 100 + RU/s + + + $ + 0.00008 + /RU + + + + + * + This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account + + + +
`; @@ -497,6 +1047,8 @@ exports[`ThroughputInputAutoPilotV3Component throughput input visible 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "30px", + "display": "inline-flex", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -518,188 +1070,365 @@ exports[`ThroughputInputAutoPilotV3Component throughput input visible 1`] = ` /> - - Estimate your required throughput with - - capacity calculator - - - - - - - - Current Cost - , - "daily": - $ - - 0.19 - , - "hourly": - $ - - 0.0080 - , - "monthly": - $ - - 5.84 - , - }, - ] + tokens={ + Object { + "childrenGap": 20, + } } - layoutMode={1} - onRenderRow={[Function]} - selectionMode={0} - /> - - ( - regions: - - 1 - , - 100 - RU/s, - $ - 0.00008 - /RU) - - - - This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account - - - -
+ + + + + + + 10,000 + + + + + 5,000 + + + 1,000,000 + + + + + + + + Instant + + + + + 4-6 hrs + + + + + + + You are not able to lower throughput below your current minimum of + 10000 + RU/s. For more information on this limit, please refer to our service quote documentation. + + Learn more + + + + + + Estimate your required RU/s with + + capacity calculator + + + + + + + + Storage capacity + + + Unlimited + + + +
+ + + + + Cost estimate* + + + + Current cost per month + + + + $ + + 0.012 + /hr + + + $ + + 0.29 + /day + + + $ + + 8.76 + /mo + + + + + How we calculate this + + + + 1 + region + + + 100 + RU/s + + + $ + 0.00008 + /RU + + + + + * + This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account + + + + `; diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ConflictResolutionComponent.test.tsx.snap b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ConflictResolutionComponent.test.tsx.snap index 420f9ddf6..dbd38fd1b 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ConflictResolutionComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ConflictResolutionComponent.test.tsx.snap @@ -28,6 +28,8 @@ exports[`ConflictResolutionComponent Path text field displayed 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": undefined, @@ -100,6 +102,8 @@ exports[`ConflictResolutionComponent Sproc text field displayed 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ScaleComponent.test.tsx.snap b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ScaleComponent.test.tsx.snap index aaa7cdb1b..330b73322 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ScaleComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ScaleComponent.test.tsx.snap @@ -39,7 +39,6 @@ exports[`ScaleComponent renders with correct initial notification 1`] = ` canExceedMaximumValue={true} collectionName="test" databaseName="test" - getThroughputWarningMessage={[Function]} isAutoPilotSelected={false} isEmulator={false} isEnabled={true} @@ -60,20 +59,6 @@ exports[`ScaleComponent renders with correct initial notification 1`] = ` usageSizeInKB={100} wasAutopilotOriginallySet={true} /> - - - Storage capacity - - - Unlimited - - `; diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/SubSettingsComponent.test.tsx.snap b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/SubSettingsComponent.test.tsx.snap index 6b3402d97..b415e19a1 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/SubSettingsComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/SubSettingsComponent.test.tsx.snap @@ -40,6 +40,8 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -106,6 +108,8 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -168,6 +172,8 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -267,6 +273,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -333,6 +341,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -385,6 +395,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": undefined, @@ -448,6 +460,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -547,6 +561,8 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -613,6 +629,8 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -665,6 +683,8 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -789,6 +809,8 @@ exports[`SubSettingsComponent renders 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -855,6 +877,8 @@ exports[`SubSettingsComponent renders 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -907,6 +931,8 @@ exports[`SubSettingsComponent renders 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -995,6 +1021,8 @@ exports[`SubSettingsComponent renders 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -1094,6 +1122,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": undefined, @@ -1135,6 +1165,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -1187,6 +1219,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", @@ -1275,6 +1309,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = ` Object { "flexContainer": Array [ Object { + "columnGap": "default", + "display": "default", "selectors": Object { ".ms-ChoiceField-field.is-checked::after": Object { "borderColor": "", diff --git a/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap b/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap index b91245668..004862ffe 100644 --- a/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap +++ b/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap @@ -2,154 +2,60 @@ exports[`SettingsUtils functions render 1`] = ` - - Your - container - throughput will automatically scale from - - - 100 - RU/s (10% of max RU/s) - - - 1000 - RU/s - - - based on usage. -
-
- - After the first - 10 - GB of data stored, the max RU/s will be automatically upgraded based on the new storage value. - - - Learn more - - . - - - Your - database - throughput will automatically scale from - - - 100 - RU/s (10% of max RU/s) - - - 1000 - RU/s - - - based on usage. -
-
- - After the first - 10 - GB of data stored, the max RU/s will be automatically upgraded based on the new storage value. - - - Learn more - - . - - - - Current Cost - , - "daily": - $ 24.48 - , - "hourly": - $ 1.02 - , - "monthly": - $ 744.6 - , - }, - ] - } - layoutMode={1} - onRenderRow={[Function]} - selectionMode={0} - /> + - ( - regions: - - 2 - , - 1000 - RU/s, - ¥ - 0.00051 - /RU) + Cost estimate* - + + How we calculate this + + + + 2 + region + + s + + + + 1000 + RU/s + + + ¥ + 0.00051 + /RU + + + + * This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account @@ -205,19 +111,6 @@ exports[`SettingsUtils functions render 1`] = ` > You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes. - - You are about to request an increase in throughput beyond the pre-allocated capacity. The service will scale out and increase throughput for the selected container. This operation will take 1-3 business days to complete. You can track the status of this request in Notifications. - { const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`; - return armRequest({ - host: configContext.ARM_ENDPOINT, - path, - method: "PATCH", - apiVersion, - body, - }); + return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PATCH", apiVersion, body }); } /* Creates or updates an Azure Cosmos DB database account. The "Update" method is preferred when performing updates on an account. */ diff --git a/src/Utils/arm/generatedClients/cosmos/gremlinResources.ts b/src/Utils/arm/generatedClients/cosmos/gremlinResources.ts index 572ef4859..832fddb0c 100644 --- a/src/Utils/arm/generatedClients/cosmos/gremlinResources.ts +++ b/src/Utils/arm/generatedClients/cosmos/gremlinResources.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Lists the Gremlin databases under an existing Azure Cosmos DB database account. */ export async function listGremlinDatabases( diff --git a/src/Utils/arm/generatedClients/cosmos/locations.ts b/src/Utils/arm/generatedClients/cosmos/locations.ts new file mode 100644 index 000000000..b41979d8c --- /dev/null +++ b/src/Utils/arm/generatedClients/cosmos/locations.ts @@ -0,0 +1,27 @@ +/* + AUTOGENERATED FILE + Run "npm run generateARMClients" to regenerate + Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs + + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json +*/ + +import { armRequest } from "../../request"; +import * as Types from "./types"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; + +/* List Cosmos DB locations and their properties */ +export async function list(subscriptionId: string): Promise { + const path = `/subscriptions/${subscriptionId}/providers/Microsoft.DocumentDB/locations`; + return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion }); +} + +/* Get the properties of an existing Cosmos DB location */ +export async function get( + subscriptionId: string, + location: string +): Promise { + const path = `/subscriptions/${subscriptionId}/providers/Microsoft.DocumentDB/locations/${location}`; + return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion }); +} diff --git a/src/Utils/arm/generatedClients/cosmos/mongoDBResources.ts b/src/Utils/arm/generatedClients/cosmos/mongoDBResources.ts index 61f2ee5ae..1ad813cd4 100644 --- a/src/Utils/arm/generatedClients/cosmos/mongoDBResources.ts +++ b/src/Utils/arm/generatedClients/cosmos/mongoDBResources.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Lists the MongoDB databases under an existing Azure Cosmos DB database account. */ export async function listMongoDBDatabases( diff --git a/src/Utils/arm/generatedClients/cosmos/operations.ts b/src/Utils/arm/generatedClients/cosmos/operations.ts index db16f7bfc..134c1de27 100644 --- a/src/Utils/arm/generatedClients/cosmos/operations.ts +++ b/src/Utils/arm/generatedClients/cosmos/operations.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Lists all of the available Cosmos DB Resource Provider operations. */ export async function list(): Promise { diff --git a/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeId.ts b/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeId.ts index 20c85cdd2..05b8a0841 100644 --- a/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeId.ts +++ b/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeId.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Retrieves the metrics determined by the given filter for the given partition key range id. */ export async function listMetrics( diff --git a/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeIdRegion.ts b/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeIdRegion.ts index eb8a00b9b..7f5f6625d 100644 --- a/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeIdRegion.ts +++ b/src/Utils/arm/generatedClients/cosmos/partitionKeyRangeIdRegion.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Retrieves the metrics determined by the given filter for the given partition key range id and region. */ export async function listMetrics( diff --git a/src/Utils/arm/generatedClients/cosmos/percentile.ts b/src/Utils/arm/generatedClients/cosmos/percentile.ts index f30a503fd..a92ed1063 100644 --- a/src/Utils/arm/generatedClients/cosmos/percentile.ts +++ b/src/Utils/arm/generatedClients/cosmos/percentile.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Retrieves the metrics determined by the given filter for the given database account. This url is only for PBS and Replication Latency data */ export async function listMetrics( diff --git a/src/Utils/arm/generatedClients/cosmos/percentileSourceTarget.ts b/src/Utils/arm/generatedClients/cosmos/percentileSourceTarget.ts index 37a3f841c..e89c014ef 100644 --- a/src/Utils/arm/generatedClients/cosmos/percentileSourceTarget.ts +++ b/src/Utils/arm/generatedClients/cosmos/percentileSourceTarget.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Retrieves the metrics determined by the given filter for the given account, source and target region. This url is only for PBS and Replication Latency data */ export async function listMetrics( diff --git a/src/Utils/arm/generatedClients/cosmos/percentileTarget.ts b/src/Utils/arm/generatedClients/cosmos/percentileTarget.ts index a318d5dd1..83618df9c 100644 --- a/src/Utils/arm/generatedClients/cosmos/percentileTarget.ts +++ b/src/Utils/arm/generatedClients/cosmos/percentileTarget.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Retrieves the metrics determined by the given filter for the given account target region. This url is only for PBS and Replication Latency data */ export async function listMetrics( diff --git a/src/Utils/arm/generatedClients/cosmos/sqlResources.ts b/src/Utils/arm/generatedClients/cosmos/sqlResources.ts index 40c68fb86..ec37f15ed 100644 --- a/src/Utils/arm/generatedClients/cosmos/sqlResources.ts +++ b/src/Utils/arm/generatedClients/cosmos/sqlResources.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Lists the SQL databases under an existing Azure Cosmos DB database account. */ export async function listSqlDatabases( @@ -197,6 +197,42 @@ export async function migrateSqlContainerToManualThroughput( return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion }); } +/* Lists the ClientEncryptionKeys under an existing Azure Cosmos DB SQL database. */ +export async function listClientEncryptionKeys( + subscriptionId: string, + resourceGroupName: string, + accountName: string, + databaseName: string +): Promise { + const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/clientEncryptionKeys`; + return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion }); +} + +/* Gets the ClientEncryptionKey under an existing Azure Cosmos DB SQL database. */ +export async function getClientEncryptionKey( + subscriptionId: string, + resourceGroupName: string, + accountName: string, + databaseName: string, + clientEncryptionKeyName: string +): Promise { + const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/clientEncryptionKeys/${clientEncryptionKeyName}`; + return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion }); +} + +/* Create or update a ClientEncryptionKey. This API is meant to be invoked via tools such as the Azure Powershell (instead of directly). */ +export async function createUpdateClientEncryptionKey( + subscriptionId: string, + resourceGroupName: string, + accountName: string, + databaseName: string, + clientEncryptionKeyName: string, + body: Types.ClientEncryptionKeyCreateUpdateParameters +): Promise { + const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/clientEncryptionKeys/${clientEncryptionKeyName}`; + return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body }); +} + /* Lists the SQL storedProcedure under an existing Azure Cosmos DB database account. */ export async function listSqlStoredProcedures( subscriptionId: string, @@ -204,7 +240,7 @@ export async function listSqlStoredProcedures( accountName: string, databaseName: string, containerName: string -): Promise { +): Promise { const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/storedProcedures`; return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion }); } diff --git a/src/Utils/arm/generatedClients/cosmos/tableResources.ts b/src/Utils/arm/generatedClients/cosmos/tableResources.ts index b68c20b08..09b9c7056 100644 --- a/src/Utils/arm/generatedClients/cosmos/tableResources.ts +++ b/src/Utils/arm/generatedClients/cosmos/tableResources.ts @@ -3,13 +3,13 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ -import { configContext } from "../../../../ConfigContext"; import { armRequest } from "../../request"; import * as Types from "./types"; -const apiVersion = "2021-04-15"; +import { configContext } from "../../../../ConfigContext"; +const apiVersion = "2023-04-15"; /* Lists the Tables under an existing Azure Cosmos DB database account. */ export async function listTables( diff --git a/src/Utils/arm/generatedClients/cosmos/types.ts b/src/Utils/arm/generatedClients/cosmos/types.ts index 9efc80d20..7834ab96e 100644 --- a/src/Utils/arm/generatedClients/cosmos/types.ts +++ b/src/Utils/arm/generatedClients/cosmos/types.ts @@ -3,9 +3,15 @@ Run "npm run generateARMClients" to regenerate Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs - Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json + Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json */ +/* The List operation response, that contains the client encryption keys and their properties. */ +export interface ClientEncryptionKeysListResult { + /* List of client encryption keys and their properties. */ + readonly value?: ClientEncryptionKeyGetResults[]; +} + /* The List operation response, that contains the database accounts and their properties. */ export interface DatabaseAccountsListResult { /* List of database account and their properties. */ @@ -161,6 +167,30 @@ export interface ARMProxyResource { readonly type?: string; } +/* Parameters to create and update ClientEncryptionKey. */ +export interface ClientEncryptionKeyCreateUpdateParameters { + /* Properties to create and update ClientEncryptionKey. */ + properties: ClientEncryptionKeyCreateUpdateProperties; +} + +/* Properties to create and update ClientEncryptionKey. */ +export interface ClientEncryptionKeyCreateUpdateProperties { + /* The standard JSON format of a ClientEncryptionKey */ + resource: ClientEncryptionKeyResource; +} + +/* Client Encryption Key. */ +export type ClientEncryptionKeyGetResults = ARMProxyResource & { + /* The properties of a ClientEncryptionKey */ + properties?: ClientEncryptionKeyGetProperties; +}; + +/* The properties of a ClientEncryptionKey resource */ +export interface ClientEncryptionKeyGetProperties { + /* undocumented */ + resource?: ClientEncryptionKeyResource & ExtendedResourceProperties; +} + /* An Azure Cosmos DB database account. */ export type DatabaseAccountGetResults = ARMResourceProperties & { /* Indicates the type of database account. This can only be set at database account creation. */ @@ -171,6 +201,9 @@ export type DatabaseAccountGetResults = ARMResourceProperties & { /* undocumented */ properties?: DatabaseAccountGetProperties; + + /* The system meta data relating to this resource. */ + readonly systemData?: unknown; }; /* The system generated resource properties associated with SQL databases, SQL containers, Gremlin databases and Gremlin graphs. */ @@ -446,6 +479,17 @@ export interface DatabaseAccountGetProperties { /* Flag to indicate whether to enable storage analytics. */ enableAnalyticalStorage?: boolean; + /* Analytical storage specific properties. */ + analyticalStorageConfiguration?: AnalyticalStorageConfiguration; + + /* A unique identifier assigned to the database account */ + readonly instanceId?: string; + /* Enum to indicate the mode of account creation. */ + createMode?: CreateMode; + + /* Parameters to indicate the information about the restore. */ + restoreParameters?: RestoreParameters; + /* The object representing the policy for taking backups on an account. */ backupPolicy?: BackupPolicy; @@ -457,6 +501,19 @@ export interface DatabaseAccountGetProperties { /* An array that contains the Resource Ids for Network Acl Bypass for the Cosmos DB account. */ networkAclBypassResourceIds?: unknown[]; + + /* Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. */ + disableLocalAuth?: boolean; + /* The object that represents all properties related to capacity enforcement on an account. */ + capacity?: Capacity; + + /* The object that represents the metadata for the Account Keys of the Cosmos DB account. */ + keysMetadata?: DatabaseAccountKeysMetadata; + + /* Flag to indicate enabling/disabling of Partition Merge feature on the account */ + enablePartitionMerge?: boolean; + /* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */ + minimalTlsVersion?: MinimalTlsVersion; } /* Properties to create and update Azure Cosmos DB database accounts. */ @@ -506,6 +563,12 @@ export interface DatabaseAccountCreateUpdateProperties { /* Flag to indicate whether to enable storage analytics. */ enableAnalyticalStorage?: boolean; + /* Analytical storage specific properties. */ + analyticalStorageConfiguration?: AnalyticalStorageConfiguration; + + /* Enum to indicate the mode of account creation. */ + createMode?: CreateMode; + /* The object representing the policy for taking backups on an account. */ backupPolicy?: BackupPolicy; @@ -517,6 +580,22 @@ export interface DatabaseAccountCreateUpdateProperties { /* An array that contains the Resource Ids for Network Acl Bypass for the Cosmos DB account. */ networkAclBypassResourceIds?: unknown[]; + + /* Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. */ + disableLocalAuth?: boolean; + /* Parameters to indicate the information about the restore. */ + restoreParameters?: RestoreParameters; + + /* The object that represents all properties related to capacity enforcement on an account. */ + capacity?: Capacity; + + /* This property is ignored during the update/create operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */ + keysMetadata?: DatabaseAccountKeysMetadata; + + /* Flag to indicate enabling/disabling of Partition Merge feature on the account */ + enablePartitionMerge?: boolean; + /* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */ + minimalTlsVersion?: MinimalTlsVersion; } /* Parameters to create and update Cosmos DB database accounts. */ @@ -575,6 +654,9 @@ export interface DatabaseAccountUpdateProperties { /* Flag to indicate whether to enable storage analytics. */ enableAnalyticalStorage?: boolean; + /* Analytical storage specific properties. */ + analyticalStorageConfiguration?: AnalyticalStorageConfiguration; + /* The object representing the policy for taking backups on an account. */ backupPolicy?: BackupPolicy; @@ -586,6 +668,19 @@ export interface DatabaseAccountUpdateProperties { /* An array that contains the Resource Ids for Network Acl Bypass for the Cosmos DB account. */ networkAclBypassResourceIds?: unknown[]; + + /* Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. */ + disableLocalAuth?: boolean; + /* The object that represents all properties related to capacity enforcement on an account. */ + capacity?: Capacity; + + /* This property is ignored during the update operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */ + keysMetadata?: DatabaseAccountKeysMetadata; + + /* Flag to indicate enabling/disabling of Partition Merge feature on the account */ + enablePartitionMerge?: boolean; + /* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */ + minimalTlsVersion?: MinimalTlsVersion; } /* Parameters for patching Azure Cosmos DB database account properties. */ @@ -624,6 +719,20 @@ export interface DatabaseAccountConnectionString { readonly connectionString?: string; /* Description of the connection string */ readonly description?: string; + /* Kind of the connection string key */ + readonly keyKind?: "Primary" | "Secondary" | "PrimaryReadonly" | "SecondaryReadonly"; + + /* Type of the connection string */ + readonly type?: + | "Sql" + | "Table" + | "MongoDB" + | "Cassandra" + | "CassandraConnectorMetadata" + | "Gremlin" + | "SqlDedicatedGateway" + | "GremlinV2" + | "Undefined"; } /* The connection strings for the given database account. */ @@ -844,6 +953,10 @@ export interface ThroughputSettingsResource { readonly minimumThroughput?: string; /* The throughput replace is pending */ readonly offerReplacePending?: string; + /* The offer throughput value to instantly scale up without triggering splits */ + readonly instantMaximumThroughput?: string; + /* The maximum throughput value or the maximum maxThroughput value (for autoscale) that can be specified */ + readonly softAllowedMaximumThroughput?: string; } /* Cosmos DB provisioned throughput settings object */ @@ -879,6 +992,30 @@ export interface OptionsResource { autoscaleSettings?: AutoscaleSettings; } +/* Cosmos DB client encryption key resource object. */ +export interface ClientEncryptionKeyResource { + /* Name of the ClientEncryptionKey */ + id?: string; + /* Encryption algorithm that will be used along with this client encryption key to encrypt/decrypt data. */ + encryptionAlgorithm?: string; + /* Wrapped (encrypted) form of the key represented as a byte array. */ + wrappedDataEncryptionKey?: string; + /* Metadata for the wrapping provider that can be used to unwrap the wrapped client encryption key. */ + keyWrapMetadata?: KeyWrapMetadata; +} + +/* Represents key wrap metadata that a key wrapping provider can use to wrap/unwrap a client encryption key. */ +export interface KeyWrapMetadata { + /* The name of associated KeyEncryptionKey (aka CustomerManagedKey). */ + name?: string; + /* ProviderName of KeyStoreProvider. */ + type?: string; + /* Reference / link to the KeyEncryptionKey. */ + value?: string; + /* Algorithm used in wrapping and unwrapping of the data encryption key. */ + algorithm?: string; +} + /* Cosmos DB SQL database resource object */ export interface SqlDatabaseResource { /* Name of the Cosmos DB SQL database */ @@ -903,6 +1040,9 @@ export interface SqlContainerResource { /* The conflict resolution policy for the container. */ conflictResolutionPolicy?: ConflictResolutionPolicy; + /* The client encryption policy for the container. */ + clientEncryptionPolicy?: ClientEncryptionPolicy; + /* Analytical TTL. */ analyticalStorageTtl?: number; } @@ -1014,6 +1154,27 @@ export interface ConflictResolutionPolicy { conflictResolutionProcedure?: string; } +/* Cosmos DB client encryption policy. */ +export interface ClientEncryptionPolicy { + /* Paths of the item that need encryption along with path-specific settings. */ + includedPaths: ClientEncryptionIncludedPath[]; + + /* Version of the client encryption policy definition. Supported versions are 1 and 2. Version 2 supports id and partition key path encryption. */ + policyFormatVersion: number; +} + +/* . */ +export interface ClientEncryptionIncludedPath { + /* Path that needs to be encrypted. */ + path: string; + /* The identifier of the Client Encryption Key to be used to encrypt the path. */ + clientEncryptionKeyId: string; + /* The type of encryption to be performed. Eg - Deterministic, Randomized. */ + encryptionType: string; + /* The encryption algorithm which will be used. Eg - AEAD_AES_256_CBC_HMAC_SHA256. */ + encryptionAlgorithm: string; +} + /* Cosmos DB SQL storedProcedure resource object */ export interface SqlStoredProcedureResource { /* Name of the Cosmos DB SQL storedProcedure */ @@ -1035,7 +1196,7 @@ export interface SqlTriggerResource { /* Name of the Cosmos DB SQL trigger */ id: string; /* Body of the Trigger */ - body: string; + body?: string; /* Type of the Trigger */ triggerType?: "Pre" | "Post"; @@ -1174,6 +1335,9 @@ export interface GremlinGraphResource { /* The conflict resolution policy for the graph. */ conflictResolutionPolicy?: ConflictResolutionPolicy; + + /* Analytical TTL. */ + analyticalStorageTtl?: number; } /* CreateUpdateOptions are a list of key-value pairs that describe the resource. Supported keys are "If-Match", "If-None-Match", "Session-Token" and "Throughput" */ @@ -1196,6 +1360,12 @@ export interface Capability { name?: string; } +/* The object that represents all properties related to capacity enforcement on an account. */ +export interface Capacity { + /* The total throughput limit imposed on the account. A totalThroughputLimit of 2000 imposes a strict limit of max throughput that can be provisioned on that account to be 2000. A totalThroughputLimit of -1 indicates no limits on provisioning of throughput. */ + totalThroughputLimit?: number; +} + /* Tags are a list of key-value pairs that describe the resource. These tags can be used in viewing and grouping this resource (across resource groups). A maximum of 15 tags can be provided for a resource. Each tag must have a key no greater than 128 characters and value no greater than 256 characters. For example, the default experience for a template type is set with "defaultExperience": "Cassandra". Current "defaultExperience" values also include "Table", "Graph", "DocumentDB", and "MongoDB". */ export type Tags = { [key: string]: string }; @@ -1235,6 +1405,27 @@ export interface VirtualNetworkRule { /* Indicates what services are allowed to bypass firewall checks. */ export type NetworkAclBypass = "None" | "AzureServices"; +/* The metadata related to an access key for a given database account. */ +export interface AccountKeyMetadata { + /* Generation time in UTC of the key in ISO-8601 format. If the value is missing from the object, it means that the last key regeneration was triggered before 2022-06-18. */ + readonly generationTime?: string; +} + +/* The metadata related to each access key for the given Cosmos DB database account. */ +export interface DatabaseAccountKeysMetadata { + /* The metadata related to the Primary Read-Write Key for the given Cosmos DB database account. */ + readonly primaryMasterKey?: AccountKeyMetadata; + + /* The metadata related to the Secondary Read-Write Key for the given Cosmos DB database account. */ + readonly secondaryMasterKey?: AccountKeyMetadata; + + /* The metadata related to the Primary Read-Only Key for the given Cosmos DB database account. */ + readonly primaryReadonlyMasterKey?: AccountKeyMetadata; + + /* The metadata related to the Secondary Read-Only Key for the given Cosmos DB database account. */ + readonly secondaryReadonlyMasterKey?: AccountKeyMetadata; +} + /* REST API operation */ export interface Operation { /* Operation name: {provider}/{resource}/{operation} */ @@ -1430,23 +1621,97 @@ export type UnitType = "Count" | "Bytes" | "Seconds" | "Percent" | "CountPerSeco export type ConnectorOffer = "Small"; /* Whether requests from Public Network are allowed */ -export type PublicNetworkAccess = "Enabled" | "Disabled"; +export type PublicNetworkAccess = "Enabled" | "Disabled" | "SecuredByPerimeter"; /* undocumented */ export interface ApiProperties { /* Describes the ServerVersion of an a MongoDB account. */ - serverVersion?: "3.2" | "3.6" | "4.0"; + serverVersion?: "3.2" | "3.6" | "4.0" | "4.2"; } +/* Analytical storage specific properties. */ +export interface AnalyticalStorageConfiguration { + /* undocumented */ + schemaType?: AnalyticalStorageSchemaType; +} + +/* Describes the types of schema for analytical storage. */ +export type AnalyticalStorageSchemaType = "WellDefined" | "FullFidelity"; + +/* Enum to indicate the mode of account creation. */ +export type CreateMode = "Default" | "Restore"; + +/* Parameters to indicate the information about the restore. */ +export interface RestoreParameters { + /* Describes the mode of the restore. */ + restoreMode?: "PointInTime"; + + /* The id of the restorable database account from which the restore has to be initiated. For example: /subscriptions/{subscriptionId}/providers/Microsoft.DocumentDB/locations/{location}/restorableDatabaseAccounts/{restorableDatabaseAccountName} */ + restoreSource?: string; + /* Time to which the account has to be restored (ISO-8601 format). */ + restoreTimestampInUtc?: string; + /* List of specific databases available for restore. */ + databasesToRestore?: DatabaseRestoreResource[]; + + /* List of specific gremlin databases available for restore. */ + gremlinDatabasesToRestore?: GremlinDatabaseRestoreResource[]; + + /* List of specific tables available for restore. */ + tablesToRestore?: TableName[]; +} + +/* Specific Databases to restore. */ +export interface DatabaseRestoreResource { + /* The name of the database available for restore. */ + databaseName?: string; + /* The names of the collections available for restore. */ + collectionNames?: CollectionName[]; +} + +/* Specific Gremlin Databases to restore. */ +export interface GremlinDatabaseRestoreResource { + /* The name of the gremlin database available for restore. */ + databaseName?: string; + /* The names of the graphs available for restore. */ + graphNames?: GraphName[]; +} + +/* The name of the collection. */ +export type CollectionName = string; + +/* The name of the graph. */ +export type GraphName = string; + +/* The name of the table. */ +export type TableName = string; + /* The object representing the policy for taking backups on an account. */ export interface BackupPolicy { - /* undocumented */ + /* Describes the mode of backups. */ type: BackupPolicyType; + + /* The object representing the state of the migration between the backup policies. */ + migrationState?: BackupPolicyMigrationState; } /* Describes the mode of backups. */ export type BackupPolicyType = "Periodic" | "Continuous"; +/* The object representing the state of the migration between the backup policies. */ +export interface BackupPolicyMigrationState { + /* Describes the status of migration between backup policy types. */ + status?: BackupPolicyMigrationStatus; + + /* Describes the target backup policy type of the backup policy migration. */ + targetType?: BackupPolicyType; + + /* Time at which the backup policy migration started (ISO-8601 format). */ + startTime?: string; +} + +/* Describes the status of migration between backup policy types. */ +export type BackupPolicyMigrationStatus = "Invalid" | "InProgress" | "Completed" | "Failed"; + /* The object representing periodic mode backup policy. */ export type PeriodicModeBackupPolicy = BackupPolicy & { /* Configuration values for periodic mode backup */ @@ -1454,7 +1719,10 @@ export type PeriodicModeBackupPolicy = BackupPolicy & { }; /* The object representing continuous mode backup policy. */ -export type ContinuousModeBackupPolicy = BackupPolicy; +export type ContinuousModeBackupPolicy = BackupPolicy & { + /* Configuration values for continuous mode backup */ + continuousModeProperties?: ContinuousModeProperties; +}; /* Configuration values for periodic mode backup */ export interface PeriodicModeProperties { @@ -1462,4 +1730,50 @@ export interface PeriodicModeProperties { backupIntervalInMinutes?: number; /* An integer representing the time (in hours) that each backup is retained */ backupRetentionIntervalInHours?: number; + /* Enum to indicate type of backup residency */ + backupStorageRedundancy?: BackupStorageRedundancy; } + +/* Configuration values for periodic mode backup */ +export interface ContinuousModeProperties { + /* Enum to indicate type of Continuous backup mode */ + tier?: ContinuousTier; +} + +/* The List operation response, that contains Cosmos DB locations and their properties. */ +export interface LocationListResult { + /* List of Cosmos DB locations and their properties. */ + readonly value?: LocationGetResult[]; +} + +/* Cosmos DB location get result */ +export type LocationGetResult = ARMProxyResource & { + /* Cosmos DB location metadata */ + properties?: LocationProperties; +}; + +/* Cosmos DB location metadata */ +export interface LocationProperties { + /* Flag indicating whether the location supports availability zones or not. */ + readonly supportsAvailabilityZone?: boolean; + /* Flag indicating whether the location is residency sensitive. */ + readonly isResidencyRestricted?: boolean; + /* The properties of available backup storage redundancies. */ + readonly backupStorageRedundancies?: BackupStorageRedundancy[]; + + /* Flag indicating whether the subscription have access in region for Non-Availability Zones. */ + readonly isSubscriptionRegionAccessAllowedForRegular?: boolean; + /* Flag indicating whether the subscription have access in region for Availability Zones(Az). */ + readonly isSubscriptionRegionAccessAllowedForAz?: boolean; + /* Enum to indicate current buildout status of the region. */ + readonly status?: "Uninitialized" | "Initializing" | "InternallyReady" | "Online" | "Deleting"; +} + +/* Enum to indicate type of backup storage redundancy. */ +export type BackupStorageRedundancy = "Geo" | "Local" | "Zone"; + +/* Enum to indicate type of Continuous backup tier. */ +export type ContinuousTier = "Continuous7Days" | "Continuous30Days"; + +/* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */ +export type MinimalTlsVersion = "Tls" | "Tls11" | "Tls12"; diff --git a/tsconfig.json b/tsconfig.json index 39dad0788..156b4abc4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,12 +15,18 @@ "target": "es2017", "experimentalDecorators": true, "emitDecoratorMetadata": true, - "lib": ["es5", "es6", "dom"], + "lib": [ + "es5", + "es6", + "dom" + ], "jsx": "react", "moduleResolution": "node", "resolveJsonModule": true, "noEmit": true, - "types": ["jest"], + "types": [ + "jest" + ], "baseUrl": "src" }, "typedocOptions": { @@ -37,6 +43,17 @@ "includes": "./src/SelfServe/Documentation", "disableSources": true }, - "include": ["src", "./src/**/*", "./utils/**/*"], - "exclude": ["./src/**/__mocks__/**/*"] -} + "include": [ + "src", + "./src/**/*", + "./utils/**/*" + ], + "exclude": [ + "./src/**/__mocks__/**/*" + ], + "ts-node": { + "compilerOptions": { + "module": "CommonJS" + } + } +} \ No newline at end of file diff --git a/utils/armClientGenerator/generator.ts b/utils/armClientGenerator/generator.ts index dd3da3db0..cb6ee23fb 100644 --- a/utils/armClientGenerator/generator.ts +++ b/utils/armClientGenerator/generator.ts @@ -16,10 +16,15 @@ Results of this file should be checked into the repo. */ // CHANGE THESE VALUES TO GENERATE NEW CLIENTS -const version = "2021-04-15"; -const resourceName = "cosmosNotebooks"; -const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/${version}/notebook.json`; -const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${resourceName}/${version}`); +const version = "2023-04-15"; +/* The following are legal options for resourceName but you generally will only use cosmos-db: +"cosmos-db" | "managedCassandra" | "mongorbac" | "notebook" | "privateEndpointConnection" | "privateLinkResources" | +"rbac" | "restorable" | "services" +*/ +const githubResourceName = "cosmos-db"; +const deResourceName = "cosmos"; +const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/${version}/${githubResourceName}.json`; +const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${deResourceName}`); // Array of strings to use for eventual output const outputTypes: string[] = [""]; @@ -142,7 +147,7 @@ const propertyToType = (property: Property, prop: string, required: boolean) => `); } else { if (property.type === undefined) { - console.log(`UHANDLED TYPE: ${prop}. Falling back to unknown`); + console.log(`generator.ts - UNHANDLED TYPE: ${prop}. Falling back to unknown`); property.type = "unknown"; } outputTypes.push(` @@ -209,7 +214,7 @@ async function main() { export type ${definition} = ${type} `); } else { - console.log("UNHANDLED MODEL:", def, schema.definitions[def]); + console.log("generator.ts - UNHANDLED MODEL:", def, schema.definitions[def]); } } } @@ -233,9 +238,9 @@ async function main() { // Write all grouped fetch functions to objects for (const clientName in clients) { const outputClient: string[] = [""]; - outputClient.push(`import { armRequest } from "../../../request"\n`); + outputClient.push(`import { armRequest } from "../../request"\n`); outputClient.push(`import * as Types from "./types"\n`); - outputClient.push(`import { configContext } from "../../../../../ConfigContext";\n`); + outputClient.push(`import { configContext } from "../../../../ConfigContext";\n`); outputClient.push(`const apiVersion = "${version}"\n\n`); for (const path of clients[clientName].paths) { for (const method in schema.paths[path]) {