diff --git a/.chronus/changes/addV4LegacyManagedIdentity-2024-5-12-18-14-55.md b/.chronus/changes/addV4LegacyManagedIdentity-2024-5-12-18-14-55.md new file mode 100644 index 0000000000..137c8af66e --- /dev/null +++ b/.chronus/changes/addV4LegacyManagedIdentity-2024-5-12-18-14-55.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Adding legacy v4 ManagedServiceIdentity model to avoid breaking changes in specs with mixed v3 and v4 common type reference \ No newline at end of file diff --git a/.chronus/changes/arm-lro-opt-2024-5-5-15-31-47.md b/.chronus/changes/arm-lro-opt-2024-5-5-15-31-47.md new file mode 100644 index 0000000000..eebafe6bc1 --- /dev/null +++ b/.chronus/changes/arm-lro-opt-2024-5-5-15-31-47.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-azure-core" +--- + +Add override decorator @useFinalStateVia for lro resolution when multiple resolution pathways exist \ No newline at end of file diff --git a/.chronus/changes/arm-lro-opt-2024-5-5-15-33-29.md b/.chronus/changes/arm-lro-opt-2024-5-5-15-33-29.md new file mode 100644 index 0000000000..e56a573539 --- /dev/null +++ b/.chronus/changes/arm-lro-opt-2024-5-5-15-33-29.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Remove OpenAPI dependencies from ARM LRO templates and test LRO overrides \ No newline at end of file diff --git a/.chronus/changes/arm-lro-opt-2024-5-5-19-32-9.md b/.chronus/changes/arm-lro-opt-2024-5-5-19-32-9.md new file mode 100644 index 0000000000..5a9d225023 --- /dev/null +++ b/.chronus/changes/arm-lro-opt-2024-5-5-19-32-9.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-autorest" +--- + +Add suppress-lro-options emitter option to control emission of x-ms-long-running-operation-options \ No newline at end of file diff --git a/.chronus/changes/arm-lro-opt-2024-5-5-2-57-50.md b/.chronus/changes/arm-lro-opt-2024-5-5-2-57-50.md new file mode 100644 index 0000000000..16b8e22136 --- /dev/null +++ b/.chronus/changes/arm-lro-opt-2024-5-5-2-57-50.md @@ -0,0 +1,9 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: feature +packages: + - "@azure-tools/typespec-autorest" + +--- + +- Add support for displaying lro options in typespec-autorest based on lro metadata diff --git a/.chronus/changes/azhang_addNameTypeToResourceNameParam-2024-4-28-12-18-25.md b/.chronus/changes/azhang_addNameTypeToResourceNameParam-2024-4-28-12-18-25.md new file mode 100644 index 0000000000..ecca809aaf --- /dev/null +++ b/.chronus/changes/azhang_addNameTypeToResourceNameParam-2024-4-28-12-18-25.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Adding an overload parameter to ResourceNameParameter that allows `name` type to be set to string union type. diff --git a/.chronus/changes/res-vis-2024-5-12-4-34-46.md b/.chronus/changes/res-vis-2024-5-12-4-34-46.md new file mode 100644 index 0000000000..a5b220fe19 --- /dev/null +++ b/.chronus/changes/res-vis-2024-5-12-4-34-46.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Make Resource Properties Bag Updatable diff --git a/.chronus/changes/update_canonical_swagger_folder_name-2024-6-6-11-44-3.md b/.chronus/changes/update_canonical_swagger_folder_name-2024-6-6-11-44-3.md new file mode 100644 index 0000000000..14101dc92c --- /dev/null +++ b/.chronus/changes/update_canonical_swagger_folder_name-2024-6-6-11-44-3.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-autorest-canonical" +--- + +update the canonical swagger file folder name diff --git a/docs/emitters/typespec-autorest-canonical/reference/emitter.md b/docs/emitters/typespec-autorest-canonical/reference/emitter.md index 4613b5348f..820c8a8995 100644 --- a/docs/emitters/typespec-autorest-canonical/reference/emitter.md +++ b/docs/emitters/typespec-autorest-canonical/reference/emitter.md @@ -33,7 +33,7 @@ Output file will interpolate the following values: - service-name: Name of the service if multiple - azure-resource-provider-folder: Value of the azure-resource-provider-folder option -Default: `{azure-resource-provider-folder}/{service-name}/{version}/openapi.json` +Default: `{azure-resource-provider-folder}/{service-name}/canonical/openapi.json` Example: Single service diff --git a/docs/emitters/typespec-autorest/reference/emitter.md b/docs/emitters/typespec-autorest/reference/emitter.md index 13979134cd..4bc24450c4 100644 --- a/docs/emitters/typespec-autorest/reference/emitter.md +++ b/docs/emitters/typespec-autorest/reference/emitter.md @@ -119,3 +119,9 @@ This extension is meant for debugging and should not be depended on. **Type:** `boolean` Create read-only property schema for lro status + +### `emit-lro-options` + +**Type:** `"none" | "final-state-only" | "all"` + +Determine whether and how to emit x-ms-long-running-operation-options for lro resolution diff --git a/docs/libraries/azure-core/reference/data-types.md b/docs/libraries/azure-core/reference/data-types.md index 91cc9c87b1..e01fc47e41 100644 --- a/docs/libraries/azure-core/reference/data-types.md +++ b/docs/libraries/azure-core/reference/data-types.md @@ -348,12 +348,12 @@ model Azure.Core.ResourceOperationStatus #### Properties -| Name | Type | Description | -| ------- | ------------------------------------------------------------------------- | -------------------------------------------------------------- | -| id | `string` | The unique ID of the operation. | -| status | [`OperationState`](./data-types.md#Azure.Core.Foundations.OperationState) | The status of the operation | -| error? | `StatusError` | Error object that describes the error when status is "Failed". | -| result? | `StatusResult` | The result of the operation. | +| Name | Type | Description | +| ------- | ------------------------------------------------------------------------- | ----------- | +| id | `string` | | +| status | [`OperationState`](./data-types.md#Azure.Core.Foundations.OperationState) | | +| error? | `StatusError` | | +| result? | `StatusResult` | | ### `ResponseProperty` {#Azure.Core.ResponseProperty} diff --git a/docs/libraries/azure-core/reference/decorators.md b/docs/libraries/azure-core/reference/decorators.md index fbefed9ebc..3734168336 100644 --- a/docs/libraries/azure-core/reference/decorators.md +++ b/docs/libraries/azure-core/reference/decorators.md @@ -309,6 +309,24 @@ Used to define how to call custom polling operations for long-running operations | --------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | targetParameter | `ModelProperty \| string` | A reference to the polling operation parameter this parameter
provides a value for, or the name of that parameter. The default value is the name of
the decorated parameter or property. | +### `@useFinalStateVia` {#@Azure.Core.useFinalStateVia} + +Overrides the final state value for an operation + +```typespec +@Azure.Core.useFinalStateVia(finalState: valueof "original-uri" | "operation-location" | "location" | "azure-async-operation") +``` + +#### Target + +`Operation` + +#### Parameters + +| Name | Type | Description | +| ---------- | ----------------------------------------------------------------------------------------- | ----------------------------- | +| finalState | `valueof "original-uri" \| "operation-location" \| "location" \| "azure-async-operation"` | The desired final state value | + ## Azure.Core.Foundations ### `@omitKeyProperties` {#@Azure.Core.Foundations.omitKeyProperties} diff --git a/docs/libraries/azure-core/reference/index.mdx b/docs/libraries/azure-core/reference/index.mdx index d6aeb6abd4..5ea11012a4 100644 --- a/docs/libraries/azure-core/reference/index.mdx +++ b/docs/libraries/azure-core/reference/index.mdx @@ -54,6 +54,7 @@ npm install --save-peer @azure-tools/typespec-azure-core - [`@pollingLocation`](./decorators.md#@Azure.Core.pollingLocation) - [`@pollingOperation`](./decorators.md#@Azure.Core.pollingOperation) - [`@pollingOperationParameter`](./decorators.md#@Azure.Core.pollingOperationParameter) +- [`@useFinalStateVia`](./decorators.md#@Azure.Core.useFinalStateVia) ### Interfaces diff --git a/docs/libraries/azure-core/reference/interfaces.md b/docs/libraries/azure-core/reference/interfaces.md index 7ed271e946..f3a8f10fb0 100644 --- a/docs/libraries/azure-core/reference/interfaces.md +++ b/docs/libraries/azure-core/reference/interfaces.md @@ -263,7 +263,7 @@ op Azure.Core.ResourceOperations.LongRunningResourceCollectionAction(apiVersion: Resource operation status operation template. ```typespec -op Azure.Core.ResourceOperations.GetResourceOperationStatus(apiVersion: string, operationId: string): Azure.Core.ResourceOperationStatus | ErrorResponse +op Azure.Core.ResourceOperations.GetResourceOperationStatus(apiVersion: string): Azure.Core.ResourceOperationStatus | ErrorResponse ``` ##### Template Parameters @@ -280,7 +280,7 @@ op Azure.Core.ResourceOperations.GetResourceOperationStatus(apiVersion: string, Operation signature to retrieve a resource operation status. ```typespec -op Azure.Core.GetResourceOperationStatus(apiVersion: string, operationId: string): Azure.Core.ResourceOperationStatus | Azure.Core.Foundations.ErrorResponse +op Azure.Core.GetResourceOperationStatus(apiVersion: string): Azure.Core.ResourceOperationStatus | Azure.Core.Foundations.ErrorResponse ``` #### Template Parameters diff --git a/docs/libraries/azure-resource-manager/reference/data-types.md b/docs/libraries/azure-resource-manager/reference/data-types.md index 1d11512ab6..a3d412af29 100644 --- a/docs/libraries/azure-resource-manager/reference/data-types.md +++ b/docs/libraries/azure-resource-manager/reference/data-types.md @@ -51,7 +51,7 @@ model Azure.ResourceManager.ArmAcceptedResponse The standard header for asynchronous operation polling ```typespec -model Azure.ResourceManager.ArmAsyncOperationHeader +model Azure.ResourceManager.ArmAsyncOperationHeader ``` #### Template Parameters @@ -60,6 +60,7 @@ model Azure.ResourceManager.ArmAsyncOperationHeader | ------------- | ------------------------------------------------- | | StatusMonitor | The status monitor type for lro polling | | UrlValue | The value type of the Azure-AsyncOperation header | +| FinalResult | The logical final result of the operation | #### Properties @@ -186,9 +187,9 @@ model Azure.ResourceManager.ArmLocationResource #### Properties -| Name | Type | Description | -| -------- | -------- | ------------------ | -| location | `string` | The location name. | +| Name | Type | Description | +| -------- | -------- | ----------------------------- | +| location | `string` | The name of the Azure region. | ### `ArmLroLocationHeader` {#Azure.ResourceManager.ArmLroLocationHeader} @@ -337,10 +338,10 @@ model Azure.ResourceManager.ArmResourceUpdatedResponse #### Properties -| Name | Type | Description | -| ---------- | ---------- | --------------------------------------------------- | -| statusCode | `200` | The status code. | -| body | `Resource` | The body type of the operation request or response. | +| Name | Type | Description | +| ---------- | ---------- | ---------------- | +| statusCode | `200` | The status code. | +| body | `Resource` | | ### `ArmResponse` {#Azure.ResourceManager.ArmResponse} @@ -512,20 +513,6 @@ model Azure.ResourceManager.LocationParameter | -------- | -------- | ------------------ | | location | `string` | The location name. | -### `LocationResourceParameter` {#Azure.ResourceManager.LocationResourceParameter} - -The default location parameter type. - -```typespec -model Azure.ResourceManager.LocationResourceParameter -``` - -#### Properties - -| Name | Type | Description | -| -------- | -------- | ------------------ | -| location | `string` | The location name. | - ### `ManagedByProperty` {#Azure.ResourceManager.ManagedByProperty} Model representing the standard `managedBy` envelope property for a resource. @@ -670,23 +657,9 @@ model Azure.ResourceManager.ResourceGroupLocationResource #### Properties -| Name | Type | Description | -| -------- | -------- | ------------------ | -| location | `string` | The location name. | - -### `ResourceGroupParameter` {#Azure.ResourceManager.ResourceGroupParameter} - -The default resource group parameter type. - -```typespec -model Azure.ResourceManager.ResourceGroupParameter -``` - -#### Properties - -| Name | Type | Description | -| ----------------- | -------- | ------------------------------------------------------------- | -| resourceGroupName | `string` | The name of the resource group. The name is case insensitive. | +| Name | Type | Description | +| -------- | -------- | ----------------------------- | +| location | `string` | The name of the Azure region. | ### `ResourceInstanceParameters` {#Azure.ResourceManager.ResourceInstanceParameters} @@ -750,10 +723,10 @@ model Azure.ResourceManager.ResourceListResult #### Properties -| Name | Type | Description | -| --------- | -------------------------------- | ---------------------------------- | -| value | `Array` | The {name} items on this page | -| nextLink? | `TypeSpec.Rest.ResourceLocation` | The link to the next page of items | +| Name | Type | Description | +| --------- | -------------------------------- | ----------- | +| value | `Array` | | +| nextLink? | `TypeSpec.Rest.ResourceLocation` | | ### `ResourceNameParameter` {#Azure.ResourceManager.ResourceNameParameter} @@ -761,24 +734,27 @@ Spread this model into ARM resource models to specify resource name parameter fo is specified, the resource name will be properly camel cased and pluralized for `@key` and `@segment` automatically. You can also apply explicit override with `KeyName` and `SegmentName` template parameters. +For additional decorators such as + ```typespec -model Azure.ResourceManager.ResourceNameParameter +model Azure.ResourceManager.ResourceNameParameter ``` #### Template Parameters -| Name | Description | -| ----------- | ----------------------------------------------------------------- | -| Resource | The ARM resource this name parameter is applying to. | -| KeyName | Override default key name of the resource. | -| SegmentName | Override default segment name of the resource. | -| NamePattern | The RegEx pattern of the name. Default is `^[a-zA-Z0-9-]{3,24}$`. | +| Name | Description | +| ----------- | -------------------------------------------------------------------------------------------------------- | +| Resource | The ARM resource this name parameter is applying to. | +| KeyName | Override default key name of the resource. | +| SegmentName | Override default segment name of the resource. | +| NamePattern | The RegEx pattern of the name. Default is `^[a-zA-Z0-9-]{3,24}$`. | +| Type | The type of the name property. Default type is string. However you can pass an union with string values. | #### Properties -| Name | Type | Description | -| ---- | -------- | ----------- | -| name | `string` | | +| Name | Type | Description | +| ---- | ------ | ----------- | +| name | `Type` | | ### `ResourceParentParameters` {#Azure.ResourceManager.ResourceParentParameters} @@ -875,9 +851,9 @@ model Azure.ResourceManager.SubscriptionLocationResource #### Properties -| Name | Type | Description | -| -------- | -------- | ------------------ | -| location | `string` | The location name. | +| Name | Type | Description | +| -------- | -------- | ----------------------------- | +| location | `string` | The name of the Azure region. | ### `TenantLocationResource` {#Azure.ResourceManager.TenantLocationResource} @@ -890,9 +866,9 @@ model Azure.ResourceManager.TenantLocationResource #### Properties -| Name | Type | Description | -| -------- | -------- | ------------------ | -| location | `string` | The location name. | +| Name | Type | Description | +| -------- | -------- | ----------------------------- | +| location | `string` | The name of the Azure region. | ### `TrackedResource` {#Azure.ResourceManager.TrackedResource} @@ -1036,12 +1012,12 @@ model Azure.ResourceManager.CommonTypes.Encryption | infrastructureEncryption? | [`InfrastructureEncryption`](./data-types.md#Azure.ResourceManager.CommonTypes.InfrastructureEncryption) | Values are enabled and disabled. | | customerManagedKeyEncryption? | [`CustomerManagedKeyEncryption`](./data-types.md#Azure.ResourceManager.CommonTypes.CustomerManagedKeyEncryption) | All Customer-managed key encryption properties for the resource. | -### `encryptionProperties` {#Azure.ResourceManager.CommonTypes.encryptionProperties} +### `EncryptionProperties` {#Azure.ResourceManager.CommonTypes.EncryptionProperties} Configuration of key for data encryption ```typespec -model Azure.ResourceManager.CommonTypes.encryptionProperties +model Azure.ResourceManager.CommonTypes.EncryptionProperties ``` #### Properties @@ -1199,12 +1175,12 @@ model Azure.ResourceManager.CommonTypes.KeyVaultProperties | keyIdentifier? | `string` | Key vault uri to access the encryption key. | | identity? | `string` | The client ID of the identity which will be used to access key vault. | -### `locationData` {#Azure.ResourceManager.CommonTypes.locationData} +### `LocationData` {#Azure.ResourceManager.CommonTypes.LocationData} Metadata pertaining to the geographic location of the resource. ```typespec -model Azure.ResourceManager.CommonTypes.locationData +model Azure.ResourceManager.CommonTypes.LocationData ``` #### Properties @@ -1230,6 +1206,20 @@ model Azure.ResourceManager.CommonTypes.LocationParameter | -------- | -------- | ------------------------- | | location | `string` | The name of Azure region. | +### `LocationResourceParameter` {#Azure.ResourceManager.CommonTypes.LocationResourceParameter} + +The default location parameter type. + +```typespec +model Azure.ResourceManager.CommonTypes.LocationResourceParameter +``` + +#### Properties + +| Name | Type | Description | +| -------- | -------- | ----------------------------- | +| location | `string` | The name of the Azure region. | + ### `ManagedServiceIdentity` {#Azure.ResourceManager.CommonTypes.ManagedServiceIdentity} Managed service identity (system assigned and/or user assigned identities) @@ -1537,7 +1527,7 @@ None ### `Resource` {#Azure.ResourceManager.CommonTypes.Resource} -Base model that defines common properties for all Azure Resource Manager resources. +Common fields that are returned in the response for all Azure Resource Manager resources ```typespec model Azure.ResourceManager.CommonTypes.Resource @@ -1661,10 +1651,10 @@ model Azure.ResourceManager.CommonTypes.SystemData | ------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------- | | createdBy? | `string` | The identity that created the resource. | | createdByType? | [`createdByType`](./data-types.md#Azure.ResourceManager.CommonTypes.createdByType) | The type of identity that created the resource. | -| createdAt? | `plainDate` | The timestamp of resource creation (UTC). | +| createdAt? | `utcDateTime` | The timestamp of resource creation (UTC). | | lastModifiedBy? | `string` | The identity that last modified the resource. | | lastModifiedByType? | [`createdByType`](./data-types.md#Azure.ResourceManager.CommonTypes.createdByType) | The type of identity that last modified the resource. | -| lastModifiedAt? | `plainDate` | The timestamp of resource last modification (UTC) | +| lastModifiedAt? | `utcDateTime` | The timestamp of resource last modification (UTC) | ### `TenantIdParameter` {#Azure.ResourceManager.CommonTypes.TenantIdParameter} @@ -1766,6 +1756,8 @@ union Azure.ResourceManager.CommonTypes.createdByType ### `EncryptionStatus` {#Azure.ResourceManager.CommonTypes.EncryptionStatus} +Indicates whether or not the encryption is enabled for container registry. + ```typespec union Azure.ResourceManager.CommonTypes.EncryptionStatus ``` @@ -1926,7 +1918,7 @@ model Azure.ResourceManager.Foundations.ExtensionScope | ----------- | -------------------------------- | ---------------------------------------------------------------------- | | apiVersion | `string` | The API version to use for this operation. | | resourceUri | `string` | The fully qualified Azure Resource manager identifier of the resource. | -| provider | `"Microsoft.ThisWillBeReplaced"` | The provider namespace for the resource. | +| provider | `"Microsoft.ThisWillBeReplaced"` | | ### `LocationBaseParameters` {#Azure.ResourceManager.Foundations.LocationBaseParameters} @@ -1965,7 +1957,7 @@ model Azure.ResourceManager.Foundations.LocationScope | apiVersion | `string` | The API version to use for this operation. | | subscriptionId | `Core.uuid` | The ID of the target subscription. The value must be an UUID. | | location | `string` | The location name. | -| provider | `"Microsoft.ThisWillBeReplaced"` | The provider namespace for the resource. | +| provider | `"Microsoft.ThisWillBeReplaced"` | | ### `ProxyResourceUpdateModel` {#Azure.ResourceManager.Foundations.ProxyResourceUpdateModel} @@ -2027,7 +2019,7 @@ model Azure.ResourceManager.Foundations.ResourceGroupScope | location | `string` | The location name. | | resourceGroupName | `string` | The name of the resource group. The name is case insensitive. | | resourceUri | `string` | The fully qualified Azure Resource manager identifier of the resource. | -| provider | `"Microsoft.ThisWillBeReplaced"` | The provider namespace for the resource. | +| provider | `"Microsoft.ThisWillBeReplaced"` | | ### `ResourceUpdateModel` {#Azure.ResourceManager.Foundations.ResourceUpdateModel} @@ -2106,7 +2098,7 @@ model Azure.ResourceManager.Foundations.SubscriptionScope | -------------- | -------------------------------- | ------------------------------------------------------------- | | apiVersion | `string` | The API version to use for this operation. | | subscriptionId | `Core.uuid` | The ID of the target subscription. The value must be an UUID. | -| provider | `"Microsoft.ThisWillBeReplaced"` | The provider namespace for the resource. | +| provider | `"Microsoft.ThisWillBeReplaced"` | | ### `TagsUpdateModel` {#Azure.ResourceManager.Foundations.TagsUpdateModel} @@ -2161,4 +2153,59 @@ model Azure.ResourceManager.Foundations.TenantScope | Name | Type | Description | | ---------- | -------------------------------- | ------------------------------------------ | | apiVersion | `string` | The API version to use for this operation. | -| provider | `"Microsoft.ThisWillBeReplaced"` | The provider namespace for the resource. | +| provider | `"Microsoft.ThisWillBeReplaced"` | | + +## Azure.ResourceManager.Legacy + +### `ManagedServiceIdentityV4` {#Azure.ResourceManager.Legacy.ManagedServiceIdentityV4} + +Managed service identity (system assigned and/or user assigned identities) + +```typespec +model Azure.ResourceManager.Legacy.ManagedServiceIdentityV4 +``` + +#### Properties + +| Name | Type | Description | +| ----------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| principalId? | `Core.uuid` | The service principal ID of the system assigned identity. This property will only be provided for a system assigned identity. | +| tenantId? | `Core.uuid` | The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity. | +| type | [`ManagedServiceIdentityType`](./data-types.md#Azure.ResourceManager.Legacy.ManagedServiceIdentityType) | The type of managed identity assigned to this resource. | +| userAssignedIdentities? | `Record` | The identities assigned to this resource by the user. | + +### `ManagedServiceIdentityV4Property` {#Azure.ResourceManager.Legacy.ManagedServiceIdentityV4Property} + +Model representing the standard `ManagedServiceIdentity` envelope property from V4 of common type. + +Please note that this is only included for legacy specs with mixed v3 and v4 types, which would cause +breaking changes due to the ManagedServiceIdentityType.SystemAndUserAssigned value changes. + +Do not use this if you are already on CommonTypes.Version.v4 or beyond. + +```typespec +model Azure.ResourceManager.Legacy.ManagedServiceIdentityV4Property +``` + +#### Examples + +```typespec +model Foo is TrackedResource { + ...ResourceNameParameter; + ...Legacy.ManagedServiceIdentityV4Property; +} +``` + +#### Properties + +| Name | Type | Description | +| --------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | +| identity? | [`ManagedServiceIdentityV4`](./data-types.md#Azure.ResourceManager.Legacy.ManagedServiceIdentityV4) | The managed service identities assigned to this resource. | + +### `ManagedServiceIdentityType` {#Azure.ResourceManager.Legacy.ManagedServiceIdentityType} + +Type of managed service identity (where both SystemAssigned and UserAssigned types are allowed). + +```typespec +union Azure.ResourceManager.Legacy.ManagedServiceIdentityType +``` diff --git a/docs/libraries/azure-resource-manager/reference/decorators.md b/docs/libraries/azure-resource-manager/reference/decorators.md index ee1d42158a..9983be00ac 100644 --- a/docs/libraries/azure-resource-manager/reference/decorators.md +++ b/docs/libraries/azure-resource-manager/reference/decorators.md @@ -23,9 +23,9 @@ the version of the Azure Resource Manager common-types to use for refs in emitte #### Parameters -| Name | Type | Description | -| ------- | ------------------------------ | ------------------------------------------------------------------------------------ | -| version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version. | +| Name | Type | Description | +| ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | +| version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". | ### `@armLibraryNamespace` {#@Azure.ResourceManager.armLibraryNamespace} diff --git a/docs/libraries/azure-resource-manager/reference/index.mdx b/docs/libraries/azure-resource-manager/reference/index.mdx index 563dfda1d7..5ecf4cb7ca 100644 --- a/docs/libraries/azure-resource-manager/reference/index.mdx +++ b/docs/libraries/azure-resource-manager/reference/index.mdx @@ -141,7 +141,6 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`ExtensionResource`](./data-types.md#Azure.ResourceManager.ExtensionResource) - [`KeysOf`](./data-types.md#Azure.ResourceManager.KeysOf) - [`LocationParameter`](./data-types.md#Azure.ResourceManager.LocationParameter) -- [`LocationResourceParameter`](./data-types.md#Azure.ResourceManager.LocationResourceParameter) - [`ManagedByProperty`](./data-types.md#Azure.ResourceManager.ManagedByProperty) - [`ManagedServiceIdentityProperty`](./data-types.md#Azure.ResourceManager.ManagedServiceIdentityProperty) - [`ManagedSystemAssignedIdentityProperty`](./data-types.md#Azure.ResourceManager.ManagedSystemAssignedIdentityProperty) @@ -149,7 +148,6 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`ProviderNamespace`](./data-types.md#Azure.ResourceManager.ProviderNamespace) - [`ProxyResource`](./data-types.md#Azure.ResourceManager.ProxyResource) - [`ResourceGroupLocationResource`](./data-types.md#Azure.ResourceManager.ResourceGroupLocationResource) -- [`ResourceGroupParameter`](./data-types.md#Azure.ResourceManager.ResourceGroupParameter) - [`ResourceInstanceParameters`](./data-types.md#Azure.ResourceManager.ResourceInstanceParameters) - [`ResourceKindProperty`](./data-types.md#Azure.ResourceManager.ResourceKindProperty) - [`ResourceListResult`](./data-types.md#Azure.ResourceManager.ResourceListResult) @@ -172,7 +170,7 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`CheckNameAvailabilityResponse`](./data-types.md#Azure.ResourceManager.CommonTypes.CheckNameAvailabilityResponse) - [`CustomerManagedKeyEncryption`](./data-types.md#Azure.ResourceManager.CommonTypes.CustomerManagedKeyEncryption) - [`Encryption`](./data-types.md#Azure.ResourceManager.CommonTypes.Encryption) -- [`encryptionProperties`](./data-types.md#Azure.ResourceManager.CommonTypes.encryptionProperties) +- [`EncryptionProperties`](./data-types.md#Azure.ResourceManager.CommonTypes.EncryptionProperties) - [`ErrorAdditionalInfo`](./data-types.md#Azure.ResourceManager.CommonTypes.ErrorAdditionalInfo) - [`ErrorDetail`](./data-types.md#Azure.ResourceManager.CommonTypes.ErrorDetail) - [`ErrorResponse`](./data-types.md#Azure.ResourceManager.CommonTypes.ErrorResponse) @@ -183,8 +181,9 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`IfNoneMatchHeader`](./data-types.md#Azure.ResourceManager.CommonTypes.IfNoneMatchHeader) - [`KeyEncryptionKeyIdentity`](./data-types.md#Azure.ResourceManager.CommonTypes.KeyEncryptionKeyIdentity) - [`KeyVaultProperties`](./data-types.md#Azure.ResourceManager.CommonTypes.KeyVaultProperties) -- [`locationData`](./data-types.md#Azure.ResourceManager.CommonTypes.locationData) +- [`LocationData`](./data-types.md#Azure.ResourceManager.CommonTypes.LocationData) - [`LocationParameter`](./data-types.md#Azure.ResourceManager.CommonTypes.LocationParameter) +- [`LocationResourceParameter`](./data-types.md#Azure.ResourceManager.CommonTypes.LocationResourceParameter) - [`ManagedServiceIdentity`](./data-types.md#Azure.ResourceManager.CommonTypes.ManagedServiceIdentity) - [`ManagementGroupNameParameter`](./data-types.md#Azure.ResourceManager.CommonTypes.ManagementGroupNameParameter) - [`Operation`](./data-types.md#Azure.ResourceManager.CommonTypes.Operation) @@ -244,3 +243,10 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`TagsUpdateModel`](./data-types.md#Azure.ResourceManager.Foundations.TagsUpdateModel) - [`TenantBaseParameters`](./data-types.md#Azure.ResourceManager.Foundations.TenantBaseParameters) - [`TenantScope`](./data-types.md#Azure.ResourceManager.Foundations.TenantScope) + +## Azure.ResourceManager.Legacy + +### Models + +- [`ManagedServiceIdentityV4`](./data-types.md#Azure.ResourceManager.Legacy.ManagedServiceIdentityV4) +- [`ManagedServiceIdentityV4Property`](./data-types.md#Azure.ResourceManager.Legacy.ManagedServiceIdentityV4Property) diff --git a/eng/feeds/arm-canonical/tspconfig.yaml b/eng/feeds/arm-canonical/tspconfig.yaml index 3e0f896eda..e75f83fbd5 100644 --- a/eng/feeds/arm-canonical/tspconfig.yaml +++ b/eng/feeds/arm-canonical/tspconfig.yaml @@ -11,7 +11,7 @@ options: '@azure-tools/typespec-autorest-canonical': emitter-output-dir: "{project-root}/.." azure-resource-provider-folder: "resource-manager" - output-file: "{azure-resource-provider-folder}/{service-name}/{version-status}/{version}/openapi.json" + output-file: "{azure-resource-provider-folder}/{service-name}/canonical/openapi.json" linter: extends: - "@azure-tools/typespec-azure-rulesets/resource-manager" diff --git a/packages/samples/specs/data-plane/api-path-parameter/main.tsp b/packages/samples/specs/data-plane/api-path-parameter/main.tsp index 07b8aa4c7a..c3d2ad15d5 100644 --- a/packages/samples/specs/data-plane/api-path-parameter/main.tsp +++ b/packages/samples/specs/data-plane/api-path-parameter/main.tsp @@ -75,7 +75,10 @@ alias Operations = Azure.Core.ResourceOperations; interface Widgets { // Operation Status @doc("Gets status of a Widget operation.") + @sharedRoute getWidgetOperationStatus is Operations.GetResourceOperationStatus; + @sharedRoute + getWidgetDeleteOperationStatus is Operations.GetResourceOperationStatus; // Widget Operations @doc("Creates or updates a Widget asynchronously") @@ -86,7 +89,7 @@ interface Widgets { getWidget is Operations.ResourceRead; @doc("Delete a Widget asynchronously.") - @pollingOperation(Widgets.getWidgetOperationStatus) + @pollingOperation(Widgets.getWidgetDeleteOperationStatus) deleteWidget is Operations.LongRunningResourceDelete; @doc("List Widget resources") @@ -98,7 +101,10 @@ interface Widgets { interface Manufacturers { @doc("Gets status of a Manufacturer operation.") - getManufacturerOperationStatus is Operations.GetResourceOperationStatus; + getManufacturerDeleteOperationStatus is Operations.GetResourceOperationStatus< + Manufacturer, + never + >; @doc("Creates or replaces a Manufacturer") createOrReplaceManufacturer is Operations.ResourceCreateOrReplace; @@ -107,7 +113,7 @@ interface Manufacturers { getManufacturer is Operations.ResourceRead; @doc("Delete a Manufacturer asynchronously.") - @pollingOperation(Manufacturers.getManufacturerOperationStatus) + @pollingOperation(Manufacturers.getManufacturerDeleteOperationStatus) deleteManufacturer is Operations.LongRunningResourceDelete; @doc("List Manufacturer resources") diff --git a/packages/samples/specs/data-plane/custom-error-type/main.tsp b/packages/samples/specs/data-plane/custom-error-type/main.tsp index df59f09165..7b7c262f87 100644 --- a/packages/samples/specs/data-plane/custom-error-type/main.tsp +++ b/packages/samples/specs/data-plane/custom-error-type/main.tsp @@ -59,7 +59,11 @@ alias Operations = Azure.Core.ResourceOperations; + /** Gets the status of a Widget delete operation */ + @sharedRoute + getWidgetDeleteOperationStatus is Operations.GetResourceOperationStatus; // Widget Operations @doc("Creates or updates a Widget asynchronously") @@ -70,7 +74,7 @@ interface Widgets { getWidget is Operations.ResourceRead; @doc("Delete a Widget asynchronously.") - @pollingOperation(Widgets.getWidgetOperationStatus) + @pollingOperation(Widgets.getWidgetDeleteOperationStatus) deleteWidget is Operations.LongRunningResourceDelete; @doc("List Widget resources") diff --git a/packages/samples/specs/data-plane/trait-versioning/main.tsp b/packages/samples/specs/data-plane/trait-versioning/main.tsp index d08af0a567..ac10a1f34c 100644 --- a/packages/samples/specs/data-plane/trait-versioning/main.tsp +++ b/packages/samples/specs/data-plane/trait-versioning/main.tsp @@ -69,8 +69,12 @@ alias Operations = Azure.Core.ResourceOperations; interface Widgets { // Operation Status + @sharedRoute @doc("Gets status of a Widget operation.") getWidgetOperationStatus is Operations.GetResourceOperationStatus; + @doc("Gets status of a Widget delete operation.") + @sharedRoute + getWidgetDeleteOperationStatus is Operations.GetResourceOperationStatus; // Widget Operations @doc("Creates or updates a Widget asynchronously") @@ -81,7 +85,7 @@ interface Widgets { getWidget is Operations.ResourceRead; @doc("Delete a Widget asynchronously.") - @pollingOperation(Widgets.getWidgetOperationStatus) + @pollingOperation(Widgets.getWidgetDeleteOperationStatus) deleteWidget is Operations.LongRunningResourceDelete; @doc("List Widget resources") @@ -92,8 +96,11 @@ interface Widgets { } interface Manufacturers { - @doc("Gets status of a Manufacturer operation.") - getManufacturerOperationStatus is Operations.GetResourceOperationStatus; + @doc("Gets status of a Manufacturer delete operation.") + getManufacturerDeleteOperationStatus is Operations.GetResourceOperationStatus< + Manufacturer, + never + >; @doc("Creates or replaces a Manufacturer") createOrReplaceManufacturer is Operations.ResourceCreateOrReplace; @@ -102,7 +109,7 @@ interface Manufacturers { getManufacturer is Operations.ResourceRead; @doc("Delete a Manufacturer asynchronously.") - @pollingOperation(Manufacturers.getManufacturerOperationStatus) + @pollingOperation(Manufacturers.getManufacturerDeleteOperationStatus) deleteManufacturer is Operations.LongRunningResourceDelete; @doc("List Manufacturer resources") diff --git a/packages/samples/specs/data-plane/widget-manager/main.tsp b/packages/samples/specs/data-plane/widget-manager/main.tsp index e39be4c2bd..83119910f9 100644 --- a/packages/samples/specs/data-plane/widget-manager/main.tsp +++ b/packages/samples/specs/data-plane/widget-manager/main.tsp @@ -173,7 +173,11 @@ alias Operations = Azure.Core.ResourceOperations; interface Widgets { // Operation Status @doc("Gets status of a Widget operation.") + @sharedRoute getWidgetOperationStatus is Operations.GetResourceOperationStatus; + @doc("Gets status of a Widget delete operation.") + @sharedRoute + getWidgetDeleteOperationStatus is Operations.GetResourceOperationStatus; // Widget Operations @doc("Creates or updates a Widget asynchronously") @@ -184,7 +188,7 @@ interface Widgets { getWidget is Operations.ResourceRead; @doc("Delete a Widget asynchronously.") - @pollingOperation(Widgets.getWidgetOperationStatus) + @pollingOperation(Widgets.getWidgetDeleteOperationStatus) deleteWidget is Operations.LongRunningResourceDelete; @doc("List Widget resources") @@ -207,7 +211,7 @@ interface Widgets { getRepairStatus is Foundations.GetOperationStatus; @doc("Schedule a widget for repairs.") - @pollingOperation(Widgets.getWidgetOperationStatus) + @pollingOperation(Widgets.getRepairStatus) scheduleRepairs is Operations.LongRunningResourceAction< Widget, WidgetRepairRequest, @@ -217,7 +221,7 @@ interface Widgets { interface WidgetParts { @doc("Gets status of a WidgetPart operation.") - getWidgetPartOperationStatus is Operations.GetResourceOperationStatus; + getWidgetPartReorderOperationStatus is Operations.GetResourceOperationStatus; @doc("Creates a WidgetPart") createWidgetPart is Operations.ResourceCreateWithServiceProvidedName; @@ -232,7 +236,7 @@ interface WidgetParts { listWidgetParts is Operations.ResourceList; @doc("Reorder all parts for the widget.") - @pollingOperation(WidgetParts.getWidgetPartOperationStatus) + @pollingOperation(WidgetParts.getWidgetPartReorderOperationStatus) reorderParts is Operations.LongRunningResourceCollectionAction< WidgetPart, WidgetPartReorderRequest, @@ -241,8 +245,11 @@ interface WidgetParts { } interface Manufacturers { - @doc("Gets status of a Manufacturer operation.") - getManufacturerOperationStatus is Operations.GetResourceOperationStatus; + @doc("Gets status of a Manufacturer delete operation.") + getManufacturerDeleteOperationStatus is Operations.GetResourceOperationStatus< + Manufacturer, + never + >; @doc("Creates or replaces a Manufacturer") createOrReplaceManufacturer is Operations.ResourceCreateOrReplace; @@ -251,7 +258,7 @@ interface Manufacturers { getManufacturer is Operations.ResourceRead; @doc("Delete a Manufacturer asynchronously.") - @pollingOperation(Manufacturers.getManufacturerOperationStatus) + @pollingOperation(Manufacturers.getManufacturerDeleteOperationStatus) deleteManufacturer is Operations.LongRunningResourceDelete; @doc("List Manufacturer resources") diff --git a/packages/samples/specs/resource-manager/legacy/managed-identity/main.tsp b/packages/samples/specs/resource-manager/legacy/managed-identity/main.tsp new file mode 100644 index 0000000000..add7878931 --- /dev/null +++ b/packages/samples/specs/resource-manager/legacy/managed-identity/main.tsp @@ -0,0 +1,62 @@ +import "@typespec/http"; +import "@typespec/rest"; +import "@typespec/versioning"; +import "@azure-tools/typespec-azure-core"; +import "@azure-tools/typespec-azure-resource-manager"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Azure.ResourceManager; +using Azure.Core; + +@armProviderNamespace("Contoso.ManagedIdentityExample") +@service({ + title: "Contoso.ManagedIdentityExample", +}) +@versioned(Versions) +@doc("An example of using the ManagedIdentity properties in a resource type.") +namespace Microsoft.UpdateTests; + +/** UpdateTests API versions */ +enum Versions { + /** 2023-03-01-preview version */ + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + @armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v3) + `2023-03-01-preview`, +} + +interface Operations extends Azure.ResourceManager.Operations {} + +@doc("Widget Resource") +model WidgetResource is TrackedResource { + @pattern("^[a-zA-Z0-9-]{3,24}$") + @doc("The name of the widget.") + @key("widgetName") + @segment("widgets") + @path + name: string; + + ...Legacy.ManagedServiceIdentityV4Property; // Or ...ManagedSystemAssignedIdentityProperty; +} + +@doc("Widget Resource Properties.") +model WidgetResourceProperties { + @doc("The widget color.") + @visibility("create", "read") + color: string; + + /** Provisioning state */ + @visibility("read") + provisioningState?: ResourceProvisioningState; +} + +@armResourceOperations +interface Widgets { + get is ArmResourceRead; + create is ArmResourceCreateOrUpdateAsync; + update is ArmTagsPatchSync; + delete is ArmResourceDeleteWithoutOkAsync; + listByResourceGroup is ArmResourceListByParent; + listBySubscription is ArmListBySubscription; +} diff --git a/packages/samples/specs/resource-manager/resource-common-properties/common-properties/main.tsp b/packages/samples/specs/resource-manager/resource-common-properties/common-properties/main.tsp new file mode 100644 index 0000000000..0b9bfdeb33 --- /dev/null +++ b/packages/samples/specs/resource-manager/resource-common-properties/common-properties/main.tsp @@ -0,0 +1,68 @@ +import "@typespec/http"; +import "@typespec/rest"; +import "@typespec/versioning"; +import "@azure-tools/typespec-azure-core"; +import "@azure-tools/typespec-azure-resource-manager"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Azure.ResourceManager; +using Azure.Core; + +@armProviderNamespace("Contoso.CommonEnvelopePropertiesExample") +@service({ + title: "Contoso.CommonEnvelopePropertiesExample", +}) +@versioned(Versions) +@doc("An example of using some of common envelope and property bag properties in a resource type. Their names are all end with 'Property'.") +namespace Microsoft.UpdateTests; + +/** UpdateTests API versions */ +enum Versions { + /** 2023-03-01-preview version */ + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + @armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v5) + `2023-03-01-preview`, +} + +interface Operations extends Azure.ResourceManager.Operations {} + +@doc("Widget Resource") +model WidgetResource is TrackedResource { + @pattern("^[a-zA-Z0-9-]{3,24}$") + @doc("The name of the widget.") + @key("widgetName") + @segment("widgets") + @path + name: string; + + ...ExtendedLocationProperty; + ...ManagedByProperty; +} + +@doc("Widget Resource Properties.") +model WidgetResourceProperties { + @doc("The widget color.") + @visibility("create", "read") + color: string; + + /** Provisioning state */ + @visibility("read") + provisioningState?: ResourceProvisioningState; + + ...EntityTagProperty; + ...ResourceKindProperty; + ...ResourcePlanProperty; + ...ResourceSkuProperty; +} + +@armResourceOperations +interface Widgets { + get is ArmResourceRead; + create is ArmResourceCreateOrReplaceAsync; + update is ArmTagsPatchSync; + delete is ArmResourceDeleteWithoutOkAsync; + listByResourceGroup is ArmResourceListByParent; + listBySubscription is ArmListBySubscription; +} diff --git a/packages/samples/specs/resource-manager/resource-common-properties/encryption/main.tsp b/packages/samples/specs/resource-manager/resource-common-properties/encryption/main.tsp index a1cc373bd2..812435d79b 100644 --- a/packages/samples/specs/resource-manager/resource-common-properties/encryption/main.tsp +++ b/packages/samples/specs/resource-manager/resource-common-properties/encryption/main.tsp @@ -14,14 +14,18 @@ using Azure.Core; @service({ title: "Contoso.CustomerManagedKeyExample", }) -@OpenAPI.info({ - version: "2023-03-01-preview", -}) +@versioned(Versions) @doc("An example of using the Customer Managed Key Encryption properties in a resource type.") -@useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) -@armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v5) namespace Microsoft.UpdateTests; +/** UpdateTests API versions */ +enum Versions { + /** 2023-03-01-preview version */ + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + @armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v5) + `2023-03-01-preview`, +} + interface Operations extends Azure.ResourceManager.Operations {} @doc("Widget Resource") @@ -44,7 +48,7 @@ model WidgetResourceProperties { @visibility("read") provisioningState?: ResourceProvisioningState; - ...Encryption; + ...EncryptionProperty; } @armResourceOperations diff --git a/packages/samples/specs/resource-manager/resource-common-properties/managed-identity/main.tsp b/packages/samples/specs/resource-manager/resource-common-properties/managed-identity/main.tsp new file mode 100644 index 0000000000..33af6987c1 --- /dev/null +++ b/packages/samples/specs/resource-manager/resource-common-properties/managed-identity/main.tsp @@ -0,0 +1,62 @@ +import "@typespec/http"; +import "@typespec/rest"; +import "@typespec/versioning"; +import "@azure-tools/typespec-azure-core"; +import "@azure-tools/typespec-azure-resource-manager"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Azure.ResourceManager; +using Azure.Core; + +@armProviderNamespace("Contoso.ManagedIdentityExample") +@service({ + title: "Contoso.ManagedIdentityExample", +}) +@versioned(Versions) +@doc("An example of using the ManagedIdentity properties in a resource type.") +namespace Microsoft.UpdateTests; + +/** UpdateTests API versions */ +enum Versions { + /** 2023-03-01-preview version */ + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + @armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v5) + `2023-03-01-preview`, +} + +interface Operations extends Azure.ResourceManager.Operations {} + +@doc("Widget Resource") +model WidgetResource is TrackedResource { + @pattern("^[a-zA-Z0-9-]{3,24}$") + @doc("The name of the widget.") + @key("widgetName") + @segment("widgets") + @path + name: string; + + ...ManagedServiceIdentityProperty; // Or ...ManagedSystemAssignedIdentityProperty; +} + +@doc("Widget Resource Properties.") +model WidgetResourceProperties { + @doc("The widget color.") + @visibility("create", "read") + color: string; + + /** Provisioning state */ + @visibility("read") + provisioningState?: ResourceProvisioningState; +} + +@armResourceOperations +interface Widgets { + get is ArmResourceRead; + create is ArmResourceCreateOrUpdateAsync; + update is ArmTagsPatchSync; + delete is ArmResourceDeleteWithoutOkAsync; + listByResourceGroup is ArmResourceListByParent; + listBySubscription is ArmListBySubscription; +} diff --git a/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@azure-tools/typespec-autorest/2022-08-31/openapi.json b/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@azure-tools/typespec-autorest/2022-08-31/openapi.json index d0d45aca02..efa0056d84 100644 --- a/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@azure-tools/typespec-autorest/2022-08-31/openapi.json +++ b/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@azure-tools/typespec-autorest/2022-08-31/openapi.json @@ -380,12 +380,15 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, "/api/{api-version}/manufacturers/{manufacturerId}/operations/{operationId}": { "get": { - "operationId": "Manufacturers_GetManufacturerOperationStatus", + "operationId": "Manufacturers_GetManufacturerDeleteOperationStatus", "description": "Gets status of a Manufacturer operation.", "parameters": [ { @@ -424,10 +427,6 @@ "error": { "$ref": "#/definitions/Azure.Core.Foundations.Error", "description": "Error object that describes the error when status is \"Failed\"." - }, - "result": { - "$ref": "#/definitions/Manufacturer", - "description": "The result of the operation." } }, "required": [ @@ -773,6 +772,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true }, "delete": { @@ -886,6 +888,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -958,6 +963,72 @@ } } }, + "x-ms-paths": { + "/api/{api-version}/widgets/{widgetName}/operations/{operationId}?_overload=getWidgetDeleteOperationStatus": { + "get": { + "operationId": "Widgets_GetWidgetDeleteOperationStatus", + "description": "Resource operation status operation template.", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionPathParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The widget name.", + "required": true, + "type": "string" + }, + { + "name": "operationId", + "in": "path", + "description": "The unique ID of the operation.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "type": "object", + "description": "Provides status details for long running operations.", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the operation." + }, + "status": { + "$ref": "#/definitions/Azure.Core.Foundations.OperationState", + "description": "The status of the operation" + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error object that describes the error when status is \"Failed\"." + } + }, + "required": [ + "id", + "status" + ] + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + } + } + }, "definitions": { "Azure.Core.Foundations.Error": { "type": "object", diff --git a/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@typespec/openapi3/openapi.2022-08-31.yaml b/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@typespec/openapi3/openapi.2022-08-31.yaml index b2f168ce4e..4be8a90a71 100644 --- a/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@typespec/openapi3/openapi.2022-08-31.yaml +++ b/packages/samples/test/output/azure/core/data-plane/api-path-parameter/@typespec/openapi3/openapi.2022-08-31.yaml @@ -237,7 +237,7 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /api/{api-version}/manufacturers/{manufacturerId}/operations/{operationId}: get: - operationId: Manufacturers_getManufacturerOperationStatus + operationId: Manufacturers_getManufacturerDeleteOperationStatus description: Gets status of a Manufacturer operation. parameters: - $ref: '#/components/parameters/ApiVersionPathParameter' @@ -275,10 +275,6 @@ paths: allOf: - $ref: '#/components/schemas/Azure.Core.Foundations.Error' description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Manufacturer' - description: The result of the operation. description: Provides status details for long running operations. default: description: An unexpected error response. @@ -578,8 +574,8 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /api/{api-version}/widgets/{widgetName}/operations/{operationId}: get: - operationId: Widgets_getWidgetOperationStatus - description: Gets status of a Widget operation. + operationId: Widgets_getWidgetOperationStatus_Widgets_getWidgetDeleteOperationStatus + description: Gets status of a Widget operation. Resource operation status operation template. parameters: - $ref: '#/components/parameters/ApiVersionPathParameter' - name: widgetName @@ -600,27 +596,45 @@ paths: content: application/json: schema: - type: object - required: - - id - - status - properties: - id: - type: string - description: The unique ID of the operation. - status: - allOf: - - $ref: '#/components/schemas/OperationState' - description: The status of the operation - error: - allOf: - - $ref: '#/components/schemas/Azure.Core.Foundations.Error' - description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Widget' - description: The result of the operation. - description: Provides status details for long running operations. + anyOf: + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + result: + allOf: + - $ref: '#/components/schemas/Widget' + description: The result of the operation. + description: Provides status details for long running operations. + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + description: Provides status details for long running operations. default: description: An unexpected error response. headers: diff --git a/packages/samples/test/output/azure/core/data-plane/custom-error-type/@azure-tools/typespec-autorest/2022-08-31/openapi.json b/packages/samples/test/output/azure/core/data-plane/custom-error-type/@azure-tools/typespec-autorest/2022-08-31/openapi.json index 2fed197afe..d5c3b5df7f 100644 --- a/packages/samples/test/output/azure/core/data-plane/custom-error-type/@azure-tools/typespec-autorest/2022-08-31/openapi.json +++ b/packages/samples/test/output/azure/core/data-plane/custom-error-type/@azure-tools/typespec-autorest/2022-08-31/openapi.json @@ -275,6 +275,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true }, "delete": { @@ -382,6 +385,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -448,6 +454,66 @@ } } }, + "x-ms-paths": { + "/widgets/{widgetName}/operations/{operationId}?_overload=getWidgetDeleteOperationStatus": { + "get": { + "operationId": "Widgets_GetWidgetDeleteOperationStatus", + "description": "Gets the status of a Widget delete operation", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The widget name.", + "required": true, + "type": "string" + }, + { + "name": "operationId", + "in": "path", + "description": "The unique ID of the operation.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "type": "object", + "description": "Provides status details for long running operations.", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the operation." + }, + "status": { + "$ref": "#/definitions/Azure.Core.Foundations.OperationState", + "description": "The status of the operation" + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error object that describes the error when status is \"Failed\"." + } + }, + "required": [ + "id", + "status" + ] + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/WidgetServiceErrorResponse" + } + } + } + } + } + }, "definitions": { "Azure.Core.Foundations.Error": { "type": "object", diff --git a/packages/samples/test/output/azure/core/data-plane/custom-error-type/@typespec/openapi3/openapi.2022-08-31.yaml b/packages/samples/test/output/azure/core/data-plane/custom-error-type/@typespec/openapi3/openapi.2022-08-31.yaml index 662608e3c6..fcf9160edb 100644 --- a/packages/samples/test/output/azure/core/data-plane/custom-error-type/@typespec/openapi3/openapi.2022-08-31.yaml +++ b/packages/samples/test/output/azure/core/data-plane/custom-error-type/@typespec/openapi3/openapi.2022-08-31.yaml @@ -229,8 +229,8 @@ paths: $ref: '#/components/schemas/WidgetServiceErrorResponse' /widgets/{widgetName}/operations/{operationId}: get: - operationId: Widgets_getWidgetOperationStatus - description: Gets status of a Widget operation. + operationId: Widgets_getWidgetOperationStatus_Widgets_getWidgetDeleteOperationStatus + description: Gets status of a Widget operation. Gets the status of a Widget delete operation parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: widgetName @@ -251,27 +251,45 @@ paths: content: application/json: schema: - type: object - required: - - id - - status - properties: - id: - type: string - description: The unique ID of the operation. - status: - allOf: - - $ref: '#/components/schemas/OperationState' - description: The status of the operation - error: - allOf: - - $ref: '#/components/schemas/Azure.Core.Foundations.Error' - description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Widget' - description: The result of the operation. - description: Provides status details for long running operations. + anyOf: + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + result: + allOf: + - $ref: '#/components/schemas/Widget' + description: The result of the operation. + description: Provides status details for long running operations. + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + description: Provides status details for long running operations. default: description: An unexpected error response. content: diff --git a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2022-08-31/openapi.json b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2022-08-31/openapi.json index 224c3e5204..238c64ce80 100644 --- a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2022-08-31/openapi.json +++ b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2022-08-31/openapi.json @@ -332,13 +332,16 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, "/manufacturers/{manufacturerId}/operations/{operationId}": { "get": { - "operationId": "Manufacturers_GetManufacturerOperationStatus", - "description": "Gets status of a Manufacturer operation.", + "operationId": "Manufacturers_GetManufacturerDeleteOperationStatus", + "description": "Gets status of a Manufacturer delete operation.", "parameters": [ { "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" @@ -376,10 +379,6 @@ "error": { "$ref": "#/definitions/Azure.Core.Foundations.Error", "description": "Error object that describes the error when status is \"Failed\"." - }, - "result": { - "$ref": "#/definitions/Manufacturer", - "description": "The result of the operation." } }, "required": [ @@ -689,6 +688,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true }, "delete": { @@ -790,6 +792,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -862,6 +867,72 @@ } } }, + "x-ms-paths": { + "/widgets/{widgetName}/operations/{operationId}?_overload=getWidgetDeleteOperationStatus": { + "get": { + "operationId": "Widgets_GetWidgetDeleteOperationStatus", + "description": "Gets status of a Widget delete operation.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The widget name.", + "required": true, + "type": "string" + }, + { + "name": "operationId", + "in": "path", + "description": "The unique ID of the operation.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "type": "object", + "description": "Provides status details for long running operations.", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the operation." + }, + "status": { + "$ref": "#/definitions/Azure.Core.Foundations.OperationState", + "description": "The status of the operation" + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error object that describes the error when status is \"Failed\"." + } + }, + "required": [ + "id", + "status" + ] + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + } + } + }, "definitions": { "Azure.Core.Foundations.Error": { "type": "object", diff --git a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2023-02-07/openapi.json b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2023-02-07/openapi.json index 2480975904..3c994233e5 100644 --- a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2023-02-07/openapi.json +++ b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@azure-tools/typespec-autorest/2023-02-07/openapi.json @@ -380,13 +380,16 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, "/manufacturers/{manufacturerId}/operations/{operationId}": { "get": { - "operationId": "Manufacturers_GetManufacturerOperationStatus", - "description": "Gets status of a Manufacturer operation.", + "operationId": "Manufacturers_GetManufacturerDeleteOperationStatus", + "description": "Gets status of a Manufacturer delete operation.", "parameters": [ { "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" @@ -424,10 +427,6 @@ "error": { "$ref": "#/definitions/Azure.Core.Foundations.Error", "description": "Error object that describes the error when status is \"Failed\"." - }, - "result": { - "$ref": "#/definitions/Manufacturer", - "description": "The result of the operation." } }, "required": [ @@ -773,6 +772,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true }, "delete": { @@ -886,6 +888,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -958,6 +963,72 @@ } } }, + "x-ms-paths": { + "/widgets/{widgetName}/operations/{operationId}?_overload=getWidgetDeleteOperationStatus": { + "get": { + "operationId": "Widgets_GetWidgetDeleteOperationStatus", + "description": "Gets status of a Widget delete operation.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The widget name.", + "required": true, + "type": "string" + }, + { + "name": "operationId", + "in": "path", + "description": "The unique ID of the operation.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "type": "object", + "description": "Provides status details for long running operations.", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the operation." + }, + "status": { + "$ref": "#/definitions/Azure.Core.Foundations.OperationState", + "description": "The status of the operation" + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error object that describes the error when status is \"Failed\"." + } + }, + "required": [ + "id", + "status" + ] + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + } + } + }, "definitions": { "Azure.Core.Foundations.Error": { "type": "object", diff --git a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2022-08-31.yaml b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2022-08-31.yaml index b5e41e4703..489042be2c 100644 --- a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2022-08-31.yaml +++ b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2022-08-31.yaml @@ -210,8 +210,8 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /manufacturers/{manufacturerId}/operations/{operationId}: get: - operationId: Manufacturers_getManufacturerOperationStatus - description: Gets status of a Manufacturer operation. + operationId: Manufacturers_getManufacturerDeleteOperationStatus + description: Gets status of a Manufacturer delete operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: manufacturerId @@ -248,10 +248,6 @@ paths: allOf: - $ref: '#/components/schemas/Azure.Core.Foundations.Error' description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Manufacturer' - description: The result of the operation. description: Provides status details for long running operations. default: description: An unexpected error response. @@ -524,8 +520,8 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /widgets/{widgetName}/operations/{operationId}: get: - operationId: Widgets_getWidgetOperationStatus - description: Gets status of a Widget operation. + operationId: Widgets_getWidgetOperationStatus_Widgets_getWidgetDeleteOperationStatus + description: Gets status of a Widget operation. Gets status of a Widget delete operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: widgetName @@ -546,27 +542,45 @@ paths: content: application/json: schema: - type: object - required: - - id - - status - properties: - id: - type: string - description: The unique ID of the operation. - status: - allOf: - - $ref: '#/components/schemas/OperationState' - description: The status of the operation - error: - allOf: - - $ref: '#/components/schemas/Azure.Core.Foundations.Error' - description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Widget' - description: The result of the operation. - description: Provides status details for long running operations. + anyOf: + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + result: + allOf: + - $ref: '#/components/schemas/Widget' + description: The result of the operation. + description: Provides status details for long running operations. + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + description: Provides status details for long running operations. default: description: An unexpected error response. headers: diff --git a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2023-02-07.yaml b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2023-02-07.yaml index 09b469a1f2..804261e13c 100644 --- a/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2023-02-07.yaml +++ b/packages/samples/test/output/azure/core/data-plane/trait-versioning/@typespec/openapi3/openapi.2023-02-07.yaml @@ -237,8 +237,8 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /manufacturers/{manufacturerId}/operations/{operationId}: get: - operationId: Manufacturers_getManufacturerOperationStatus - description: Gets status of a Manufacturer operation. + operationId: Manufacturers_getManufacturerDeleteOperationStatus + description: Gets status of a Manufacturer delete operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: manufacturerId @@ -275,10 +275,6 @@ paths: allOf: - $ref: '#/components/schemas/Azure.Core.Foundations.Error' description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Manufacturer' - description: The result of the operation. description: Provides status details for long running operations. default: description: An unexpected error response. @@ -578,8 +574,8 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /widgets/{widgetName}/operations/{operationId}: get: - operationId: Widgets_getWidgetOperationStatus - description: Gets status of a Widget operation. + operationId: Widgets_getWidgetOperationStatus_Widgets_getWidgetDeleteOperationStatus + description: Gets status of a Widget operation. Gets status of a Widget delete operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: widgetName @@ -600,27 +596,45 @@ paths: content: application/json: schema: - type: object - required: - - id - - status - properties: - id: - type: string - description: The unique ID of the operation. - status: - allOf: - - $ref: '#/components/schemas/OperationState' - description: The status of the operation - error: - allOf: - - $ref: '#/components/schemas/Azure.Core.Foundations.Error' - description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Widget' - description: The result of the operation. - description: Provides status details for long running operations. + anyOf: + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + result: + allOf: + - $ref: '#/components/schemas/Widget' + description: The result of the operation. + description: Provides status details for long running operations. + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + description: Provides status details for long running operations. default: description: An unexpected error response. headers: diff --git a/packages/samples/test/output/azure/core/data-plane/widget-manager/@azure-tools/typespec-autorest/2022-08-31/openapi.json b/packages/samples/test/output/azure/core/data-plane/widget-manager/@azure-tools/typespec-autorest/2022-08-31/openapi.json index bff35fe74b..49b7c56657 100644 --- a/packages/samples/test/output/azure/core/data-plane/widget-manager/@azure-tools/typespec-autorest/2022-08-31/openapi.json +++ b/packages/samples/test/output/azure/core/data-plane/widget-manager/@azure-tools/typespec-autorest/2022-08-31/openapi.json @@ -380,13 +380,16 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, "/manufacturers/{manufacturerId}/operations/{operationId}": { "get": { - "operationId": "Manufacturers_GetManufacturerOperationStatus", - "description": "Gets status of a Manufacturer operation.", + "operationId": "Manufacturers_GetManufacturerDeleteOperationStatus", + "description": "Gets status of a Manufacturer delete operation.", "parameters": [ { "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" @@ -424,10 +427,6 @@ "error": { "$ref": "#/definitions/Azure.Core.Foundations.Error", "description": "Error object that describes the error when status is \"Failed\"." - }, - "result": { - "$ref": "#/definitions/Manufacturer", - "description": "The result of the operation." } }, "required": [ @@ -773,6 +772,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true }, "delete": { @@ -886,6 +888,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -1006,6 +1011,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -1605,7 +1613,7 @@ }, "/widgets/{widgetName}/parts/{widgetPartName}/operations/{operationId}": { "get": { - "operationId": "WidgetParts_GetWidgetPartOperationStatus", + "operationId": "WidgetParts_GetWidgetPartReorderOperationStatus", "description": "Gets status of a WidgetPart operation.", "parameters": [ { @@ -1651,10 +1659,6 @@ "error": { "$ref": "#/definitions/Azure.Core.Foundations.Error", "description": "Error object that describes the error when status is \"Failed\"." - }, - "result": { - "$ref": "#/definitions/WidgetPart", - "description": "The result of the operation." } }, "required": [ @@ -1786,6 +1790,9 @@ } } }, + "x-ms-long-running-operation-options": { + "final-state-via": "operation-location" + }, "x-ms-long-running-operation": true } }, @@ -1854,6 +1861,72 @@ } } }, + "x-ms-paths": { + "/widgets/{widgetName}/operations/{operationId}?_overload=getWidgetDeleteOperationStatus": { + "get": { + "operationId": "Widgets_GetWidgetDeleteOperationStatus", + "description": "Gets status of a Widget delete operation.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The widget name.", + "required": true, + "type": "string" + }, + { + "name": "operationId", + "in": "path", + "description": "The unique ID of the operation.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "type": "object", + "description": "Provides status details for long running operations.", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the operation." + }, + "status": { + "$ref": "#/definitions/Azure.Core.Foundations.OperationState", + "description": "The status of the operation" + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error object that describes the error when status is \"Failed\"." + } + }, + "required": [ + "id", + "status" + ] + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + } + } + }, "definitions": { "Azure.Core.Foundations.Error": { "type": "object", diff --git a/packages/samples/test/output/azure/core/data-plane/widget-manager/@typespec/openapi3/openapi.2022-08-31.yaml b/packages/samples/test/output/azure/core/data-plane/widget-manager/@typespec/openapi3/openapi.2022-08-31.yaml index e3dac09e94..37f1c4fad9 100644 --- a/packages/samples/test/output/azure/core/data-plane/widget-manager/@typespec/openapi3/openapi.2022-08-31.yaml +++ b/packages/samples/test/output/azure/core/data-plane/widget-manager/@typespec/openapi3/openapi.2022-08-31.yaml @@ -237,8 +237,8 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /manufacturers/{manufacturerId}/operations/{operationId}: get: - operationId: Manufacturers_getManufacturerOperationStatus - description: Gets status of a Manufacturer operation. + operationId: Manufacturers_getManufacturerDeleteOperationStatus + description: Gets status of a Manufacturer delete operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: manufacturerId @@ -275,10 +275,6 @@ paths: allOf: - $ref: '#/components/schemas/Azure.Core.Foundations.Error' description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Manufacturer' - description: The result of the operation. description: Provides status details for long running operations. default: description: An unexpected error response. @@ -759,8 +755,8 @@ paths: $ref: '#/components/schemas/WidgetAnalyticsCreateOrUpdate' /widgets/{widgetName}/operations/{operationId}: get: - operationId: Widgets_getWidgetOperationStatus - description: Gets status of a Widget operation. + operationId: Widgets_getWidgetOperationStatus_Widgets_getWidgetDeleteOperationStatus + description: Gets status of a Widget operation. Gets status of a Widget delete operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' - name: widgetName @@ -781,27 +777,45 @@ paths: content: application/json: schema: - type: object - required: - - id - - status - properties: - id: - type: string - description: The unique ID of the operation. - status: - allOf: - - $ref: '#/components/schemas/OperationState' - description: The status of the operation - error: - allOf: - - $ref: '#/components/schemas/Azure.Core.Foundations.Error' - description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/Widget' - description: The result of the operation. - description: Provides status details for long running operations. + anyOf: + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + result: + allOf: + - $ref: '#/components/schemas/Widget' + description: The result of the operation. + description: Provides status details for long running operations. + - type: object + required: + - id + - status + properties: + id: + type: string + description: The unique ID of the operation. + status: + allOf: + - $ref: '#/components/schemas/OperationState' + description: The status of the operation + error: + allOf: + - $ref: '#/components/schemas/Azure.Core.Foundations.Error' + description: Error object that describes the error when status is "Failed". + description: Provides status details for long running operations. default: description: An unexpected error response. headers: @@ -1018,7 +1032,7 @@ paths: $ref: '#/components/schemas/Azure.Core.Foundations.ErrorResponse' /widgets/{widgetName}/parts/{widgetPartName}/operations/{operationId}: get: - operationId: WidgetParts_getWidgetPartOperationStatus + operationId: WidgetParts_getWidgetPartReorderOperationStatus description: Gets status of a WidgetPart operation. parameters: - $ref: '#/components/parameters/Azure.Core.Foundations.ApiVersionParameter' @@ -1062,10 +1076,6 @@ paths: allOf: - $ref: '#/components/schemas/Azure.Core.Foundations.Error' description: Error object that describes the error when status is "Failed". - result: - allOf: - - $ref: '#/components/schemas/WidgetPart' - description: The result of the operation. description: Provides status details for long running operations. default: description: An unexpected error response. diff --git a/packages/samples/test/output/azure/resource-manager/arm-library/@azure-tools/typespec-autorest/openapi.json b/packages/samples/test/output/azure/resource-manager/arm-library/@azure-tools/typespec-autorest/openapi.json index e64a5f5311..bc2f3ddd5f 100644 --- a/packages/samples/test/output/azure/resource-manager/arm-library/@azure-tools/typespec-autorest/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/arm-library/@azure-tools/typespec-autorest/openapi.json @@ -177,6 +177,10 @@ "$ref": "#/definitions/Microsoft.InterfacesTest.TestExtensionResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -436,6 +440,10 @@ "$ref": "#/definitions/Microsoft.InterfacesTest.TestTenantResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -778,6 +786,10 @@ "$ref": "#/definitions/AllPropertiesResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -1253,6 +1265,10 @@ "$ref": "#/definitions/Microsoft.InterfacesTest.TestTrackedResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -1529,6 +1545,10 @@ "$ref": "#/definitions/Microsoft.InterfacesTest.TestTrackedChild" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -1640,11 +1660,7 @@ "properties": { "$ref": "#/definitions/AllPropertiesProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true }, "eTag": { "type": "string", @@ -1802,11 +1818,7 @@ "properties": { "$ref": "#/definitions/Microsoft.InterfacesTest.TestExtensionProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -1838,11 +1850,7 @@ "properties": { "$ref": "#/definitions/Microsoft.InterfacesTest.TestTenantProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -1858,11 +1866,7 @@ "properties": { "$ref": "#/definitions/Microsoft.InterfacesTest.TrackedChildProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -1898,11 +1902,7 @@ "properties": { "$ref": "#/definitions/Microsoft.InterfacesTest.TestTrackedProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -1952,11 +1952,7 @@ "properties": { "$ref": "#/definitions/Microsoft.OperationsTest.TestTrackedProperties2", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/contoso/@azure-tools/typespec-autorest/openapi.json b/packages/samples/test/output/azure/resource-manager/contoso/@azure-tools/typespec-autorest/openapi.json index f413392fac..31b260c10d 100644 --- a/packages/samples/test/output/azure/resource-manager/contoso/@azure-tools/typespec-autorest/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/contoso/@azure-tools/typespec-autorest/openapi.json @@ -237,6 +237,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -373,11 +377,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/legacy/managed-identity/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/legacy/managed-identity/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json new file mode 100644 index 0000000000..dc8b04501c --- /dev/null +++ b/packages/samples/test/output/azure/resource-manager/legacy/managed-identity/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json @@ -0,0 +1,479 @@ +{ + "swagger": "2.0", + "info": { + "title": "Contoso.ManagedIdentityExample", + "version": "2023-03-01-preview", + "description": "An example of using the ManagedIdentity properties in a resource type.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Widgets" + } + ], + "paths": { + "/providers/Contoso.ManagedIdentityExample/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Contoso.ManagedIdentityExample/widgets": { + "get": { + "operationId": "Widgets_ListBySubscription", + "tags": [ + "Widgets" + ], + "description": "List WidgetResource resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.ManagedIdentityExample/widgets": { + "get": { + "operationId": "Widgets_ListByResourceGroup", + "tags": [ + "Widgets" + ], + "description": "List WidgetResource resources by resource group", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.ManagedIdentityExample/widgets/{widgetName}": { + "get": { + "operationId": "Widgets_Get", + "tags": [ + "Widgets" + ], + "description": "Get a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "operationId": "Widgets_Create", + "tags": [ + "Widgets" + ], + "description": "Create a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/WidgetResource" + } + } + ], + "responses": { + "200": { + "description": "Resource 'WidgetResource' update operation succeeded", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "201": { + "description": "Resource 'WidgetResource' create operation succeeded", + "schema": { + "$ref": "#/definitions/WidgetResource" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Widgets_Update", + "tags": [ + "Widgets" + ], + "description": "Update a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/WidgetResourceTagsUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "operationId": "Widgets_Delete", + "tags": [ + "Widgets" + ], + "description": "Delete a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.ResourceProvisioningState": { + "type": "string", + "description": "The provisioning state of a resource type.", + "enum": [ + "Succeeded", + "Failed", + "Canceled" + ], + "x-ms-enum": { + "name": "ResourceProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + } + ] + }, + "readOnly": true + }, + "WidgetResource": { + "type": "object", + "description": "Widget Resource", + "properties": { + "properties": { + "$ref": "#/definitions/WidgetResourceProperties", + "description": "The resource-specific properties for this resource.", + "x-ms-client-flatten": true + }, + "identity": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v4/managedidentity.json#/definitions/ManagedServiceIdentity", + "description": "The managed service identities assigned to this resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v3/types.json#/definitions/TrackedResource" + } + ] + }, + "WidgetResourceListResult": { + "type": "object", + "description": "The response of a WidgetResource list operation.", + "properties": { + "value": { + "type": "array", + "description": "The WidgetResource items on this page", + "items": { + "$ref": "#/definitions/WidgetResource" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "WidgetResourceProperties": { + "type": "object", + "description": "Widget Resource Properties.", + "properties": { + "color": { + "type": "string", + "description": "The widget color.", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "provisioningState": { + "$ref": "#/definitions/Azure.ResourceManager.ResourceProvisioningState", + "description": "Provisioning state", + "readOnly": true + } + }, + "required": [ + "color" + ] + }, + "WidgetResourceTagsUpdate": { + "type": "object", + "description": "The type used for updating tags in WidgetResource resources.", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "parameters": {} +} diff --git a/packages/samples/test/output/azure/resource-manager/operations/nobody-action/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/operations/nobody-action/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index 6e0d4c499d..daecccb955 100644 --- a/packages/samples/test/output/azure/resource-manager/operations/nobody-action/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/operations/nobody-action/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -237,6 +237,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -584,11 +588,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-common-properties/common-properties/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-common-properties/common-properties/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json new file mode 100644 index 0000000000..22d4543ac4 --- /dev/null +++ b/packages/samples/test/output/azure/resource-manager/resource-common-properties/common-properties/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json @@ -0,0 +1,550 @@ +{ + "swagger": "2.0", + "info": { + "title": "Contoso.CommonEnvelopePropertiesExample", + "version": "2023-03-01-preview", + "description": "An example of using some of common envelope and property bag properties in a resource type. Their names are all end with 'Property'.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Widgets" + } + ], + "paths": { + "/providers/Contoso.CommonEnvelopePropertiesExample/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Contoso.CommonEnvelopePropertiesExample/widgets": { + "get": { + "operationId": "Widgets_ListBySubscription", + "tags": [ + "Widgets" + ], + "description": "List WidgetResource resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.CommonEnvelopePropertiesExample/widgets": { + "get": { + "operationId": "Widgets_ListByResourceGroup", + "tags": [ + "Widgets" + ], + "description": "List WidgetResource resources by resource group", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.CommonEnvelopePropertiesExample/widgets/{widgetName}": { + "get": { + "operationId": "Widgets_Get", + "tags": [ + "Widgets" + ], + "description": "Get a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "operationId": "Widgets_Create", + "tags": [ + "Widgets" + ], + "description": "Create a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/WidgetResource" + } + } + ], + "responses": { + "200": { + "description": "Resource 'WidgetResource' update operation succeeded", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "201": { + "description": "Resource 'WidgetResource' create operation succeeded", + "schema": { + "$ref": "#/definitions/WidgetResource" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Widgets_Update", + "tags": [ + "Widgets" + ], + "description": "Update a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/WidgetResourceTagsUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "operationId": "Widgets_Delete", + "tags": [ + "Widgets" + ], + "description": "Delete a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.CommonTypes.ExtendedLocation": { + "type": "object", + "description": "The complex type of the extended location.", + "properties": { + "name": { + "type": "string", + "description": "The name of the extended location." + }, + "type": { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.ExtendedLocationType", + "description": "The type of the extended location." + } + }, + "required": [ + "name", + "type" + ] + }, + "Azure.ResourceManager.CommonTypes.ExtendedLocationType": { + "type": "string", + "description": "The supported ExtendedLocation types.", + "enum": [ + "EdgeZone", + "CustomLocation" + ], + "x-ms-enum": { + "name": "ExtendedLocationType", + "modelAsString": true, + "values": [ + { + "name": "EdgeZone", + "value": "EdgeZone", + "description": "Azure Edge Zones location type" + }, + { + "name": "CustomLocation", + "value": "CustomLocation", + "description": "Azure Custom Locations type" + } + ] + } + }, + "Azure.ResourceManager.ResourceProvisioningState": { + "type": "string", + "description": "The provisioning state of a resource type.", + "enum": [ + "Succeeded", + "Failed", + "Canceled" + ], + "x-ms-enum": { + "name": "ResourceProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + } + ] + }, + "readOnly": true + }, + "WidgetResource": { + "type": "object", + "description": "Widget Resource", + "properties": { + "properties": { + "$ref": "#/definitions/WidgetResourceProperties", + "description": "The resource-specific properties for this resource.", + "x-ms-client-flatten": true + }, + "extendedLocation": { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.ExtendedLocation", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "managedBy": { + "type": "string", + "description": "The fully qualified resource ID of the resource that manages this resource. Indicates if this resource is managed by another Azure resource. If this is present, complete mode deployment will not delete the resource if it is removed from the template since it is managed by another resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/TrackedResource" + } + ] + }, + "WidgetResourceListResult": { + "type": "object", + "description": "The response of a WidgetResource list operation.", + "properties": { + "value": { + "type": "array", + "description": "The WidgetResource items on this page", + "items": { + "$ref": "#/definitions/WidgetResource" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "WidgetResourceProperties": { + "type": "object", + "description": "Widget Resource Properties.", + "properties": { + "color": { + "type": "string", + "description": "The widget color.", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "provisioningState": { + "$ref": "#/definitions/Azure.ResourceManager.ResourceProvisioningState", + "description": "Provisioning state", + "readOnly": true + }, + "eTag": { + "type": "string", + "description": "If eTag is provided in the response body, it may also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields.", + "readOnly": true + }, + "kind": { + "type": "string", + "description": "Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type; e.g. ApiApps are a kind of Microsoft.Web/sites type. If supported, the resource provider must validate and persist this value.", + "pattern": "^[-\\w\\._,\\(\\\\\\)]+$", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "plan": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/Plan", + "description": "Details of the resource plan." + }, + "sku": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/Sku", + "description": "The SKU (Stock Keeping Unit) assigned to this resource." + } + }, + "required": [ + "color" + ] + }, + "WidgetResourceTagsUpdate": { + "type": "object", + "description": "The type used for updating tags in WidgetResource resources.", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "parameters": {} +} diff --git a/packages/samples/test/output/azure/resource-manager/resource-common-properties/encryption/@azure-tools/typespec-autorest/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-common-properties/encryption/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json similarity index 75% rename from packages/samples/test/output/azure/resource-manager/resource-common-properties/encryption/@azure-tools/typespec-autorest/openapi.json rename to packages/samples/test/output/azure/resource-manager/resource-common-properties/encryption/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json index 70e4581c32..c31a6041a9 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-common-properties/encryption/@azure-tools/typespec-autorest/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-common-properties/encryption/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json @@ -56,20 +56,20 @@ "description": "List the operations for the provider", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" } ], "responses": { "200": { "description": "Azure operation completed successfully.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/OperationListResult" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/OperationListResult" } }, "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } }, @@ -87,10 +87,10 @@ "description": "List WidgetResource resources by subscription ID", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" } ], "responses": { @@ -103,7 +103,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } }, @@ -121,13 +121,13 @@ "description": "List WidgetResource resources by resource group", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" } ], "responses": { @@ -140,7 +140,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } }, @@ -158,13 +158,13 @@ "description": "Get a WidgetResource", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" }, { "name": "widgetName", @@ -185,7 +185,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } } @@ -198,13 +198,13 @@ "description": "Create a WidgetResource", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" }, { "name": "widgetName", @@ -237,6 +237,10 @@ "$ref": "#/definitions/WidgetResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -247,7 +251,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } }, @@ -264,13 +268,13 @@ "description": "Update a WidgetResource", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" }, { "name": "widgetName", @@ -300,7 +304,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } } @@ -313,13 +317,13 @@ "description": "Delete a WidgetResource", "parameters": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" }, { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" }, { "name": "widgetName", @@ -351,7 +355,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" } } }, @@ -401,16 +405,12 @@ "properties": { "$ref": "#/definitions/WidgetResourceProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/TrackedResource" + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/TrackedResource" } ] }, @@ -453,7 +453,7 @@ "readOnly": true }, "encryption": { - "$ref": "../../../../../../../../specs/resource-manager/common-types/v5/customermanagedkeys.json#/definitions/encryption", + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/customermanagedkeys.json#/definitions/encryption", "description": "All encryption configuration for a resource." } }, diff --git a/packages/samples/test/output/azure/resource-manager/resource-common-properties/managed-identity/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-common-properties/managed-identity/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json new file mode 100644 index 0000000000..a476b4b43c --- /dev/null +++ b/packages/samples/test/output/azure/resource-manager/resource-common-properties/managed-identity/@azure-tools/typespec-autorest/2023-03-01-preview/openapi.json @@ -0,0 +1,479 @@ +{ + "swagger": "2.0", + "info": { + "title": "Contoso.ManagedIdentityExample", + "version": "2023-03-01-preview", + "description": "An example of using the ManagedIdentity properties in a resource type.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Widgets" + } + ], + "paths": { + "/providers/Contoso.ManagedIdentityExample/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Contoso.ManagedIdentityExample/widgets": { + "get": { + "operationId": "Widgets_ListBySubscription", + "tags": [ + "Widgets" + ], + "description": "List WidgetResource resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.ManagedIdentityExample/widgets": { + "get": { + "operationId": "Widgets_ListByResourceGroup", + "tags": [ + "Widgets" + ], + "description": "List WidgetResource resources by resource group", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResourceListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.ManagedIdentityExample/widgets/{widgetName}": { + "get": { + "operationId": "Widgets_Get", + "tags": [ + "Widgets" + ], + "description": "Get a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "operationId": "Widgets_Create", + "tags": [ + "Widgets" + ], + "description": "Create a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/WidgetResource" + } + } + ], + "responses": { + "200": { + "description": "Resource 'WidgetResource' update operation succeeded", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "201": { + "description": "Resource 'WidgetResource' create operation succeeded", + "schema": { + "$ref": "#/definitions/WidgetResource" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Widgets_Update", + "tags": [ + "Widgets" + ], + "description": "Update a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/WidgetResourceTagsUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/WidgetResource" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "operationId": "Widgets_Delete", + "tags": [ + "Widgets" + ], + "description": "Delete a WidgetResource", + "parameters": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "widgetName", + "in": "path", + "description": "The name of the widget.", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.ResourceProvisioningState": { + "type": "string", + "description": "The provisioning state of a resource type.", + "enum": [ + "Succeeded", + "Failed", + "Canceled" + ], + "x-ms-enum": { + "name": "ResourceProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + } + ] + }, + "readOnly": true + }, + "WidgetResource": { + "type": "object", + "description": "Widget Resource", + "properties": { + "properties": { + "$ref": "#/definitions/WidgetResourceProperties", + "description": "The resource-specific properties for this resource.", + "x-ms-client-flatten": true + }, + "identity": { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/managedidentity.json#/definitions/ManagedServiceIdentity", + "description": "The managed service identities assigned to this resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/types.json#/definitions/TrackedResource" + } + ] + }, + "WidgetResourceListResult": { + "type": "object", + "description": "The response of a WidgetResource list operation.", + "properties": { + "value": { + "type": "array", + "description": "The WidgetResource items on this page", + "items": { + "$ref": "#/definitions/WidgetResource" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "WidgetResourceProperties": { + "type": "object", + "description": "Widget Resource Properties.", + "properties": { + "color": { + "type": "string", + "description": "The widget color.", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "provisioningState": { + "$ref": "#/definitions/Azure.ResourceManager.ResourceProvisioningState", + "description": "Provisioning state", + "readOnly": true + } + }, + "required": [ + "color" + ] + }, + "WidgetResourceTagsUpdate": { + "type": "object", + "description": "The type used for updating tags in WidgetResource resources.", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "parameters": {} +} diff --git a/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-08-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-08-01-preview/openapi.json index 720e17dcba..410346aa0f 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-08-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-08-01-preview/openapi.json @@ -242,6 +242,10 @@ "$ref": "#/definitions/TestTrackedResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -645,11 +649,7 @@ "properties": { "$ref": "../../../../../../../../../specs/resource-manager/common-types/v4/privatelinks.json#/definitions/PrivateEndpointConnectionProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -686,11 +686,7 @@ "properties": { "$ref": "../../../../../../../../../specs/resource-manager/common-types/v4/privatelinks.json#/definitions/PrivateLinkResourceProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -755,11 +751,7 @@ "properties": { "$ref": "#/definitions/TestTrackedProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-11-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-11-01-preview/openapi.json index 0703111702..4645f79a80 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-11-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-common-properties/private-links/@azure-tools/typespec-autorest/2023-11-01-preview/openapi.json @@ -242,6 +242,10 @@ "$ref": "#/definitions/TestTrackedResource" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -645,11 +649,7 @@ "properties": { "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/privatelinks.json#/definitions/PrivateEndpointConnectionProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -686,11 +686,7 @@ "properties": { "$ref": "../../../../../../../../../specs/resource-manager/common-types/v5/privatelinks.json#/definitions/PrivateLinkResourceProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -755,11 +751,7 @@ "properties": { "$ref": "#/definitions/TestTrackedProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/extension/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/extension/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index 2ee82524a3..b9c7ea9a6d 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/extension/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/extension/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -163,6 +163,10 @@ "$ref": "#/definitions/RoleAssignment" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -398,11 +402,7 @@ "properties": { "$ref": "#/definitions/RoleAssignmentProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/location/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/location/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index 0382c5b3f1..08ccc875f8 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/location/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/location/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -212,6 +212,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -433,11 +437,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/proxy/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/proxy/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index 38d01ad902..05ff8d16da 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/proxy/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/proxy/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -240,6 +240,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -538,6 +542,10 @@ "$ref": "#/definitions/Dependent" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -723,11 +731,7 @@ "properties": { "$ref": "#/definitions/DependentProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ @@ -813,11 +817,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/singleton/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/singleton/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index 0a7ddbb8f4..c432ec176d 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/singleton/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/singleton/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -187,6 +187,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -332,11 +336,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/tenant/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/tenant/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index b53b27f57d..0e3dd4ae27 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/tenant/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/tenant/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -154,6 +154,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -370,11 +374,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/tracked/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/tracked/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index 161c075401..409703629a 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/tracked/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/tracked/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -237,6 +237,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -446,11 +450,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/samples/test/output/azure/resource-manager/resource-types/virtual-resource/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json b/packages/samples/test/output/azure/resource-manager/resource-types/virtual-resource/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json index a10528b874..8fead9ff27 100644 --- a/packages/samples/test/output/azure/resource-manager/resource-types/virtual-resource/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json +++ b/packages/samples/test/output/azure/resource-manager/resource-types/virtual-resource/@azure-tools/typespec-autorest/2021-10-01-preview/openapi.json @@ -251,6 +251,10 @@ "$ref": "#/definitions/Employee" }, "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, "Retry-After": { "type": "integer", "format": "int32", @@ -538,11 +542,7 @@ "properties": { "$ref": "#/definitions/EmployeeProperties", "description": "The resource-specific properties for this resource.", - "x-ms-client-flatten": true, - "x-ms-mutability": [ - "read", - "create" - ] + "x-ms-client-flatten": true } }, "allOf": [ diff --git a/packages/typespec-autorest-canonical/README.md b/packages/typespec-autorest-canonical/README.md index b11edfc352..1eacd104bf 100644 --- a/packages/typespec-autorest-canonical/README.md +++ b/packages/typespec-autorest-canonical/README.md @@ -37,7 +37,7 @@ Output file will interpolate the following values: - service-name: Name of the service if multiple - azure-resource-provider-folder: Value of the azure-resource-provider-folder option -Default: `{azure-resource-provider-folder}/{service-name}/{version}/openapi.json` +Default: `{azure-resource-provider-folder}/{service-name}/canonical/openapi.json` Example: Single service diff --git a/packages/typespec-autorest-canonical/src/emitter.ts b/packages/typespec-autorest-canonical/src/emitter.ts index 0b36e004f5..e4919b12b6 100644 --- a/packages/typespec-autorest-canonical/src/emitter.ts +++ b/packages/typespec-autorest-canonical/src/emitter.ts @@ -134,8 +134,7 @@ async function emitAllServices( function resolveOutputFile( service: Service, multipleServices: boolean, - options: ResolvedAutorestCanonicalEmitterOptions, - version?: string + options: ResolvedAutorestCanonicalEmitterOptions ): string { const azureResourceProviderFolder = options.azureResourceProviderFolder; const interpolated = interpolatePath(options.outputFile, { @@ -144,12 +143,6 @@ function resolveOutputFile( multipleServices || azureResourceProviderFolder ? getNamespaceFullName(service.type) : undefined, - "version-status": azureResourceProviderFolder - ? version?.includes("preview") - ? "preview" - : "stable" - : undefined, - version, }); return resolvePath(options.outputDir, interpolated); diff --git a/packages/typespec-autorest-canonical/src/lib.ts b/packages/typespec-autorest-canonical/src/lib.ts index 92dc95e549..0122ea8e62 100644 --- a/packages/typespec-autorest-canonical/src/lib.ts +++ b/packages/typespec-autorest-canonical/src/lib.ts @@ -8,7 +8,7 @@ export interface AutorestCanonicalEmitterOptions { * - version: Version of the service if multiple * - azure-resource-provider-folder: Value of the azure-resource-provider-folder option * - * @default `{azure-resource-provider-folder}/{service-name}/{version}/openapi.json` + * @default `{azure-resource-provider-folder}/{service-name}/canonical/openapi.json` * * * @example Single service no versioning @@ -68,7 +68,7 @@ const EmitterOptionsSchema: JSONSchemaType = { " - service-name: Name of the service if multiple", " - azure-resource-provider-folder: Value of the azure-resource-provider-folder option", "", - "Default: `{azure-resource-provider-folder}/{service-name}/{version}/openapi.json`", + "Default: `{azure-resource-provider-folder}/{service-name}/canonical/openapi.json`", "", "", "Example: Single service", diff --git a/packages/typespec-autorest/README.md b/packages/typespec-autorest/README.md index c9425dbb81..d0e5b6e3d1 100644 --- a/packages/typespec-autorest/README.md +++ b/packages/typespec-autorest/README.md @@ -124,6 +124,12 @@ This extension is meant for debugging and should not be depended on. Create read-only property schema for lro status +#### `emit-lro-options` + +**Type:** `"none" | "final-state-only" | "all"` + +Determine whether and how to emit x-ms-long-running-operation-options for lro resolution + ## Decorators ### Autorest diff --git a/packages/typespec-autorest/schema/autorest-openapi-schema.tsp b/packages/typespec-autorest/schema/autorest-openapi-schema.tsp index d0d7a5adf8..5d90f426bc 100644 --- a/packages/typespec-autorest/schema/autorest-openapi-schema.tsp +++ b/packages/typespec-autorest/schema/autorest-openapi-schema.tsp @@ -145,17 +145,19 @@ model XmsPageable { @doc("Indicates whether the operation is long running (asynchronous). `true` value indicates that it is a long running operation.") model XmsLongRunningOperationOptions { @doc(""" -How to determine the final state of the operation. Possible Values: -- `azure-async-operation` - poll until terminal state, the final response will be available at the uri pointed to by the header `Azure-AsyncOperation` -- `location` - poll until terminal state, the final response will be available at the uri pointed to by the header `Location` -- `operation-location` - poll until terminal state, the final response will be available at the uri pointed to by the header `Operation-Location` -""") + How to determine the final state of the operation. Possible Values: + - `azure-async-operation` - poll until terminal state, the final response will be available at the uri pointed to by the header `Azure-AsyncOperation` + - `location` - poll until terminal state, the final response will be available at the uri pointed to by the header `Location` + - `operation-location` - poll until terminal state, the final response will be available at the uri pointed to by the header `Operation-Location` + """) `final-state-via`: | "azure-async-operation" | "location" | "original-uri" | "operation-location" | "final-state-schema"; + + `final-state-schema`?: string; } /** Describes the 'x-ms-examples' extension. */ diff --git a/packages/typespec-autorest/src/emit.ts b/packages/typespec-autorest/src/emit.ts index 565d6dcab9..abeecf1f7a 100644 --- a/packages/typespec-autorest/src/emit.ts +++ b/packages/typespec-autorest/src/emit.ts @@ -90,6 +90,7 @@ export function resolveAutorestOptions( includeXTypeSpecName: resolvedOptions["include-x-typespec-name"], armTypesDir, useReadOnlyStatusSchema: resolvedOptions["use-read-only-status-schema"], + emitLroOptions: resolvedOptions["emit-lro-options"], }; } diff --git a/packages/typespec-autorest/src/lib.ts b/packages/typespec-autorest/src/lib.ts index 855434046a..11d002f7fd 100644 --- a/packages/typespec-autorest/src/lib.ts +++ b/packages/typespec-autorest/src/lib.ts @@ -84,6 +84,12 @@ export interface AutorestEmitterOptions { * @default false */ "use-read-only-status-schema"?: boolean; + + /** + * Determines whether and how to emit the x-ms-long-running-operation-options + * @default "final-state-only" + */ + "emit-lro-options"?: "none" | "final-state-only" | "all"; } const EmitterOptionsSchema: JSONSchemaType = { @@ -179,6 +185,14 @@ const EmitterOptionsSchema: JSONSchemaType = { default: false, description: "Create read-only property schema for lro status", }, + "emit-lro-options": { + type: "string", + enum: ["none", "final-state-only", "all"], + nullable: true, + default: "final-state-only", + description: + "Determine whether and how to emit x-ms-long-running-operation-options for lro resolution", + }, }, required: [], }; diff --git a/packages/typespec-autorest/src/openapi.ts b/packages/typespec-autorest/src/openapi.ts index 8c46f7e7f8..df257b3d38 100644 --- a/packages/typespec-autorest/src/openapi.ts +++ b/packages/typespec-autorest/src/openapi.ts @@ -1,4 +1,6 @@ import { + FinalStateValue, + LroMetadata, PagedResultMetadata, UnionEnum, extractLroStates, @@ -144,6 +146,7 @@ import { OpenAPI2StatusCode, PrimitiveItems, Refable, + XMSLongRunningFinalState, } from "./openapi2-document.js"; import type { AutorestEmitterResult, LoadedExample } from "./types.js"; import { AutorestEmitterContext, getClientName, resolveOperationId } from "./utils.js"; @@ -185,6 +188,13 @@ export interface AutorestDocumentEmitterOptions { * @default "omit" */ readonly versionEnumStrategy?: "omit" | "include"; + + /** + * Determines whether and how to emit x-ms-long-running-operation-options + * to describe resolution of asynchronous operations + * @default "final-state-only" + */ + readonly emitLroOptions?: "none" | "final-state-only" | "all"; } /** @@ -486,6 +496,45 @@ export async function getOpenAPIForService( return path.replace(/\/?\?.*/, ""); } + function getFinalStateVia(metadata: LroMetadata): XMSLongRunningFinalState | undefined { + switch (metadata.finalStateVia) { + case FinalStateValue.azureAsyncOperation: + return "azure-async-operation"; + case FinalStateValue.location: + return "location"; + case FinalStateValue.operationLocation: + return "operation-location"; + case FinalStateValue.originalUri: + return "original-uri"; + default: + return undefined; + } + } + + function getFinalStateSchema(metadata: LroMetadata): { "final-state-schema": Ref } | undefined { + if ( + metadata.finalResult !== undefined && + metadata.finalResult !== "void" && + metadata.finalResult.name.length > 0 + ) { + const model: Model = metadata.finalResult; + const schemaOrRef = resolveExternalRef(metadata.finalResult); + + if (schemaOrRef !== undefined) { + const ref = new Ref(); + ref.value = schemaOrRef.$ref; + return { "final-state-schema": ref }; + } + const pending = pendingSchemas.getOrAdd(metadata.finalResult, Visibility.Read, () => ({ + type: model, + visibility: Visibility.Read, + ref: refs.getOrAdd(model, Visibility.Read, () => new Ref()), + })); + return { "final-state-schema": pending.ref }; + } + return undefined; + } + function emitOperation(operation: HttpOperation) { let { path: fullPath, operation: op, verb, parameters } = operation; let pathsObject: Record = root.paths; @@ -548,6 +597,24 @@ export async function getOpenAPIForService( // which does have LRO metadata. if (lroMetadata !== undefined && operation.verb !== "get") { currentEndpoint["x-ms-long-running-operation"] = true; + if (options.emitLroOptions !== "none") { + const finalState = getFinalStateVia(lroMetadata); + if (finalState !== undefined) { + const finalSchema = getFinalStateSchema(lroMetadata); + let lroOptions = { + "final-state-via": finalState, + }; + + if (finalSchema !== undefined && options.emitLroOptions === "all") { + lroOptions = { + "final-state-via": finalState, + ...finalSchema, + }; + } + + currentEndpoint["x-ms-long-running-operation-options"] = lroOptions; + } + } } // Extract paged metadata from Azure.Core.Page diff --git a/packages/typespec-autorest/src/openapi2-document.ts b/packages/typespec-autorest/src/openapi2-document.ts index b6d041394e..1afef8fb0b 100644 --- a/packages/typespec-autorest/src/openapi2-document.ts +++ b/packages/typespec-autorest/src/openapi2-document.ts @@ -451,6 +451,21 @@ export type OpenAPI2Operation = Extensions & { "x-ms-examples"?: Record>; "x-ms-long-running-operation"?: boolean; + + "x-ms-long-running-operation-options"?: XMSLongRunningOperationOptions; +}; + +export type XMSLongRunningFinalState = + | "azure-async-operation" + | "location" + | "original-uri" + | "operation-location" + | "final-state-schema"; + +export type XMSLongRunningOperationOptions = { + "final-state-via": XMSLongRunningFinalState; + + "final-state-schema"?: string; }; export type OpenAPI2StatusCode = string | "default" | "1XX" | "2XX" | "3XX" | "4XX" | "5XX"; diff --git a/packages/typespec-autorest/test/arm/resources.test.ts b/packages/typespec-autorest/test/arm/resources.test.ts index 23f762d76d..e71ade9be9 100644 --- a/packages/typespec-autorest/test/arm/resources.test.ts +++ b/packages/typespec-autorest/test/arm/resources.test.ts @@ -205,3 +205,105 @@ it("emits correct paths for ArmResourceHead operation", async () => { }, }); }); + +it("emits correct fixed union name parameter for resource", async () => { + const openApi = await openApiFor(` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso; + + @doc("Widget resource") + model Widget is ProxyResource { + ...ResourceNameParameter; + } + + @doc("The properties of a widget") + model WidgetProperties { + size: int32; + } + + /** different type of widget used on resource path */ + union WidgetNameType { + string, + /** small widget */ + Small: "Small", + /** large widget */ + Large: "Large" + } + + interface Widgets extends Operations { + get is ArmResourceRead; + } +`); + const getOperation = + openApi.paths[ + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/widgets/{widgetName}" + ].get; + ok(getOperation); + deepEqual(getOperation.parameters[3], { + description: "The name of the Widget", + enum: ["Small", "Large"], + "x-ms-enum": { + modelAsString: true, + name: "WidgetNameType", + values: [ + { + name: "Small", + value: "Small", + description: "small widget", + }, + { + name: "Large", + value: "Large", + description: "large widget", + }, + ], + }, + in: "path", + name: "widgetName", + required: true, + type: "string", + }); +}); + +it("emits a scalar string with decorator parameter for resource", async () => { + const openApi = await openApiFor(` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso; + + @doc("Widget resource") + model Widget is ProxyResource { + ...ResourceNameParameter; + } + + @doc("The properties of a widget") + model WidgetProperties { + size: int32; + } + + @minLength(1) + @maxLength(10) + @pattern("xxxxxx") + scalar WidgetNameType extends string; + + interface Widgets extends Operations { + get is ArmResourceRead; + } +`); + const getOperation = + openApi.paths[ + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/widgets/{widgetName}" + ].get; + ok(getOperation); + deepEqual(getOperation.parameters[3], { + description: "The name of the Widget", + in: "path", + maxLength: 10, + minLength: 1, + name: "widgetName", + pattern: "^[a-zA-Z0-9-]{3,24}$", + required: true, + type: "string", + }); +}); diff --git a/packages/typespec-autorest/test/lro.test.ts b/packages/typespec-autorest/test/lro.test.ts index f6c54919f8..f2c74c57f0 100644 --- a/packages/typespec-autorest/test/lro.test.ts +++ b/packages/typespec-autorest/test/lro.test.ts @@ -1,3 +1,4 @@ +import { paramMessage } from "@typespec/compiler"; import { deepStrictEqual } from "assert"; import { describe, it } from "vitest"; import { openApiFor } from "./test-host.js"; @@ -55,13 +56,22 @@ describe("typespec-autorest: Long-running Operations", () => { @pollingOperation(getWidgetOperationStatus) op createOrUpdateWidget is Operations.LongRunningResourceCreateOrUpdate; - ` + `, + undefined, + { "emit-lro-options": "all" } ); deepStrictEqual( openapi.paths["/widgets/{widgetName}"].patch["x-ms-long-running-operation"], true ); + deepStrictEqual( + openapi.paths["/widgets/{widgetName}"].patch["x-ms-long-running-operation-options"], + { + "final-state-via": "operation-location", + "final-state-schema": "#/definitions/Widget", + } + ); deepStrictEqual( openapi.paths["/widgets/{widgetName}/operations/{operationId}"].get[ "x-ms-long-running-operation" @@ -69,4 +79,151 @@ describe("typespec-autorest: Long-running Operations", () => { undefined ); }); + + const armCode = paramMessage` + @armProviderNamespace + @useDependency(Azure.Core.Versions.v1_0_Preview_2) + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Test; + + interface Operations extends Azure.ResourceManager.Operations {} + + @doc("The state of the resource") + enum ResourceState { + Succeeded, + Canceled, + Failed + } + + @doc("The widget properties") + model WidgetProperties { + @doc("I am a simple Resource Identifier") + simpleArmId: Azure.Core.armResourceIdentifier; + + @doc("The provisioning State") + provisioningState: ResourceState; + } + + @doc("Foo resource") + model Widget is TrackedResource { + @doc("Widget name") + @key("widgetName") + @segment("widgets") + @path + name: string; + } + @armResourceOperations(Widget) + interface Widgets { + get is ArmResourceRead; + ${"putOp"} + update is ArmResourcePatchAsync; + delete is ArmResourceDeleteWithoutOkAsync; + restart is ArmResourceActionAsync; + munge is ArmResourceActionAsync; + listByResourceGroup is ArmResourceListByParent; + listBySubscription is ArmListBySubscription; + } + `; + it("includes x-ms-long-running-operation-options for ARM operations", async () => { + const openapi = await openApiFor( + armCode.apply(armCode, [ + { putOp: "createOrUpdate is ArmResourceCreateOrReplaceAsync;" }, + ]), + undefined, + { "emit-lro-options": "all" } + ); + + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "azure-async-operation", + "final-state-schema": "#/definitions/Widget", + }); + + deepStrictEqual(openapi.paths[itemPath].patch["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[itemPath].patch["x-ms-long-running-operation-options"], { + "final-state-via": "location", + "final-state-schema": "#/definitions/Widget", + }); + + deepStrictEqual(openapi.paths[itemPath].delete["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[itemPath].delete["x-ms-long-running-operation-options"], { + "final-state-via": "location", + }); + const restartPath = `${itemPath}/restart`; + deepStrictEqual(openapi.paths[restartPath].post["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[restartPath].post["x-ms-long-running-operation-options"], { + "final-state-via": "location", + }); + const mungePath = `${itemPath}/munge`; + deepStrictEqual(openapi.paths[mungePath].post["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[mungePath].post["x-ms-long-running-operation-options"], { + "final-state-via": "location", + "final-state-schema": "#/definitions/Widget", + }); + }); + it("Uses final-state-via: location when location is provided for ARM PUT", async () => { + const openapi = await openApiFor( + armCode.apply(armCode, [ + { + putOp: + "createOrUpdate is ArmResourceCreateOrReplaceAsync & Azure.Core.Foundations.RetryAfterHeader>;", + }, + ]), + undefined, + { "emit-lro-options": "all" } + ); + + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "location", + "final-state-schema": "#/definitions/Widget", + }); + }); + it("Uses final-state-via: original-uri when no lro headers are provided for ARM PUT", async () => { + const openapi = await openApiFor( + armCode.apply(armCode, [ + { + putOp: + "createOrUpdate is ArmResourceCreateOrReplaceAsync;", + }, + ]), + undefined, + { "emit-lro-options": "all" } + ); + + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "original-uri", + "final-state-schema": "#/definitions/Widget", + }); + }); + + it("Allows azure-async-operation override without headers for ARM PUT", async () => { + const openapi = await openApiFor( + armCode.apply(armCode, [ + { + putOp: `#suppress "@azure-tools/typespec-azure-core/invalid-final-state" "test" + @useFinalStateVia("azure-async-operation") + createOrUpdate is ArmResourceCreateOrReplaceAsync; + `, + }, + ]), + undefined, + { "emit-lro-options": "all" } + ); + + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(openapi.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "azure-async-operation", + "final-state-schema": "#/definitions/Widget", + }); + }); }); diff --git a/packages/typespec-autorest/test/options.test.ts b/packages/typespec-autorest/test/options.test.ts index 8e9d23bb14..365aacb655 100644 --- a/packages/typespec-autorest/test/options.test.ts +++ b/packages/typespec-autorest/test/options.test.ts @@ -292,4 +292,97 @@ op test(): void; strictEqual(prop["x-typespec-name"], `string[]`); }); }); + + describe("'suppress-lro-options' option", () => { + const lroCode = ` + @armProviderNamespace + @useDependency(Azure.Core.Versions.v1_0_Preview_2) + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Test; + + interface Operations extends Azure.ResourceManager.Operations {} + + @doc("The state of the resource") + enum ResourceState { + Succeeded, + Canceled, + Failed + } + + @doc("The widget properties") + model WidgetProperties { + @doc("I am a simple Resource Identifier") + simpleArmId: Azure.Core.armResourceIdentifier; + + @doc("The provisioning State") + provisioningState: ResourceState; + } + + @doc("Foo resource") + model Widget is TrackedResource { + @doc("Widget name") + @key("widgetName") + @segment("widgets") + @path + name: string; + } + @armResourceOperations(Widget) + interface Widgets { + get is ArmResourceRead; + @Azure.Core.useFinalStateVia("azure-async-operation") + createOrUpdate is ArmResourceCreateOrReplaceAsync; + update is ArmResourcePatchSync; + delete is ArmResourceDeleteSync; + listByResourceGroup is ArmResourceListByParent; + listBySubscription is ArmListBySubscription; + } + `; + + it("emits all x-ms-long-running-operation-options", async () => { + const output = await openapiWithOptions(lroCode, { "emit-lro-options": "all" }); + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + ok(output.paths[itemPath]); + ok(output.paths[itemPath].put); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "azure-async-operation", + "final-state-schema": "#/definitions/Widget", + }); + }); + + it("emits final-state-via by default", async () => { + const output = await openapiWithOptions(lroCode, {}); + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + ok(output.paths[itemPath]); + ok(output.paths[itemPath].put); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "azure-async-operation", + }); + }); + + it("emits final-state-via when configured", async () => { + const output = await openapiWithOptions(lroCode, { "emit-lro-options": "final-state-only" }); + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + ok(output.paths[itemPath]); + ok(output.paths[itemPath].put); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation-options"], { + "final-state-via": "azure-async-operation", + }); + }); + + it("suppress x-ms-long-running operation options when configured", async () => { + const output = await openapiWithOptions(lroCode, { "emit-lro-options": "none" }); + const itemPath = + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Test/widgets/{widgetName}"; + ok(output.paths[itemPath]); + ok(output.paths[itemPath].put); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation"], true); + deepStrictEqual(output.paths[itemPath].put["x-ms-long-running-operation-options"], undefined); + }); + }); }); diff --git a/packages/typespec-azure-core/README.md b/packages/typespec-azure-core/README.md index 2ba23bff3e..bf19105d4b 100644 --- a/packages/typespec-azure-core/README.md +++ b/packages/typespec-azure-core/README.md @@ -87,6 +87,7 @@ Available ruleSets: - [`@pollingLocation`](#@pollinglocation) - [`@pollingOperation`](#@pollingoperation) - [`@pollingOperationParameter`](#@pollingoperationparameter) +- [`@useFinalStateVia`](#@usefinalstatevia) #### `@finalLocation` @@ -389,6 +390,24 @@ Used to define how to call custom polling operations for long-running operations | --------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | targetParameter | `ModelProperty \| string` | A reference to the polling operation parameter this parameter
provides a value for, or the name of that parameter. The default value is the name of
the decorated parameter or property. | +#### `@useFinalStateVia` + +Overrides the final state value for an operation + +```typespec +@Azure.Core.useFinalStateVia(finalState: valueof "original-uri" | "operation-location" | "location" | "azure-async-operation") +``` + +##### Target + +`Operation` + +##### Parameters + +| Name | Type | Description | +| ---------- | ----------------------------------------------------------------------------------------- | ----------------------------- | +| finalState | `valueof "original-uri" \| "operation-location" \| "location" \| "azure-async-operation"` | The desired final state value | + ### Azure.Core.Foundations - [`@omitKeyProperties`](#@omitkeyproperties) diff --git a/packages/typespec-azure-core/lib/decorators.tsp b/packages/typespec-azure-core/lib/decorators.tsp index f6718e69ee..61a84cdda8 100644 --- a/packages/typespec-azure-core/lib/decorators.tsp +++ b/packages/typespec-azure-core/lib/decorators.tsp @@ -118,6 +118,15 @@ namespace Azure.Core { */ extern dec finalOperation(entity: Operation, linkedOperation: Operation, parameters?: {}); + /** + * Overrides the final state value for an operation + * @param finalState The desired final state value + */ + extern dec useFinalStateVia( + entity: Operation, + finalState: valueof "original-uri" | "operation-location" | "location" | "azure-async-operation" + ); + /** * Identifies that an operation is used to retrieve the next page for paged operations. * @param linkedOperation The linked Operation @@ -197,4 +206,13 @@ namespace Azure.Core.Foundations.Private { target: Scalar, options: ArmResourceIdentifierConfigOptions ); + + /** + * Sets the priority order of default final-state-via options for an operation + * @param states: list of final-state-via options in priority order + */ + extern dec defaultFinalStateVia( + target: TypeSpec.Reflection.Operation, + states: valueof ("operation-location" | "location" | "azure-async-operation")[] + ); } diff --git a/packages/typespec-azure-core/lib/models.tsp b/packages/typespec-azure-core/lib/models.tsp index 4dae8dfa1d..7661e3dc07 100644 --- a/packages/typespec-azure-core/lib/models.tsp +++ b/packages/typespec-azure-core/lib/models.tsp @@ -157,9 +157,9 @@ model ConditionalRequestHeaders { } @doc(""" -Provides the 'ETag' field to enable conditional (cached) requests. This model can be spread -into responses and item models to convey the ETag when it cannot simply conveyed in a header. -""") + Provides the 'ETag' field to enable conditional (cached) requests. This model can be spread + into responses and item models to convey the ETag when it cannot simply conveyed in a header. + """) model EtagProperty { @visibility("read") @doc("The entity tag for this resource.") diff --git a/packages/typespec-azure-core/src/decorators.ts b/packages/typespec-azure-core/src/decorators.ts index f65a709591..01633fc728 100644 --- a/packages/typespec-azure-core/src/decorators.ts +++ b/packages/typespec-azure-core/src/decorators.ts @@ -31,9 +31,14 @@ import { UnionVariant, walkPropertiesInherited, } from "@typespec/compiler"; -import { getHttpOperation, getRoutePath } from "@typespec/http"; +import { + getHttpOperation, + getRoutePath, + HttpOperation, + HttpOperationResponse, +} from "@typespec/http"; import { getResourceTypeKey, getSegment, isAutoRoute } from "@typespec/rest"; -import { OperationLink } from "./lro-helpers.js"; +import { FinalStateValue, OperationLink } from "./lro-helpers.js"; import { extractStatusMonitorInfo, getLroOperationInfo, @@ -743,6 +748,7 @@ function extractPollingLocationInfo( pollingModel?: Model | IntrinsicType; finalResult?: Model | IntrinsicType; target: ModelProperty; + useForFinalState?: boolean; } = { target: target }; const pollingModel = options.properties.get(pollingModelKey)?.type; if (pollingModel && pollingModel.kind === "Model") pollingInfo.pollingModel = pollingModel; @@ -765,6 +771,7 @@ function extractStatusMonitorLocationInfo( pollingModel?: Model | IntrinsicType; finalResult?: Model | IntrinsicType; target: ModelProperty; + useForFInalState?: boolean; } ): StatusMonitorPollingLocationInfo | undefined { const kind = options.properties.get(optionsKindKey); @@ -845,6 +852,173 @@ export function getFinalLocationValue( return program.stateMap(finalLocationResultsKey).get(entity); } +const finalStateOverrideKey = createStateSymbol("finalStateOverride"); +/** + * overrides the final state for an lro + * @param context The execution context for the decorator + * @param entity The decorated operation + * @param finalState The desired value for final-state-via + */ +export function $useFinalStateVia( + context: DecoratorContext, + entity: Operation, + finalState: string +) { + const { program } = context; + let finalStateVia: FinalStateValue; + switch (finalState?.toLowerCase()) { + case "original-uri": + finalStateVia = FinalStateValue.originalUri; + break; + case "operation-location": + finalStateVia = FinalStateValue.operationLocation; + break; + case "location": + finalStateVia = FinalStateValue.location; + break; + case "azure-async-operation": + finalStateVia = FinalStateValue.azureAsyncOperation; + break; + default: + reportDiagnostic(program, { + code: "invalid-final-state", + target: entity, + messageId: "badValue", + format: { finalStateValue: finalState }, + }); + return; + } + + const operation = ignoreDiagnostics(getHttpOperation(program, entity)); + const storedValue = validateFinalState(program, operation, finalStateVia); + if (storedValue !== undefined || operation.verb === "put") { + program.stateMap(finalStateOverrideKey).set(entity, finalStateVia); + } + if ( + storedValue === undefined && + [ + FinalStateValue.operationLocation, + FinalStateValue.location, + FinalStateValue.azureAsyncOperation, + ].includes(finalStateVia) + ) { + reportDiagnostic(program, { + code: "invalid-final-state", + target: entity, + messageId: "noHeader", + format: { finalStateValue: finalStateVia }, + }); + } +} + +type LroHeader = "azure-asyncoperation" | "location" | "operation-location"; + +function getLroHeaderName(finalState: FinalStateValue): LroHeader | undefined { + switch (finalState) { + case FinalStateValue.azureAsyncOperation: + return "azure-asyncoperation"; + case FinalStateValue.location: + return "location"; + case FinalStateValue.operationLocation: + return "operation-location"; + default: + return undefined; + } +} + +function getLroHeader(propertyName: string): LroHeader | undefined { + const name = propertyName.toLowerCase(); + switch (name) { + case "azure-asyncoperation": + case "location": + case "operation-location": + return name; + default: + return undefined; + } +} + +function getLroHeaders(response: HttpOperationResponse): Set | undefined { + const result = new Set(); + for (const content of response.responses) { + if (content.headers) { + for (const candidate of Object.keys(content.headers)) { + const headerName = getLroHeader(candidate); + if (headerName !== undefined) { + result.add(headerName); + } + } + } + } + + return result; +} + +function validateFinalState( + program: Program, + operation: HttpOperation, + finalState: FinalStateValue +): FinalStateValue | undefined { + if (finalState === FinalStateValue.originalUri) { + if (operation.verb !== "put") { + reportDiagnostic(program, { + code: "invalid-final-state", + target: operation.operation, + messageId: "notPut", + }); + return undefined; + } + + return FinalStateValue.originalUri; + } + + const header = getLroHeaderName(finalState); + if (header === undefined) { + reportDiagnostic(program, { + code: "invalid-final-state", + target: operation.operation, + messageId: "badValue", + format: { finalStateValue: finalState }, + }); + return undefined; + } + + for (const response of operation.responses) { + const lroHeaders = getLroHeaders(response); + if (lroHeaders?.has(header)) { + return finalState; + } + } + + return undefined; +} + +function validateFinalStates( + program: Program, + operation: Operation, + finalStates: FinalStateValue[] +): FinalStateValue | undefined { + const httpOp = ignoreDiagnostics(getHttpOperation(program, operation)); + for (const state of finalStates) { + if (validateFinalState(program, httpOp, state)) return state; + } + + return undefined; +} + +/** + * Get the overridden final state value for this operation, if any + * @param program The program to process + * @param operation The operation to check for an override value + * @returns The FInalStateValue if it exists, otherwise undefined + */ +export function getFinalStateOverride( + program: Program, + operation: Operation +): FinalStateValue | undefined { + return program.stateMap(finalStateOverrideKey).get(operation); +} + export function $omitKeyProperties(context: DecoratorContext, entity: Model) { // Delete any key properties from the model for (const [key, prop] of entity.properties) { @@ -1294,6 +1468,40 @@ export function getArmResourceIdentifierConfig( return program.stateMap(armResourceIdentifierConfigKey).get(entity); } +export function $defaultFinalStateVia( + context: DecoratorContext, + target: Operation, + states: LroHeader[] +) { + const { program } = context; + const finalStateValues: FinalStateValue[] = []; + for (const finalState of states) { + switch (finalState?.toLowerCase()) { + case "operation-location": + finalStateValues.push(FinalStateValue.operationLocation); + break; + case "location": + finalStateValues.push(FinalStateValue.location); + break; + case "azure-async-operation": + finalStateValues.push(FinalStateValue.azureAsyncOperation); + break; + default: + reportDiagnostic(program, { + code: "invalid-final-state", + target: target, + messageId: "badValue", + format: { finalStateValue: finalState }, + }); + return; + } + } + const storedValue = validateFinalStates(program, target, finalStateValues); + if (storedValue !== undefined) { + program.stateMap(finalStateOverrideKey).set(target, storedValue); + } +} + setTypeSpecNamespace("Foundations", $omitKeyProperties, $requestParameter, $responseProperty); setTypeSpecNamespace( "Foundations.Private", @@ -1303,5 +1511,6 @@ setTypeSpecNamespace( $needsRoute, $ensureVerb, $embeddingVector, - $armResourceIdentifierConfig + $armResourceIdentifierConfig, + $defaultFinalStateVia ); diff --git a/packages/typespec-azure-core/src/lib.ts b/packages/typespec-azure-core/src/lib.ts index 18743de4c2..a3e41a17dd 100644 --- a/packages/typespec-azure-core/src/lib.ts +++ b/packages/typespec-azure-core/src/lib.ts @@ -27,6 +27,14 @@ export const $lib = createTypeSpecLibrary({ default: paramMessage`StatusMonitor has more than one ${"resultType"} property marked with '${"decorator"}'. Ensure that only one property in the model is marked with this decorator.`, }, }, + "invalid-final-state": { + severity: "warning", + messages: { + badValue: paramMessage`Specified final state value '${"finalStateValue"}' is not valid. It must be one of ("operation-location", "original-uri", "location", "azure-async-operation")`, + notPut: "The final state value 'original-uri' can only be used in http PUT operations", + noHeader: paramMessage`There was no header corresponding to the desired final-state-via value '${"finalStateValue"}'.`, + }, + }, "bad-record-type": { severity: "warning", messages: { diff --git a/packages/typespec-azure-core/src/lro-helpers.ts b/packages/typespec-azure-core/src/lro-helpers.ts index e3f5ccbd2c..d4d1761143 100644 --- a/packages/typespec-azure-core/src/lro-helpers.ts +++ b/packages/typespec-azure-core/src/lro-helpers.ts @@ -37,6 +37,7 @@ import { extractLroStates, FinalOperationKey, getFinalLocationValue, + getFinalStateOverride, getLroResult, getOperationLink, getOperationLinks, @@ -572,7 +573,9 @@ function getFinalStateVia( let model: Model | IntrinsicType | undefined = context.originalModel?.name !== undefined ? context.originalModel : undefined; let finalState: FinalStateValue = FinalStateValue.originalUri; + const finalStateOverride = getFinalStateOverride(program, operation); const resOp = getLogicalResourceOperation(program, operation, model); + if (operationAction !== undefined || resOp?.operation === "delete") { finalState = FinalStateValue.operationLocation; model = context.pollingStep?.responseModel ?? context.originalModel; @@ -603,7 +606,7 @@ function getFinalStateVia( } else { finalState = getStatusFromLinkOrReference(program, operation, context.finalStep.target); } - return [finalState, model]; + return [finalStateOverride || finalState, model]; } if ( @@ -613,7 +616,7 @@ function getFinalStateVia( resOp.resourceType !== undefined ) { model = resOp.resourceType; - return [FinalStateValue.originalUri, model]; + return [finalStateOverride || FinalStateValue.originalUri, model]; } // handle actions and delete operations @@ -643,7 +646,7 @@ function getFinalStateVia( } } - return [finalState, model]; + return [finalStateOverride || finalState, model]; } function getLroStatusFromHeaderProperty( diff --git a/packages/typespec-azure-core/test/decorators.test.ts b/packages/typespec-azure-core/test/decorators.test.ts index ee481dd10b..d35bb67b45 100644 --- a/packages/typespec-azure-core/test/decorators.test.ts +++ b/packages/typespec-azure-core/test/decorators.test.ts @@ -8,11 +8,13 @@ import assert, { deepStrictEqual, ok, strictEqual } from "assert"; import { beforeEach, describe, it } from "vitest"; import { OperationLinkMetadata, + getFinalStateOverride, getLongRunningStates, getOperationLinks, getPagedResult, isFixed, } from "../src/decorators.js"; +import { FinalStateValue } from "../src/lro-helpers.js"; import { createAzureCoreTestRunner } from "./test-host.js"; describe("typespec-azure-core: decorators", () => { @@ -729,7 +731,80 @@ describe("typespec-azure-core: decorators", () => { expectDiagnosticEmpty(diagnostics); }); }); + describe("@useFinalStateVia", () => { + it("correctly overrides PUT lro final-state-via", async () => { + const code = ` + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @pollingOperation(bar) + @useFinalStateVia("operation-location") + @test @put op foo(): {@header("Operation-Location") loc: string}; + + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @route("/polling") + @get op bar(): {status: "Succeeded" | "Failed" | "Cancelled"}; + `; + const [{ foo }, diagnostics] = await runner.compileAndDiagnose(code); + expectDiagnosticEmpty(diagnostics); + const op = foo as Operation; + + assert.ok(op); + assert.deepStrictEqual(op.kind, "Operation"); + const finalState = getFinalStateOverride(runner.program, op); + assert.deepStrictEqual(finalState, FinalStateValue.operationLocation); + }); + it("emits diagnostic for invalid PUT override", async () => { + const code = ` + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @pollingOperation(bar) + @useFinalStateVia("operation-location") + @test @put op foo(): {loc: string}; + + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @route("/polling") + @get op bar(): {status: "Succeeded" | "Failed" | "Cancelled"}; + `; + const diagnostics = await runner.diagnose(code); + expectDiagnostics(diagnostics, { + code: "@azure-tools/typespec-azure-core/invalid-final-state", + message: + "There was no header corresponding to the desired final-state-via value 'operation-location'.", + }); + }); + it("emits error for missing header", async () => { + const code = ` + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @pollingOperation(bar) + @useFinalStateVia("location") + @post op foo(): {}; + + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @route("/polling") + @get op bar(): {status: "Succeeded" | "Failed" | "Cancelled"}; + `; + const diagnostics = await runner.diagnose(code); + expectDiagnostics(diagnostics, { + code: "@azure-tools/typespec-azure-core/invalid-final-state", + message: `There was no header corresponding to the desired final-state-via value 'location'.`, + }); + }); + it("emits error for original-uri on non-PUT request", async () => { + const code = ` + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @pollingOperation(bar) + @useFinalStateVia("original-uri") + @post op foo(): {}; + #suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is test code." + @route("/polling") + @get op bar(): {status: "Succeeded" | "Failed" | "Cancelled"}; + `; + const diagnostics = await runner.diagnose(code); + expectDiagnostics(diagnostics, { + code: "@azure-tools/typespec-azure-core/invalid-final-state", + message: "The final state value 'original-uri' can only be used in http PUT operations", + }); + }); + }); describe("@pollingOperation", () => { it("emit error if response of operation is a scalar", async () => { const code = ` diff --git a/packages/typespec-azure-playground-website/samples/azure-core.tsp b/packages/typespec-azure-playground-website/samples/azure-core.tsp index ed597517a2..c0a19622c6 100644 --- a/packages/typespec-azure-playground-website/samples/azure-core.tsp +++ b/packages/typespec-azure-playground-website/samples/azure-core.tsp @@ -193,7 +193,11 @@ alias Operations = Azure.Core.ResourceOperations; interface Widgets { // Operation Status /** Gets status of a Widget operation. */ + @sharedRoute getWidgetOperationStatus is Operations.GetResourceOperationStatus; + /** Gets status of a Widget delete operation. */ + @sharedRoute + getWidgetDeleteOperationStatus is Operations.GetResourceOperationStatus; // Widget Operations /** Creates or updates a Widget asynchronously */ @@ -204,7 +208,7 @@ interface Widgets { getWidget is Operations.ResourceRead; /** Delete a Widget asynchronously. */ - @pollingOperation(Widgets.getWidgetOperationStatus) + @pollingOperation(Widgets.getWidgetDeleteOperationStatus) deleteWidget is Operations.LongRunningResourceDelete; /** List Widget resources */ diff --git a/packages/typespec-azure-resource-manager/README.md b/packages/typespec-azure-resource-manager/README.md index 5c1b20fd24..703b9022a6 100644 --- a/packages/typespec-azure-resource-manager/README.md +++ b/packages/typespec-azure-resource-manager/README.md @@ -103,9 +103,9 @@ the version of the Azure Resource Manager common-types to use for refs in emitte ##### Parameters -| Name | Type | Description | -| ------- | ------------------------------ | ------------------------------------------------------------------------------------ | -| version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version. | +| Name | Type | Description | +| ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | +| version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". | #### `@armLibraryNamespace` diff --git a/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp b/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp new file mode 100644 index 0000000000..65fe4b9ae1 --- /dev/null +++ b/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp @@ -0,0 +1 @@ +import "./managed-identity.tsp"; diff --git a/packages/typespec-azure-resource-manager/lib/Legacy/managed-identity.tsp b/packages/typespec-azure-resource-manager/lib/Legacy/managed-identity.tsp new file mode 100644 index 0000000000..5983443382 --- /dev/null +++ b/packages/typespec-azure-resource-manager/lib/Legacy/managed-identity.tsp @@ -0,0 +1,74 @@ +import "@azure-tools/typespec-azure-core"; +import "../common-types/common-types.tsp"; + +using Azure.Core; +using Azure.ResourceManager.CommonTypes.Private; + +namespace Azure.ResourceManager.Legacy; + +/** + * Model representing the standard `ManagedServiceIdentity` envelope property from V4 of common type. + * + * Please note that this is only included for legacy specs with mixed v3 and v4 types, which would cause + * breaking changes due to the ManagedServiceIdentityType.SystemAndUserAssigned value changes. + * + * Do not use this if you are already on CommonTypes.Version.v4 or beyond. + * + * @example + * + * ```typespec + * model Foo is TrackedResource { + * ...ResourceNameParameter; + * ...Legacy.ManagedServiceIdentityV4Property; + * } + * ``` + */ +@doc("The managed service identities envelope.") +model ManagedServiceIdentityV4Property { + @doc("The managed service identities assigned to this resource.") + identity?: ManagedServiceIdentityV4; +} + +/** + * Managed service identity (system assigned and/or user assigned identities) + */ +#suppress "@azure-tools/typespec-azure-resource-manager/arm-common-types-incompatible-version" "intended only for v3/v4 mix backcompat cases" +@armCommonDefinition( + "ManagedServiceIdentity", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + "managedidentity.json" +) +model ManagedServiceIdentityV4 { + /** The service principal ID of the system assigned identity. This property will only be provided for a system assigned identity. */ + @visibility("read") + principalId?: uuid; + + /** The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity. */ + @visibility("read") + tenantId?: uuid; + + /** The type of managed identity assigned to this resource. */ + type: ManagedServiceIdentityType; + + /** The identities assigned to this resource by the user. */ + userAssignedIdentities?: Record; +} + +/** + * Type of managed service identity (where both SystemAssigned and UserAssigned types are allowed). + */ +union ManagedServiceIdentityType { + /** No managed identity. */ + None: "None", + + /** System assigned managed identity. */ + SystemAssigned: "SystemAssigned", + + /** User assigned managed identity. */ + UserAssigned: "UserAssigned", + + /** System and user assigned managed identity. */ + SystemAndUserAssigned: "SystemAssigned, UserAssigned", + + string, +} diff --git a/packages/typespec-azure-resource-manager/lib/arm.tsp b/packages/typespec-azure-resource-manager/lib/arm.tsp index 0a471f32bc..f80479cab0 100644 --- a/packages/typespec-azure-resource-manager/lib/arm.tsp +++ b/packages/typespec-azure-resource-manager/lib/arm.tsp @@ -6,6 +6,7 @@ import "@typespec/versioning"; import "@azure-tools/typespec-azure-core"; import "./foundations/arm.foundations.tsp"; +import "./Legacy/arm.legacy.tsp"; import "./common-types/common-types.tsp"; import "./backcompat.tsp"; import "./private.decorators.tsp"; diff --git a/packages/typespec-azure-resource-manager/lib/common-types/common-types.tsp b/packages/typespec-azure-resource-manager/lib/common-types/common-types.tsp index 45f0371ca0..211ef3d5e5 100644 --- a/packages/typespec-azure-resource-manager/lib/common-types/common-types.tsp +++ b/packages/typespec-azure-resource-manager/lib/common-types/common-types.tsp @@ -8,6 +8,21 @@ import "./customer-managed-keys-ref.tsp"; import "./extended-location-ref.tsp"; import "./internal.tsp"; import "./commontypes.private.decorators.tsp"; -import "./versions.tsp"; -@@Private.armCommonTypesVersions(Azure.ResourceManager.CommonTypes.Versions); +using TypeSpec.Versioning; + +@versioned(Versions) +namespace Azure.ResourceManager.CommonTypes; + +@CommonTypes.Private.armCommonTypesVersions +@doc("The Azure Resource Manager common-types versions.") +enum Versions { + @doc("The Azure Resource Manager v3 common types.") + v3, + + @doc("The Azure Resource Manager v4 common types.") + v4, + + @doc("The Azure Resource Manager v5 common types.") + v5, +} diff --git a/packages/typespec-azure-resource-manager/lib/common-types/customer-managed-keys-ref.tsp b/packages/typespec-azure-resource-manager/lib/common-types/customer-managed-keys-ref.tsp index 617b7375f5..3df1e5168a 100644 --- a/packages/typespec-azure-resource-manager/lib/common-types/customer-managed-keys-ref.tsp +++ b/packages/typespec-azure-resource-manager/lib/common-types/customer-managed-keys-ref.tsp @@ -6,7 +6,7 @@ namespace Azure.ResourceManager.CommonTypes; @@armCommonDefinition(Encryption, "encryption", - Azure.ResourceManager.CommonTypes.Versions.v4, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, "customermanagedkeys.json" ); @@armCommonDefinition(Encryption, @@ -14,3 +14,14 @@ namespace Azure.ResourceManager.CommonTypes; Azure.ResourceManager.CommonTypes.Versions.v5, "customermanagedkeys.json" ); + +@@armCommonDefinition(CustomerManagedKeyEncryption, + "customerManagedKeyEncryption", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + "customermanagedkeys.json" +); +@@armCommonDefinition(CustomerManagedKeyEncryption, + "customerManagedKeyEncryption", + Azure.ResourceManager.CommonTypes.Versions.v5, + "customermanagedkeys.json" +); diff --git a/packages/typespec-azure-resource-manager/lib/common-types/managed-identity-ref.tsp b/packages/typespec-azure-resource-manager/lib/common-types/managed-identity-ref.tsp index c32751ba18..c839d489ed 100644 --- a/packages/typespec-azure-resource-manager/lib/common-types/managed-identity-ref.tsp +++ b/packages/typespec-azure-resource-manager/lib/common-types/managed-identity-ref.tsp @@ -9,7 +9,12 @@ namespace Azure.ResourceManager.CommonTypes; */ @@armCommonDefinition(ManagedServiceIdentity, "ManagedServiceIdentity", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "managedidentity.json" +); +@@armCommonDefinition(ManagedServiceIdentity, + "ManagedServiceIdentity", + Azure.ResourceManager.CommonTypes.Versions.v4, "managedidentity.json" ); @@armCommonDefinition(ManagedServiceIdentity, @@ -21,7 +26,12 @@ namespace Azure.ResourceManager.CommonTypes; /** The set of user assigned identities associated with the resource. The userAssignedIdentities dictionary keys will be ARM resource ids in the form: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}. The dictionary values can be empty objects ({}) in requests.", */ @@armCommonDefinition(UserAssignedIdentities, "UserAssignedIdentities", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "managedidentity.json" +); +@@armCommonDefinition(UserAssignedIdentities, + "UserAssignedIdentities", + Azure.ResourceManager.CommonTypes.Versions.v4, "managedidentity.json" ); @@armCommonDefinition(UserAssignedIdentities, @@ -35,7 +45,12 @@ namespace Azure.ResourceManager.CommonTypes; */ @@armCommonDefinition(SystemAssignedServiceIdentity, "SystemAssignedServiceIdentity", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "managedidentity.json" +); +@@armCommonDefinition(SystemAssignedServiceIdentity, + "SystemAssignedServiceIdentity", + Azure.ResourceManager.CommonTypes.Versions.v4, "managedidentity.json" ); @@armCommonDefinition(SystemAssignedServiceIdentity, @@ -49,7 +64,12 @@ namespace Azure.ResourceManager.CommonTypes; */ @@armCommonDefinition(UserAssignedIdentity, "UserAssignedIdentity", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "managedidentity.json" +); +@@armCommonDefinition(UserAssignedIdentity, + "UserAssignedIdentity", + Azure.ResourceManager.CommonTypes.Versions.v4, "managedidentity.json" ); @@armCommonDefinition(UserAssignedIdentity, diff --git a/packages/typespec-azure-resource-manager/lib/common-types/private-links-ref.tsp b/packages/typespec-azure-resource-manager/lib/common-types/private-links-ref.tsp index c1f5c6c1ed..2fca19e18d 100644 --- a/packages/typespec-azure-resource-manager/lib/common-types/private-links-ref.tsp +++ b/packages/typespec-azure-resource-manager/lib/common-types/private-links-ref.tsp @@ -4,14 +4,53 @@ using Azure.ResourceManager.CommonTypes.Private; namespace Azure.ResourceManager.CommonTypes; -/** The private endpoint resource */ +/** The private endpoint */ @@armCommonDefinition(PrivateEndpoint, "PrivateEndpoint", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, "privatelinks.json" ); @@armCommonDefinition(PrivateEndpoint, "PrivateEndpoint", + Azure.ResourceManager.CommonTypes.Versions.v4, + "privatelinks.json" +); +@@armCommonDefinition(PrivateEndpoint, + "PrivateEndpoint", + Azure.ResourceManager.CommonTypes.Versions.v5, + "privatelinks.json" +); + +/** The private endpoint resource */ +@@armCommonDefinition(PrivateLinkResource, + "PrivateLinkResource", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateLinkResource, + "PrivateLinkResource", + Azure.ResourceManager.CommonTypes.Versions.v4, + "privatelinks.json" +); +@@armCommonDefinition(PrivateLinkResource, + "PrivateLinkResource", + Azure.ResourceManager.CommonTypes.Versions.v5, + "privatelinks.json" +); + +/** PrivateEndpointConnection */ +@@armCommonDefinition(PrivateEndpointConnection, + "PrivateEndpointConnection", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateEndpointConnection, + "PrivateEndpointConnection", + Azure.ResourceManager.CommonTypes.Versions.v4, + "privatelinks.json" +); +@@armCommonDefinition(PrivateEndpointConnection, + "PrivateEndpointConnection", Azure.ResourceManager.CommonTypes.Versions.v5, "privatelinks.json" ); @@ -19,7 +58,12 @@ namespace Azure.ResourceManager.CommonTypes; /** Properties of he private endpoint connection resource */ @@armCommonDefinition(PrivateEndpointConnectionProperties, "PrivateEndpointConnectionProperties", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateEndpointConnectionProperties, + "PrivateEndpointConnectionProperties", + Azure.ResourceManager.CommonTypes.Versions.v4, "privatelinks.json" ); @@armCommonDefinition(PrivateEndpointConnectionProperties, @@ -31,7 +75,12 @@ namespace Azure.ResourceManager.CommonTypes; /** A collection of information about the state of the connection between service consumer and provider. */ @@armCommonDefinition(PrivateLinkServiceConnectionState, "PrivateLinkServiceConnectionState", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateLinkServiceConnectionState, + "PrivateLinkServiceConnectionState", + Azure.ResourceManager.CommonTypes.Versions.v4, "privatelinks.json" ); @@armCommonDefinition(PrivateLinkServiceConnectionState, @@ -44,7 +93,12 @@ namespace Azure.ResourceManager.CommonTypes; #suppress "@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state" "Matches current common code" @@armCommonDefinition(PrivateLinkResourceProperties, "PrivateLinkResourceProperties", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateLinkResourceProperties, + "PrivateLinkResourceProperties", + Azure.ResourceManager.CommonTypes.Versions.v4, "privatelinks.json" ); @@armCommonDefinition(PrivateLinkResourceProperties, @@ -53,9 +107,49 @@ namespace Azure.ResourceManager.CommonTypes; "privatelinks.json" ); +/** PrivateEndpointConnectionListResult */ +@@armCommonDefinition(PrivateEndpointConnectionListResult, + "PrivateEndpointConnectionListResult", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateEndpointConnectionListResult, + "PrivateEndpointConnectionListResult", + Azure.ResourceManager.CommonTypes.Versions.v4, + "privatelinks.json" +); +@@armCommonDefinition(PrivateEndpointConnectionListResult, + "PrivateEndpointConnectionListResult", + Azure.ResourceManager.CommonTypes.Versions.v5, + "privatelinks.json" +); + +/** PrivateLinkResourceListResult */ +@@armCommonDefinition(PrivateLinkResourceListResult, + "PrivateLinkResourceListResult", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); +@@armCommonDefinition(PrivateLinkResourceListResult, + "PrivateLinkResourceListResult", + Azure.ResourceManager.CommonTypes.Versions.v4, + "privatelinks.json" +); +@@armCommonDefinition(PrivateLinkResourceListResult, + "PrivateLinkResourceListResult", + Azure.ResourceManager.CommonTypes.Versions.v5, + "privatelinks.json" +); + +/** PrivateEndpointConnectionParameter */ +@@CommonTypes.Private.armCommonParameter(PrivateEndpointConnectionParameter.name, + "PrivateEndpointConnectionName", + #{ version: Azure.ResourceManager.CommonTypes.Versions.v3, isDefault: true }, + "privatelinks.json" +); @@CommonTypes.Private.armCommonParameter(PrivateEndpointConnectionParameter.name, "PrivateEndpointConnectionName", - #{ version: Azure.ResourceManager.CommonTypes.Versions.v4, isDefault: true }, + Azure.ResourceManager.CommonTypes.Versions.v4, "privatelinks.json" ); @@CommonTypes.Private.armCommonParameter(PrivateEndpointConnectionParameter.name, diff --git a/packages/typespec-azure-resource-manager/lib/common-types/types-ref.tsp b/packages/typespec-azure-resource-manager/lib/common-types/types-ref.tsp index d2bd98898c..09cadfb7ba 100644 --- a/packages/typespec-azure-resource-manager/lib/common-types/types-ref.tsp +++ b/packages/typespec-azure-resource-manager/lib/common-types/types-ref.tsp @@ -137,20 +137,11 @@ namespace Azure.ResourceManager.CommonTypes; ); /** - * The default operationId parameter type. + * locationData */ -@@armCommonDefinition(OperationIdParameter, - "OperationIdParameter", - Azure.ResourceManager.CommonTypes.Versions.v3 -); -@@armCommonDefinition(OperationIdParameter, - "OperationIdParameter", - Azure.ResourceManager.CommonTypes.Versions.v4 -); -@@armCommonDefinition(OperationIdParameter, - "OperationIdParameter", - Azure.ResourceManager.CommonTypes.Versions.v5 -); +@@armCommonDefinition(LocationData, "locationData", Azure.ResourceManager.CommonTypes.Versions.v3); +@@armCommonDefinition(LocationData, "locationData", Azure.ResourceManager.CommonTypes.Versions.v4); +@@armCommonDefinition(LocationData, "locationData", Azure.ResourceManager.CommonTypes.Versions.v5); /** * The error detail. @@ -175,6 +166,13 @@ namespace Azure.ResourceManager.CommonTypes; Azure.ResourceManager.CommonTypes.Versions.v5 ); +/** + * Identity + */ +@@armCommonDefinition(Identity, "Identity", Azure.ResourceManager.CommonTypes.Versions.v3); +@@armCommonDefinition(Identity, "Identity", Azure.ResourceManager.CommonTypes.Versions.v4); +@@armCommonDefinition(Identity, "Identity", Azure.ResourceManager.CommonTypes.Versions.v5); + /** * Metadata pertaining to creation and last modification of the resource. */ @@ -189,6 +187,54 @@ namespace Azure.ResourceManager.CommonTypes; @@armCommonDefinition(Plan, "Plan", Azure.ResourceManager.CommonTypes.Versions.v4); @@armCommonDefinition(Plan, "Plan", Azure.ResourceManager.CommonTypes.Versions.v5); +/** + * encryptionProperties + */ +@@armCommonDefinition(EncryptionProperties, + "encryptionProperties", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonDefinition(EncryptionProperties, + "encryptionProperties", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonDefinition(EncryptionProperties, + "encryptionProperties", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +/** + * KeyVaultProperties + */ +@@armCommonDefinition(KeyVaultProperties, + "KeyVaultProperties", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonDefinition(KeyVaultProperties, + "KeyVaultProperties", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonDefinition(KeyVaultProperties, + "KeyVaultProperties", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +/** + * ResourceModelWithAllowedPropertySet + */ +@@armCommonDefinition(ResourceModelWithAllowedPropertySet, + "ResourceModelWithAllowedPropertySet", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonDefinition(ResourceModelWithAllowedPropertySet, + "ResourceModelWithAllowedPropertySet", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonDefinition(ResourceModelWithAllowedPropertySet, + "ResourceModelWithAllowedPropertySet", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + /** * The check availability request body. */ @@ -221,6 +267,21 @@ namespace Azure.ResourceManager.CommonTypes; Azure.ResourceManager.CommonTypes.Versions.v5 ); +@@armCommonDefinition(ErrorResponse, + "ErrorResponse", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonDefinition(ErrorResponse, + "ErrorResponse", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonDefinition(ErrorResponse, + "ErrorResponse", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +// -- Parameters +/** ApiVersionParameter */ @@armCommonParameter(ApiVersionParameter.apiVersion, "ApiVersionParameter", Azure.ResourceManager.CommonTypes.Versions.v3 @@ -244,6 +305,7 @@ namespace Azure.ResourceManager.CommonTypes; ] ); +/** SubscriptionIdParameter */ @@armCommonParameter(SubscriptionIdParameter.subscriptionId, "SubscriptionIdParameter", Azure.ResourceManager.CommonTypes.Versions.v3 @@ -260,15 +322,93 @@ namespace Azure.ResourceManager.CommonTypes; [ResourceHome.ResourceGroup, ResourceHome.Subscription, ResourceHome.Location] ); -@@armCommonDefinition(ErrorResponse, - "ErrorResponse", +/** ResourceGroupNameParameter */ +@@armCommonParameter(ResourceGroupNameParameter.resourceGroupName, + "ResourceGroupNameParameter", Azure.ResourceManager.CommonTypes.Versions.v3 ); -@@armCommonDefinition(ErrorResponse, - "ErrorResponse", +@@armCommonParameter(ResourceGroupNameParameter.resourceGroupName, + "ResourceGroupNameParameter", Azure.ResourceManager.CommonTypes.Versions.v4 ); -@@armCommonDefinition(ErrorResponse, - "ErrorResponse", +@@armCommonParameter(ResourceGroupNameParameter.resourceGroupName, + "ResourceGroupNameParameter", + Azure.ResourceManager.CommonTypes.Versions.v5 +); +@@resourceParameterBaseFor(ResourceGroupNameParameter.resourceGroupName, + [ResourceHome.ResourceGroup] +); + +/** ManagementGroupNameParameter */ +@@armCommonParameter(ManagementGroupNameParameter.managementGroupName, + "ManagementGroupNameParameter", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonParameter(ManagementGroupNameParameter.managementGroupName, + "ManagementGroupNameParameter", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonParameter(ManagementGroupNameParameter.managementGroupName, + "ManagementGroupNameParameter", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +/** ScopeParameter */ +@@armCommonParameter(ScopeParameter.scope, + "ScopeParameter", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonParameter(ScopeParameter.scope, + "ScopeParameter", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonParameter(ScopeParameter.scope, + "ScopeParameter", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +/** LocationResourceParameter */ +@@armCommonParameter(LocationResourceParameter.location, + "LocationParameter", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonParameter(LocationResourceParameter.location, + "LocationParameter", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonParameter(LocationResourceParameter.location, + "LocationParameter", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +/** + * The default operationId parameter type. + */ +@@armCommonParameter(OperationIdParameter.operationId, + "OperationIdParameter", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonParameter(OperationIdParameter.operationId, + "OperationIdParameter", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonParameter(OperationIdParameter.operationId, + "OperationIdParameter", + Azure.ResourceManager.CommonTypes.Versions.v5 +); + +/** + * TenantIdParameter + */ +@@armCommonParameter(TenantIdParameter.tenantId, + "TenantIdParameter", + Azure.ResourceManager.CommonTypes.Versions.v3 +); +@@armCommonParameter(TenantIdParameter.tenantId, + "TenantIdParameter", + Azure.ResourceManager.CommonTypes.Versions.v4 +); +@@armCommonParameter(TenantIdParameter.tenantId, + "TenantIdParameter", Azure.ResourceManager.CommonTypes.Versions.v5 ); diff --git a/packages/typespec-azure-resource-manager/lib/common-types/types.tsp b/packages/typespec-azure-resource-manager/lib/common-types/types.tsp index 31d119c93a..b2d5c8b19a 100644 --- a/packages/typespec-azure-resource-manager/lib/common-types/types.tsp +++ b/packages/typespec-azure-resource-manager/lib/common-types/types.tsp @@ -6,10 +6,7 @@ using Azure.Core; namespace Azure.ResourceManager.CommonTypes; -/** - * Base model that defines common properties for all Azure Resource Manager resources. - */ -@doc("Common fields that are returned in the response for all Azure Resource Manager resources") +/** Common fields that are returned in the response for all Azure Resource Manager resources */ @extension("x-ms-azure-resource", true) model Resource { /** Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} */ @@ -72,6 +69,7 @@ model ResourceModelWithAllowedPropertySet extends TrackedResource { /** Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type; e.g. ApiApps are a kind of Microsoft.Web/sites type. * If supported, the resource provider must validate and persist this value. */ @pattern("^[-\\w\\._,\\(\\)]+$") + @visibility("read", "create") kind?: string; /** The etag field is *not* required. If it is provided in the response body, it must also be provided as a header per the normal etag convention. @@ -132,14 +130,14 @@ model OperationListResult is Azure.Core.Page; */ model Operation { /** - The name of the operation, as per Resource-Based Access Control (RBAC). Examples: "Microsoft.Compute/virtualMachines/write", "Microsoft.Compute/virtualMachines/capture/action" - */ + The name of the operation, as per Resource-Based Access Control (RBAC). Examples: "Microsoft.Compute/virtualMachines/write", "Microsoft.Compute/virtualMachines/capture/action" + */ @visibility("read") name?: string; /** - Whether the operation applies to data-plane. This is "true" for data-plane operations and "false" for Azure Resource Manager/control-plane operations. - */ + Whether the operation applies to data-plane. This is "true" for data-plane operations and "false" for Azure Resource Manager/control-plane operations. + */ @visibility("read") isDataAction?: boolean; @@ -147,15 +145,14 @@ model Operation { display?: OperationDisplay; /** - The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is "user,system" - */ + The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is "user,system" + */ @visibility("read") origin?: Origin; /** - Extensible enum. Indicates the action type. "Internal" refers to actions that are for internal only APIs. - */ - @visibility("read") + Extensible enum. Indicates the action type. "Internal" refers to actions that are for internal only APIs. + */ actionType?: ActionType; } @@ -169,13 +166,13 @@ model OperationDisplay { provider?: string; /** - The localized friendly name of the resource type related to this operation. E.g. "Virtual Machines" or "Job Schedule Collections". - */ + The localized friendly name of the resource type related to this operation. E.g. "Virtual Machines" or "Job Schedule Collections". + */ resource?: string; /** - The concise, localized friendly name for the operation; suitable for dropdowns. E.g. "Create or Update Virtual Machine", "Restart Virtual Machine". - */ + The concise, localized friendly name for the operation; suitable for dropdowns. E.g. "Create or Update Virtual Machine", "Restart Virtual Machine". + */ operation?: string; /** The short, localized friendly description of the operation; suitable for tool tips and detailed views. */ @@ -270,7 +267,7 @@ model ErrorDetail { */ @error model ErrorResponse { - @doc("The error object.") + /** The error object. */ error?: ErrorDetail; } @@ -292,28 +289,22 @@ model ErrorAdditionalInfo { */ model SystemData { /** The identity that created the resource. */ - @visibility("read") createdBy?: string; /** The type of identity that created the resource. */ - @visibility("read") createdByType?: createdByType; /** The timestamp of resource creation (UTC). */ - @visibility("read") - createdAt?: plainDate; + createdAt?: utcDateTime; /** The identity that last modified the resource. */ - @visibility("read") lastModifiedBy?: string; /** The type of identity that last modified the resource. */ - @visibility("read") lastModifiedByType?: createdByType; /** The timestamp of resource last modification (UTC) */ - @visibility("read") - lastModifiedAt?: plainDate; + lastModifiedAt?: utcDateTime; } /** @@ -421,15 +412,20 @@ union CheckNameAvailabilityReason { string, } +/** Indicates whether or not the encryption is enabled for container registry. */ union EncryptionStatus { + /** Encryption is enabled. */ enabled: "enabled", + + /** Encryption is disabled. */ disabled: "disabled", + string, } /** * Configuration of key for data encryption */ -model encryptionProperties { +model EncryptionProperties { /** Indicates whether or not the encryption is enabled for container registry. */ status?: EncryptionStatus; @@ -440,7 +436,7 @@ model encryptionProperties { /** * Metadata pertaining to the geographic location of the resource. */ -model locationData { +model LocationData { /** A canonical name for the geographic or physical location. */ @maxLength(256) name: string; @@ -458,11 +454,10 @@ model locationData { /** * The default api-version parameter type. */ -@doc("The default api-version parameter type.") model ApiVersionParameter { + /** The API version to use for this operation. */ @query("api-version") @minLength(1) - @doc("The API version to use for this operation.") apiVersion: string; } @@ -503,15 +498,24 @@ model ResourceGroupNameParameter { /** * The default subscriptionId parameter type. */ -@doc("The default subscriptionId parameter type.") model SubscriptionIdParameter { + /** The ID of the target subscription. The value must be an UUID. */ @typeChangedFrom(Versions.v4, string) @path @segment("subscriptions") - @doc("The ID of the target subscription. The value must be an UUID.") subscriptionId: uuid; } +/** The default location parameter type. */ +model LocationResourceParameter { + /** The name of the Azure region. */ + @path + @minLength(1) + @segment("locations") + @key + location: string; +} + /** * The default ManagementGroupName parameter type. */ diff --git a/packages/typespec-azure-resource-manager/lib/decorators.tsp b/packages/typespec-azure-resource-manager/lib/decorators.tsp index 2781366d97..6923f09652 100644 --- a/packages/typespec-azure-resource-manager/lib/decorators.tsp +++ b/packages/typespec-azure-resource-manager/lib/decorators.tsp @@ -180,7 +180,7 @@ extern dec armResourceOperations(target: Interface, _?: unknown); * This decorator is used either on a namespace or a version enum value to indicate * the version of the Azure Resource Manager common-types to use for refs in emitted Swagger files. * - * @param version The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version. + * @param version The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". */ extern dec armCommonTypesVersion( target: Namespace | EnumMember, diff --git a/packages/typespec-azure-resource-manager/lib/foundations/arm.foundations.tsp b/packages/typespec-azure-resource-manager/lib/foundations/arm.foundations.tsp index 644bc0437f..454caec07a 100644 --- a/packages/typespec-azure-resource-manager/lib/foundations/arm.foundations.tsp +++ b/packages/typespec-azure-resource-manager/lib/foundations/arm.foundations.tsp @@ -115,7 +115,11 @@ model ResourceUpdateModelProperties< model ResourceUpdateModel< Resource extends Foundations.Resource, Properties extends TypeSpec.Reflection.Model -> is OptionalProperties>> { +> + is OptionalProperties>> { @extension("x-ms-client-flatten", true) properties?: ResourceUpdateModelProperties; } diff --git a/packages/typespec-azure-resource-manager/lib/models.tsp b/packages/typespec-azure-resource-manager/lib/models.tsp index 1f21dc5a06..fb0bfca16e 100644 --- a/packages/typespec-azure-resource-manager/lib/models.tsp +++ b/packages/typespec-azure-resource-manager/lib/models.tsp @@ -11,22 +11,27 @@ namespace Azure.ResourceManager; * Spread this model into ARM resource models to specify resource name parameter for its operations. If `Resource` parameter * is specified, the resource name will be properly camel cased and pluralized for `@key` and `@segment` * automatically. You can also apply explicit override with `KeyName` and `SegmentName` template parameters. + * + * For additional decorators such as @minLength, you can use either augment decorator on `[Resource].name` or passing in a scalar string type with decorators. + * * @template Resource The ARM resource this name parameter is applying to. * @template KeyName Override default key name of the resource. * @template SegmentName Override default segment name of the resource. * @template NamePattern The RegEx pattern of the name. Default is `^[a-zA-Z0-9-]{3,24}$`. + * @template Type The type of the name property. Default type is string. However you can pass an union with string values. */ model ResourceNameParameter< Resource extends Foundations.Resource, KeyName extends valueof string = "", SegmentName extends valueof string = "", - NamePattern extends valueof string = "^[a-zA-Z0-9-]{3,24}$" + NamePattern extends valueof string = "^[a-zA-Z0-9-]{3,24}$", + Type extends string = string > { @doc("The name of the {name}", Resource) @pattern(NamePattern) @defaultResourceKeySegmentName(Resource, KeyName, SegmentName) @path - name: string; + name: Type; } //#region Standard Resource Operation Interfaces @@ -41,7 +46,6 @@ model ResourceNameParameter< @includeInapplicableMetadataInPayload(false) model TrackedResource extends Foundations.TrackedResource { @doc("The resource-specific properties for this resource.") - @visibility("read", "create") @extension("x-ms-client-flatten", true) properties?: Properties; } @@ -57,7 +61,6 @@ model TrackedResource extends Foundations.TrackedResource @includeInapplicableMetadataInPayload(false) model ProxyResource extends Foundations.ProxyResource { @doc("The resource-specific properties for this resource.") - @visibility("read", "create") @extension("x-ms-client-flatten", true) properties?: Properties; } @@ -74,7 +77,6 @@ model ProxyResource extends Foundations.ProxyResource { @includeInapplicableMetadataInPayload(false) model ExtensionResource extends Foundations.ExtensionResource { @doc("The resource-specific properties for this resource.") - @visibility("read", "create") @extension("x-ms-client-flatten", true) properties?: Properties; } diff --git a/packages/typespec-azure-resource-manager/lib/operations.tsp b/packages/typespec-azure-resource-manager/lib/operations.tsp index 546febe1e0..d5211d4358 100644 --- a/packages/typespec-azure-resource-manager/lib/operations.tsp +++ b/packages/typespec-azure-resource-manager/lib/operations.tsp @@ -1,6 +1,5 @@ using TypeSpec.Http; using TypeSpec.Rest; -using TypeSpec.OpenAPI; using Azure.ResourceManager.Foundations; namespace Azure.ResourceManager; @@ -144,20 +143,15 @@ op ArmResourceCheckExistence< */ @autoRoute @doc("Create a {name}", Resource) -@extension("x-ms-long-running-operation", true) -@extension( - "x-ms-long-running-operation-options", - { - `final-state-via`: "azure-async-operation", - } -) @armResourceCreateOrUpdate(Resource) @Private.enforceConstraint(Resource, Foundations.Resource) +@Azure.Core.Foundations.Private.defaultFinalStateVia(#["location", "azure-async-operation"]) @put op ArmResourceCreateOrUpdateAsync< Resource extends Foundations.Resource, BaseParameters = DefaultBaseParameters, - LroHeaders extends TypeSpec.Reflection.Model = Azure.Core.Foundations.RetryAfterHeader, + LroHeaders extends TypeSpec.Reflection.Model = ArmAsyncOperationHeader & + Azure.Core.Foundations.RetryAfterHeader, Parameters extends {} = {}, Response extends {} = ArmResourceUpdatedResponse | ArmResourceCreatedResponse< Resource, @@ -237,7 +231,8 @@ op ArmResourceCreateOrReplaceSync< op ArmResourceCreateOrReplaceAsync< Resource extends Foundations.Resource, BaseParameters = DefaultBaseParameters, - LroHeaders extends TypeSpec.Reflection.Model = Azure.Core.Foundations.RetryAfterHeader, + LroHeaders extends TypeSpec.Reflection.Model = ArmAsyncOperationHeader & + Azure.Core.Foundations.RetryAfterHeader, Parameters extends {} = {}, Response extends {} = ArmResourceUpdatedResponse | ArmResourceCreatedResponse< Resource, @@ -320,13 +315,6 @@ op ArmResourcePatchAsync< */ @autoRoute @doc("Update a {name}", Resource) -@extension("x-ms-long-running-operation", true) -@extension( - "x-ms-long-running-operation-options", - { - `final-state-via`: "location", - } -) @armResourceUpdate(Resource) @Private.enforceConstraint(Resource, Foundations.Resource) @patch @@ -424,13 +412,6 @@ op ArmCustomPatchSync< */ @autoRoute @doc("Delete a {name}", Resource) -@extension("x-ms-long-running-operation", true) -@extension( - "x-ms-long-running-operation-options", - { - `final-state-via`: "location", - } -) @armResourceDelete(Resource) @Private.enforceConstraint(Resource, Foundations.Resource) @delete @@ -514,13 +495,6 @@ op ArmResourceDeleteSync< * @template Error Optional. The error response, if non-standard. */ @autoRoute -@extension("x-ms-long-running-operation", true) -@extension( - "x-ms-long-running-operation-options", - { - `final-state-via`: "location", - } -) @armResourceAction(Resource) @Private.enforceConstraint(Resource, Foundations.Resource) @post diff --git a/packages/typespec-azure-resource-manager/lib/parameters.tsp b/packages/typespec-azure-resource-manager/lib/parameters.tsp index 5d614fb073..43a17c652e 100644 --- a/packages/typespec-azure-resource-manager/lib/parameters.tsp +++ b/packages/typespec-azure-resource-manager/lib/parameters.tsp @@ -19,35 +19,29 @@ alias ApiVersionParameter = CommonTypes.ApiVersionParameter; alias SubscriptionIdParameter = CommonTypes.SubscriptionIdParameter; /** - * DEPRECATED - DO NOT USE - * The default location parameter type. + * The default ResourceGroup parameter type. */ -@doc("The default location parameter type.") -model LocationParameter { - @path - @minLength(1) - @segment("locations") - @doc("The location name.") - @armCommonParameter("LocationParameter", Azure.ResourceManager.CommonTypes.Versions.v3) - @armCommonParameter("LocationParameter", Azure.ResourceManager.CommonTypes.Versions.v4) - @armCommonParameter("LocationParameter", Azure.ResourceManager.CommonTypes.Versions.v5) - @resourceParameterBaseFor([ResourceHome.Location]) - location: string; -} +alias ResourceGroupParameter = CommonTypes.ResourceGroupNameParameter; + +/** + * The default LocationResource parameter type. + */ +alias LocationResourceParameter = CommonTypes.LocationResourceParameter; /** + * DEPRECATED - DO NOT USE * The default location parameter type. */ @doc("The default location parameter type.") -model LocationResourceParameter { +model LocationParameter { @path @minLength(1) @segment("locations") @doc("The location name.") - @key @armCommonParameter("LocationParameter", Azure.ResourceManager.CommonTypes.Versions.v3) @armCommonParameter("LocationParameter", Azure.ResourceManager.CommonTypes.Versions.v4) @armCommonParameter("LocationParameter", Azure.ResourceManager.CommonTypes.Versions.v5) + @resourceParameterBaseFor([ResourceHome.Location]) location: string; } @@ -84,24 +78,6 @@ model ArmLocationResource { /** A link to the status monitor */ @header("Azure-AsyncOperation") - @Azure.Core.pollingLocation(Azure.Core.StatusMonitorPollingOptions) + @Azure.Core.pollingLocation(Azure.Core.StatusMonitorPollingOptions) + @Azure.Core.finalLocation(FinalResult) azureAsyncOperation?: UrlValue; } @@ -151,7 +154,7 @@ model ArmAsyncOperationHeader< * @template UrlValue The value type for the location header */ model ArmLroLocationHeader< - LroPollingOptions extends Azure.Core.PollingOptions = Azure.Core.StatusMonitorPollingOptions, + LroPollingOptions extends Azure.Core.PollingOptions = Azure.Core.StatusMonitorPollingOptions, FinalResult extends {} | void = void, UrlValue extends string = string > { diff --git a/packages/typespec-azure-resource-manager/src/common-types.ts b/packages/typespec-azure-resource-manager/src/common-types.ts index 8b69d3bf93..f0cb277c79 100644 --- a/packages/typespec-azure-resource-manager/src/common-types.ts +++ b/packages/typespec-azure-resource-manager/src/common-types.ts @@ -187,11 +187,13 @@ export function findArmCommonTypeRecord( break; } } - } else { + } + if (record === undefined) { // If no version was found, use the default version record = records[defaultKey ?? ArmCommonTypesDefaultVersion]; } + // If after resolve version AND unable to load default version, report diagnostic if (record === undefined) { return [ undefined, diff --git a/packages/typespec-azure-resource-manager/src/lib.ts b/packages/typespec-azure-resource-manager/src/lib.ts index 141c9aa66b..11dd6eca9c 100644 --- a/packages/typespec-azure-resource-manager/src/lib.ts +++ b/packages/typespec-azure-resource-manager/src/lib.ts @@ -79,7 +79,7 @@ export const $lib = createTypeSpecLibrary({ "arm-common-types-invalid-version": { severity: "error", messages: { - default: paramMessage`No ARM common-types version match the version string ${"versionString"}. The following versions are supported: ${"supportedVersions"}`, + default: paramMessage`No ARM common-types version matches the version string ${"versionString"}. The following versions are supported: ${"supportedVersions"}`, }, }, "decorator-in-namespace": { diff --git a/packages/typespec-azure-resource-manager/test/lro-metadata.test.ts b/packages/typespec-azure-resource-manager/test/lro-metadata.test.ts index 27780cdda0..67192c79eb 100644 --- a/packages/typespec-azure-resource-manager/test/lro-metadata.test.ts +++ b/packages/typespec-azure-resource-manager/test/lro-metadata.test.ts @@ -77,7 +77,7 @@ describe("typespec-azure-resource-manager: ARM LRO Tests", () => { deepStrictEqual((metadata.finalResult as Model)?.name, "Widget"); deepStrictEqual((metadata.finalEnvelopeResult as Model)?.name, "Widget"); deepStrictEqual(metadata.finalResultPath, undefined); - deepStrictEqual(metadata.finalStateVia, "original-uri"); + deepStrictEqual(metadata.finalStateVia, "azure-async-operation"); }); it("Returns correct metadata for Async CreateOrUpdate with final location", async () => { @@ -362,7 +362,7 @@ describe("typespec-azure-resource-manager: ARM LRO Tests", () => { deepStrictEqual((metadata.finalResult as Model)?.name, "Widget"); deepStrictEqual((metadata.finalEnvelopeResult as Model)?.name, "Widget"); deepStrictEqual(metadata.finalResultPath, undefined); - deepStrictEqual(metadata.finalStateVia, "original-uri"); + deepStrictEqual(metadata.finalStateVia, "azure-async-operation"); }); it("Returns correct metadata for Async CreateOrUpdate with final location, with union type ProvisioningState", async () => { diff --git a/packages/typespec-azure-resource-manager/test/resource.test.ts b/packages/typespec-azure-resource-manager/test/resource.test.ts index b8d672948f..8d634817b5 100644 --- a/packages/typespec-azure-resource-manager/test/resource.test.ts +++ b/packages/typespec-azure-resource-manager/test/resource.test.ts @@ -652,4 +652,68 @@ describe("typespec-azure-resource-manager: ARM resource model", () => { strictEqual(resources.length, 1); ok(resources[0].typespecType.properties.has("extendedLocation")); }); + + it("emits correct fixed union name parameter for resource", async () => { + const { program, diagnostics } = await checkFor(` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso; + + @doc("Widget resource") + model Widget is ProxyResource { + ...ResourceNameParameter; + } + + @doc("The properties of a widget") + model WidgetProperties { + size: int32; + } + + /** different type of widget used on resource path */ + union WidgetNameType { + string, + /** small widget */ + Small: "Small", + /** large widget */ + Large: "Large" + } + `); + const resources = getArmResources(program); + expectDiagnosticEmpty(diagnostics); + strictEqual(resources.length, 1); + ok(resources[0].typespecType.properties.has("name")); + const nameProperty = resources[0].typespecType.properties.get("name"); + strictEqual(nameProperty?.type.kind, "Union"); + strictEqual(nameProperty?.type.name, "WidgetNameType"); + }); + + it("emits a scalar string with decorator parameter for resource", async () => { + const { program, diagnostics } = await checkFor(` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso; + + @doc("Widget resource") + model Widget is ProxyResource { + ...ResourceNameParameter; + } + + @doc("The properties of a widget") + model WidgetProperties { + size: int32; + } + + @minLength(1) + @maxLength(10) + @pattern("xxxxxx") + scalar WidgetNameType extends string; + `); + const resources = getArmResources(program); + expectDiagnosticEmpty(diagnostics); + strictEqual(resources.length, 1); + ok(resources[0].typespecType.properties.has("name")); + const nameProperty = resources[0].typespecType.properties.get("name"); + strictEqual(nameProperty?.type.kind, "Scalar"); + strictEqual(nameProperty?.type.name, "WidgetNameType"); + }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2038c332a8..7860bf3e64 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -199,8 +199,8 @@ importers: core/packages/bundle-uploader: dependencies: '@azure/identity': - specifier: ~4.2.0 - version: 4.2.0 + specifier: ~4.2.1 + version: 4.2.1 '@azure/storage-blob': specifier: ~12.18.0 version: 12.18.0 @@ -2496,8 +2496,8 @@ packages: '@azure/abort-controller': 2.1.2 tslib: 2.6.2 - /@azure/identity@4.2.0: - resolution: {integrity: sha512-ve3aYv79qXOJ8wRxQ5jO0eIz2DZ4o0TyME4m4vlGV5YyePddVZ+pFMzusAMODNAflYAAv1cBIhKnd4xytmXyig==} + /@azure/identity@4.2.1: + resolution: {integrity: sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q==} engines: {node: '>=18.0.0'} dependencies: '@azure/abort-controller': 1.1.0 @@ -2508,7 +2508,7 @@ packages: '@azure/core-util': 1.9.0 '@azure/logger': 1.1.2 '@azure/msal-browser': 3.14.0 - '@azure/msal-node': 2.8.1 + '@azure/msal-node': 2.9.2 events: 3.3.0 jws: 4.0.0 open: 8.4.2 @@ -2533,11 +2533,15 @@ packages: resolution: {integrity: sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA==} engines: {node: '>=0.8.0'} - /@azure/msal-node@2.8.1: - resolution: {integrity: sha512-VcZZM+5VvCWRBTOF7SxMKaxrz+EXjntx2u5AQe7QE06e6FuPJElGBrImgNgCh5QmFaNCfVFO+3qNR7UoFD/Gfw==} + /@azure/msal-common@14.12.0: + resolution: {integrity: sha512-IDDXmzfdwmDkv4SSmMEyAniJf6fDu3FJ7ncOjlxkDuT85uSnLEhZi3fGZpoR7T4XZpOMx9teM9GXBgrfJgyeBw==} + engines: {node: '>=0.8.0'} + + /@azure/msal-node@2.9.2: + resolution: {integrity: sha512-8tvi6Cos3m+0KmRbPjgkySXi+UQU/QiuVRFnrxIwt5xZlEEFa69O04RTaNESGgImyBBlYbo2mfE8/U8Bbdk1WQ==} engines: {node: '>=16'} dependencies: - '@azure/msal-common': 14.10.0 + '@azure/msal-common': 14.12.0 jsonwebtoken: 9.0.2 uuid: 8.3.2 @@ -10754,7 +10758,7 @@ packages: engines: {node: '>= 16'} hasBin: true dependencies: - '@azure/identity': 4.2.0 + '@azure/identity': 4.2.1 azure-devops-node-api: 12.5.0 chalk: 2.4.2 cheerio: 1.0.0-rc.12